Search code examples
ethereumsoliditysmartcontractschainlink

How fix TypeError and DeclarationError with ChainLink Solidity smart contract?


I have created a smart contract which return to each user the amount deposited + a certain amount if the price of ETH decreases during the lock period. I have two problems with the last part of the code.

The first one concerns mapping the price of ethereum at the moment the user makes the deposit. I have tried several solutions but none of them seem to work. The problem arises on line 64 mapping(uint => uint) ethPrice;. Console returns:

DeclarationError: Identifier already declared.
--> oracle.sol:65:5:
|
65 | mapping(uint => uint) ethPrice;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: The previous declaration is here:
--> oracle.sol:63:5:
|
63 | uint public ethPrice = 0; 
| ^^^^^^^^^^^^^^^^^^^^^^^^

The second is found on line no. 91. msg.sender.transfer(amountToWithdraw); with the transfer function. The console continues to return the following error despite the fact that the address of each user is defined as payable in the previous functions. Console returns:

TypeError: "send" and "transfer" are only available for objects of type "address payable", not "address".
--> oracle.sol:97:9:
|
97 | msg.sender.transfer(amountToWithdraw);
| ^^^^^^^^^^^^^^^^^^^

These two problems severely invalidate the smart contract and are holding up the completion of coding the latest functions. I have contacted several people and looked in forums concerning programming on solidity but no one seems to have an answer to my problem.

I hope that my question can be answered by the community and can help any other person trying to use ChainLink with Solidity in the future. I am happy to listen to any advice on the matter.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;


import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

    // EACAggregatorProxy is used for chainlink oracle
interface EACAggregatorProxy {
    function latestAnswer() external view returns (int256);
}

contract oracleLink {

    // Address dev
    address public dev;
    // Dev's public deposit amount
    uint public devDeposit;
    // Array dev's public amount
    uint[] public devDeposits;

    // List each user and amount
    address[] public users;                   
    uint[] public totalDeposited;  

    // Mapping user's deposit
    mapping(address => uint) balances;

    // Deployer = dev & Dev deposit function 
    function deployerIsDeveloper() public payable {
        dev = msg.sender;
        devDeposit = msg.value;
        devDeposits.push(devDeposit);                   
    }

    // User's address
    address user;
    // Amount's address 
    uint amountDeposit;
    // Deadline time 
    uint256 deadline;

    // Amount's each user
    uint256 lockAmount = lockAmounts[msg.sender];
    // Mapping of deposit for each user        
    mapping(address => uint) lockAmounts;

    // Timestamp for each user 
    uint256 startTime = startTimes[block.timestamp];
    // Mapping timestamp for each user  
    mapping(uint => uint) startTimes; 

    // Kovan ETH/USD oracle address 
    address public chainLinkETHUSDAddress = 0x9326BFA02ADD2366b30bacB125260Af641031331;

    // ethPrice 
    uint public ethPrice = 0; 
    uint256 price = ethPrice;
    mapping(uint => uint) ethPrice;

    // Deposit function for each user 
    function deposit(uint256 numberOfSeconds) public payable {

        lockAmounts[msg.sender] = msg.value;
        startTimes[block.timestamp] = block.timestamp;
        
        user = msg.sender;           
        amountDeposit = msg.value;      
        
        users.push(user);                     
        totalDeposited.push(amountDeposit);

        deadline = block.timestamp + (numberOfSeconds * 1 seconds);

        int256 chainLinkEthPrice = EACAggregatorProxy(chainLinkETHUSDAddress).latestAnswer();
        ethPrice = uint(chainLinkEthPrice / 100000000);
        //return ethPrice = price;
        //price.push(ethPrice);
    }

    // Withdraw function for each user 
    function withdraw() public payable {
        require(block.timestamp >= deadline);
        uint amountToWithdraw = lockAmounts[msg.sender];
        lockAmounts[msg.sender] = 0; 
        msg.sender.transfer(amountToWithdraw); 
    }
}

Solution

  • For the first issue, Solidity compiler said that you declared two variables with the identifier. In details in your case, you give ethPrice for mapping and uint variable. To solve this issue, try to change one of these names in this way:

     uint256 price = ethPrice;
     mapping(uint => uint) mappingEthPrice;
    

    Second issue refers that msg.sender keyword doesn't cast automatically with address payable and to solve it you can use payable() function that allows you convert an address to address payable. In your smart contract you must to change in this way:

    payable(msg.sender).transfer(amountToWithdraw); 
    

    This should be your smart contract fixed:

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.6;
    
    
    import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
    
        // EACAggregatorProxy is used for chainlink oracle
    interface EACAggregatorProxy {
        function latestAnswer() external view returns (int256);
    }
    
    contract oracleLink {
    
        // Address dev
        address public dev;
        // Dev's public deposit amount
        uint public devDeposit;
        // Array dev's public amount
        uint[] public devDeposits;
    
        // List each user and amount
        address[] public users;                   
        uint[] public totalDeposited;  
    
        // Mapping user's deposit
        mapping(address => uint) balances;
    
        // Deployer = dev & Dev deposit function 
        function deployerIsDeveloper() public payable {
            dev = msg.sender;
            devDeposit = msg.value;
            devDeposits.push(devDeposit);                   
        }
    
        // User's address
        address user;
        // Amount's address 
        uint amountDeposit;
        // Deadline time 
        uint256 deadline;
    
        // Amount's each user
        uint256 lockAmount = lockAmounts[msg.sender];
        // Mapping of deposit for each user        
        mapping(address => uint) lockAmounts;
    
        // Timestamp for each user 
        uint256 startTime = startTimes[block.timestamp];
        // Mapping timestamp for each user  
        mapping(uint => uint) startTimes; 
    
        // Kovan ETH/USD oracle address 
        address public chainLinkETHUSDAddress = 0x9326BFA02ADD2366b30bacB125260Af641031331;
    
        // ethPrice 
        uint public ethPrice = 0; 
        uint256 price = ethPrice;
        mapping(uint => uint) mappingEthPrice;
    
        // Deposit function for each user 
        function deposit(uint256 numberOfSeconds) public payable {
    
            lockAmounts[msg.sender] = msg.value;
            startTimes[block.timestamp] = block.timestamp;
            
            user = msg.sender;           
            amountDeposit = msg.value;      
            
            users.push(user);                     
            totalDeposited.push(amountDeposit);
    
            deadline = block.timestamp + (numberOfSeconds * 1 seconds);
    
            int256 chainLinkEthPrice = EACAggregatorProxy(chainLinkETHUSDAddress).latestAnswer();
            ethPrice = uint(chainLinkEthPrice / 100000000);
            //return ethPrice = price;
            //price.push(ethPrice);
        }
    
        // Withdraw function for each user 
        function withdraw() public payable {
            require(block.timestamp >= deadline);
            uint amountToWithdraw = lockAmounts[msg.sender];
            lockAmounts[msg.sender] = 0; 
            payable(msg.sender).transfer(amountToWithdraw); 
        }
    }