title | description | parent | tags | slug | contentType | root | ||
---|---|---|---|---|---|---|---|---|
Dai Token |
Learn about Dai and integrate it into applications |
dai |
|
dai-token |
guides |
false |
Level: Beginner
Estimated Time: 30 - 60 minutes
Dai is a decentralized stablecoin built on Ethereum. The Dai token contract conforms to the ERC20 token standard which allows wallets, exchanges, and other applications to easily integrate with minimal effort. This guide will be useful to developers integrating Dai in applications like wallets, exchanges, and smart contracts to get a better understanding of the token contract and its functionality.
-
You will learn basic information about the token.
-
Understand the additional functions supported by the token contract.
-
Deploy your own token to an Ethereum testnet.
-
Integrate the Dai token effectively with your application.
-
Knowledge of the ERC20 token standard.
-
Ability to send ethereum transactions from your preferred dev environment.
Dai is available on the:
- Ethereum mainnet at 0x6B175474E89094C44Da98b954EedeAC495271d0F
- Kovan testnet at 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa
Other deployments are listed on changelog.makerdao.com.
The symbol field is set to ‘DAI’ and the name field is currently set to ‘Dai Stablecoin’.
Token precision field decimals is set to 18 like most other ERC20 tokens.
In addition, the contract has the version
field set to 1. This field is a constant, so once the contract is deployed, this field cannot be changed. This field is added for use in the permit()
function in the contract. And this variable is part of the EIP-712 signing standard. Read more on the permit()
function below.
Multi Collateral Dai has been live on the Ethereum mainnet since November 18, 2019 and its current total supply can be viewed on DaiStats.
The system internally uses 1 USD as the target price of Dai when new Dai is generated or burned through the Maker Vaults, but the market price of the token could vary based on a variety of conditions like exchange liquidity, trading pair etc.
Care should be taken before using the price of Dai directly reported by sources like CoinMarketCap, because exchange bugs may produce unreasonable price data. In many scenarios, such as displaying the value of Dai in a wallet, it is perfectly fine to hard code the price of a token to 1 USD.
Dai can be purchased with Ether on many popular exchanges, which many are listed on https://coinmarketcap.com/currencies/multi-collateral-dai/markets/. It is also available on many decentralized exchanges like Oasis, KyberSwap, and Uniswap.
You can also generate Dai by opening a Vault with https://oasis.app/.
There are no Dai faucet on testnets, but you can generate your own Dai on the major Ethereum testnets: Goerli, Kovan, Rinkeby and Ropsten. After having obtained testnet-ETH, you can head over to Oasis and open a Vault. Make sure to change the ?network=<networkName>
parameter to your preferred network
Alternatively, if you're more comfortable with cli-tools, then you can the seth guide.
Another option is to buy Kovan Dai with Kovan ETH on Oasis Trade if there is sufficient liquidity available.
The codebase at commit 6fa5581 was used for deployments on mainnet.
The Dai token contract, follows the ERC-20 standard with some additional features. The added features are
- The
permit()
function that uses the EIP-712 signing standard as defined by EIP-2612 (draft). - The
mint()
andburn()
functions that the Maker Protocol is authorised to use.
The EIP-712 signing standard allows to sign structured typed data instead of just byte strings. This allows in the creation of the permit()
function. The permit()
function allows the user to send Dai without paying gas. This works as follows:
- User signs a
permit
message allowing adestination
address to withdraw an amount of Dai from his wallet. - This message is read by a relayer that takes the signed message and processes it by paying the transaction fee for the user. This relayer then takes a Dai cut from the user for processing the transaction.
- The user can send Dai by paying for the transaction fee with Dai, while a relayer in the backend is doing the processing.
Check https://stablecoin.services/ and https://gasless.mosendo.com/ for live examples. The EIP for this functionnality is currently in draft.
Tokens are created when a user adds collateral to their Vault and generates new Dai from it. Tokens are burned, when the same user pays back the same amount of Dai they’ve previously issued for the system to remove them from the supply to free their locked collateral back. Also mint
and burn
functions are used when user deposits and withdraws Dai from the Dai Savings Rate contract.
The MCD_DAI_JOIN adapter contract in the Maker Protocol is authorized to calls the mint and burn functions of Dai token which to increase or decrease the total supply.
mint
has the function signature:mint(address guy, uint wad)
. It increases the total supply of the token as well as theguy
’s token balance by thewad
amount. All calls tomint()
originate from theexit()
function on the DaiJoin contract.burn
has the function signature:burn(address guy, uint wad)
. It decreases the total supply of the token as well as theguy
’s token balance by thewad
amount. Calls toburn()
originate fromjoin()
function on the DaiJoin contract. Contrary to Mint, Burn is not restricted to DaiJoin, this means that any user if he intends to do so, can burn his Dai. This however is not recommended.
The transferFrom()
function has a few aliases available: push
, pull
, and move
. These are available if function caller doesn't want to specify msg.sender
parameter in the function call.
Some functions in the Dai contract can only be called by an authorized address. This address can be an externally owned account (EOA) or a contract address. In the Dai contract, the only authorized address is the DaiJoin Adapter that is part of the Maker Protocol. As such, only the DaiJoin Adapter is able to call the mint
function.
The Dai contract uses a simplified authority for its functions, where only addresses known as wards
are authorized by the rely
function, and deauthorized by deny
. Because rely
and deny
can be called only by members of wards
, and the only address in wards is the DaiJoin adapter, which does not contain instructions to call rely
or deny
, the wards
list is effectively frozen and cannot be modified on the mainnet deployment. The only occasion where rely and deny is expected to be used is during deployment.
The ERC20 Dai Token contract does not represent all Dai supply, as Dai can be in the form of internal balances to the Maker Protocol contracts. For a rundown of the different types of Dai, and the relation between them, please see the guide Tracking Dai Supply
The DaiJoin Adapter is used to convert internal Dai to a ERC20 token usable by wallets and exchanges. Typically, contracts and users deposit their internal Dai into the DaiJoin Adapter and obtain ERC20 tokens in exchange. Any holder of a ERC20 Dai token can also withdraw internal Dai from the contract by burning ERC20 Dai.
exit(address usr, uint wad)
: Transfers an internal Dai balance of the amountwad
from addressusr
to the DaiJoin contract, and mint new ERC20 in favor ofusr
.join(address usr, uint wad)
: Burnswad
Dai from addressusr
and transfer the equivalent internal Dai in its favor. Note that join is possible only if the DaiJoin contract is approved.
MKR holders can through the governance contract vote to shut down the system by executing the cage()
function on the ESM contract.
After emergency shutdown, all DAI holders are allowed to claim collateral for each token at the last price reported by price feed oracles. Two functions cash()
and pack()
, are activated in END contract. cash()
allows token holders to redeem Dai for ETH at the exchange ratio set at emergency shutdown.
More information about the Emergency Shutdown can be found in the Emergency Shutdown Guide.
Dai and the associated MCD contracts are deployed on various testnets, but you may want do deploy your own version of the Dai contract to test your ERC20 or permit
integrations. The following instructions require a working configuration of dapp.tools, including dapp
(tested with v0.27.0) and seth
(v0.8.4) and a provisionned test account with its associated keys.
git clone
https://github.com/makerdao/dsscd dss
dapp update
dapp build
export SETH_CHAIN=kovan
: Change kovan for your prefered chainexport ETH_KEYSTORE=~/keys
: Define where your keys are storeexport ETH_FROM=<address>
: Set your test accountexport ETH_RPC_URL=<RPC URL>
: Set the URL for a testnet RPC node (Infura or other)export chainid= $(seth --to-uint256 42)
: Deploying the contract requires passing the chain id, for use with the permit function. For Kovan, the id is 42.dapp create Dai $chainid
: To deploy the contract. If successful, this will return the address of your new contract.
If you want to verify your contract on Etherscan, use the output of
hevm flatten --source-file src/dai.sol --json-file out/dapp.sol.json
and specify the content of $chainid
as the ABI formatted constructor.
Once deployed, you may test your contract
export DAIK=<deployed contract address>
seth call $DAIK 'wards(address)' $ETH_FROM
: Should return 1 because the adress that deployed the contract is part of wards by default.seth send $DAIK 'mint(address,uint256)' $ETH_FROM $(seth --to-uint256 $(seth --to-wei 100000000 eth))
: Will mint yourself 100,000,000 test-DAIseth --from-wei $(seth --to-dec $(seth call $DAIK 'balanceOf(address)' $ETH_FROM))
: To see your test-Dai balance
In this guide, we briefly discussed the technical details of the Dai token contract as well as a quick summary of its role in the Maker Protocol. Please refer to the links embedded in the document as well as the additional resources section for more information. We also urge you to explore the various tools and services built on top of Dai by our partner ecosystem.
- https://github.com/makerdao/dss/blob/master/src/dai.sol
- Using Dai in smart contracts
- Emergency Shutdown Guide
- Tracking Dai Supply
- Rocket chat - #dev channel