ERC20锁仓解锁代码详解

发布时间:2018年10月02日 价值:20000.00 / 共识:25

1、简单示意图

2、ERC20代码详解
1)、 基本合约提供总发行量和余额的查询,交易转账函数以及转账事件。view是只读标识, returns是返回(后面可以是返回值的类型或者返回值的字段以及类型)
ERC20接口

2)、SafeMath加减乘除library 库。SafeMath库能够实现四则运算的安全操作,像之前BEC被攻击就是因为没有使用SafeMath库导致批量转账函数存在漏洞。因此四则运算涉及金钱的尽量采用该库,虽然Gas可能耗费多一些,但是还是值得的。



3)、ERC20合约提供允许转账金额查询,从A账户到B账户的交易,授权A-》B的转账以及授权事件。
ERC20标准接口

4)、实现ERC20Basic合约的function。主要包括了总发行量的查询,转账函数,余额查询功能。转账函数要检查转入的地址是否是无效地址,以及转账金额是否足够。另外说明,原先对于EVM有些漏洞,导致短地址攻击,但是目前该漏洞EVM已经修复,本人已经亲自测试过。对于地址最后一位或者两位有0的不会造成对方接受的币比实际多。前段时间看到不少人写的合约里面有避免短地址攻击。本人认为完全没有必要,浪费一些Gas呗吧,下图有这个代码。

ERC20函数实现

5)、实现ERC20, BasicToken合约


3、锁仓解锁代码:

1)、创建创世块,使用构造函数初始化参数。

可以看到创建Token的名称,单位,符号,总的供应量等。
2)、定义管理员,为了对代币进行管理,首先需要给合约添加一个管理者。也可以为该合约指定一个新的管理者。

3)、锁仓解锁合约核心代码,由于注释完备,所以就不叙述。主要思路:将要锁定的币打到锁仓合约中,合约中将币预分配到对应的地址,然后执行锁定函数,等待锁定时间解除后,将币打到对应预分配的地址。相当于一个中转合约。

