Timelock in Solidity

Rahul Ravindran

A timelock is a piece of code that locks functionality on an application until a certain amount of time has passed. It was widely used as a type of smart contract primitive in many Bitcoin scripts in order to lock-up bitcoins usually for periods of months or years.

Later, the ICO craze brought many scam projects where the founders dumped their tokens as soon as they could get some profit. Legit projects started implementing timelocks to signal commitment from the founders, as the timelock worked as a vesting mechanism widely used in the startup world.

Yield farming and DeFi have brought a new series of ponzinomics, dump and run schemes, and governance issues. Sushiswap had a recent episode where the founder dumped millions of dollars on Sushi Tokens from the dev pool and affected Sushi holders, wrong or not a timelock could have prevented this behavior.

pragma solidity ^0.7.0;
contract DeFiProtocol {
    address public ERC20Token;
    address public uniswapPool;
    uint256 public burnFee;
    function setERC20(address _erc) public {
        ERC20Token = _erc;
    }

    function setUniswapPool(address _pool) public {
        uniswapPool = _pool;
    }

    function setFee(uint256 _fee) public {
        burnFee = _fee;
    }
}

Features of a timelock:
– Extending from Ownable, allow us to add the onlyOwner modifier to our functions which allow only the owner of the contract to execute it.
– The enum allows us to access the time-locked function in a more readable way.
– The _TIMELOCK constant defines how much we want our functions to wait until they can be executed.
– We also create a timelock mapping which helps us to see which function is currently unlocked and create our own modifiers accordingly

Timelock function in solidity

pragma solidity ^0.7.0;

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

contract DeFiProtocol is Ownable {

   address public ERC20Token;
   address public uniswapPool;
   uint256 public burnFee;

   enum Functions { ERC, POOL, FEE }    
   uint256 private constant _TIMELOCK = 1 days;
   mapping(Functions => uint256) public timelock;

   modifier notLocked(Functions _fn) {
     require(timelock[_fn] != 0 && timelock[_fn] <= block.timestamp, "Function is timelocked");
     _;
   }

  //unlock timelock
  function unlockFunction(Functions _fn) public onlyOwner {
    timelock[_fn] = block.timestamp + _TIMELOCK;
  }

  //lock timelock
  function lockFunction(Functions _fn) public onlyOwner {
    timelock[_fn] = 0;
  }

  function setERC20(address _erc) public onlyOwner notLocked(Functions.ERC) {
      ERC20Token = _erc;
      timelock[ERC] = 0;
  }

  function setUniswapPool(address _pool) public onlyOwner notLocked(Functions.POOL) {
      uniswapPool = _pool;
      timelock[POOL] = 0;
  }

  function setFee(uint256 _fee) public onlyOwner notLocked(Functions.FEE) {
      burnFee = _fee;
      timelock[FEE] = 0;
  }
}

0 Comments

Leave a Reply

More great articles

New Ebook To Learn How to Build Ethereum Dapps

I have just turned the tutorial series on how to build a todo list Dapp into an 62 pages ebook.…

Read Story

The 3 most important smart contracts in DeFi

It’s so exhausting to keep up with all these new DeFi projects. 

But very few DeFi projects are really original.…

Read Story

Solidity explained in 2 mins

Solidity is a language for creating Blockchain smart contracts.

You can use it to create smart contracts, on more than 200…

Read Story

Never miss a minute

Get great content to your inbox every week. No spam.
[contact-form-7 id="6" title="Footer CTA Subscribe Form"]
Arrow-up