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

Updates added to “Learn Ethereum Dapps” ebook – v1.1.0

Last week I released my ebook Learn Ethereum Dapps, where I teach how to build a ToDo list Dapp on…

Read Story

Genesis Post | Episode 0

https://youtu.be/S4Q9T4EZjSs Hi and welcome to Eat The Blocks! My name is Julien Klepatch. I am a blockchain developer, and I…

Read Story

How I Got 2 jobs As A Blockchain Developer | Real story

There are a few other articles /videos that claim to explain how to get a job as a blockchain developer.…

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