Solidity 103

1. ERC20
2. Token Faucet
3. Token Faucet
4. ERC721
5. Dutch Auction
6. Merkle Tree
7. Digital Signature
8. NFT Exchange
9. Chainlink Randomness
10. ERC1155
11. WETH
12. Payment Splitting
13. Linear Release
14. Token Lock
15. Time Lock
16. Proxy Contract
17. Upgradeable Contract
18. Transparent Proxy
19. UUPS
20. Multisignature Wallet
21. ERC4626 Tokenization of Vault Standard
22. EIP712 Typed Data Signature
23. ERC-2612 ERC20Permit
24. 跨链桥
25. 多重调用
26. 去中心化交易所
27. 闪电贷
.
Token Lock

I have been relearning Solidity recently to solidify my understanding of the language and to create a "WTF Solidity Crash Course" for beginners (advanced programmers can find other tutorials). I will update it weekly with 1-3 lessons.

Feel free to follow me on Twitter: @0xAA_Science

You are also welcome to join the WTF Scientists community and find information on how to join the WeChat group: link

All of the code and tutorials are open source and can be found on GitHub (I will provide a course certification for 1024 stars and a community NFT for 2048 stars): github.com/AmazingAng/WTF-Solidity


Token Lock

A Token Lock is a simple time-based smart contract that allows one to lock a number of tokens for a certain period of time. After the lock-up period is over, the beneficiary can then withdraw the tokens. A Token Lock is commonly used to lock LP tokens.

What are LP Tokens?

In decentralized exchanges (DEX), users trade tokens, such as in the case of Uniswap. Unlike centralized exchanges (CEX), decentralized exchanges use Automated Market Maker (AMM) mechanisms. Users or projects provide a liquidity pool so that other users can buy and sell tokens instantly. To compensate the user or project for providing the liquidity pool, the DEX will mint corresponding LP tokens, which represent their contribution and entitle them to transaction fees.

Why Lock Liquidity?

If a project suddenly withdraws LP tokens from a liquidity pool without warning, the investors' tokens would become worthless. This act is commonly referred to as a "rug-pull." In 2021 alone, different "rug-pull" scams have defrauded investors of more than $2.8 billion in cryptocurrency.

However, by locking LP tokens into a Token Lock smart contract, the project cannot withdraw the tokens from the liquidity pool before the lock-up period expires, preventing them from committing a "rug-pull". A Token Lock can, therefore, prevent projects from running away with investors' tokens prematurely (though one should still be wary of projects "running away" once the lock-up period ends).

Token Lock Contract

Below is a contract TokenLocker for locking ERC20 tokens. Its logic is simple:

  • The developer specifies the locking time, beneficiary address, and token contract when deploying the contract.
  • The developer transfers the tokens to the TokenLocker contract.
  • After the lockup period expires, the beneficiary can withdraw the tokens from the contract.

Events

There are two events in the TokenLocker contract.

  • TokenLockStart: This event is triggered when the lockup starts, which occurs when the contract is deployed. It records the beneficiary address, token address, lockup start time, and end time.
  • Release: This event is triggered when the beneficiary withdraws the tokens. It records the beneficiary address, token address, release time, and token amount.
event TokenLockStart(
        address indexed beneficiary,
        address indexed token,
        uint256 startTime,
        uint256 lockTime
    );
    event Release(
        address indexed beneficiary,
        address indexed token,
        uint256 releaseTime,
        uint256 amount
    );

State Variables

There are a total of 4 state variables in the TokenLocker contract:

  • token: the address of the locked token.
  • beneficiary: the address of the beneficiary.
  • locktime: the lock-up period in seconds.
  • startTime: the timestamp when the lock-up period starts (in seconds).
// Locked ERC20 token contracts
    IERC20 public immutable token;
    // Beneficiary address
    address public immutable beneficiary;
    // Lockup time (seconds)
    uint256 public immutable lockTime;
    // Lockup start timestamp (seconds)
    uint256 public immutable startTime;

Functions

There are 2 functions in the TokenLocker contract.

  • Constructor: Initializes the contract with the token contract, beneficiary address, and lock-up period.
  • release(): Releases the tokens to the beneficiary after the lock-up period. The beneficiary needs to call the release() function to extract the tokens.
/**
     * @dev Deploy the time lock contract, initialize the token contract address, beneficiary address and lock time.
     * @param token_: Locked ERC20 token contract
     * @param beneficiary_: Beneficiary address
     * @param lockTime_: Lockup time (seconds)
     */
    constructor(IERC20 token_, address beneficiary_, uint256 lockTime_) {
        require(lockTime_ > 0, "TokenLock: lock time should greater than 0");
        token = token_;
        beneficiary = beneficiary_;
        lockTime = lockTime_;
        startTime = block.timestamp;

        emit TokenLockStart(
            beneficiary_,
            address(token_),
            block.timestamp,
            lockTime_
        );
    }

    /**
     * @dev After the lockup time, the tokens are released to the beneficiaries.
     */
    function release() public {
        require(
            block.timestamp >= startTime + lockTime,
            "TokenLock: current time is before release time"
        );

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

        token.transfer(beneficiary, amount);

        emit Release(msg.sender, address(token), block.timestamp, amount);
    }

Remix Demonstration

1. Deploy the ERC20 contract in Lesson 31, and mint 10000 tokens for yourself

Remix Demonstration

2. Deploy the TokenLocker contract with the ERC20 contract address, set yourself as the beneficiary, and set the lock-up period to 180 seconds

Remix Demonstration

3. Transfer 10000 tokens to the contract

Remix Demonstration

4. Within the lock-up period of 180 seconds, call the release() function, but you won't be able to withdraw the tokens

Remix Demonstration

5. After the lock-up period, call the release() function again, and successfully withdraw the tokens

Remix Demo

Summary

In this lesson, we introduced the token lock contract. Project parties generally provide liquidity on DEX for investors to trade. If the project suddenly withdraws the LP, it will cause a rug-pull. However, locking the LP in the token lock contract can avoid this situation.

PreviousNext