文件 1 的 1:Jamie.sol
pragma solidity ^0.5.17;
pragma experimental ABIEncoderV2;
contract Context {
constructor () internal { }
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this;
return msg.data;
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
contract ERC20 is Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal {
require(account != address(0), "ERC20: mint to the zero address");
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal {
require(account != address(0), "ERC20: burn from the zero address");
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _burnFrom(address account, uint256 amount) internal {
_burn(account, amount);
_approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
}
}
contract ERC20Burnable is Context, ERC20 {
function burn(uint256 amount) public {
_burn(_msgSender(), amount);
}
function burnFrom(address account, uint256 amount) public {
_burnFrom(account, amount);
}
}
contract ERC20Detailed is IERC20 {
string private _name;
string private _symbol;
uint8 private _decimals;
constructor (string memory name, string memory symbol, uint8 decimals) public {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
}
library Roles {
struct Role {
mapping (address => bool) bearer;
}
function add(Role storage role, address account) internal {
require(!has(role, account), "Roles: account already has role");
role.bearer[account] = true;
}
function remove(Role storage role, address account) internal {
require(has(role, account), "Roles: account does not have role");
role.bearer[account] = false;
}
function has(Role storage role, address account) internal view returns (bool) {
require(account != address(0), "Roles: account is the zero address");
return role.bearer[account];
}
}
contract MinterRole is Context {
using Roles for Roles.Role;
event MinterAdded(address indexed account);
event MinterRemoved(address indexed account);
Roles.Role private _minters;
constructor () internal {
_addMinter(_msgSender());
}
modifier onlyMinter() {
require(isMinter(_msgSender()), "MinterRole: caller does not have the Minter role");
_;
}
function isMinter(address account) public view returns (bool) {
return _minters.has(account);
}
function addMinter(address account) public onlyMinter {
_addMinter(account);
}
function renounceMinter() public {
_removeMinter(_msgSender());
}
function _addMinter(address account) internal {
_minters.add(account);
emit MinterAdded(account);
}
function _removeMinter(address account) internal {
_minters.remove(account);
emit MinterRemoved(account);
}
}
library Require {
uint256 constant ASCII_ZERO = 48;
uint256 constant ASCII_RELATIVE_ZERO = 87;
uint256 constant ASCII_LOWER_EX = 120;
bytes2 constant COLON = 0x3a20;
bytes2 constant COMMA = 0x2c20;
bytes2 constant LPAREN = 0x203c;
byte constant RPAREN = 0x3e;
uint256 constant FOUR_BIT_MASK = 0xf;
function that(
bool must,
bytes32 file,
bytes32 reason
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason)
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
uint256 payloadA
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason),
LPAREN,
stringify(payloadA),
RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
uint256 payloadA,
uint256 payloadB
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason),
LPAREN,
stringify(payloadA),
COMMA,
stringify(payloadB),
RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
address payloadA
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason),
LPAREN,
stringify(payloadA),
RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
address payloadA,
uint256 payloadB
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason),
LPAREN,
stringify(payloadA),
COMMA,
stringify(payloadB),
RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
address payloadA,
uint256 payloadB,
uint256 payloadC
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason),
LPAREN,
stringify(payloadA),
COMMA,
stringify(payloadB),
COMMA,
stringify(payloadC),
RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
bytes32 payloadA
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason),
LPAREN,
stringify(payloadA),
RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
bytes32 payloadA,
uint256 payloadB,
uint256 payloadC
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason),
LPAREN,
stringify(payloadA),
COMMA,
stringify(payloadB),
COMMA,
stringify(payloadC),
RPAREN
)
)
);
}
}
function stringifyTruncated(
bytes32 input
)
private
pure
returns (bytes memory)
{
bytes memory result = abi.encodePacked(input);
for (uint256 i = 32; i > 0; ) {
i--;
if (result[i] != 0) {
uint256 length = i + 1;
assembly {
mstore(result, length)
}
return result;
}
}
return new bytes(0);
}
function stringify(
uint256 input
)
private
pure
returns (bytes memory)
{
if (input == 0) {
return "0";
}
uint256 j = input;
uint256 length;
while (j != 0) {
length++;
j /= 10;
}
bytes memory bstr = new bytes(length);
j = input;
for (uint256 i = length; i > 0; ) {
i--;
bstr[i] = byte(uint8(ASCII_ZERO + (j % 10)));
j /= 10;
}
return bstr;
}
function stringify(
address input
)
private
pure
returns (bytes memory)
{
uint256 z = uint256(input);
bytes memory result = new bytes(42);
result[0] = byte(uint8(ASCII_ZERO));
result[1] = byte(uint8(ASCII_LOWER_EX));
for (uint256 i = 0; i < 20; i++) {
uint256 shift = i * 2;
result[41 - shift] = char(z & FOUR_BIT_MASK);
z = z >> 4;
result[40 - shift] = char(z & FOUR_BIT_MASK);
z = z >> 4;
}
return result;
}
function stringify(
bytes32 input
)
private
pure
returns (bytes memory)
{
uint256 z = uint256(input);
bytes memory result = new bytes(66);
result[0] = byte(uint8(ASCII_ZERO));
result[1] = byte(uint8(ASCII_LOWER_EX));
for (uint256 i = 0; i < 32; i++) {
uint256 shift = i * 2;
result[65 - shift] = char(z & FOUR_BIT_MASK);
z = z >> 4;
result[64 - shift] = char(z & FOUR_BIT_MASK);
z = z >> 4;
}
return result;
}
function char(
uint256 input
)
private
pure
returns (byte)
{
if (input < 10) {
return byte(uint8(input + ASCII_ZERO));
}
return byte(uint8(input + ASCII_RELATIVE_ZERO));
}
}
library LibEIP712 {
bytes32 constant internal _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;
function hashEIP712Domain(
string memory name,
string memory version,
uint256 chainId,
address verifyingContract
)
internal
pure
returns (bytes32 result)
{
bytes32 schemaHash = _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH;
assembly {
let nameHash := keccak256(add(name, 32), mload(name))
let versionHash := keccak256(add(version, 32), mload(version))
let memPtr := mload(64)
mstore(memPtr, schemaHash)
mstore(add(memPtr, 32), nameHash)
mstore(add(memPtr, 64), versionHash)
mstore(add(memPtr, 96), chainId)
mstore(add(memPtr, 128), verifyingContract)
result := keccak256(memPtr, 160)
}
return result;
}
function hashEIP712Message(bytes32 eip712DomainHash, bytes32 hashStruct)
internal
pure
returns (bytes32 result)
{
assembly {
let memPtr := mload(64)
mstore(memPtr, 0x1901000000000000000000000000000000000000000000000000000000000000)
mstore(add(memPtr, 2), eip712DomainHash)
mstore(add(memPtr, 34), hashStruct)
result := keccak256(memPtr, 66)
}
return result;
}
}
library Decimal {
using SafeMath for uint256;
uint256 constant BASE = 10**18;
struct D256 {
uint256 value;
}
function zero()
internal
pure
returns (D256 memory)
{
return D256({ value: 0 });
}
function one()
internal
pure
returns (D256 memory)
{
return D256({ value: BASE });
}
function from(
uint256 a
)
internal
pure
returns (D256 memory)
{
return D256({ value: a.mul(BASE) });
}
function ratio(
uint256 a,
uint256 b
)
internal
pure
returns (D256 memory)
{
return D256({ value: getPartial(a, BASE, b) });
}
function add(
D256 memory self,
uint256 b
)
internal
pure
returns (D256 memory)
{
return D256({ value: self.value.add(b.mul(BASE)) });
}
function sub(
D256 memory self,
uint256 b
)
internal
pure
returns (D256 memory)
{
return D256({ value: self.value.sub(b.mul(BASE)) });
}
function sub(
D256 memory self,
uint256 b,
string memory reason
)
internal
pure
returns (D256 memory)
{
return D256({ value: self.value.sub(b.mul(BASE), reason) });
}
function mul(
D256 memory self,
uint256 b
)
internal
pure
returns (D256 memory)
{
return D256({ value: self.value.mul(b) });
}
function div(
D256 memory self,
uint256 b
)
internal
pure
returns (D256 memory)
{
return D256({ value: self.value.div(b) });
}
function pow(
D256 memory self,
uint256 b
)
internal
pure
returns (D256 memory)
{
if (b == 0) {
return from(1);
}
D256 memory temp = D256({ value: self.value });
for (uint256 i = 1; i < b; i++) {
temp = mul(temp, self);
}
return temp;
}
function add(
D256 memory self,
D256 memory b
)
internal
pure
returns (D256 memory)
{
return D256({ value: self.value.add(b.value) });
}
function sub(
D256 memory self,
D256 memory b
)
internal
pure
returns (D256 memory)
{
return D256({ value: self.value.sub(b.value) });
}
function sub(
D256 memory self,
D256 memory b,
string memory reason
)
internal
pure
returns (D256 memory)
{
return D256({ value: self.value.sub(b.value, reason) });
}
function mul(
D256 memory self,
D256 memory b
)
internal
pure
returns (D256 memory)
{
return D256({ value: getPartial(self.value, b.value, BASE) });
}
function div(
D256 memory self,
D256 memory b
)
internal
pure
returns (D256 memory)
{
return D256({ value: getPartial(self.value, BASE, b.value) });
}
function equals(D256 memory self, D256 memory b) internal pure returns (bool) {
return self.value == b.value;
}
function greaterThan(D256 memory self, D256 memory b) internal pure returns (bool) {
return compareTo(self, b) == 2;
}
function lessThan(D256 memory self, D256 memory b) internal pure returns (bool) {
return compareTo(self, b) == 0;
}
function greaterThanOrEqualTo(D256 memory self, D256 memory b) internal pure returns (bool) {
return compareTo(self, b) > 0;
}
function lessThanOrEqualTo(D256 memory self, D256 memory b) internal pure returns (bool) {
return compareTo(self, b) < 2;
}
function isZero(D256 memory self) internal pure returns (bool) {
return self.value == 0;
}
function asUint256(D256 memory self) internal pure returns (uint256) {
return self.value.div(BASE);
}
function getPartial(
uint256 target,
uint256 numerator,
uint256 denominator
)
private
pure
returns (uint256)
{
return target.mul(numerator).div(denominator);
}
function compareTo(
D256 memory a,
D256 memory b
)
private
pure
returns (uint256)
{
if (a.value == b.value) {
return 1;
}
return a.value > b.value ? 2 : 0;
}
}
library Constants {
uint256 private constant CHAIN_ID = 1;
uint256 private constant BOOTSTRAPPING_PERIOD = 120;
uint256 private constant BOOTSTRAPPING_PRICE = 154e16;
address private constant USDC = address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
uint256 private constant ORACLE_RESERVE_MINIMUM = 1e10;
uint256 private constant INITIAL_STAKE_MULTIPLE = 1e6;
struct EpochStrategy {
uint256 offset;
uint256 start;
uint256 period;
}
uint256 private constant EPOCH_OFFSET = 0;
uint256 private constant EPOCH_START = 1609539545;
uint256 private constant EPOCH_PERIOD = 21600;
uint256 private constant GOVERNANCE_PERIOD = 36;
uint256 private constant GOVERNANCE_QUORUM = 33e16;
uint256 private constant GOVERNANCE_SUPER_MAJORITY = 66e16;
uint256 private constant GOVERNANCE_EMERGENCY_DELAY = 6;
uint256 private constant ADVANCE_INCENTIVE = 40e18;
uint256 private constant DAO_EXIT_LOCKUP_EPOCHS = 36;
uint256 private constant POOL_EXIT_LOCKUP_EPOCHS = 12;
uint256 private constant COUPON_EXPIRATION = 360;
uint256 private constant DEBT_RATIO_CAP = 35e16;
uint256 private constant INITIAL_COUPON_REDEMPTION_PENALTY = 50e16;
uint256 private constant COUPON_REDEMPTION_PENALTY_DECAY = 3600;
uint256 private constant SUPPLY_CHANGE_DIVISOR = 12e18;
uint256 private constant SUPPLY_CHANGE_LIMIT = 10e16;
uint256 private constant ORACLE_POOL_RATIO = 40;
function getUsdcAddress() internal pure returns (address) {
return USDC;
}
function getOracleReserveMinimum() internal pure returns (uint256) {
return ORACLE_RESERVE_MINIMUM;
}
function getEpochStrategy() internal pure returns (EpochStrategy memory) {
return EpochStrategy({
offset: EPOCH_OFFSET,
start: EPOCH_START,
period: EPOCH_PERIOD
});
}
function getInitialStakeMultiple() internal pure returns (uint256) {
return INITIAL_STAKE_MULTIPLE;
}
function getBootstrappingPeriod() internal pure returns (uint256) {
return BOOTSTRAPPING_PERIOD;
}
function getBootstrappingPrice() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: BOOTSTRAPPING_PRICE});
}
function getGovernancePeriod() internal pure returns (uint256) {
return GOVERNANCE_PERIOD;
}
function getGovernanceQuorum() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: GOVERNANCE_QUORUM});
}
function getGovernanceSuperMajority() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: GOVERNANCE_SUPER_MAJORITY});
}
function getGovernanceEmergencyDelay() internal pure returns (uint256) {
return GOVERNANCE_EMERGENCY_DELAY;
}
function getAdvanceIncentive() internal pure returns (uint256) {
return ADVANCE_INCENTIVE;
}
function getDAOExitLockupEpochs() internal pure returns (uint256) {
return DAO_EXIT_LOCKUP_EPOCHS;
}
function getPoolExitLockupEpochs() internal pure returns (uint256) {
return POOL_EXIT_LOCKUP_EPOCHS;
}
function getCouponExpiration() internal pure returns (uint256) {
return COUPON_EXPIRATION;
}
function getDebtRatioCap() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: DEBT_RATIO_CAP});
}
function getInitialCouponRedemptionPenalty() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: INITIAL_COUPON_REDEMPTION_PENALTY});
}
function getCouponRedemptionPenaltyDecay() internal pure returns (uint256) {
return COUPON_REDEMPTION_PENALTY_DECAY;
}
function getSupplyChangeLimit() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: SUPPLY_CHANGE_LIMIT});
}
function getSupplyChangeDivisor() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: SUPPLY_CHANGE_DIVISOR});
}
function getOraclePoolRatio() internal pure returns (uint256) {
return ORACLE_POOL_RATIO;
}
function getChainId() internal pure returns (uint256) {
return CHAIN_ID;
}
}
contract Permittable is ERC20Detailed, ERC20 {
bytes32 constant FILE = "Permittable";
bytes32 public constant EIP712_PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
string private constant EIP712_VERSION = "1";
bytes32 public EIP712_DOMAIN_SEPARATOR;
mapping(address => uint256) nonces;
constructor() public {
EIP712_DOMAIN_SEPARATOR = LibEIP712.hashEIP712Domain(name(), EIP712_VERSION, Constants.getChainId(), address(this));
}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external {
bytes32 digest = LibEIP712.hashEIP712Message(
EIP712_DOMAIN_SEPARATOR,
keccak256(abi.encode(
EIP712_PERMIT_TYPEHASH,
owner,
spender,
value,
nonces[owner]++,
deadline
))
);
address recovered = ecrecover(digest, v, r, s);
Require.that(
recovered == owner,
FILE,
"Invalid signature"
);
Require.that(
recovered != address(0),
FILE,
"Zero address"
);
Require.that(
now <= deadline,
FILE,
"Expired"
);
_approve(owner, spender, value);
}
}
contract BDollar is IERC20 {
function burn(uint256 amount) public;
function burnFrom(address account, uint256 amount) public;
function mint(address account, uint256 amount) public returns (bool);
}
contract Jamie is BDollar, MinterRole, ERC20Detailed, Permittable, ERC20Burnable {
constructor()
ERC20Detailed("Xero Set Dollar", "XERO", 18)
Permittable()
public
{ }
function mint(address account, uint256 amount) public onlyMinter returns (bool) {
_mint(account, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
_transfer(sender, recipient, amount);
if (allowance(sender, _msgSender()) != uint256(-1)) {
_approve(
sender,
_msgSender(),
allowance(sender, _msgSender()).sub(amount, "Dollar: transfer amount exceeds allowance"));
}
return true;
}
}