/**

  • @dev 锁仓解锁合约

    */

    contract LibraTokenVault is Ownable {

    using SafeMath for uint256;

    /**

    • @dev 创建三个账户地址,将解锁后的余额预分配到三个地址

    • 每个地址根据不同的解锁时间,在调用合约后将对应的余额按照一定规则转移到相应的地址

    */

    address public teamReserveWallet = 0x373c69fDedE072A3F5ab1843a0e5fE0102Cc6793;

    address public firstReserveWallet = 0x99C83f62DBE1a488f9C9d370DA8e86EC55224eB4;

    address public secondReserveWallet = 0x90DfF11810dA6227d348C86C59257C1C0033D307;

    /* 三个账户地址对应的锁仓金额 /

    uint256 public teamReserveAllocation = 2 (10 ** 8) (10 ** 18);

    uint256 public firstReserveAllocation = 15 (10 ** 7) (10 ** 18);

    uint256 public secondReserveAllocation = 15 (10 ** 7) (10 ** 18);

    // 总锁仓的金额

    uint256 public totalAllocation = 5 (10 ** 8) (10 ** 18);

    /* 三个账户地址对应的锁仓时间 /

    uint256 public teamTimeLock = 2 * 365 days;

    /* 分多少次解锁到对应的地址 /

    uint256 public teamVestingStages = 8;

    uint256 public firstReserveTimeLock = 2 * 365 days;

    uint256 public secondReserveTimeLock = 3 * 365 days;

    /* Reserve allocations /

    mapping(address => uint256) public allocations; // 每个地址对应锁仓金额的映射表

    /* When timeLocks are over (UNIX Timestamp) /

    mapping(address => uint256) public timeLocks; // 每个地址对应锁仓时间的映射表

    /* How many tokens each reserve wallet has claimed /

    mapping(address => uint256) public claimed; // 每个地址对应锁仓后已经解锁的金额的映射表

    /* When this vault was locked (UNIX Timestamp)/

    uint256 public lockedAt = 0;

    LibraToken public token;

    /* Allocated reserve tokens /

    event Allocated(address wallet, uint256 value);

    /* Distributed reserved tokens /

    event Distributed(address wallet, uint256 value);

    /* Tokens have been locked /

    event Locked(uint256 lockTime);

    //Any of the three reserve wallets

    modifier onlyReserveWallets { // 合约调用者的锁仓余额大于0才能查询锁仓余额

    1. require(allocations[msg.sender] > 0);
    2. _;

    }

    //Only Libra team reserve wallet

    modifier onlyTeamReserve { // 合约调用者的地址为teamReserveWallet

    1. require(msg.sender == teamReserveWallet);
    2. require(allocations[msg.sender] > 0);
    3. _;

    }

    //Only first and second token reserve wallets

    modifier onlyTokenReserve { // 合约调用者的地址为firstReserveWallet或者secondReserveWallet

    1. require(msg.sender == firstReserveWallet || msg.sender == secondReserveWallet);
    2. require(allocations[msg.sender] > 0);
    3. _;

    }

    //Has not been locked yet

    modifier notLocked { // 未锁定

    1. require(lockedAt == 0);
    2. _;

    }

    modifier locked { // 锁定

    1. require(lockedAt > 0);
    2. _;

    }

    //Token allocations have not been set

    modifier notAllocated { // 没有为每个地址分配对应的锁仓金额时

    1. require(allocations[teamReserveWallet] == 0);
    2. require(allocations[firstReserveWallet] == 0);
    3. require(allocations[secondReserveWallet] == 0);
    4. _;

    }

    function LibraTokenVault(ERC20 _token) public { // 构造LibraToken模式的合约

    1. owner = msg.sender; // msg.sender 是指直接调用当前合约的调用方地址
    2. token = LibraToken(_token);

    }

    /* 当合约调用者是ower时才可执行锁仓功能,锁仓为解锁对应的地址分配对应金额

    • 调用分配事件

    • 分配成功后,执行锁操作
      打到该合约的金额必须要与总共要锁的金额相等,该函数才会执行成功

    */

    function allocate() public notLocked notAllocated onlyOwner {

    1. //Makes sure Token Contract has the exact number of tokens
    2. require(token.balanceOf(address(this)) == totalAllocation); // 合约调用方要求锁的金额与预定义分配的金额是否相等
    3. allocations[teamReserveWallet] = teamReserveAllocation;
    4. allocations[firstReserveWallet] = firstReserveAllocation;
    5. allocations[secondReserveWallet] = secondReserveAllocation;
    6. Allocated(teamReserveWallet, teamReserveAllocation);
    7. Allocated(firstReserveWallet, firstReserveAllocation);
    8. Allocated(secondReserveWallet, secondReserveAllocation);
    9. lock();

    }

    /* internal:内部函数,并且只有owner才拥有才权限

    • 从调用该合约的lock方法起,算出每一个地址对应的解锁时间

    • 执行锁事件

    */

    function lock() internal notLocked onlyOwner {

    1. lockedAt = block.timestamp; // 区块当前时间
    2. timeLocks[teamReserveWallet] = lockedAt.add(teamTimeLock);
    3. timeLocks[firstReserveWallet] = lockedAt.add(firstReserveTimeLock);
    4. timeLocks[secondReserveWallet] = lockedAt.add(secondReserveTimeLock);
    5. Locked(lockedAt);

    }

    //In the case locking failed, then allow the owner to reclaim the tokens on the contract.

    //Recover Tokens in case incorrect amount was sent to contract.

    // 失败回滚

    function recoverFailedLock() external notLocked notAllocated onlyOwner {

    1. // Transfer all tokens on this contract back to the owner
    2. require(token.transfer(owner, token.balanceOf(address(this))));

    }

    // Total number of tokens currently in the vault

    // 查询当前合约所持有的金额

    function getTotalBalance() public view returns (uint256 tokensCurrentlyInVault) {

    1. return token.balanceOf(address(this));

    }

    // Number of tokens that are still locked

    // 根据锁住的地址查询对应锁住的金额

    function getLockedBalance() public view onlyReserveWallets returns (uint256 tokensLocked) {

    1. return allocations[msg.sender].sub(claimed[msg.sender]); // 某一个地址对应的分配金额-该地址已经解锁的金额

    }

    //Claim tokens for first/second reserve wallets

    /* 解锁函数,拥有firstReserveWallet或者secondReserveWallet地址的用户才具有此权限,并且此地址已经被锁住,当前时间大于该地址的解锁时间

    • 从调用该合约的lock方法起,算出每一个地址对应的解锁时间

    • 执行锁事件

    */

    function claimTokenReserve() onlyTokenReserve locked public {

    1. address reserveWallet = msg.sender;
    2. // Can't claim before Lock ends
    3. require(block.timestamp > timeLocks[reserveWallet]); // 当前时间大于第一个或者第二个解锁时间
    4. // Must Only claim once
    5. require(claimed[reserveWallet] == 0); // 已解锁发放出额度为0
    6. uint256 amount = allocations[reserveWallet]; // 当前账号分配量
    7. claimed[reserveWallet] = amount; // 一次性解锁发放
    8. require(token.transfer(reserveWallet, amount)); // 解锁到对应的地址
    9. Distributed(reserveWallet, amount);

    }

    //Claim tokens for Libra team reserve wallet

    /* 解锁函数,拥有teamReserveWallet地址的用户才具有此权限,并且此地址已经被锁住,当前时间大于该地址的解锁时间

    • 从调用该合约的lock方法起,算出每一个地址对应的解锁时间,每三个月发放一次

    • 执行锁事件

    */

    function claimTeamReserve() onlyTeamReserve locked public {

    1. uint256 vestingStage = teamVestingStage();
    2. //Amount of tokens the team should have at this vesting stage
    3. uint256 totalUnlocked = vestingStage.mul(allocations[teamReserveWallet]).div(teamVestingStages); // 总的解锁量
    4. require(totalUnlocked <= allocations[teamReserveWallet]);
    5. //Previously claimed tokens must be less than what is unlocked
    6. require(claimed[teamReserveWallet] < totalUnlocked); // 解锁已经发放量<总的解锁量
    7. uint256 payment = totalUnlocked.sub(claimed[teamReserveWallet]); // 本次解锁发放量 = 总的解锁量 - 解锁已经发放量
    8. claimed[teamReserveWallet] = totalUnlocked; // 解锁已经发放量 = 总的解锁量
    9. require(token.transfer(teamReserveWallet, payment)); // 发放
    10. Distributed(teamReserveWallet, payment);

    }

    //Current Vesting stage for Libra team

    function teamVestingStage() public view onlyTeamReserve returns(uint256){

    1. // Every 3 months
    2. uint256 vestingMonths = teamTimeLock.div(teamVestingStages); // 解锁每个的时间=锁定时间/解锁次数
    3. uint256 stage = (block.timestamp.sub(lockedAt)).div(vestingMonths); // 已经解锁的次数 =(当前时间-锁定时间)/每个解锁时间
    4. //Ensures team vesting stage doesn't go past teamVestingStages
    5. if(stage > teamVestingStages){ // 已经解锁的次数大于解锁次数
    6. stage = teamVestingStages;
    7. }
    8. return stage;

    }

}

  • 分享 收藏
0 条评论
  • 这篇文章暂无评论,赶紧评论一下吧~