Trying to Add Timelock to token contract

Hey everyone. I'm a total newbie to coding smart contracts. I must say i'm facisnated and can't stop.

I am currently stuck on trying to add a time lock to y current contract. I keep getting errors on new pragma solidity versions - even though Im running the same versions.

Also, can I deploy a simple smart contract and deploy separate Timelock contracts with wallet address that will automatically lock up the tokens for the allocated time frame. For example. I would send 1 million tokens to an address and that specific address already has a lock on it which would only release tokens after the 12 months is up.

I'm trying to avoid adding too many functions to my smart contract.

Thank You

2 Likes

Are you talking about our TimelockController or TokenTimelock contract?

Can you show us the version errors you see?

You can deploy separate TokenTimelock instances. Although I’m not sure what you mean by “that address already has a lock on it”.

1 Like

I’m not sure if I understand your issue… You can deploy a TokenTimelock to act as a timelocked wallet.

1 Like

I am not familiar with BEP20, as far as I know it’s the same as ERC20 so it should be compatible. Run tests to make sure.

2 Likes

When you deploy the contract SimpleTimelock, it will ask you to pass two parameters:

_beneficiary,
_releaseTime

So I think at the constructor , you can pass the release time.
And as for January 1st 2023, you should change it to the timestamp, but it should be counted in seconds.

No, absolutely not. You are not supposed to change the code! You have to deploy the code as-is and use the constructor parameters.

I’m sorry, but you need to do some serious learning before deploying a contract that will deal with real money. You will be putting your or other people’s funds at risk.

We can’t help any further.

2 Likes

Sorry if I was mean before. I would just suggest you go through more basic Solidity exercises before jumping onto this timelock project.

Take a look at the Solidity docs for Creating contracts to learn about constructor arguments.

Take a look at Solidity by Example for more basic Solidity material to play with.


As a general guideline, never modify the code you take from OpenZeppelin.

2 Likes

Thank you. I appreciate it

1 Like

Hello :slight_smile: So, I keep getting this error message when i try to deploy to JSVM in remix.

creation of TokenTimelock errored: Error encoding arguments: Error: invalid address (argument=“address”, value="", code=INVALID_ARGUMENT, version=address/5.1.0) (argument=null, value="", code=INVALID_ARGUMENT, version=abi/5.1.2)

I’m trying to add beneficiary as msg.sender (me) is that ok ?

pragma solidity ^0.8.1;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol";

// SPDX-License-Identifier: MIT


/**
 * @dev A token holder contract that will allow a beneficiary to extract the
 * tokens after a given release time.
 *
 * Useful for simple vesting schedules like "advisors get all of their tokens
 * after 1 year".
 */
contract TokenTimelock {
    using SafeERC20 for IERC20;

    // ERC20 basic token contract being held
    IERC20 immutable private _token;

    // beneficiary of tokens after they are released
    address immutable private _beneficiary;

    // timestamp when token release is enabled
    uint256 immutable private _releaseTime;

    constructor (IERC20 token_, address beneficiary_, uint256 releaseTime_) {
        // solhint-disable-next-line not-rely-on-time
        require(releaseTime_ > block.timestamp, "TokenTimelock: release time is before current time");
        _token = token_;
        _beneficiary = msg.sender;
        _releaseTime = 86400;
    }

    /**
     * @return the token being held.
     */
    function token() public view virtual returns (IERC20) {
        return _token;
    }

    /**
     * @return the beneficiary of the tokens.
     */
    function beneficiary() public view virtual returns (address) {
        return _beneficiary;
    }

    /**
     * @return the time when the tokens are released.
     */
    function releaseTime() public view virtual returns (uint256) {
        return _releaseTime;
    }

    /**
     * @notice Transfers tokens held by timelock to beneficiary.
     */
    function release() public virtual {
        // solhint-disable-next-line not-rely-on-time
        require(block.timestamp >= releaseTime(), "TokenTimelock: current time is before release time");

        uint256 amount = token().balanceOf(address(this));
        require(amount > 0, "TokenTimelock: no tokens to release");

        token().safeTransfer(beneficiary(), amount);
    }
}

When you write constructor arguments you need to give it actual values. msg.sender is like a variable in the Solidity context, it’s not a value itself. So you need to pass in the actual address. In Remix you can copy the address of the current account using the copy icon next to the Account dropdown.

image

Thanks Frangio - I did initially try that wallet address and kept getting the same error.

The contract compiles fine - It’s just on deployment I get this error

creation of TokenTimelock errored: Error encoding arguments: Error: invalid address (argument=“address”, value="", code=INVALID_ARGUMENT, version=address/5.1.0) (argument=null, value="", code=INVALID_ARGUMENT, version=abi/5.1.2)

Here is an example of deployment that works correctly for me:

The parameters are:

0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 1654368599

I’m using the code

pragma solidity 0.8.0;

import "@openzeppelin/contracts@4.1.0/token/ERC20/utils/TokenTimelock.sol";

I notice that you are using the same address. Is that your wallet address or your token/smart contract address ?

I’m still getting this error… Don’t hate me :-/


Like I said before, you shouldn’t modify the source code like you’re doing in this screenshot. This is a matter of security. The code that we provide should not be modified.

Paste this in Remix and set the parameters in the Deploy text input field like I showed in my screenshot. Use whatever addresses you want. I just used the same address because I was in a hurry.

pragma solidity 0.8.4;

import "@openzeppelin/contracts@4.1.0/token/ERC20/utils/TokenTimelock.sol";

Amazing - It worked - Thanks so much. Appreciate it.
I was trying to deploy the wrong contract. Remix doesn’t automatically default to the contract you’re working on, so I had to select from the drop down menu Timelock.sol then the contstructor options appeared prior to deployment.

One more Question though… It’s not allowing me to set release time for anything under 100000000000 - it just says error gas fee. I’ve tried on regular blockchain as I thought it might be to do with the block.timestamp. I get this error.

that’s with a release time set at 1000000

Yeah, I've reported it to them before, hope they'll fix it soon.

That's odd. What value are you trying to put in? It needs to be a timestamp in the future.

I’ve tried 86400 (seconds) I just wanted to run a 24 hour test.

I ran a debug and it stops at the block.timestamp line in the constructor.

Problem fixed - I have to set time to epoch :slight_smile:

Thanks a bunch I really appreciate your help on this!!

1 Like

The contract in the side of wallet address have to appear?

Sorry i’m not sure what you mean.