0

I am writing the below code for a staking smart contract.

pragma solidity ^0.8.9;

import "@openzeppelin/contracts/access/Ownable.sol";

interface Token
{
    function transfer(address _To, uint256 _Amount) external returns (bool);
    function CheckBalance(address account) external view returns(uint);
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
    function mint(address account, uint256 amount) external returns(bool);
}

contract Staking is Ownable
{
    Token ELONToken;

    // 2 months = (60*24*60*60)
    uint256 public StakeDuration = 1;

    // 10% intreset foer the Stakers.
    uint8 IntrestRate = 10;

    uint256 TotalStakers;
    bool public _pause = false;
    bool lock;

    // Structure to hold details regarding the stakers.
    struct StakerInfo
    {
        uint256 startTS;
        uint256 endTS;
        uint256 amount;
        uint256 claimed;
    }

    //mapping which maps to the structure inorder to have the details of each staker.
    mapping(address => StakerInfo) public StakerInfos;

    //mapping to hold addresses of stakers.
    mapping(address => bool) public StakedAddress;

    constructor(Token ERC20_add)
    {
        require(address(ERC20_add)!= address(0),"Enter Valid Contract address");
        ELONToken = ERC20_add;
        TotalStakers = 0;
    }

    modifier whenNotPaused
    {
        require(_pause == false, "Contract has been paused by the owner");
        _;
    }

    //Function to check when the Stake period will end.
    function CheckExpieryDate() external view returns(uint256)
    {
        require(StakedAddress[msg.sender]==true,"You have not staked any tokens");
        return(StakerInfos[msg.sender].endTS);
    }

    // Function to pause and Unpause the contract.
    function Pause() external onlyOwner returns(bool) 
    {
        _pause = true;
        return(_pause);
    }

    // Function to check balance
    function CheckBalance(address account) external view returns(uint)
    {
        return(ELONToken.CheckBalance(account));
    }
    // Function to call the Mint from ERC20
    function MintTokens(uint256 Mintamount) internal
    {
        ELONToken.mint(address(this),Mintamount);
    }
    
    //Function to Stake Tokens in the smart Contract.
    function StakeTokens(uint256 _Stakeamount) external payable whenNotPaused
    {
        require(_Stakeamount > 0, "Stake amount cannot be Zero");
        require(StakedAddress[msg.sender] == false,"You have already Staked");
        require(ELONToken.CheckBalance(msg.sender) >= _Stakeamount, "Insufficient Tokens");
        require(lock == false,"Aborting Transfer is locked");
        lock = true;
        ELONToken.transferFrom(msg.sender, address(this), _Stakeamount);
        lock = false;
        unchecked
        {
            ++TotalStakers;
        }
        StakedAddress[msg.sender] = true;
        StakerInfos[msg.sender] = StakerInfo({
            startTS: block.timestamp,
            endTS: block.timestamp + StakeDuration,
            amount: _Stakeamount,
            claimed: 0
        });
    }

    function ClaimRewards(uint256 ClaimAmount) external returns (bool)
    {
        require(StakedAddress[msg.sender] == true,"You have not Staked any Tokens");
        require(StakerInfos[msg.sender].endTS < block.timestamp, "Stake Time is not over yet");
        require(ClaimAmount <= StakerInfos[msg.sender].amount,"Not enough Tokens to Claim");
        require(lock == false,"Aborting!!! Transfer is locked");
        uint256 Mintamount = ClaimAmount*IntrestRate/100;
        uint256 totalReward = ClaimAmount + Mintamount; 
        MintTokens(Mintamount);
        StakerInfos[msg.sender].claimed += totalReward;
        lock = true;
        ELONToken.transfer(msg.sender, totalReward);
        lock = false;
        return true;
    }
}

If you notice the Claim Reward function, it will call the mine function from ERC20.sol so the rewards for the Stakers can be minted.

But as soon the program goes into the mine function the transaction reverts. Giving the following error:

[call]from: 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4to: Staking.StakeDuration()data: 0x491...05fd4 transact to Staking.ClaimRewards pending ... transact to Staking.ClaimRewards errored: VM error: revert. revert The transaction has been reverted to the initial state. Note: The called function should be payable if you send value and the value you send should be less than your current balance. Debug the transaction to get more information.

Is it because the gas is too low? and the function is exceeding the gas limit? Or is there some other reason behind this?

2
  • If you are interacting with it via remix, then can you click the debug button once? Clicking it will give the exact line where the code is failing. May 11, 2023 at 5:38
  • Hi Afser I did try that as well, it fails when I try to call the mint function from the ERC20 contract. But I am not sure why it fails. May 11, 2023 at 6:28

1 Answer 1

1

Your constructor will receive an address to the Token contract. Is the Token contract deployed? It does not look like it hence the revert.

1
  • This might be the case. May 12, 2023 at 13:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.