> BLACK FRIDAY 70% OFF! Limited Time Offer

May 14, 2022

Timelock in Solidity

Timelock in Solidity image

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;
  }
}
Share this article
Author
Rahul Ravindran's photo
Rahul Ravindran
0 Comments
Leave a reply