Address Contract Partially Verified
Address
0xA2cd3D43c775978A96BdBf12d733D5A1ED94fb18
Balance
0 ETH
Nonce
1
Code Size
6726 bytes
Creator
0xe864C943...6d73 at tx 0xcb4305e1...055fc7
Last Active
Indexed Transactions
1 (24,586,740 → 24,586,740)
Gas Used (indexed)
56,050
Contract Bytecode
6726 bytes
0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c806370a0823111610104578063a457c2d7116100a2578063c3cda52011610071578063c3cda5201461057a578063dd62ed3e146105c1578063e7a324dc146105ef578063f1127ed8146105f7576101cf565b8063a457c2d7146104d6578063a9059cbb14610502578063aa271e1a1461052e578063b4b5ea5714610554576101cf565b806381ea3cc7116100de57806381ea3cc71461049857806395d89b41146104a0578063983b2d56146104a857806398650275146104ce576101cf565b806370a0823114610420578063782d6fe1146104465780637ecebe0014610472576101cf565b8063313ce5671161017157806340c10f191161014b57806340c10f191461034b578063587cde1e146103775780635c19a95c146103b95780636fcfff45146103e1576101cf565b8063313ce5671461030f57806332cb6b0c14610317578063395093511461031f576101cf565b806320606b70116101ad57806320606b70146102ab57806323b872dd146102b35780632e0f2625146102e95780632ff2e9dc14610307576101cf565b806306fdde03146101d4578063095ea7b31461025157806318160ddd14610291575b600080fd5b6101dc610649565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102165781810151838201526020016101fe565b50505050905090810190601f1680156102435780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61027d6004803603604081101561026757600080fd5b506001600160a01b0381351690602001356106df565b604080519115158252519081900360200190f35b6102996106f6565b60408051918252519081900360200190f35b6102996106fc565b61027d600480360360608110156102c957600080fd5b506001600160a01b03813581169160208101359091169060400135610717565b6102f1610783565b6040805160ff9092168252519081900360200190f35b610299610788565b6102f1610798565b6102996107a1565b61027d6004803603604081101561033557600080fd5b506001600160a01b0381351690602001356107b1565b61027d6004803603604081101561036157600080fd5b506001600160a01b0381351690602001356107ed565b61039d6004803603602081101561038d57600080fd5b50356001600160a01b0316610a42565b604080516001600160a01b039092168252519081900360200190f35b6103df600480360360208110156103cf57600080fd5b50356001600160a01b0316610a5d565b005b610407600480360360208110156103f757600080fd5b50356001600160a01b0316610a6a565b6040805163ffffffff9092168252519081900360200190f35b6102996004803603602081101561043657600080fd5b50356001600160a01b0316610a82565b6102996004803603604081101561045c57600080fd5b506001600160a01b038135169060200135610a9d565b6102996004803603602081101561048857600080fd5b50356001600160a01b0316610ca5565b61039d610cb7565b6101dc610ccf565b6103df600480360360208110156104be57600080fd5b50356001600160a01b0316610d30565b6103df610d4b565b61027d600480360360408110156104ec57600080fd5b506001600160a01b038135169060200135610d56565b61027d6004803603604081101561051857600080fd5b506001600160a01b038135169060200135610d92565b61027d6004803603602081101561054457600080fd5b50356001600160a01b0316610dd0565b6102996004803603602081101561056a57600080fd5b50356001600160a01b0316610de3565b6103df600480360360c081101561059057600080fd5b506001600160a01b038135169060208101359060408101359060ff6060820135169060808101359060a00135610e47565b610299600480360360408110156105d757600080fd5b506001600160a01b03813581169160200135166110bd565b6102996110e8565b6106296004803603604081101561060d57600080fd5b5080356001600160a01b0316906020013563ffffffff16611103565b6040805163ffffffff909316835260208301919091528051918290030190f35b60068054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106d55780601f106106aa576101008083540402835291602001916106d5565b820191906000526020600020905b8154815290600101906020018083116106b857829003601f168201915b5050505050905090565b60006106ec338484611130565b5060015b92915050565b60025490565b60405180604361192982396043019050604051809103902081565b60006107248484846111b8565b61074884336107438561073789336110bd565b9063ffffffff61128316565b611130565b33600090815260096020526040808220546001600160a01b0386811684529190922054610779928216911684611298565b5060019392505050565b601281565b6b45973f00c8e87ed73560000081565b60085460ff1690565b6bde9cf95c90fa9269d684000081565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916106ec918590610743908663ffffffff6113e616565b60048054604080516370a0823160e01b815233938101939093525160009284926001600160a01b0316916370a0823191602480820192602092909190829003018186803b15801561083d57600080fd5b505afa158015610851573d6000803e3d6000fd5b505050506040513d602081101561086757600080fd5b505110156108bc576040805162461bcd60e51b815260206004820152601c60248201527f4d696e74204261736520546f6b656e20496e73756666696369656e7400000000604482015290519081900360640190fd5b6005546108e86108d4846103e863ffffffff6113f816565b6108dc6106f6565b9063ffffffff6113e616565b1061093a576040805162461bcd60e51b815260206004820152601760248201527f4d696e74206c696d69746564206d617820737570706c79000000000000000000604482015290519081900360640190fd5b60048054604080516323b872dd60e01b8152339381019390935230602484015260448301859052516001600160a01b03909116916323b872dd9160648083019260209291908290030181600087803b15801561099557600080fd5b505af11580156109a9573d6000803e3d6000fd5b505050506040513d60208110156109bf57600080fd5b50506004805460408051630852cd8d60e31b8152928301859052516001600160a01b03909116916342966c6891602480830192600092919082900301818387803b158015610a0c57600080fd5b505af1158015610a20573d6000803e3d6000fd5b505050506106ec83610a3d6103e8856113f890919063ffffffff16565b61141f565b6009602052600090815260409020546001600160a01b031681565b610a6733826114c7565b50565b600b6020526000908152604090205463ffffffff1681565b6001600160a01b031660009081526020819052604090205490565b6000438210610add5760405162461bcd60e51b815260040180806020018281038252602681526020018061196c6026913960400191505060405180910390fd5b6001600160a01b0383166000908152600b602052604090205463ffffffff1680610b0b5760009150506106f0565b6001600160a01b0384166000908152600a6020908152604080832063ffffffff600019860181168552925290912054168310610b7a576001600160a01b0384166000908152600a602090815260408083206000199490940163ffffffff168352929052206001015490506106f0565b6001600160a01b0384166000908152600a6020908152604080832083805290915290205463ffffffff16831015610bb55760009150506106f0565b600060001982015b8163ffffffff168163ffffffff161115610c6e57600282820363ffffffff16048103610be76118b9565b506001600160a01b0387166000908152600a6020908152604080832063ffffffff808616855290835292819020815180830190925280549093168082526001909301549181019190915290871415610c49576020015194506106f09350505050565b805163ffffffff16871115610c6057819350610c67565b6001820392505b5050610bbd565b506001600160a01b0385166000908152600a6020908152604080832063ffffffff9094168352929052206001015491505092915050565b600c6020526000908152604090205481565b7341c37a4683d6a05adb31c39d71348a8403b13ca981565b60078054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106d55780601f106106aa576101008083540402835291602001916106d5565b610d3933610dd0565b610d4257600080fd5b610a678161155c565b610d54336115a4565b565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916106ec918590610743908663ffffffff61128316565b6000610d9f3384846111b8565b33600090815260096020526040808220546001600160a01b03868116845291909220546106ec928216911684611298565b60006106f060038363ffffffff6115ec16565b6001600160a01b0381166000908152600b602052604081205463ffffffff1680610e0e576000610e40565b6001600160a01b0383166000908152600a6020908152604080832063ffffffff60001986011684529091529020600101545b9392505050565b600060405180806119296043913960430190506040518091039020610e6a610649565b80519060200120610e79611621565b3060405160200180858152602001848152602001838152602001826001600160a01b03166001600160a01b03168152602001945050505050604051602081830303815290604052805190602001209050600060405180806119b7603a91396040805191829003603a0182206020808401919091526001600160a01b038c1683830152606083018b905260808084018b90528251808503909101815260a08401835280519082012061190160f01b60c085015260c2840187905260e2808501829052835180860390910181526101028501808552815191840191909120600091829052610122860180865281905260ff8c1661014287015261016286018b905261018286018a9052935191965092945091926001926101a28083019392601f198301929081900390910190855afa158015610fb7573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166110095760405162461bcd60e51b81526004018080602001828103825260258152602001806119046025913960400191505060405180910390fd5b6001600160a01b0381166000908152600c6020526040902080546001810190915589146110675760405162461bcd60e51b81526004018080602001828103825260218152602001806119f16021913960400191505060405180910390fd5b874211156110a65760405162461bcd60e51b81526004018080602001828103825260258152602001806119926025913960400191505060405180910390fd5b6110b0818b6114c7565b505050505b505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60405180603a6119b78239603a019050604051809103902081565b600a6020908152600092835260408084209091529082529020805460019091015463ffffffff9091169082565b6001600160a01b03821661114357600080fd5b6001600160a01b03831661115657600080fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0382166111cb57600080fd5b6001600160a01b0383166000908152602081905260409020546111f4908263ffffffff61128316565b6001600160a01b038085166000908152602081905260408082209390935590841681522054611229908263ffffffff6113e616565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008282111561129257600080fd5b50900390565b816001600160a01b0316836001600160a01b0316141580156112ba5750600081115b156113e1576001600160a01b03831615611352576001600160a01b0383166000908152600b602052604081205463ffffffff1690816112fa57600061132c565b6001600160a01b0385166000908152600a6020908152604080832063ffffffff60001987011684529091529020600101545b90506000611340828563ffffffff61128316565b905061134e86848484611625565b5050505b6001600160a01b038216156113e1576001600160a01b0382166000908152600b602052604081205463ffffffff16908161138d5760006113bf565b6001600160a01b0384166000908152600a6020908152604080832063ffffffff60001987011684529091529020600101545b905060006113d3828563ffffffff6113e616565b90506110b585848484611625565b505050565b600082820183811015610e4057600080fd5b600082611407575060006106f0565b8282028284828161141457fe5b0414610e4057600080fd5b6001600160a01b03821661143257600080fd5b600254611445908263ffffffff6113e616565b6002556001600160a01b038216600090815260208190526040902054611471908263ffffffff6113e616565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b03808316600090815260096020526040812054909116906114ee84610a82565b6001600160a01b0385811660008181526009602052604080822080546001600160a01b031916898616908117909155905194955093928616927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a4611556828483611298565b50505050565b61156d60038263ffffffff61178a16565b6040516001600160a01b038216907f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f690600090a250565b6115b560038263ffffffff6117d616565b6040516001600160a01b038216907fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669290600090a250565b60006001600160a01b03821661160157600080fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b4690565b6000611649436040518060600160405280603381526020016118d16033913961181e565b905060008463ffffffff1611801561169257506001600160a01b0385166000908152600a6020908152604080832063ffffffff6000198901811685529252909120548282169116145b156116cf576001600160a01b0385166000908152600a6020908152604080832063ffffffff60001989011684529091529020600101829055611740565b60408051808201825263ffffffff808416825260208083018681526001600160a01b038a166000818152600a84528681208b8616825284528681209551865490861663ffffffff199182161787559251600196870155908152600b9092529390208054928801909116919092161790555b604080518481526020810184905281516001600160a01b038816927fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724928290030190a25050505050565b6001600160a01b03811661179d57600080fd5b6117a782826115ec565b156117b157600080fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b6001600160a01b0381166117e957600080fd5b6117f382826115ec565b6117fc57600080fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b60008164010000000084106118b15760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561187657818101518382015260200161185e565b50505050905090810190601f1680156118a35780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509192915050565b60408051808201909152600080825260208201529056fe58636e3a3a5f7772697465436865636b706f696e743a20626c6f636b206e756d6265722065786365656473203332206269747358636e3a3a64656c656761746542795369673a20696e76616c6964207369676e6174757265454950373132446f6d61696e28737472696e67206e616d652c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e74726163742958636e3a3a6765745072696f72566f7465733a206e6f74207965742064657465726d696e656458636e3a3a64656c656761746542795369673a207369676e6174757265206578706972656444656c65676174696f6e28616464726573732064656c6567617465652c75696e74323536206e6f6e63652c75696e74323536206578706972792958636e3a3a64656c656761746542795369673a20696e76616c6964206e6f6e6365a265627a7a72315820785d674bad5af3e332f4d46ffd3287330c425b188408647655b04b6ef1ce6e5c64736f6c63430005100032
Verified Source Code Partial Match
Compiler: v0.5.16+commit.9c3226ce
EVM: istanbul
Optimization: Yes (200 runs)
Chain.sol 663 lines
pragma solidity 0.5.16;
/**
* @title Roles
* @dev Library for managing addresses assigned to a Role.
*/
library Roles {
struct Role {
mapping (address => bool) bearer;
}
/**
* @dev give an account access to this role
*/
function add(Role storage role, address account) internal {
require(account != address(0));
require(!has(role, account));
role.bearer[account] = true;
}
/**
* @dev remove an account's access to this role
*/
function remove(Role storage role, address account) internal {
require(account != address(0));
require(has(role, account));
role.bearer[account] = false;
}
/**
* @dev check if an account has this role
* @return bool
*/
function has(Role storage role, address account) internal view returns (bool) {
require(account != address(0));
return role.bearer[account];
}
}
contract MinterRole {
using Roles for Roles.Role;
event MinterAdded(address indexed account);
event MinterRemoved(address indexed account);
Roles.Role private _minters;
constructor () internal {
_addMinter(msg.sender);
}
modifier onlyMinter() {
require(isMinter(msg.sender));
_;
}
function isMinter(address account) public view returns (bool) {
return _minters.has(account);
}
function addMinter(address account) public onlyMinter {
_addMinter(account);
}
function renounceMinter() public {
_removeMinter(msg.sender);
}
function _addMinter(address account) internal {
_minters.add(account);
emit MinterAdded(account);
}
function _removeMinter(address account) internal {
_minters.remove(account);
emit MinterRemoved(account);
}
}
/**
* @title SafeMath
* @dev Unsigned math operations with safety checks that revert on error
*/
library SafeMath {
/**
* @dev Multiplies two unsigned integers, reverts on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two unsigned integers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
* reverts when dividing by zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
/**
* @title SafeMath96
* @dev Unsigned math operations with safety checks that revert on error with 96 bit unsiged integer
*/
library SafeMath96 {
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
require(n < 2**32, errorMessage);
return uint32(n);
}
function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {
require(n < 2**96, errorMessage);
return uint96(n);
}
function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {
uint96 c = a + b;
require(c >= a, errorMessage);
return c;
}
function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @title ERC20 interface
* @dev see https://eips.ethereum.org/EIPS/eip-20
*/
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
/**
* @title CHN interface
* @dev see https://github.com/chain/chain-token/blob/main/ChainToken.sol
*/
interface CHNInterface {
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function burn(uint256 _value) external;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
event Burn(address indexed burner, uint256 value);
}
/**
* @title Standard ERC20 token
*
* @dev Implementation of the basic standard token.
* https://eips.ethereum.org/EIPS/eip-20
* Originally based on code by FirstBlood:
* https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
*
* This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for
* all accounts just by listening to said events. Note that this isn't required by the specification, and other
* compliant implementations may not do it.
*/
contract ERC20 is IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowed;
uint256 private _totalSupply;
/**
* @dev Total number of tokens in existence
*/
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
/**
* @dev Gets the balance of the specified address.
* @param owner The address to query the balance of.
* @return An uint256 representing the amount owned by the passed address.
*/
function balanceOf(address owner) public view returns (uint256) {
return _balances[owner];
}
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
* @param owner address The address which owns the funds.
* @param spender address The address which will spend the funds.
* @return A uint256 specifying the amount of tokens still available for the spender.
*/
function allowance(address owner, address spender) public view returns (uint256) {
return _allowed[owner][spender];
}
/**
* @dev Transfer token to a specified address
* @param to The address to transfer to.
* @param value The amount to be transferred.
*/
function transfer(address to, uint256 value) public returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
* Beware that changing an allowance with this method brings the risk that someone may use both the old
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
*/
function approve(address spender, uint256 value) public returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
/**
* @dev Transfer tokens from one address to another.
* Note that while this function emits an Approval event, this is not required as per the specification,
* and other compliant implementations may not emit the event.
* @param from address The address which you want to send tokens from
* @param to address The address which you want to transfer to
* @param value uint256 the amount of tokens to be transferred
*/
function transferFrom(address from, address to, uint256 value) public returns (bool) {
_transfer(from, to, value);
_approve(from, msg.sender, _allowed[from][msg.sender].sub(value));
return true;
}
/**
* @dev Increase the amount of tokens that an owner allowed to a spender.
* approve should be called when _allowed[msg.sender][spender] == 0. To increment
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* Emits an Approval event.
* @param spender The address which will spend the funds.
* @param addedValue The amount of tokens to increase the allowance by.
*/
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue));
return true;
}
/**
* @dev Decrease the amount of tokens that an owner allowed to a spender.
* approve should be called when _allowed[msg.sender][spender] == 0. To decrement
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* Emits an Approval event.
* @param spender The address which will spend the funds.
* @param subtractedValue The amount of tokens to decrease the allowance by.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue));
return true;
}
/**
* @dev Transfer token for a specified addresses
* @param from The address to transfer from.
* @param to The address to transfer to.
* @param value The amount to be transferred.
*/
function _transfer(address from, address to, uint256 value) internal {
require(to != address(0));
_balances[from] = _balances[from].sub(value);
_balances[to] = _balances[to].add(value);
emit Transfer(from, to, value);
}
/**
* @dev Internal function that mints an amount of the token and assigns it to
* an account. This encapsulates the modification of balances such that the
* proper events are emitted.
* @param account The account that will receive the created tokens.
* @param value The amount that will be created.
*/
function _mint(address account, uint256 value) internal {
require(account != address(0));
_totalSupply = _totalSupply.add(value);
_balances[account] = _balances[account].add(value);
emit Transfer(address(0), account, value);
}
/**
* @dev Internal function that burns an amount of the token of a given
* account.
* @param account The account whose tokens will be burnt.
* @param value The amount that will be burnt.
*/
function _burn(address account, uint256 value) internal {
require(account != address(0));
_totalSupply = _totalSupply.sub(value);
_balances[account] = _balances[account].sub(value);
emit Transfer(account, address(0), value);
}
/**
* @dev Approve an address to spend another addresses' tokens.
* @param owner The address that owns the tokens.
* @param spender The address that will spend the tokens.
* @param value The number of tokens that can be spent.
*/
function _approve(address owner, address spender, uint256 value) internal {
require(spender != address(0));
require(owner != address(0));
_allowed[owner][spender] = value;
emit Approval(owner, spender, value);
}
/**
* @dev Internal function that burns an amount of the token of a given
* account, deducting from the sender's allowance for said account. Uses the
* internal burn function.
* Emits an Approval event (reflecting the reduced allowance).
* @param account The account whose tokens will be burnt.
* @param value The amount that will be burnt.
*/
function _burnFrom(address account, uint256 value) internal {
_burn(account, value);
_approve(account, msg.sender, _allowed[account][msg.sender].sub(value));
}
}
/**
* @title ERC20Mintable
* @dev ERC20 minting logic
*/
contract ERC20Mintable is ERC20, MinterRole {
address private MINT_BASE_TOKEN;
uint256 private MAX_SUPPLY_AMOUNT;
constructor (address mintBaseToken, uint256 MAX_SUPPLY) public {
MINT_BASE_TOKEN = mintBaseToken;
MAX_SUPPLY_AMOUNT = MAX_SUPPLY;
}
/**
* @dev Function to mint tokens
* @param to The address that will receive the minted tokens.
* @param value The amount of tokens to mint.
* @return A boolean that indicates if the operation was successful.
*/
function mint(address to, uint256 value) public returns (bool) {
require(CHNInterface(MINT_BASE_TOKEN).balanceOf(msg.sender) >= value, "Mint Base Token Insufficient");
require(totalSupply().add(value.mul(1000)) < MAX_SUPPLY_AMOUNT, "Mint limited max supply");
IERC20(MINT_BASE_TOKEN).transferFrom(msg.sender, address(this), value);
CHNInterface(MINT_BASE_TOKEN).burn(value);
_mint(to, value.mul(1000));
return true;
}
}
/**
* @title ERC20Detailed token
* @dev The decimals are only for visualization purposes.
* All the operations are done using the smallest and indivisible token unit,
* just as on Ethereum all the operations are done in wei.
*/
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;
}
/**
* @return the name of the token.
*/
function name() public view returns (string memory) {
return _name;
}
/**
* @return the symbol of the token.
*/
function symbol() public view returns (string memory) {
return _symbol;
}
/**
* @return the number of decimals of the token.
*/
function decimals() public view returns (uint8) {
return _decimals;
}
}
contract Chain is ERC20Mintable, ERC20Detailed {
using SafeMath96 for uint96;
uint8 public constant DECIMALS = 18;
uint256 public constant INITIAL_SUPPLY = 21537311000 * (10 ** uint256(DECIMALS));
uint256 public constant MAX_SUPPLY = 68895442185 * (10 ** uint256(DECIMALS));
address public constant MINT_BASE = 0x41C37A4683d6a05adB31c39D71348A8403B13Ca9;
/// @notice A record of each accounts delegate
mapping (address => address) public delegates;
/// @notice A checkpoint for marking number of votes from a given block
struct Checkpoint {
uint32 fromBlock;
uint256 votes;
}
/// @notice A record of votes checkpoints for each account, by index
mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;
/// @notice The number of checkpoints for each account
mapping (address => uint32) public numCheckpoints;
/// @notice The EIP-712 typehash for the contract's domain
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
/// @notice The EIP-712 typehash for the delegation struct used by the contract
bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
/// @notice A record of states for signing / validating signatures
mapping (address => uint) public nonces;
/// @notice An event thats emitted when an account changes its delegate
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
/// @notice An event thats emitted when a delegate account's vote balance changes
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
/**
* @dev Constructor that gives msg.sender all of existing tokens.
*/
constructor () public ERC20Detailed("Chain", "XCN", DECIMALS) ERC20Mintable(MINT_BASE, MAX_SUPPLY) {
_mint(msg.sender, INITIAL_SUPPLY);
}
function transfer(address to, uint256 value) public returns (bool) {
_transfer(msg.sender, to, value);
_moveDelegates(delegates[msg.sender], delegates[to], value);
return true;
}
function transferFrom(address from, address to, uint256 value) public returns (bool) {
_transfer(from, to, value);
_approve(from, msg.sender, allowance(from, msg.sender).sub(value));
_moveDelegates(delegates[msg.sender], delegates[to], value);
return true;
}
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegatee The address to delegate votes to
*/
function delegate(address delegatee) public {
return _delegate(msg.sender, delegatee);
}
/**
* @notice Delegates votes from signatory to `delegatee`
* @param delegatee The address to delegate votes to
* @param nonce The contract state required to match the signature
* @param expiry The time at which to expire the signature
* @param v The recovery byte of the signature
* @param r Half of the ECDSA signature pair
* @param s Half of the ECDSA signature pair
*/
function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {
bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name())), getChainId(), address(this)));
bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));
bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
address signatory = ecrecover(digest, v, r, s);
require(signatory != address(0), "Xcn::delegateBySig: invalid signature");
require(nonce == nonces[signatory]++, "Xcn::delegateBySig: invalid nonce");
require(now <= expiry, "Xcn::delegateBySig: signature expired");
return _delegate(signatory, delegatee);
}
/**
* @notice Gets the current votes balance for `account`
* @param account The address to get votes balance
* @return The number of current votes for `account`
*/
function getCurrentVotes(address account) external view returns (uint256) {
uint32 nCheckpoints = numCheckpoints[account];
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
}
/**
* @notice Determine the prior number of votes for an account as of a block number
* @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
* @param account The address of the account to check
* @param blockNumber The block number to get the vote balance at
* @return The number of votes the account had as of the given block
*/
function getPriorVotes(address account, uint blockNumber) public view returns (uint256) {
require(blockNumber < block.number, "Xcn::getPriorVotes: not yet determined");
uint32 nCheckpoints = numCheckpoints[account];
if (nCheckpoints == 0) {
return 0;
}
// First check most recent balance
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
return checkpoints[account][nCheckpoints - 1].votes;
}
// Next check implicit zero balance
if (checkpoints[account][0].fromBlock > blockNumber) {
return 0;
}
uint32 lower = 0;
uint32 upper = nCheckpoints - 1;
while (upper > lower) {
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
Checkpoint memory cp = checkpoints[account][center];
if (cp.fromBlock == blockNumber) {
return cp.votes;
} else if (cp.fromBlock < blockNumber) {
lower = center;
} else {
upper = center - 1;
}
}
return checkpoints[account][lower].votes;
}
function _delegate(address delegator, address delegatee) internal {
address currentDelegate = delegates[delegator];
uint256 delegatorBalance = balanceOf(delegator);
delegates[delegator] = delegatee;
emit DelegateChanged(delegator, currentDelegate, delegatee);
_moveDelegates(currentDelegate, delegatee, delegatorBalance);
}
function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal {
if (srcRep != dstRep && amount > 0) {
if (srcRep != address(0)) {
uint32 srcRepNum = numCheckpoints[srcRep];
uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
uint256 srcRepNew = srcRepOld.sub(amount);
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
}
if (dstRep != address(0)) {
uint32 dstRepNum = numCheckpoints[dstRep];
uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
uint256 dstRepNew = dstRepOld.add(amount);
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
}
}
}
function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint256 oldVotes, uint256 newVotes) internal {
uint32 blockNumber = safe32(block.number, "Xcn::_writeCheckpoint: block number exceeds 32 bits");
if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
} else {
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
numCheckpoints[delegatee] = nCheckpoints + 1;
}
emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
}
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
require(n < 2**32, errorMessage);
return uint32(n);
}
function getChainId() internal pure returns (uint) {
uint256 chainId;
assembly { chainId := chainid() }
return chainId;
}
}
Read Contract
DECIMALS 0x2e0f2625 → uint8
DELEGATION_TYPEHASH 0xe7a324dc → bytes32
DOMAIN_TYPEHASH 0x20606b70 → bytes32
INITIAL_SUPPLY 0x2ff2e9dc → uint256
MAX_SUPPLY 0x32cb6b0c → uint256
MINT_BASE 0x81ea3cc7 → address
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
checkpoints 0xf1127ed8 → uint32, uint256
decimals 0x313ce567 → uint8
delegates 0x587cde1e → address
getCurrentVotes 0xb4b5ea57 → uint256
getPriorVotes 0x782d6fe1 → uint256
isMinter 0xaa271e1a → bool
name 0x06fdde03 → string
nonces 0x7ecebe00 → uint256
numCheckpoints 0x6fcfff45 → uint32
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256
Write Contract 10 functions
These functions modify contract state and require a wallet transaction to execute.
addMinter 0x983b2d56
address account
approve 0x095ea7b3
address spender
uint256 value
returns: bool
decreaseAllowance 0xa457c2d7
address spender
uint256 subtractedValue
returns: bool
delegate 0x5c19a95c
address delegatee
delegateBySig 0xc3cda520
address delegatee
uint256 nonce
uint256 expiry
uint8 v
bytes32 r
bytes32 s
increaseAllowance 0x39509351
address spender
uint256 addedValue
returns: bool
mint 0x40c10f19
address to
uint256 value
returns: bool
renounceMinter 0x98650275
No parameters
transfer 0xa9059cbb
address to
uint256 value
returns: bool
transferFrom 0x23b872dd
address from
address to
uint256 value
returns: bool
Top Interactions
| Address | Txns | Sent | Received |
|---|---|---|---|
| 0x1C727a55...de5d | 1 | 1 |
Token Balances (1)
View Transfers →Recent Transactions
|
| Hash | Block | Age | From/To | Value | |
|---|---|---|---|---|---|
| 0x55b855b8...98483f | 24,586,740 | IN | 0x1C727a55...de5d | 0 ETH |