• Stars
    star
    147
  • Rank 251,347 (Top 5 %)
  • Language
    Solidity
  • License
    GNU Affero Genera...
  • Created about 5 years ago
  • Updated over 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

ERC20 wrapper over the Dai Savings Rate

🍵

1 Chai = 1 Dai * Pot.chi

chai is an ERC20 token representing a claim on deposits in the DSR. It can be freely converted to and from dai: the amount of dai claimed by one chai is always increasing, at the Dai Savings Rate. Like any well-behaved token, a user's chai balance won't change unexpectedly, while the chai's value grows day by day.

chai is a very simple contract. Apart from the standard ERC20 functionality, it also implements the same permit off-chain approval as dai itself. You can also call dai(address usr) to check how many dai a given user's chai balance claims. The token has no owner or authority. That's all there is to it.

mainnet deployment

chai is live on the mainnet since December 1st at 0x06af07097c9eeb7fd685c692751d5c66db49c215

You can interact with the Chai contract at chai.money. The source for the ui is hosted here.

audit

The deployed chai contract underwent a two day audit by Trail Of Bits in the beginning of February, finding no security related issues. A summary can be found here.

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 WETH, MKR 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);
    }

A 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.

A 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);
    }

More Repositories

1

dapptools

Dapp, Seth, Hevm, and more
Haskell
2,086
star
2

dappsys

Composable building blocks for Ethereum contracts
Nix
580
star
3

ds-proxy

a proxy object that can compose transactions on owner's behalf
Solidity
311
star
4

dapple

EVM contract system developer multitool
JavaScript
298
star
5

ds-math

Safe arithmetic
Solidity
268
star
6

dapp

This repository has been moved to dapphub/dapptools
249
star
7

ds-token

A simple and sufficient ERC20 implementation
Solidity
225
star
8

ds-test

Assertions, equality checks and other test helpers
Solidity
208
star
9

seth

(OLD REPO) The command-line Ethereum army knife by DappHub
147
star
10

ds-auth

Updatable, unobtrusive Solidity authorization pattern
Solidity
138
star
11

klab

K framework proof explorer & smart contract specification format
JavaScript
124
star
12

hevm

(OLD REPO) A debug-oriented Ethereum VM (EVM)
114
star
13

dmap

registry contract with no time to argue
JavaScript
58
star
14

ds-dach

Dai Automated Clearing House
Shell
52
star
15

dpack

simple lockfile for your dapp's addresses and artifacts
TypeScript
46
star
16

k-dss

formal verification of multicollateral dai in the K framework
GCC Machine Description
45
star
17

ds-feeds

Simple data access pattern for dumb, durable software objects
Makefile
32
star
18

ds-chief

approval voting to select who wears the hat by consensus
Solidity
29
star
19

ds-weth

ETH->ERC20 with extra opinions
Solidity
27
star
20

ds-pause

Schedule function calls that can only be executed once some delay has elapsed
Solidity
26
star
21

ethrun

Directly run EVM bytecode (using Parity technology)
Rust
24
star
22

ds-vault

DSAuth-protected ERC20 token vault
Solidity
24
star
23

erc20

erc20 interface definition container package
Solidity
24
star
24

ds-guard

Whitelist DSAuthority for use with DSAuth
Solidity
22
star
25

ds-group

Multisig with a command-line interface
Shell
22
star
26

dapp-tools

Code for the dapp.tools website
Nix
21
star
27

dappsys-monolithic

Dappsys for all
Solidity
21
star
28

ds-cabal

Simple m-of-n multisig proxy written in handcrafted EVM bytcode
Makefile
21
star
29

keeper

Admin toolkit for incentive-following software daemons
Shell
19
star
30

ds-roles

A DSAuthority for up to 256 roles
Solidity
17
star
31

ds-note

Log function calls as events
Solidity
17
star
32

ds-value

Set and get a value
Solidity
14
star
33

fv-tutorial

Materials for the devcon4 workshop
GCC Machine Description
14
star
34

ds-eth-token

ERC20 ETH token wrapper. No more special case logic for Ether.
Makefile
13
star
35

ds-exec

