I know this is a noob question but I have this staking function but it fails when I tried to call function stake
.
Deployed Contract: 0x25187f46197BB0e0d343968df5318F630d3f6992
Code to reproduce
CCAToken.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/AccessControlEnumerable.sol";
contract CCAToken is ERC20, AccessControlEnumerable {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
constructor() ERC20("CCA Token", "CCA") {}
function mint(address to, uint256 amount) public virtual {
require(hasRole(MINTER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have minter role to mint");
_mint(to, amount);
}
}
CCAFarm.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol";
import "./CCAToken.sol";
contract CCAFarm is CCAToken, Ownable, ERC20Burnable, ERC20Pausable {
IERC20 public stakingToken;
CCAToken public ccaToken;
event Stake(address indexed from, uint256 amount);
event Unstake(address indexed from, uint256 amount);
event YieldWithdraw(address indexed to, uint256 amount);
mapping(address => uint256) public stakingBalance;
mapping(address => bool) public isStaking;
mapping(address => uint256) public startTime;
mapping(address => uint256) public ccaBalance;
constructor(
IERC20 _stakingToken,
CCAToken _ccaToken
) {
stakingToken = _stakingToken;
ccaToken = _ccaToken;
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
_setupRole(MINTER_ROLE, _msgSender());
_setupRole(PAUSER_ROLE, _msgSender());
}
function decimals() public view virtual override returns (uint8) {
return 5;
}
function mint(address to, uint256 amount) public override virtual {
require(hasRole(MINTER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have minter role to mint");
_mint(to, amount);
}
/**
* @dev Pauses all token transfers.
*
* See {ERC20Pausable} and {Pausable-_pause}.
*
* Requirements:
*
* - the caller must have the `PAUSER_ROLE`.
*/
function pause() public virtual {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to pause");
_pause();
}
function unpause() public virtual {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to unpause");
_unpause();
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual override(ERC20, ERC20Pausable) {
super._beforeTokenTransfer(from, to, amount);
}
function stake(uint256 _amount) public {
address from = msg.sender;
address to = address(this);
uint256 amount = _amount;
if(isStaking[from] == true){
uint256 toTransfer = calculateYieldTotal(from);
ccaBalance[from] += toTransfer;
}
stakingToken.transferFrom(from, to, amount);
stakingBalance[from] += amount;
startTime[from] = block.timestamp;
isStaking[from] = true;
emit Stake(from, amount);
}
function unstake(uint256 amount) public {
require(isStaking[msg.sender] = true && stakingBalance[msg.sender] >= amount, "Nothing to unstake");
uint256 yieldTransfer = calculateYieldTotal(msg.sender);
startTime[msg.sender] = block.timestamp;
uint256 balTransfer = amount;
amount = 0;
stakingBalance[msg.sender] -= balTransfer;
stakingToken.transfer(msg.sender, balTransfer);
ccaBalance[msg.sender] += yieldTransfer;
if(stakingBalance[msg.sender] == 0){
isStaking[msg.sender] = false;
}
emit Unstake(msg.sender, balTransfer);
}
function calculateYieldTime(address user) public view returns(uint256){
uint256 end = block.timestamp;
uint256 totalTime = end - startTime[user];
return totalTime;
}
function calculateYieldTotal(address user) public view returns(uint256) {
uint256 time = calculateYieldTime(user) * 10**18;
uint256 rate = 86400;
uint256 timeRate = time / rate;
uint256 rawYield = (stakingBalance[user] * timeRate) / 10**18;
return rawYield;
}
function withdrawYield() public {
uint256 toTransfer = calculateYieldTotal(msg.sender);
require(toTransfer > 0 || ccaBalance[msg.sender] > 0, "Nothing to withdraw");
if(ccaBalance[msg.sender] != 0){
uint256 oldBalance = ccaBalance[msg.sender];
ccaBalance[msg.sender] = 0;
toTransfer += oldBalance;
}
startTime[msg.sender] = block.timestamp;
ccaToken.mint(msg.sender, toTransfer);
emit YieldWithdraw(msg.sender, toTransfer);
}
}
I have problem on this part of function,
function stake(uint256 _amount) public {
address from = msg.sender;
address to = address(this);
uint256 amount = _amount;
if(isStaking[from] == true){
uint256 toTransfer = calculateYieldTotal(from);
ccaBalance[from] += toTransfer;
}
stakingToken.transferFrom(from, to, amount);
stakingBalance[from] += amount;
startTime[from] = block.timestamp;
isStaking[from] = true;
emit Stake(from, amount);
}
Environment
I tried the both options but still the same problem:
- Remix version 0.8.4
- Hardhat version 0.8.4