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);
}
}
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);
}
}