Better exception handling
Solidity
9
star
36

ll

Linear Logic references
HTML
8
star
37

awesome-dmap

awesome dmap links
7
star
38

nixpkgs-dapphub

Dapp development overlay for Nix
Nix
7
star
39

locktopus

sqlite file of locked values in the dmap
JavaScript
6
star
40

ds-warp

Time travel for Ethereum
Nix
6
star
41

token

(OLD REPO) Command-line utility for ERC20 tokens
6
star
42

ACS

Applied Computer Science Working Group
6
star
43

ds-pain

Shell
5
star
44

erc20-golf

GCC Machine Description
5
star
45

chronobank-contracts

audit branch of chronobank contracts
JavaScript
5
star
46

ds-items

Ownable, transferrable, non-fungible unsigned integers
Makefile
4
star
47

dapphub.com

HTML
4
star
48

dapphub-registry

JavaScript
4
star
49

ds-forkable

Forkable Datastore Service
4
star
50

ds-cache

DSValue with expiry
Solidity
3
star
51

dapple-script

DappleScript - A simple ethereum interaction language.
JavaScript
3
star
52

ds-thing

Your things should be DSThings
Solidity
3
star
53

dapp-wizard

Racket
3
star
54

remappings-test

dummy project for testing dapp remappings
Solidity
2
star
55

kyo

know-your-origin, don't use this terrible anti-pattern you fool
2
star
56

k

k-fork
Java
2
star
57

ethsign

(OLD REPO) Simple Ethereum transaction signer using Geth as a library
2
star
58

ds-spell

An object that does one thing once.
Makefile
2
star
59

dappsys-graphics

dappsys visualizations
JavaScript
2
star
60

ethkey

Create Ethereum accounts using Geth as a library
Go
2
star
61

ds-store

Dappsys data management components
Makefile
2
star
62

qrtx

JavaScript
2
star
63

dapple-quicktest

Blazingly fast EVM test runner
JavaScript
2
star
64

cage

Nix
2
star
65

maker-docs

Reference documentation for Maker and the Dai Credit System
HTML
2
star
66

libethjet-haskell

2
star
67

tr-base

dummy repo for testing some dapp-remappings stuff
Solidity
1
star
68

lockpack

1
star
69

LLPoster

TeX
1
star
70

dapp.org-old

HTML
1
star
71

guts

1
star
72

ds-delay

Makefile
1
star
73

dapp.tools

Unused - obsolete github pages site for dapp.tools.
HTML
1
star
74

fv-tutorial-solutions

GCC Machine Description
1
star
75

celf-evm

EVM written in celf
JavaScript
1
star
76

llmotivation

Motivational Paper on Linear Logic as a blockchain programming language
TeX
1
star
77

ds-read

Makefile
1
star
78

dapp.org

1
star
79

dapp.coop

HTML
1
star
80

exp-squaring-percise-dapp

Makefile
1
star
81

mod-blockchain

JavaScript
1
star
82

wiki.dapp.coop

JavaScript
1
star
83

klab-explorer.github.io

klab explorer webpage
1
star
84

ds-rpow

Makefile
1
star
85

k-gas-analyser

Haskell
1
star
86

chronobank-review

review of chronobank contracts
HTML
1
star
87

ds-base

building up a reasonable base class
Makefile
1
star
88

ds-stop

DSAuth-protected stop and start
Solidity
1
star
89

dappsys-docs

Python
1
star
90

klab-multipleCalls

proving that one contract can call another one, wow
GCC Machine Description
1
star
91

tr0

dummy repo for testing dapp-remappings
Solidity
1
star
92

k-ds-rpow

SMT
1
star
93

manny

Manny O'Malley, Malicious Oracle
1
star
94

bat-rewrite

Makefile
1
star
95

hubot-channel-welcome

JavaScript
1
star
96

dappsys-nix

Shell
1
star
97

dapple-wevm

Wallet side ethereum virtual machine
JavaScript
1
star
98

dpath

dpath syntax and semantics
1
star
99

dai-semantics

K specification of the dai stablecoin system
Lua
1
star
100

dapple-pkg

Dapple packages module
JavaScript
1
star