[Ethereum] How to impose a timelock || Vesting for ERC20 tokens during ICO(Crowdsale)


Hello I am writing a crowdsale using Zeppelin-Solidity where I need to integrate the token lock function so the ERC20 tokens can be locked for a specific period of time.

The zeppelin-solidity seems to provide Tokenvesting.sol for this purpose.

pragma solidity ^0.4.11;

import './ERC20Basic.sol';
import './SafeERC20.sol';
import '../ownership/Ownable.sol';
import '../math/Math.sol';
import '../math/SafeMath.sol';

 * @title TokenVesting
 * @dev A token holder contract that can release its token balance gradually like a
 * typical vesting scheme, with a cliff and vesting period. Optionally revocable by the
 * owner.
contract TokenVesting is Ownable {
  using SafeMath for uint256;
  using SafeERC20 for ERC20Basic;

  event Released(uint256 amount);
  event Revoked();

  // beneficiary of tokens after they are released
  address public beneficiary;

  uint256 public cliff;
  uint256 public start;
  uint256 public duration;

  bool public revocable;

  mapping (address => uint256) public released;
  mapping (address => bool) public revoked;

   * @dev Creates a vesting contract that vests its balance of any ERC20 token to the
   * _beneficiary, gradually in a linear fashion until _start + _duration. By then all
   * of the balance will have vested.
   * @param _beneficiary address of the beneficiary to whom vested tokens are transferred
   * @param _cliff duration in seconds of the cliff in which tokens will begin to vest
   * @param _duration duration in seconds of the period in which the tokens will vest
   * @param _revocable whether the vesting is revocable or not
  function TokenVesting(address _beneficiary, uint256 _start, uint256 _cliff, uint256 _duration, bool _revocable) {
    require(_beneficiary != address(0));
    require(_cliff <= _duration);

    beneficiary = _beneficiary;
    revocable = _revocable;
    duration = _duration;
    cliff = _start.add(_cliff);
    start = _start;

   * @notice Transfers vested tokens to beneficiary.
   * @param token ERC20 token which is being vested
  function release(ERC20Basic token) public {
    uint256 unreleased = releasableAmount(token);

    require(unreleased > 0);

    released[token] = released[token].add(unreleased);

    token.safeTransfer(beneficiary, unreleased);


   * @notice Allows the owner to revoke the vesting. Tokens already vested
   * remain in the contract, the rest are returned to the owner.
   * @param token ERC20 token which is being vested
  function revoke(ERC20Basic token) public onlyOwner {

    uint256 balance = token.balanceOf(this);

    uint256 unreleased = releasableAmount(token);
    uint256 refund = balance.sub(unreleased);

    revoked[token] = true;

    token.safeTransfer(owner, refund);


   * @dev Calculates the amount that has already vested but hasn't been released yet.
   * @param token ERC20 token which is being vested
  function releasableAmount(ERC20Basic token) public constant returns (uint256) {
    return vestedAmount(token).sub(released[token]);

   * @dev Calculates the amount that has already vested.
   * @param token ERC20 token which is being vested
  function vestedAmount(ERC20Basic token) public constant returns (uint256) {
    uint256 currentBalance = token.balanceOf(this);
    uint256 totalBalance = currentBalance.add(released[token]);

    if (now < cliff) {
      return 0;
    } else if (now >= start.add(duration) || revoked[token]) {
      return totalBalance;
    } else {
      return totalBalance.mul(now.sub(start)).div(duration);
© 2017 GitHub, Inc.

But there are different paramters in it (start , vesting period and cliff). I am not sure how this will work

-Whether tokens are transferred to the beneficiary first and then gets lock
or tokens are stored in locked contract and released later.
And how vesting and cliff works.
I have researched vesting and cliff on Investopedia but doesn't clarify the concept on how this will be described with respect to crowdsale(cliff, Vesting And Revoked)

Best Answer

Vesting with a cliff is a typical requirement for founders holding shares of a company so they don't just leave the company when they are most needed with the shares they have. The same concept has been translated to ICOs so the founders (and key team members, advisors, etc) don't just dump their tokens as soon as they are listed on exchanges.

Vesting period refers to the duration of the vesting. For example, if the vesting period is 48 months (4 years would be a typical vesting period for founders) this means that every month I'm still at the company 1/48th of the shares I'm entitled to will be released for me. So, if for some reason, I leave the company only after 24 months, I'll only get half of the shares I "owned".

Sometimes a cliff is also added to the equation. A cliff will determine when all these shares I accumulated will be released to me. For example, if there's a cliff of 1 year and a vesting period of 4 years, if I leave the company anytime before the cliff period has passed (from month 1 to 12) I won't get anything. If I leave on month 13 then I get 13/48th of my shares.

In the case the vesting period hasn't been completed for someone and they leave with less shares they were entitled to, the rest of the shares are returned to the company for them to use as they want. In the case of the token sale, the tokens will be returned to the owner of the contract.

So, in this particular contract, when the crowdsale is successfully finished, instead of transferring the tokens to the founders or advisors or team members directly you could use this contract to establish the vesting. Say I'm entitled to 1200 tokens which should be vested in 12 months with a 6 months cliff.

  • Month 1: I get 0 tokens
  • Month 2: I get 0 tokens
  • Month 3: I get 0 tokens
  • Month 4: I get 0 tokens
  • Month 5: I get 0 tokens
  • Month 6: I get 0 tokens --------- End of cliff
  • Month 7: I get 700 tokens (7/12th)
  • Month 8: I get 100 tokens (8/12th)
  • Month 9: I get 100 tokens (9/12th)
  • Month 10: I get 100 tokens (10/12th)
  • Month 11: I get 100 tokens (11/12th)
  • Month 12: I get 100 tokens (12/12th)

First, you would deploy the contract and call tokenVesting() passing my address, when this starts (now), cliff will be 6 months (in seconds), duration would be 12 months (in seconds) and revocable boolean. Revocable flag allows the owner to revoke pending token vesting for the beneficiary, so, if that person leaves the company, they will not get vested anymore.

Then, at any moment, the beneficiary can call release() to calculate how many tokens have already vested for them and have them transferred.

Notice that, as opposed to my explanation above (which comes from having worked at a VC firm with more traditional vesting schemes), the vesting is not broken into months. The vesting is calculated in seconds, so you can get a more granular vesting done. (if the duration is 100.000 seconds I could call this function every second to get my corresponding 1/100.000th of tokens).

Related Topic