右侧或者下方下载ERC20 wrapper over the Dai Savings Rate

1 Chai = 1 Dai * Pot.chi

chai是一个 ERC20 代币,代表对 DSR 中存款的索赔。它可以自由转换为dai:以 Dai 储蓄利率,dai一个人的申领金额chai总是在增加。像任何乖巧的令牌,用户的chai 余额不会意外更改,而chai价值与日俱增。

chai是一个非常简单的合同。除了标准的 ERC20 功能外,它还实现了与自身相同permit的链下批准dai。您还可以致电dai(address usr)检查dai给定用户的chai余额索赔数量。令牌没有所有者或权限。这里的所有都是它的。

building and testing

This contract is built using dapptools, and follows the standard dapptools procedure for building and testing.

To compile:

$ make all

To run the tests:

$ make test

documentation

ERC20 functions

Chai.sol implements the standard ERC20 functions (balanceOf, allowance, approve, transfer, transferFrom).

Similar to tokens like WETHMKR and DAI, an allowance of uint(-1) is treated as “infinity”, so transferFrom calls from an address that has been given an allowance of uint(-1) will not cause the allowance to decrease.

Join

The chai contract is an ERC20 token where minting happens in a function called join, which converts a users Dai balance into Chai:

    function join(address dst, uint wad) external {
        uint chi = (now > pot.rho()) ? pot.drip() : pot.chi();
        uint pie = rdiv(wad, chi);
        balanceOf[dst] = add(balanceOf[dst], pie);
        totalSupply    = add(totalSupply, pie);

        daiToken.transferFrom(msg.sender, address(this), wad);
        daiJoin.join(address(this), wad);
        pot.join(pie);
        emit Transfer(address(0), dst, pie);
    }

Calling this function transfers wad Dai into the pot contract from msg.sender, granting the dst address a Chai balance representing their claim of Dai in the pot contract.

Exit

Chai is burned (converted into Dai) through a function called exit:

    function exit(address src, uint wad) public {
        require(balanceOf[src] >= wad, "chai/insufficient-balance");
        if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) {
            require(allowance[src][msg.sender] >= wad, "chai/insufficient-allowance");
            allowance[src][msg.sender] = sub(allowance[src][msg.sender], wad);
        }
        balanceOf[src] = sub(balanceOf[src], wad);
        totalSupply    = sub(totalSupply, wad);

        uint chi = (now > pot.rho()) ? pot.drip() : pot.chi();
        pot.exit(wad);
        daiJoin.exit(msg.sender, rmul(chi, wad));
        emit Transfer(src, address(0), wad);
    }

msg.sender with sufficient approval from the address src can call this function to decrease their Chai balance by wad and transfer its underlying Dai value to the msg.sender.

Draw

Since the wad argument to the exit function above is denominated in chai, the exact Dai transferred will be determined at the time the transaction is included in a block. If you want to ensure that a specific Dai amount must be transfered, you can use the draw function instead, which takes a dai denominated argument:

    // wad is denominated in dai
    function draw(address src, uint wad) external {
        uint chi = (now > pot.rho()) ? pot.drip() : pot.chi();
        // rounding up ensures usr gets at least wad dai
        exit(src, rdivup(wad, chi));
    }

Move

Similarly to draw, there is a transferFrom function with a dai denominated argument, ensuring that the receiving address will receive Chai worth at least wad dai:

    // like transferFrom but dai-denominated
    function move(address src, address dst, uint wad) external returns (bool) {
        uint chi = (now > pot.rho()) ? pot.drip() : pot.chi();
        // rounding up ensures dst gets at least wad dai
        return transferFrom(src, dst, rdivup(wad, chi));
    }

Permit

The permit method lets a user approve an address to spend on their behalf by signing a ERC712 typed message called permit.

permit consists of the following components:

  • holder, the address granting the permission and the signer of the message
  • spender, the address to which permission is being granted or denied
  • nonce, for replay attack protection
  • allowed, whether the spenders permission is being granted or revoked

Messages are signed using the procedure described in ERC712, using the PERMIT_TYPEHASH and DOMAIN_SEPARATOR constants:

    bytes32 public constant DOMAIN_SEPARATOR = 0x0b50407de9fa158c2cba01a99633329490dfd22989a150c20e8c7b4c1fb0fcc3;
    // keccak256("Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)"));
    bytes32 public constant PERMIT_TYPEHASH  = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb;

permit are processed by calling the permit method, which increments the holder nonce and approves the spender to spend on the behalf of holder if allowed is true, and revokes it otherwise:

    // --- Approve by signature ---
    function permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s) external
    {
        bytes32 digest = keccak256(abi.encodePacked(
            "\x19\x01",
            DOMAIN_SEPARATOR,
            keccak256(abi.encode(PERMIT_TYPEHASH,
                                 holder,
                                 spender,
                                 nonce,
                                 expiry,
                                 allowed))));
        require(holder != address(0), "chai/invalid holder");
        require(holder == ecrecover(digest, v, r, s), "chai/invalid-permit");
        require(expiry == 0 || now <= expiry, "chai/permit-expired");
        require(nonce == nonces[holder]++, "chai/invalid-nonce");

        uint can = allowed ? uint(-1) : 0;
        allowance[holder][spender] = can;
        emit Approval(holder, spender, can);
    }
区块链毕设网(www.interchains.cc)全网最靠谱的原创区块链毕设代做网站 部分资料来自网络,侵权联系删除! 最全最大的区块链源码站 ! QQ3039046426
区块链知识分享网, 以太坊dapp资源网, 区块链教程, fabric教程下载, 区块链书籍下载, 区块链资料下载, 区块链视频教程下载, 区块链基础教程, 区块链入门教程, 区块链资源 » chai源码

提供最优质的资源集合

立即查看 了解详情