Created
August 29, 2021 01:47
-
-
Save jacks0n9/333bae10a64fe627fc453cd406f3be90 to your computer and use it in GitHub Desktop.
The Dai stablecoin source code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
*Submitted for verification at Etherscan.io on 2019-11-14 | |
*/ | |
// hevm: flattened sources of /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/dai.sol | |
pragma solidity =0.5.12; | |
////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/lib.sol | |
// This program is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// This program is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details. | |
// You should have received a copy of the GNU General Public License | |
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |
/* pragma solidity 0.5.12; */ | |
contract LibNote { | |
event LogNote( | |
bytes4 indexed sig, | |
address indexed usr, | |
bytes32 indexed arg1, | |
bytes32 indexed arg2, | |
bytes data | |
) anonymous; | |
modifier note { | |
_; | |
assembly { | |
// log an 'anonymous' event with a constant 6 words of calldata | |
// and four indexed topics: selector, caller, arg1 and arg2 | |
let mark := msize // end of memory ensures zero | |
mstore(0x40, add(mark, 288)) // update free memory pointer | |
mstore(mark, 0x20) // bytes type data offset | |
mstore(add(mark, 0x20), 224) // bytes size (padded) | |
calldatacopy(add(mark, 0x40), 0, 224) // bytes payload | |
log4(mark, 288, // calldata | |
shl(224, shr(224, calldataload(0))), // msg.sig | |
caller, // msg.sender | |
calldataload(4), // arg1 | |
calldataload(36) // arg2 | |
) | |
} | |
} | |
} | |
////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/dai.sol | |
// Copyright (C) 2017, 2018, 2019 dbrock, rain, mrchico | |
// This program is free software: you can redistribute it and/or modify | |
// it under the terms of the GNU Affero General Public License as published by | |
// the Free Software Foundation, either version 3 of the License, or | |
// (at your option) any later version. | |
// | |
// This program is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU Affero General Public License for more details. | |
// | |
// You should have received a copy of the GNU Affero General Public License | |
// along with this program. If not, see <https://www.gnu.org/licenses/>. | |
/* pragma solidity 0.5.12; */ | |
/* import "./lib.sol"; */ | |
contract Dai is LibNote { | |
// --- Auth --- | |
mapping (address => uint) public wards; | |
function rely(address guy) external note auth { wards[guy] = 1; } | |
function deny(address guy) external note auth { wards[guy] = 0; } | |
modifier auth { | |
require(wards[msg.sender] == 1, "Dai/not-authorized"); | |
_; | |
} | |
// --- ERC20 Data --- | |
string public constant name = "Dai Stablecoin"; | |
string public constant symbol = "DAI"; | |
string public constant version = "1"; | |
uint8 public constant decimals = 18; | |
uint256 public totalSupply; | |
mapping (address => uint) public balanceOf; | |
mapping (address => mapping (address => uint)) public allowance; | |
mapping (address => uint) public nonces; | |
event Approval(address indexed src, address indexed guy, uint wad); | |
event Transfer(address indexed src, address indexed dst, uint wad); | |
// --- Math --- | |
function add(uint x, uint y) internal pure returns (uint z) { | |
require((z = x + y) >= x); | |
} | |
function sub(uint x, uint y) internal pure returns (uint z) { | |
require((z = x - y) <= x); | |
} | |
// --- EIP712 niceties --- | |
bytes32 public DOMAIN_SEPARATOR; | |
// bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)"); | |
bytes32 public constant PERMIT_TYPEHASH = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb; | |
constructor(uint256 chainId_) public { | |
wards[msg.sender] = 1; | |
DOMAIN_SEPARATOR = keccak256(abi.encode( | |
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), | |
keccak256(bytes(name)), | |
keccak256(bytes(version)), | |
chainId_, | |
address(this) | |
)); | |
} | |
// --- Token --- | |
function transfer(address dst, uint wad) external returns (bool) { | |
return transferFrom(msg.sender, dst, wad); | |
} | |
function transferFrom(address src, address dst, uint wad) | |
public returns (bool) | |
{ | |
require(balanceOf[src] >= wad, "Dai/insufficient-balance"); | |
if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) { | |
require(allowance[src][msg.sender] >= wad, "Dai/insufficient-allowance"); | |
allowance[src][msg.sender] = sub(allowance[src][msg.sender], wad); | |
} | |
balanceOf[src] = sub(balanceOf[src], wad); | |
balanceOf[dst] = add(balanceOf[dst], wad); | |
emit Transfer(src, dst, wad); | |
return true; | |
} | |
function mint(address usr, uint wad) external auth { | |
balanceOf[usr] = add(balanceOf[usr], wad); | |
totalSupply = add(totalSupply, wad); | |
emit Transfer(address(0), usr, wad); | |
} | |
function burn(address usr, uint wad) external { | |
require(balanceOf[usr] >= wad, "Dai/insufficient-balance"); | |
if (usr != msg.sender && allowance[usr][msg.sender] != uint(-1)) { | |
require(allowance[usr][msg.sender] >= wad, "Dai/insufficient-allowance"); | |
allowance[usr][msg.sender] = sub(allowance[usr][msg.sender], wad); | |
} | |
balanceOf[usr] = sub(balanceOf[usr], wad); | |
totalSupply = sub(totalSupply, wad); | |
emit Transfer(usr, address(0), wad); | |
} | |
function approve(address usr, uint wad) external returns (bool) { | |
allowance[msg.sender][usr] = wad; | |
emit Approval(msg.sender, usr, wad); | |
return true; | |
} | |
// --- Alias --- | |
function push(address usr, uint wad) external { | |
transferFrom(msg.sender, usr, wad); | |
} | |
function pull(address usr, uint wad) external { | |
transferFrom(usr, msg.sender, wad); | |
} | |
function move(address src, address dst, uint wad) external { | |
transferFrom(src, dst, wad); | |
} | |
// --- 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), "Dai/invalid-address-0"); | |
require(holder == ecrecover(digest, v, r, s), "Dai/invalid-permit"); | |
require(expiry == 0 || now <= expiry, "Dai/permit-expired"); | |
require(nonce == nonces[holder]++, "Dai/invalid-nonce"); | |
uint wad = allowed ? uint(-1) : 0; | |
allowance[holder][spender] = wad; | |
emit Approval(holder, spender, wad); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment