Transaction Hash:
Block:
12379853 at May-06-2021 09:15:03 AM +UTC
Transaction Fee:
0.01580625051247375 ETH
$29.04
Gas Used:
351,250 Gas / 45.000001459 Gwei
Emitted Events:
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x2A0eEe94...f753EA0f6
Miner
| 33.121775634910529584 Eth | 33.137581885423003334 Eth | 0.01580625051247375 | ||
0x2be5e8c1...a9b3433C5 | |||||
0x565865C1...867204B1a | |||||
0x56E465f6...7195CEe43 | |||||
0x6FC20Ca2...525f7AeEf | |||||
0xc4A11aaf...84F15bff2 | |||||
0xd86d8950...CE249E1CF | |||||
0xFfdcabff...CB68670E8 |
1.01152629 Eth
Nonce: 368
|
0.99572003948752625 Eth
Nonce: 369
| 0.01580625051247375 |
Execution Trace
TON.approveAndCall( spender=0xc4A11aaf6ea915Ed7Ac194161d2fC9384F15bff2, amount=6053156211600000000000, data=0x00000000000000000000000056E465F654393FA48F007ED7346105C7195CEE43000000000000000000000000BC8896EBB2E3939B1849298EF8DA59E09946CF66 ) => ( True )

-
WTON.supportsInterface( interfaceId=System.Byte[] ) => ( True )
-
WTON.supportsInterface( interfaceId=System.Byte[] ) => ( False )
-
WTON.supportsInterface( interfaceId=System.Byte[] ) => ( True )
WTON.onApprove( owner=0xFfdcabffB9EC425FD0B469eF626c844CB68670E8, spender=0xc4A11aaf6ea915Ed7Ac194161d2fC9384F15bff2, tonAmount=6053156211600000000000, data=0x00000000000000000000000056E465F654393FA48F007ED7346105C7195CEE43000000000000000000000000BC8896EBB2E3939B1849298EF8DA59E09946CF66 ) => ( True )
-
TON.transferFrom( sender=0xFfdcabffB9EC425FD0B469eF626c844CB68670E8, recipient=0xc4A11aaf6ea915Ed7Ac194161d2fC9384F15bff2, amount=6053156211600000000000 ) => ( True )
-
DepositManager.supportsInterface( interfaceId=System.Byte[] ) => ( True )
-
DepositManager.supportsInterface( interfaceId=System.Byte[] ) => ( False )
-
DepositManager.supportsInterface( interfaceId=System.Byte[] ) => ( True )
DepositManager.onApprove( owner=0xFfdcabffB9EC425FD0B469eF626c844CB68670E8, spender=0x56E465f654393fa48f007Ed7346105c7195CEe43, amount=6053156211600000000000000000000, data=0x000000000000000000000000BC8896EBB2E3939B1849298EF8DA59E09946CF66 ) => ( True )
-
Layer2Registry.layer2s( layer2=0xBC8896Ebb2E3939B1849298Ef8da59E09946cF66 ) => ( True )
-
WTON.transferFrom( sender=0xFfdcabffB9EC425FD0B469eF626c844CB68670E8, recipient=0x56E465f654393fa48f007Ed7346105c7195CEe43, amount=6053156211600000000000000000000 ) => ( True )
SeigManager.onDeposit( layer2=0xBC8896Ebb2E3939B1849298Ef8da59E09946cF66, account=0xFfdcabffB9EC425FD0B469eF626c844CB68670E8, amount=6053156211600000000000000000000 ) => ( True )
-
0xbc8896ebb2e3939b1849298ef8da59e09946cf66.STATICCALL( )
-
AutoRefactorCoinage.mint( account=0xBC8896Ebb2E3939B1849298Ef8da59E09946cF66, amount=6053156211600000000000000000000 ) => ( True )
-
AutoRefactorCoinage.mint( account=0xFfdcabffB9EC425FD0B469eF626c844CB68670E8, amount=6053156211600000000000000000000 ) => ( True )
-
PowerTON.onDeposit( layer2=0xBC8896Ebb2E3939B1849298Ef8da59E09946cF66, account=0xFfdcabffB9EC425FD0B469eF626c844CB68670E8, amount=6053156211600000000000000000000 )
-
-
-
approveAndCall[ERC20OnApprove (ln:991)]
approve[ERC20OnApprove (ln:992)]
_callOnApprove[ERC20OnApprove (ln:993)]
_supportsInterface[ERC20OnApprove (ln:1000)]
_supportsERC165[ERC165Checker (ln:785)]
_supportsERC165Interface[ERC165Checker (ln:773)]
_callERC165SupportsInterface[ERC165Checker (ln:829)]
encodeWithSelector[ERC165Checker (ln:847)]
gas[ERC165Checker (ln:848)]
decode[ERC165Checker (ln:850)]
_supportsERC165Interface[ERC165Checker (ln:774)]
_callERC165SupportsInterface[ERC165Checker (ln:829)]
encodeWithSelector[ERC165Checker (ln:847)]
gas[ERC165Checker (ln:848)]
decode[ERC165Checker (ln:850)]
_supportsERC165Interface[ERC165Checker (ln:786)]
_callERC165SupportsInterface[ERC165Checker (ln:829)]
encodeWithSelector[ERC165Checker (ln:847)]
gas[ERC165Checker (ln:848)]
decode[ERC165Checker (ln:850)]
call[ERC20OnApprove (ln:1003)]
encodeWithSelector[ERC20OnApprove (ln:1004)]
File 1 of 8: TON
File 2 of 8: WTON
File 3 of 8: DepositManager
File 4 of 8: AutoRefactorCoinage
File 5 of 8: AutoRefactorCoinage
File 6 of 8: PowerTON
File 7 of 8: Layer2Registry
File 8 of 8: SeigManager
// File: openzeppelin-solidity/contracts/GSN/Context.sol pragma solidity ^0.5.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: openzeppelin-solidity/contracts/ownership/Ownable.sol pragma solidity ^0.5.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: 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 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: openzeppelin-solidity/contracts/math/SafeMath.sol pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot 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-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol pragma solidity ^0.5.0; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20Mintable}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for `sender`'s tokens of at least * `amount`. */ 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; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ 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); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ 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); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ 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); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ 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); } /** * @dev Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); } } // File: openzeppelin-solidity/contracts/access/Roles.sol pragma solidity ^0.5.0; /** * @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(!has(role, account), "Roles: account already has role"); role.bearer[account] = true; } /** * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { require(has(role, account), "Roles: account does not have role"); 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), "Roles: account is the zero address"); return role.bearer[account]; } } // File: openzeppelin-solidity/contracts/access/roles/MinterRole.sol pragma solidity ^0.5.0; 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); } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol pragma solidity ^0.5.0; /** * @dev Extension of {ERC20} that adds a set of accounts with the {MinterRole}, * which have permission to mint (create) new tokens as they see fit. * * At construction, the deployer of the contract is the only minter. */ contract ERC20Mintable is ERC20, MinterRole { /** * @dev See {ERC20-_mint}. * * Requirements: * * - the caller must have the {MinterRole}. */ function mint(address account, uint256 amount) public onlyMinter returns (bool) { _mint(account, amount); return true; } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol pragma solidity ^0.5.0; /** * @dev Optional functions from the ERC20 standard. */ contract ERC20Detailed is IERC20 { string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of * these values are immutable: they can only be set once during * construction. */ constructor (string memory name, string memory symbol, uint8 decimals) public { _name = name; _symbol = symbol; _decimals = decimals; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } } // File: openzeppelin-solidity/contracts/introspection/ERC165Checker.sol pragma solidity ^0.5.10; /** * @dev Library used to query support of an interface declared via {IERC165}. * * Note that these functions return the actual result of the query: they do not * `revert` if an interface is not supported. It is up to the caller to decide * what to do in these cases. */ library ERC165Checker { // As per the EIP-165 spec, no interface should ever match 0xffffffff bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff; /* * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 */ bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * @dev Returns true if `account` supports the {IERC165} interface, */ function _supportsERC165(address account) internal view returns (bool) { // Any contract that implements ERC165 must explicitly indicate support of // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) && !_supportsERC165Interface(account, _INTERFACE_ID_INVALID); } /** * @dev Returns true if `account` supports the interface defined by * `interfaceId`. Support for {IERC165} itself is queried automatically. * * See {IERC165-supportsInterface}. */ function _supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { // query support of both ERC165 as per the spec and support of _interfaceId return _supportsERC165(account) && _supportsERC165Interface(account, interfaceId); } /** * @dev Returns true if `account` supports all the interfaces defined in * `interfaceIds`. Support for {IERC165} itself is queried automatically. * * Batch-querying can lead to gas savings by skipping repeated checks for * {IERC165} support. * * See {IERC165-supportsInterface}. */ function _supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { // query support of ERC165 itself if (!_supportsERC165(account)) { return false; } // query support of each interface in _interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { if (!_supportsERC165Interface(account, interfaceIds[i])) { return false; } } // all interfaces supported return true; } /** * @notice Query if a contract implements an interface, does not check ERC165 support * @param account The address of the contract to query for support of an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @return true if the contract at account indicates support of the interface with * identifier interfaceId, false otherwise * @dev Assumes that account contains a contract that supports ERC165, otherwise * the behavior of this method is undefined. This precondition can be checked * with the `supportsERC165` method in this library. * Interface identification is specified in ERC-165. */ function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) { // success determines whether the staticcall succeeded and result determines // whether the contract at account indicates support of _interfaceId (bool success, bool result) = _callERC165SupportsInterface(account, interfaceId); return (success && result); } /** * @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw * @param account The address of the contract to query for support of an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @return success true if the STATICCALL succeeded, false otherwise * @return result true if the STATICCALL succeeded and the contract at account * indicates support of the interface with identifier interfaceId, false otherwise */ function _callERC165SupportsInterface(address account, bytes4 interfaceId) private view returns (bool, bool) { bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId); (bool success, bytes memory result) = account.staticcall.gas(30000)(encodedParams); if (result.length < 32) return (false, false); return (success, abi.decode(result, (bool))); } } // File: contracts/stake/interfaces/SeigManagerI.sol pragma solidity ^0.5.12; interface SeigManagerI { function registry() external view returns (address); function depositManager() external view returns (address); function ton() external view returns (address); function wton() external view returns (address); function powerton() external view returns (address); function tot() external view returns (address); function coinages(address rootchain) external view returns (address); function commissionRates(address rootchain) external view returns (uint256); function lastCommitBlock(address rootchain) external view returns (uint256); function seigPerBlock() external view returns (uint256); function lastSeigBlock() external view returns (uint256); function pausedBlock() external view returns (uint256); function unpausedBlock() external view returns (uint256); function DEFAULT_FACTOR() external view returns (uint256); function deployCoinage(address rootchain) external returns (bool); function setCommissionRate(address rootchain, uint256 commission, bool isCommissionRateNegative) external returns (bool); function uncomittedStakeOf(address rootchain, address account) external view returns (uint256); function stakeOf(address rootchain, address account) external view returns (uint256); function additionalTotBurnAmount(address rootchain, address account, uint256 amount) external view returns (uint256 totAmount); function onTransfer(address sender, address recipient, uint256 amount) external returns (bool); function onCommit() external returns (bool); function onDeposit(address rootchain, address account, uint256 amount) external returns (bool); function onWithdraw(address rootchain, address account, uint256 amount) external returns (bool); } // File: openzeppelin-solidity/contracts/introspection/IERC165.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File: openzeppelin-solidity/contracts/introspection/ERC165.sol pragma solidity ^0.5.0; /** * @dev Implementation of the {IERC165} interface. * * Contracts may inherit from this and call {_registerInterface} to declare * their support of an interface. */ contract ERC165 is IERC165 { /* * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 */ bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * @dev Mapping of interface ids to whether or not it's supported. */ mapping(bytes4 => bool) private _supportedInterfaces; constructor () internal { // Derived contracts need only register support for their own interfaces, // we register support for ERC165 itself here _registerInterface(_INTERFACE_ID_ERC165); } /** * @dev See {IERC165-supportsInterface}. * * Time complexity O(1), guaranteed to always use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool) { return _supportedInterfaces[interfaceId]; } /** * @dev Registers the contract as an implementer of the interface defined by * `interfaceId`. Support of the actual ERC165 interface is automatic and * registering its interface id is not required. * * See {IERC165-supportsInterface}. * * Requirements: * * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). */ function _registerInterface(bytes4 interfaceId) internal { require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); _supportedInterfaces[interfaceId] = true; } } // File: contracts/stake/tokens/OnApprove.sol pragma solidity ^0.5.12; contract OnApprove is ERC165 { constructor() public { _registerInterface(OnApprove(this).onApprove.selector); } function onApprove(address owner, address spender, uint256 amount, bytes calldata data) external returns (bool); } // File: contracts/stake/tokens/ERC20OnApprove.sol pragma solidity ^0.5.12; contract ERC20OnApprove is ERC20 { function approveAndCall(address spender, uint256 amount, bytes memory data) public returns (bool) { require(approve(spender, amount)); _callOnApprove(msg.sender, spender, amount, data); return true; } function _callOnApprove(address owner, address spender, uint256 amount, bytes memory data) internal { bytes4 onApproveSelector = OnApprove(spender).onApprove.selector; require(ERC165Checker._supportsInterface(spender, onApproveSelector), "ERC20OnApprove: spender doesn't support onApprove"); (bool ok, bytes memory res) = spender.call( abi.encodeWithSelector( onApproveSelector, owner, spender, amount, data ) ); // check if low-level call reverted or not require(ok, string(res)); assembly { ok := mload(add(res, 0x20)) } // check if OnApprove.onApprove returns true or false require(ok, "ERC20OnApprove: failed to call onApprove"); } } // File: contracts/stake/tokens/AuthController.sol pragma solidity ^0.5.12; interface MinterRoleRenounceTarget { function renounceMinter() external; } interface PauserRoleRenounceTarget { function renouncePauser() external; } interface OwnableTarget { function renounceOwnership() external; function transferOwnership(address newOwner) external; } contract AuthController is Ownable { function renounceMinter(address target) public onlyOwner { MinterRoleRenounceTarget(target).renounceMinter(); } function renouncePauser(address target) public onlyOwner { PauserRoleRenounceTarget(target).renouncePauser(); } function renounceOwnership(address target) public onlyOwner { OwnableTarget(target).renounceOwnership(); } function transferOwnership(address target, address newOwner) public onlyOwner { OwnableTarget(target).transferOwnership(newOwner); } } // File: contracts/stake/tokens/SeigToken.sol pragma solidity ^0.5.12; contract SeigToken is ERC20, Ownable, ERC20OnApprove, AuthController { SeigManagerI public seigManager; bool public callbackEnabled; function enableCallback(bool _callbackEnabled) external onlyOwner { callbackEnabled = _callbackEnabled; } function setSeigManager(SeigManagerI _seigManager) external onlyOwner { seigManager = _seigManager; } ////////////////////// // Override ERC20 functions ////////////////////// function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { require(msg.sender == sender || msg.sender == recipient, "SeigToken: only sender or recipient can transfer"); return super.transferFrom(sender, recipient, amount); } function _transfer(address sender, address recipient, uint256 amount) internal { super._transfer(sender, recipient, amount); if (callbackEnabled && address(seigManager) != address(0)) { require(seigManager.onTransfer(sender, recipient, amount)); } } function _mint(address account, uint256 amount) internal { super._mint(account, amount); if (callbackEnabled && address(seigManager) != address(0)) { require(seigManager.onTransfer(address(0), account, amount)); } } function _burn(address account, uint256 amount) internal { super._burn(account, amount); if (callbackEnabled && address(seigManager) != address(0)) { require(seigManager.onTransfer(account, address(0), amount)); } } } // File: contracts/stake/tokens/TON.sol pragma solidity ^0.5.12; /** * @dev Current implementations is just for testing seigniorage manager. */ contract TON is Ownable, ERC20Mintable, ERC20Detailed, SeigToken { constructor() public ERC20Detailed("Tokamak Network Token", "TON", 18) {} function setSeigManager(SeigManagerI _seigManager) external { revert("TON: TON doesn't allow setSeigManager"); } }
File 2 of 8: WTON
// File: openzeppelin-solidity/contracts/GSN/Context.sol pragma solidity ^0.5.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: openzeppelin-solidity/contracts/ownership/Ownable.sol pragma solidity ^0.5.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: openzeppelin-solidity/contracts/math/SafeMath.sol pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot 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-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: 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 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol pragma solidity ^0.5.0; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20Mintable}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for `sender`'s tokens of at least * `amount`. */ 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; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ 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); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ 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); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ 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); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ 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); } /** * @dev Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); } } // File: openzeppelin-solidity/contracts/access/Roles.sol pragma solidity ^0.5.0; /** * @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(!has(role, account), "Roles: account already has role"); role.bearer[account] = true; } /** * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { require(has(role, account), "Roles: account does not have role"); 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), "Roles: account is the zero address"); return role.bearer[account]; } } // File: openzeppelin-solidity/contracts/access/roles/MinterRole.sol pragma solidity ^0.5.0; 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); } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol pragma solidity ^0.5.0; /** * @dev Extension of {ERC20} that adds a set of accounts with the {MinterRole}, * which have permission to mint (create) new tokens as they see fit. * * At construction, the deployer of the contract is the only minter. */ contract ERC20Mintable is ERC20, MinterRole { /** * @dev See {ERC20-_mint}. * * Requirements: * * - the caller must have the {MinterRole}. */ function mint(address account, uint256 amount) public onlyMinter returns (bool) { _mint(account, amount); return true; } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol pragma solidity ^0.5.0; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ contract ERC20Burnable is Context, ERC20 { /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 amount) public { _burn(_msgSender(), amount); } /** * @dev See {ERC20-_burnFrom}. */ function burnFrom(address account, uint256 amount) public { _burnFrom(account, amount); } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol pragma solidity ^0.5.0; /** * @dev Optional functions from the ERC20 standard. */ contract ERC20Detailed is IERC20 { string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of * these values are immutable: they can only be set once during * construction. */ constructor (string memory name, string memory symbol, uint8 decimals) public { _name = name; _symbol = symbol; _decimals = decimals; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } } // File: openzeppelin-solidity/contracts/utils/Address.sol pragma solidity ^0.5.5; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Converts an `address` into `address payable`. Note that this is * simply a type cast: the actual underlying value is not changed. * * _Available since v2.4.0._ */ function toPayable(address account) internal pure returns (address payable) { return address(uint160(account)); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. * * _Available since v2.4.0._ */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-call-value (bool success, ) = recipient.call.value(amount)(""); require(success, "Address: unable to send value, recipient may have reverted"); } } // File: openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol pragma solidity ^0.5.0; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol pragma solidity ^0.5.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. * * _Since v2.5.0:_ this module is now much more gas efficient, given net gas * metering changes introduced in the Istanbul hardfork. */ contract ReentrancyGuard { bool private _notEntered; constructor () internal { // Storing an initial non-zero value makes deployment a bit more // expensive, but in exchange the refund on every call to nonReentrant // will be lower in amount. Since refunds are capped to a percetange of // the total transaction's gas, it is best to keep them low in cases // like this one, to increase the likelihood of the full refund coming // into effect. _notEntered = true; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_notEntered, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _notEntered = false; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _notEntered = true; } } // File: openzeppelin-solidity/contracts/introspection/IERC165.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File: openzeppelin-solidity/contracts/introspection/ERC165.sol pragma solidity ^0.5.0; /** * @dev Implementation of the {IERC165} interface. * * Contracts may inherit from this and call {_registerInterface} to declare * their support of an interface. */ contract ERC165 is IERC165 { /* * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 */ bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * @dev Mapping of interface ids to whether or not it's supported. */ mapping(bytes4 => bool) private _supportedInterfaces; constructor () internal { // Derived contracts need only register support for their own interfaces, // we register support for ERC165 itself here _registerInterface(_INTERFACE_ID_ERC165); } /** * @dev See {IERC165-supportsInterface}. * * Time complexity O(1), guaranteed to always use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool) { return _supportedInterfaces[interfaceId]; } /** * @dev Registers the contract as an implementer of the interface defined by * `interfaceId`. Support of the actual ERC165 interface is automatic and * registering its interface id is not required. * * See {IERC165-supportsInterface}. * * Requirements: * * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). */ function _registerInterface(bytes4 interfaceId) internal { require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); _supportedInterfaces[interfaceId] = true; } } // File: openzeppelin-solidity/contracts/introspection/ERC165Checker.sol pragma solidity ^0.5.10; /** * @dev Library used to query support of an interface declared via {IERC165}. * * Note that these functions return the actual result of the query: they do not * `revert` if an interface is not supported. It is up to the caller to decide * what to do in these cases. */ library ERC165Checker { // As per the EIP-165 spec, no interface should ever match 0xffffffff bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff; /* * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 */ bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * @dev Returns true if `account` supports the {IERC165} interface, */ function _supportsERC165(address account) internal view returns (bool) { // Any contract that implements ERC165 must explicitly indicate support of // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) && !_supportsERC165Interface(account, _INTERFACE_ID_INVALID); } /** * @dev Returns true if `account` supports the interface defined by * `interfaceId`. Support for {IERC165} itself is queried automatically. * * See {IERC165-supportsInterface}. */ function _supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { // query support of both ERC165 as per the spec and support of _interfaceId return _supportsERC165(account) && _supportsERC165Interface(account, interfaceId); } /** * @dev Returns true if `account` supports all the interfaces defined in * `interfaceIds`. Support for {IERC165} itself is queried automatically. * * Batch-querying can lead to gas savings by skipping repeated checks for * {IERC165} support. * * See {IERC165-supportsInterface}. */ function _supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { // query support of ERC165 itself if (!_supportsERC165(account)) { return false; } // query support of each interface in _interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { if (!_supportsERC165Interface(account, interfaceIds[i])) { return false; } } // all interfaces supported return true; } /** * @notice Query if a contract implements an interface, does not check ERC165 support * @param account The address of the contract to query for support of an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @return true if the contract at account indicates support of the interface with * identifier interfaceId, false otherwise * @dev Assumes that account contains a contract that supports ERC165, otherwise * the behavior of this method is undefined. This precondition can be checked * with the `supportsERC165` method in this library. * Interface identification is specified in ERC-165. */ function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) { // success determines whether the staticcall succeeded and result determines // whether the contract at account indicates support of _interfaceId (bool success, bool result) = _callERC165SupportsInterface(account, interfaceId); return (success && result); } /** * @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw * @param account The address of the contract to query for support of an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @return success true if the STATICCALL succeeded, false otherwise * @return result true if the STATICCALL succeeded and the contract at account * indicates support of the interface with identifier interfaceId, false otherwise */ function _callERC165SupportsInterface(address account, bytes4 interfaceId) private view returns (bool, bool) { bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId); (bool success, bytes memory result) = account.staticcall.gas(30000)(encodedParams); if (result.length < 32) return (false, false); return (success, abi.decode(result, (bool))); } } // File: coinage-token/contracts/lib/DSMath.sol // https://github.com/dapphub/ds-math/blob/de45767/src/math.sol /// math.sol -- mixin for inline numerical wizardry // 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.4.13; contract DSMath { function add(uint x, uint y) internal pure returns (uint z) { require((z = x + y) >= x, "ds-math-add-overflow"); } function sub(uint x, uint y) internal pure returns (uint z) { require((z = x - y) <= x, "ds-math-sub-underflow"); } function mul(uint x, uint y) internal pure returns (uint z) { require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow"); } function min(uint x, uint y) internal pure returns (uint z) { return x <= y ? x : y; } function max(uint x, uint y) internal pure returns (uint z) { return x >= y ? x : y; } function imin(int x, int y) internal pure returns (int z) { return x <= y ? x : y; } function imax(int x, int y) internal pure returns (int z) { return x >= y ? x : y; } uint constant WAD = 10 ** 18; uint constant RAY = 10 ** 27; function wmul(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, y), WAD / 2) / WAD; } function rmul(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, y), RAY / 2) / RAY; } function wdiv(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, WAD), y / 2) / y; } function rdiv(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, RAY), y / 2) / y; } // This famous algorithm is called "exponentiation by squaring" // and calculates x^n with x as fixed-point and n as regular unsigned. // // It's O(log n), instead of O(n) for naive repeated multiplication. // // These facts are why it works: // // If n is even, then x^n = (x^2)^(n/2). // If n is odd, then x^n = x * x^(n-1), // and applying the equation for even x gives // x^n = x * (x^2)^((n-1) / 2). // // Also, EVM division is flooring and // floor[(n-1) / 2] = floor[n / 2]. // function wpow(uint x, uint n) internal pure returns (uint z) { z = n % 2 != 0 ? x : WAD; for (n /= 2; n != 0; n /= 2) { x = wmul(x, x); if (n % 2 != 0) { z = wmul(z, x); } } } function rpow(uint x, uint n) internal pure returns (uint z) { z = n % 2 != 0 ? x : RAY; for (n /= 2; n != 0; n /= 2) { x = rmul(x, x); if (n % 2 != 0) { z = rmul(z, x); } } } } // File: contracts/stake/interfaces/SeigManagerI.sol pragma solidity ^0.5.12; interface SeigManagerI { function registry() external view returns (address); function depositManager() external view returns (address); function ton() external view returns (address); function wton() external view returns (address); function powerton() external view returns (address); function tot() external view returns (address); function coinages(address layer2) external view returns (address); function commissionRates(address layer2) external view returns (uint256); function lastCommitBlock(address layer2) external view returns (uint256); function seigPerBlock() external view returns (uint256); function lastSeigBlock() external view returns (uint256); function pausedBlock() external view returns (uint256); function unpausedBlock() external view returns (uint256); function DEFAULT_FACTOR() external view returns (uint256); function deployCoinage(address layer2) external returns (bool); function setCommissionRate(address layer2, uint256 commission, bool isCommissionRateNegative) external returns (bool); function uncomittedStakeOf(address layer2, address account) external view returns (uint256); function stakeOf(address layer2, address account) external view returns (uint256); function additionalTotBurnAmount(address layer2, address account, uint256 amount) external view returns (uint256 totAmount); function onTransfer(address sender, address recipient, uint256 amount) external returns (bool); function updateSeigniorage() external returns (bool); function onDeposit(address layer2, address account, uint256 amount) external returns (bool); function onWithdraw(address layer2, address account, uint256 amount) external returns (bool); } // File: contracts/stake/tokens/OnApprove.sol pragma solidity ^0.5.12; contract OnApprove is ERC165 { constructor() public { _registerInterface(OnApprove(this).onApprove.selector); } function onApprove(address owner, address spender, uint256 amount, bytes calldata data) external returns (bool); } // File: contracts/stake/tokens/ERC20OnApprove.sol pragma solidity ^0.5.12; contract ERC20OnApprove is ERC20 { function approveAndCall(address spender, uint256 amount, bytes memory data) public returns (bool) { require(approve(spender, amount)); _callOnApprove(msg.sender, spender, amount, data); return true; } function _callOnApprove(address owner, address spender, uint256 amount, bytes memory data) internal { bytes4 onApproveSelector = OnApprove(spender).onApprove.selector; require(ERC165Checker._supportsInterface(spender, onApproveSelector), "ERC20OnApprove: spender doesn't support onApprove"); (bool ok, bytes memory res) = spender.call( abi.encodeWithSelector( onApproveSelector, owner, spender, amount, data ) ); // check if low-level call reverted or not require(ok, string(res)); assembly { ok := mload(add(res, 0x20)) } // check if OnApprove.onApprove returns true or false require(ok, "ERC20OnApprove: failed to call onApprove"); } } // File: contracts/stake/tokens/AuthController.sol pragma solidity ^0.5.12; interface MinterRoleRenounceTarget { function renounceMinter() external; } interface PauserRoleRenounceTarget { function renouncePauser() external; } interface OwnableTarget { function renounceOwnership() external; function transferOwnership(address newOwner) external; } contract AuthController is Ownable { function renounceMinter(address target) public onlyOwner { MinterRoleRenounceTarget(target).renounceMinter(); } function renouncePauser(address target) public onlyOwner { PauserRoleRenounceTarget(target).renouncePauser(); } function renounceOwnership(address target) public onlyOwner { OwnableTarget(target).renounceOwnership(); } function transferOwnership(address target, address newOwner) public onlyOwner { OwnableTarget(target).transferOwnership(newOwner); } } // File: contracts/stake/tokens/SeigToken.sol pragma solidity ^0.5.12; contract SeigToken is ERC20, Ownable, ERC20OnApprove, AuthController { SeigManagerI public seigManager; bool public callbackEnabled; function enableCallback(bool _callbackEnabled) external onlyOwner { callbackEnabled = _callbackEnabled; } function setSeigManager(SeigManagerI _seigManager) external onlyOwner { seigManager = _seigManager; } ////////////////////// // Override ERC20 functions ////////////////////// function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { return super.transferFrom(sender, recipient, amount); } function _transfer(address sender, address recipient, uint256 amount) internal { super._transfer(sender, recipient, amount); if (callbackEnabled && address(seigManager) != address(0)) { require(seigManager.onTransfer(sender, recipient, amount)); } } function _mint(address account, uint256 amount) internal { super._mint(account, amount); if (callbackEnabled && address(seigManager) != address(0)) { require(seigManager.onTransfer(address(0), account, amount)); } } function _burn(address account, uint256 amount) internal { super._burn(account, amount); if (callbackEnabled && address(seigManager) != address(0)) { require(seigManager.onTransfer(account, address(0), amount)); } } } // File: contracts/stake/tokens/WTON.sol pragma solidity ^0.5.12; contract WTON is DSMath, ReentrancyGuard, Ownable, ERC20Mintable, ERC20Burnable, ERC20Detailed, SeigToken, OnApprove { using SafeERC20 for ERC20Mintable; ERC20Mintable public ton; constructor ( ERC20Mintable _ton ) public ERC20Detailed("Wrapped TON", "WTON", 27) { require(ERC20Detailed(address(_ton)).decimals() == 18, "WTON: decimals of TON must be 18"); ton = _ton; } ////////////////////// // TON Approve callback ////////////////////// function onApprove( address owner, address spender, uint256 tonAmount, bytes calldata data ) external returns (bool) { require(msg.sender == address(ton), "WTON: only accept TON approve callback"); // swap owner's TON to WTON _swapFromTON(owner, owner, tonAmount); uint256 wtonAmount = _toRAY(tonAmount); (address depositManager, address layer2) = _decodeTONApproveData(data); // approve WTON to DepositManager _approve(owner, depositManager, wtonAmount); // call DepositManager.onApprove to deposit WTON bytes memory depositManagerOnApproveData = _encodeDepositManagerOnApproveData(layer2); _callOnApprove(owner, depositManager, wtonAmount, depositManagerOnApproveData); return true; } /** * @dev data is 64 bytes of 2 addresses in left-padded 32 bytes */ function _decodeTONApproveData( bytes memory data ) internal pure returns (address depositManager, address layer2) { require(data.length == 0x40); assembly { depositManager := mload(add(data, 0x20)) layer2 := mload(add(data, 0x40)) } } function _encodeDepositManagerOnApproveData( address layer2 ) internal pure returns (bytes memory data) { data = new bytes(0x20); assembly { mstore(add(data, 0x20), layer2) } } ////////////////////// // Override ERC20 functions ////////////////////// function burnFrom(address account, uint256 amount) public { if (isMinter(msg.sender)) { _burn(account, amount); return; } super.burnFrom(account, amount); } ////////////////////// // Swap functions ////////////////////// /** * @dev swap WTON to TON */ function swapToTON(uint256 wtonAmount) public nonReentrant returns (bool) { return _swapToTON(msg.sender, msg.sender, wtonAmount); } /** * @dev swap TON to WTON */ function swapFromTON(uint256 tonAmount) public nonReentrant returns (bool) { return _swapFromTON(msg.sender, msg.sender, tonAmount); } /** * @dev swap WTON to TON, and transfer TON * NOTE: TON's transfer event's `from` argument is not `msg.sender` but `WTON` address. */ function swapToTONAndTransfer(address to, uint256 wtonAmount) public nonReentrant returns (bool) { return _swapToTON(to, msg.sender, wtonAmount); } /** * @dev swap TON to WTON, and transfer WTON */ function swapFromTONAndTransfer(address to, uint256 tonAmount) public nonReentrant returns (bool) { return _swapFromTON(msg.sender, to, tonAmount); } function renounceTonMinter() external onlyOwner { ton.renounceMinter(); } ////////////////////// // Internal functions ////////////////////// function _swapToTON(address tonAccount, address wtonAccount, uint256 wtonAmount) internal returns (bool) { _burn(wtonAccount, wtonAmount); // mint TON if WTON contract has not enough TON to transfer uint256 tonAmount = _toWAD(wtonAmount); uint256 tonBalance = ton.balanceOf(address(this)); if (tonBalance < tonAmount) { ton.mint(address(this), tonAmount.sub(tonBalance)); } ton.safeTransfer(tonAccount, tonAmount); return true; } function _swapFromTON(address tonAccount, address wtonAccount, uint256 tonAmount) internal returns (bool) { _mint(wtonAccount, _toRAY(tonAmount)); ton.safeTransferFrom(tonAccount, address(this), tonAmount); return true; } /** * @dev transform WAD to RAY */ function _toRAY(uint256 v) internal pure returns (uint256) { return v * 10 ** 9; } /** * @dev transform RAY to WAD */ function _toWAD(uint256 v) internal pure returns (uint256) { return v / 10 ** 9; } }
File 3 of 8: DepositManager
// File: openzeppelin-solidity/contracts/GSN/Context.sol pragma solidity ^0.5.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: openzeppelin-solidity/contracts/ownership/Ownable.sol pragma solidity ^0.5.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: openzeppelin-solidity/contracts/math/SafeMath.sol pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot 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-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: 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 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: openzeppelin-solidity/contracts/utils/Address.sol pragma solidity ^0.5.5; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Converts an `address` into `address payable`. Note that this is * simply a type cast: the actual underlying value is not changed. * * _Available since v2.4.0._ */ function toPayable(address account) internal pure returns (address payable) { return address(uint160(account)); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. * * _Available since v2.4.0._ */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-call-value (bool success, ) = recipient.call.value(amount)(""); require(success, "Address: unable to send value, recipient may have reverted"); } } // File: openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol pragma solidity ^0.5.0; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: openzeppelin-solidity/contracts/introspection/IERC165.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File: openzeppelin-solidity/contracts/introspection/ERC165.sol pragma solidity ^0.5.0; /** * @dev Implementation of the {IERC165} interface. * * Contracts may inherit from this and call {_registerInterface} to declare * their support of an interface. */ contract ERC165 is IERC165 { /* * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 */ bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * @dev Mapping of interface ids to whether or not it's supported. */ mapping(bytes4 => bool) private _supportedInterfaces; constructor () internal { // Derived contracts need only register support for their own interfaces, // we register support for ERC165 itself here _registerInterface(_INTERFACE_ID_ERC165); } /** * @dev See {IERC165-supportsInterface}. * * Time complexity O(1), guaranteed to always use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool) { return _supportedInterfaces[interfaceId]; } /** * @dev Registers the contract as an implementer of the interface defined by * `interfaceId`. Support of the actual ERC165 interface is automatic and * registering its interface id is not required. * * See {IERC165-supportsInterface}. * * Requirements: * * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). */ function _registerInterface(bytes4 interfaceId) internal { require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); _supportedInterfaces[interfaceId] = true; } } // File: contracts/Layer2I.sol pragma solidity ^0.5.12; interface Layer2I { function operator() external view returns (address); function isLayer2() external view returns (bool); function currentFork() external view returns (uint); function lastEpoch(uint forkNumber) external view returns (uint); function changeOperator(address _operator) external; } // File: contracts/stake/interfaces/DepositManagerI.sol pragma solidity ^0.5.12; interface DepositManagerI { function owner() external view returns (address); function wton() external view returns (address); function registry() external view returns (address); function seigManager() external view returns (address); function accStaked(address layer2, address account) external view returns (uint256 wtonAmount); function accStakedLayer2(address layer2) external view returns (uint256 wtonAmount); function accStakedAccount(address account) external view returns (uint256 wtonAmount); function pendingUnstaked(address layer2, address account) external view returns (uint256 wtonAmount); function pendingUnstakedLayer2(address layer2) external view returns (uint256 wtonAmount); function pendingUnstakedAccount(address account) external view returns (uint256 wtonAmount); function accUnstaked(address layer2, address account) external view returns (uint256 wtonAmount); function accUnstakedLayer2(address layer2) external view returns (uint256 wtonAmount); function accUnstakedAccount(address account) external view returns (uint256 wtonAmount); function withdrawalRequestIndex(address layer2, address account) external view returns (uint256 index); function withdrawalRequest(address layer2, address account, uint256 index) external view returns (uint128 withdrawableBlockNumber, uint128 amount, bool processed ); function WITHDRAWAL_DELAY() external view returns (uint256); function setSeigManager(address seigManager) external; function deposit(address layer2, uint256 amount) external returns (bool); function requestWithdrawal(address layer2, uint256 amount) external returns (bool); function processRequest(address layer2) external returns (bool); function requestWithdrawalAll(address layer2) external returns (bool); function processRequests(address layer2, uint256 n) external returns (bool); function numRequests(address layer2, address account) external view returns (uint256); function numPendingRequests(address layer2, address account) external view returns (uint256); function slash(address layer2, address recipient, uint256 amount) external returns (bool); } // File: contracts/stake/interfaces/Layer2RegistryI.sol pragma solidity ^0.5.12; interface Layer2RegistryI { function layer2s(address layer2) external view returns (bool); function register(address layer2) external returns (bool); function numLayer2s() external view returns (uint256); function layer2ByIndex(uint256 index) external view returns (address); function deployCoinage(address layer2, address seigManager) external returns (bool); function registerAndDeployCoinage(address layer2, address seigManager) external returns (bool); function unregister(address layer2) external returns (bool); } // File: contracts/stake/interfaces/SeigManagerI.sol pragma solidity ^0.5.12; interface SeigManagerI { function registry() external view returns (address); function depositManager() external view returns (address); function ton() external view returns (address); function wton() external view returns (address); function powerton() external view returns (address); function tot() external view returns (address); function coinages(address layer2) external view returns (address); function commissionRates(address layer2) external view returns (uint256); function lastCommitBlock(address layer2) external view returns (uint256); function seigPerBlock() external view returns (uint256); function lastSeigBlock() external view returns (uint256); function pausedBlock() external view returns (uint256); function unpausedBlock() external view returns (uint256); function DEFAULT_FACTOR() external view returns (uint256); function deployCoinage(address layer2) external returns (bool); function setCommissionRate(address layer2, uint256 commission, bool isCommissionRateNegative) external returns (bool); function uncomittedStakeOf(address layer2, address account) external view returns (uint256); function stakeOf(address layer2, address account) external view returns (uint256); function additionalTotBurnAmount(address layer2, address account, uint256 amount) external view returns (uint256 totAmount); function onTransfer(address sender, address recipient, uint256 amount) external returns (bool); function updateSeigniorage() external returns (bool); function onDeposit(address layer2, address account, uint256 amount) external returns (bool); function onWithdraw(address layer2, address account, uint256 amount) external returns (bool); } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol pragma solidity ^0.5.0; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20Mintable}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for `sender`'s tokens of at least * `amount`. */ 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; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ 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); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ 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); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ 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); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ 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); } /** * @dev Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); } } // File: openzeppelin-solidity/contracts/access/Roles.sol pragma solidity ^0.5.0; /** * @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(!has(role, account), "Roles: account already has role"); role.bearer[account] = true; } /** * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { require(has(role, account), "Roles: account does not have role"); 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), "Roles: account is the zero address"); return role.bearer[account]; } } // File: openzeppelin-solidity/contracts/access/roles/MinterRole.sol pragma solidity ^0.5.0; 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); } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol pragma solidity ^0.5.0; /** * @dev Extension of {ERC20} that adds a set of accounts with the {MinterRole}, * which have permission to mint (create) new tokens as they see fit. * * At construction, the deployer of the contract is the only minter. */ contract ERC20Mintable is ERC20, MinterRole { /** * @dev See {ERC20-_mint}. * * Requirements: * * - the caller must have the {MinterRole}. */ function mint(address account, uint256 amount) public onlyMinter returns (bool) { _mint(account, amount); return true; } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol pragma solidity ^0.5.0; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ contract ERC20Burnable is Context, ERC20 { /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 amount) public { _burn(_msgSender(), amount); } /** * @dev See {ERC20-_burnFrom}. */ function burnFrom(address account, uint256 amount) public { _burnFrom(account, amount); } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol pragma solidity ^0.5.0; /** * @dev Optional functions from the ERC20 standard. */ contract ERC20Detailed is IERC20 { string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of * these values are immutable: they can only be set once during * construction. */ constructor (string memory name, string memory symbol, uint8 decimals) public { _name = name; _symbol = symbol; _decimals = decimals; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } } // File: openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol pragma solidity ^0.5.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. * * _Since v2.5.0:_ this module is now much more gas efficient, given net gas * metering changes introduced in the Istanbul hardfork. */ contract ReentrancyGuard { bool private _notEntered; constructor () internal { // Storing an initial non-zero value makes deployment a bit more // expensive, but in exchange the refund on every call to nonReentrant // will be lower in amount. Since refunds are capped to a percetange of // the total transaction's gas, it is best to keep them low in cases // like this one, to increase the likelihood of the full refund coming // into effect. _notEntered = true; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_notEntered, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _notEntered = false; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _notEntered = true; } } // File: openzeppelin-solidity/contracts/introspection/ERC165Checker.sol pragma solidity ^0.5.10; /** * @dev Library used to query support of an interface declared via {IERC165}. * * Note that these functions return the actual result of the query: they do not * `revert` if an interface is not supported. It is up to the caller to decide * what to do in these cases. */ library ERC165Checker { // As per the EIP-165 spec, no interface should ever match 0xffffffff bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff; /* * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 */ bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * @dev Returns true if `account` supports the {IERC165} interface, */ function _supportsERC165(address account) internal view returns (bool) { // Any contract that implements ERC165 must explicitly indicate support of // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) && !_supportsERC165Interface(account, _INTERFACE_ID_INVALID); } /** * @dev Returns true if `account` supports the interface defined by * `interfaceId`. Support for {IERC165} itself is queried automatically. * * See {IERC165-supportsInterface}. */ function _supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { // query support of both ERC165 as per the spec and support of _interfaceId return _supportsERC165(account) && _supportsERC165Interface(account, interfaceId); } /** * @dev Returns true if `account` supports all the interfaces defined in * `interfaceIds`. Support for {IERC165} itself is queried automatically. * * Batch-querying can lead to gas savings by skipping repeated checks for * {IERC165} support. * * See {IERC165-supportsInterface}. */ function _supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { // query support of ERC165 itself if (!_supportsERC165(account)) { return false; } // query support of each interface in _interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { if (!_supportsERC165Interface(account, interfaceIds[i])) { return false; } } // all interfaces supported return true; } /** * @notice Query if a contract implements an interface, does not check ERC165 support * @param account The address of the contract to query for support of an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @return true if the contract at account indicates support of the interface with * identifier interfaceId, false otherwise * @dev Assumes that account contains a contract that supports ERC165, otherwise * the behavior of this method is undefined. This precondition can be checked * with the `supportsERC165` method in this library. * Interface identification is specified in ERC-165. */ function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) { // success determines whether the staticcall succeeded and result determines // whether the contract at account indicates support of _interfaceId (bool success, bool result) = _callERC165SupportsInterface(account, interfaceId); return (success && result); } /** * @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw * @param account The address of the contract to query for support of an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @return success true if the STATICCALL succeeded, false otherwise * @return result true if the STATICCALL succeeded and the contract at account * indicates support of the interface with identifier interfaceId, false otherwise */ function _callERC165SupportsInterface(address account, bytes4 interfaceId) private view returns (bool, bool) { bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId); (bool success, bytes memory result) = account.staticcall.gas(30000)(encodedParams); if (result.length < 32) return (false, false); return (success, abi.decode(result, (bool))); } } // File: coinage-token/contracts/lib/DSMath.sol // https://github.com/dapphub/ds-math/blob/de45767/src/math.sol /// math.sol -- mixin for inline numerical wizardry // 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.4.13; contract DSMath { function add(uint x, uint y) internal pure returns (uint z) { require((z = x + y) >= x, "ds-math-add-overflow"); } function sub(uint x, uint y) internal pure returns (uint z) { require((z = x - y) <= x, "ds-math-sub-underflow"); } function mul(uint x, uint y) internal pure returns (uint z) { require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow"); } function min(uint x, uint y) internal pure returns (uint z) { return x <= y ? x : y; } function max(uint x, uint y) internal pure returns (uint z) { return x >= y ? x : y; } function imin(int x, int y) internal pure returns (int z) { return x <= y ? x : y; } function imax(int x, int y) internal pure returns (int z) { return x >= y ? x : y; } uint constant WAD = 10 ** 18; uint constant RAY = 10 ** 27; function wmul(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, y), WAD / 2) / WAD; } function rmul(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, y), RAY / 2) / RAY; } function wdiv(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, WAD), y / 2) / y; } function rdiv(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, RAY), y / 2) / y; } // This famous algorithm is called "exponentiation by squaring" // and calculates x^n with x as fixed-point and n as regular unsigned. // // It's O(log n), instead of O(n) for naive repeated multiplication. // // These facts are why it works: // // If n is even, then x^n = (x^2)^(n/2). // If n is odd, then x^n = x * x^(n-1), // and applying the equation for even x gives // x^n = x * (x^2)^((n-1) / 2). // // Also, EVM division is flooring and // floor[(n-1) / 2] = floor[n / 2]. // function wpow(uint x, uint n) internal pure returns (uint z) { z = n % 2 != 0 ? x : WAD; for (n /= 2; n != 0; n /= 2) { x = wmul(x, x); if (n % 2 != 0) { z = wmul(z, x); } } } function rpow(uint x, uint n) internal pure returns (uint z) { z = n % 2 != 0 ? x : RAY; for (n /= 2; n != 0; n /= 2) { x = rmul(x, x); if (n % 2 != 0) { z = rmul(z, x); } } } } // File: contracts/stake/tokens/OnApprove.sol pragma solidity ^0.5.12; contract OnApprove is ERC165 { constructor() public { _registerInterface(OnApprove(this).onApprove.selector); } function onApprove(address owner, address spender, uint256 amount, bytes calldata data) external returns (bool); } // File: contracts/stake/tokens/ERC20OnApprove.sol pragma solidity ^0.5.12; contract ERC20OnApprove is ERC20 { function approveAndCall(address spender, uint256 amount, bytes memory data) public returns (bool) { require(approve(spender, amount)); _callOnApprove(msg.sender, spender, amount, data); return true; } function _callOnApprove(address owner, address spender, uint256 amount, bytes memory data) internal { bytes4 onApproveSelector = OnApprove(spender).onApprove.selector; require(ERC165Checker._supportsInterface(spender, onApproveSelector), "ERC20OnApprove: spender doesn't support onApprove"); (bool ok, bytes memory res) = spender.call( abi.encodeWithSelector( onApproveSelector, owner, spender, amount, data ) ); // check if low-level call reverted or not require(ok, string(res)); assembly { ok := mload(add(res, 0x20)) } // check if OnApprove.onApprove returns true or false require(ok, "ERC20OnApprove: failed to call onApprove"); } } // File: contracts/stake/tokens/AuthController.sol pragma solidity ^0.5.12; interface MinterRoleRenounceTarget { function renounceMinter() external; } interface PauserRoleRenounceTarget { function renouncePauser() external; } interface OwnableTarget { function renounceOwnership() external; function transferOwnership(address newOwner) external; } contract AuthController is Ownable { function renounceMinter(address target) public onlyOwner { MinterRoleRenounceTarget(target).renounceMinter(); } function renouncePauser(address target) public onlyOwner { PauserRoleRenounceTarget(target).renouncePauser(); } function renounceOwnership(address target) public onlyOwner { OwnableTarget(target).renounceOwnership(); } function transferOwnership(address target, address newOwner) public onlyOwner { OwnableTarget(target).transferOwnership(newOwner); } } // File: contracts/stake/tokens/SeigToken.sol pragma solidity ^0.5.12; contract SeigToken is ERC20, Ownable, ERC20OnApprove, AuthController { SeigManagerI public seigManager; bool public callbackEnabled; function enableCallback(bool _callbackEnabled) external onlyOwner { callbackEnabled = _callbackEnabled; } function setSeigManager(SeigManagerI _seigManager) external onlyOwner { seigManager = _seigManager; } ////////////////////// // Override ERC20 functions ////////////////////// function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { return super.transferFrom(sender, recipient, amount); } function _transfer(address sender, address recipient, uint256 amount) internal { super._transfer(sender, recipient, amount); if (callbackEnabled && address(seigManager) != address(0)) { require(seigManager.onTransfer(sender, recipient, amount)); } } function _mint(address account, uint256 amount) internal { super._mint(account, amount); if (callbackEnabled && address(seigManager) != address(0)) { require(seigManager.onTransfer(address(0), account, amount)); } } function _burn(address account, uint256 amount) internal { super._burn(account, amount); if (callbackEnabled && address(seigManager) != address(0)) { require(seigManager.onTransfer(account, address(0), amount)); } } } // File: contracts/stake/tokens/WTON.sol pragma solidity ^0.5.12; contract WTON is DSMath, ReentrancyGuard, Ownable, ERC20Mintable, ERC20Burnable, ERC20Detailed, SeigToken, OnApprove { using SafeERC20 for ERC20Mintable; ERC20Mintable public ton; constructor ( ERC20Mintable _ton ) public ERC20Detailed("Wrapped TON", "WTON", 27) { require(ERC20Detailed(address(_ton)).decimals() == 18, "WTON: decimals of TON must be 18"); ton = _ton; } ////////////////////// // TON Approve callback ////////////////////// function onApprove( address owner, address spender, uint256 tonAmount, bytes calldata data ) external returns (bool) { require(msg.sender == address(ton), "WTON: only accept TON approve callback"); // swap owner's TON to WTON _swapFromTON(owner, owner, tonAmount); uint256 wtonAmount = _toRAY(tonAmount); (address depositManager, address layer2) = _decodeTONApproveData(data); // approve WTON to DepositManager _approve(owner, depositManager, wtonAmount); // call DepositManager.onApprove to deposit WTON bytes memory depositManagerOnApproveData = _encodeDepositManagerOnApproveData(layer2); _callOnApprove(owner, depositManager, wtonAmount, depositManagerOnApproveData); return true; } /** * @dev data is 64 bytes of 2 addresses in left-padded 32 bytes */ function _decodeTONApproveData( bytes memory data ) internal pure returns (address depositManager, address layer2) { require(data.length == 0x40); assembly { depositManager := mload(add(data, 0x20)) layer2 := mload(add(data, 0x40)) } } function _encodeDepositManagerOnApproveData( address layer2 ) internal pure returns (bytes memory data) { data = new bytes(0x20); assembly { mstore(add(data, 0x20), layer2) } } ////////////////////// // Override ERC20 functions ////////////////////// function burnFrom(address account, uint256 amount) public { if (isMinter(msg.sender)) { _burn(account, amount); return; } super.burnFrom(account, amount); } ////////////////////// // Swap functions ////////////////////// /** * @dev swap WTON to TON */ function swapToTON(uint256 wtonAmount) public nonReentrant returns (bool) { return _swapToTON(msg.sender, msg.sender, wtonAmount); } /** * @dev swap TON to WTON */ function swapFromTON(uint256 tonAmount) public nonReentrant returns (bool) { return _swapFromTON(msg.sender, msg.sender, tonAmount); } /** * @dev swap WTON to TON, and transfer TON * NOTE: TON's transfer event's `from` argument is not `msg.sender` but `WTON` address. */ function swapToTONAndTransfer(address to, uint256 wtonAmount) public nonReentrant returns (bool) { return _swapToTON(to, msg.sender, wtonAmount); } /** * @dev swap TON to WTON, and transfer WTON */ function swapFromTONAndTransfer(address to, uint256 tonAmount) public nonReentrant returns (bool) { return _swapFromTON(msg.sender, to, tonAmount); } function renounceTonMinter() external onlyOwner { ton.renounceMinter(); } ////////////////////// // Internal functions ////////////////////// function _swapToTON(address tonAccount, address wtonAccount, uint256 wtonAmount) internal returns (bool) { _burn(wtonAccount, wtonAmount); // mint TON if WTON contract has not enough TON to transfer uint256 tonAmount = _toWAD(wtonAmount); uint256 tonBalance = ton.balanceOf(address(this)); if (tonBalance < tonAmount) { ton.mint(address(this), tonAmount.sub(tonBalance)); } ton.safeTransfer(tonAccount, tonAmount); return true; } function _swapFromTON(address tonAccount, address wtonAccount, uint256 tonAmount) internal returns (bool) { _mint(wtonAccount, _toRAY(tonAmount)); ton.safeTransferFrom(tonAccount, address(this), tonAmount); return true; } /** * @dev transform WAD to RAY */ function _toRAY(uint256 v) internal pure returns (uint256) { return v * 10 ** 9; } /** * @dev transform RAY to WAD */ function _toWAD(uint256 v) internal pure returns (uint256) { return v / 10 ** 9; } } // File: contracts/stake/managers/DepositManager.sol pragma solidity ^0.5.12; // TODO: add events // TODO: check deposit/withdraw WTON amount (1e27) /** * @dev DepositManager manages WTON deposit and withdrawal from operator and WTON holders. */ contract DepositManager is Ownable, ERC165, OnApprove { using SafeMath for uint256; using SafeERC20 for WTON; //////////////////// // Storage - contracts //////////////////// WTON internal _wton; Layer2RegistryI internal _registry; SeigManagerI internal _seigManager; //////////////////// // Storage - token amount //////////////////// // accumulated staked amount // layer2 => msg.sender => wton amount mapping (address => mapping (address => uint256)) internal _accStaked; // layer2 => wton amount mapping (address => uint256) internal _accStakedLayer2; // msg.sender => wton amount mapping (address => uint256) internal _accStakedAccount; // pending unstaked amount // layer2 => msg.sender => wton amount mapping (address => mapping (address => uint256)) internal _pendingUnstaked; // layer2 => wton amount mapping (address => uint256) internal _pendingUnstakedLayer2; // msg.sender => wton amount mapping (address => uint256) internal _pendingUnstakedAccount; // accumulated unstaked amount // layer2 => msg.sender => wton amount mapping (address => mapping (address => uint256)) internal _accUnstaked; // layer2 => wton amount mapping (address => uint256) internal _accUnstakedLayer2; // msg.sender => wton amount mapping (address => uint256) internal _accUnstakedAccount; // layer2 => msg.sender => withdrawal requests mapping (address => mapping (address => WithdrawalReqeust[])) internal _withdrawalRequests; // layer2 => msg.sender => index mapping (address => mapping (address => uint256)) internal _withdrawalRequestIndex; //////////////////// // Storage - configuration / ERC165 interfaces //////////////////// // withdrawal delay in block number // @TODO: change delay unit to CYCLE? uint256 public globalWithdrawalDelay; mapping (address => uint256) public withdrawalDelay; struct WithdrawalReqeust { uint128 withdrawableBlockNumber; uint128 amount; bool processed; } //////////////////// // Modifiers //////////////////// modifier onlyLayer2(address layer2) { require(_registry.layer2s(layer2)); _; } modifier onlySeigManager() { require(msg.sender == address(_seigManager)); _; } //////////////////// // Events //////////////////// event Deposited(address indexed layer2, address depositor, uint256 amount); event WithdrawalRequested(address indexed layer2, address depositor, uint256 amount); event WithdrawalProcessed(address indexed layer2, address depositor, uint256 amount); //////////////////// // Constructor //////////////////// constructor ( WTON wton, Layer2RegistryI registry, uint256 globalWithdrawalDelay_ ) public { _wton = wton; _registry = registry; globalWithdrawalDelay = globalWithdrawalDelay_; } //////////////////// // SeiManager function //////////////////// function setSeigManager(SeigManagerI seigManager) external onlyOwner { _seigManager = seigManager; } //////////////////// // ERC20 Approve callback //////////////////// function onApprove( address owner, address spender, uint256 amount, bytes calldata data ) external returns (bool) { require(msg.sender == address(_wton), "DepositManager: only accept WTON approve callback"); address layer2 = _decodeDepositManagerOnApproveData(data); require(_deposit(layer2, owner, amount)); return true; } function _decodeDepositManagerOnApproveData( bytes memory data ) internal pure returns (address layer2) { require(data.length == 0x20); assembly { layer2 := mload(add(data, 0x20)) } } //////////////////// // Deposit function //////////////////// /** * @dev deposit `amount` WTON in RAY */ function deposit(address layer2, uint256 amount) external returns (bool) { require(_deposit(layer2, msg.sender, amount)); } function _deposit(address layer2, address account, uint256 amount) internal onlyLayer2(layer2) returns (bool) { _accStaked[layer2][account] = _accStaked[layer2][account].add(amount); _accStakedLayer2[layer2] = _accStakedLayer2[layer2].add(amount); _accStakedAccount[account] = _accStakedAccount[account].add(amount); _wton.safeTransferFrom(account, address(this), amount); emit Deposited(layer2, account, amount); require(_seigManager.onDeposit(layer2, account, amount)); return true; } //////////////////// // Re-deposit function //////////////////// /** * @dev re-deposit pending requests in the pending queue */ function redeposit(address layer2) external returns (bool) { uint256 i = _withdrawalRequestIndex[layer2][msg.sender]; require(_redeposit(layer2, i, 1)); } function redepositMulti(address layer2, uint256 n) external returns (bool) { uint256 i = _withdrawalRequestIndex[layer2][msg.sender]; require(_redeposit(layer2, i, n)); } function _redeposit(address layer2, uint256 i, uint256 n) internal onlyLayer2(layer2) returns (bool) { uint256 accAmount; require(_withdrawalRequests[layer2][msg.sender].length > 0, "DepositManager: no request"); require(_withdrawalRequests[layer2][msg.sender].length - i >= n, "DepositManager: n exceeds num of pending requests"); uint256 e = i + n; for (; i < e; i++) { WithdrawalReqeust storage r = _withdrawalRequests[layer2][msg.sender][i]; uint256 amount = r.amount; require(!r.processed, "DepositManager: pending request already processed"); require(amount > 0, "DepositManager: no valid pending request"); accAmount = accAmount.add(amount); r.processed = true; } // deposit-related storages _accStaked[layer2][msg.sender] = _accStaked[layer2][msg.sender].add(accAmount); _accStakedLayer2[layer2] = _accStakedLayer2[layer2].add(accAmount); _accStakedAccount[msg.sender] = _accStakedAccount[msg.sender].add(accAmount); // withdrawal-related storages _pendingUnstaked[layer2][msg.sender] = _pendingUnstaked[layer2][msg.sender].sub(accAmount); _pendingUnstakedLayer2[layer2] = _pendingUnstakedLayer2[layer2].sub(accAmount); _pendingUnstakedAccount[msg.sender] = _pendingUnstakedAccount[msg.sender].sub(accAmount); _withdrawalRequestIndex[layer2][msg.sender] += n; emit Deposited(layer2, msg.sender, accAmount); require(_seigManager.onDeposit(layer2, msg.sender, accAmount)); return true; } //////////////////// // Slash functions //////////////////// function slash(address layer2, address recipient, uint256 amount) external onlySeigManager returns (bool) { //return _wton.transferFrom(owner, recipient, amount); } //////////////////// // Setter //////////////////// function setGlobalWithdrawalDelay(uint256 globalWithdrawalDelay_) external onlyOwner { globalWithdrawalDelay = globalWithdrawalDelay_; } function setWithdrawalDelay(address l2chain, uint256 withdrawalDelay_) external { require(_isOperator(l2chain, msg.sender)); withdrawalDelay[l2chain] = withdrawalDelay_; } //////////////////// // Withdrawal functions //////////////////// function requestWithdrawal(address layer2, uint256 amount) external returns (bool) { return _requestWithdrawal(layer2, amount); } function _requestWithdrawal(address layer2, uint256 amount) internal onlyLayer2(layer2) returns (bool) { require(amount > 0, "DepositManager: amount must not be zero"); uint256 delay = globalWithdrawalDelay > withdrawalDelay[layer2] ? globalWithdrawalDelay : withdrawalDelay[layer2]; _withdrawalRequests[layer2][msg.sender].push(WithdrawalReqeust({ withdrawableBlockNumber: uint128(block.number + delay), amount: uint128(amount), processed: false })); _pendingUnstaked[layer2][msg.sender] = _pendingUnstaked[layer2][msg.sender].add(amount); _pendingUnstakedLayer2[layer2] = _pendingUnstakedLayer2[layer2].add(amount); _pendingUnstakedAccount[msg.sender] = _pendingUnstakedAccount[msg.sender].add(amount); emit WithdrawalRequested(layer2, msg.sender, amount); require(_seigManager.onWithdraw(layer2, msg.sender, amount)); return true; } function processRequest(address layer2, bool receiveTON) external returns (bool) { return _processRequest(layer2, receiveTON); } function _processRequest(address layer2, bool receiveTON) internal returns (bool) { uint256 index = _withdrawalRequestIndex[layer2][msg.sender]; require(_withdrawalRequests[layer2][msg.sender].length > index, "DepositManager: no request to process"); WithdrawalReqeust storage r = _withdrawalRequests[layer2][msg.sender][index]; require(r.withdrawableBlockNumber <= block.number, "DepositManager: wait for withdrawal delay"); r.processed = true; _withdrawalRequestIndex[layer2][msg.sender] += 1; uint256 amount = r.amount; _pendingUnstaked[layer2][msg.sender] = _pendingUnstaked[layer2][msg.sender].sub(amount); _pendingUnstakedLayer2[layer2] = _pendingUnstakedLayer2[layer2].sub(amount); _pendingUnstakedAccount[msg.sender] = _pendingUnstakedAccount[msg.sender].sub(amount); _accUnstaked[layer2][msg.sender] = _accUnstaked[layer2][msg.sender].add(amount); _accUnstakedLayer2[layer2] = _accUnstakedLayer2[layer2].add(amount); _accUnstakedAccount[msg.sender] = _accUnstakedAccount[msg.sender].add(amount); if (receiveTON) { require(_wton.swapToTONAndTransfer(msg.sender, amount)); } else { _wton.safeTransfer(msg.sender, amount); } emit WithdrawalProcessed(layer2, msg.sender, amount); return true; } function requestWithdrawalAll(address layer2) external onlyLayer2(layer2) returns (bool) { uint256 amount = _seigManager.stakeOf(layer2, msg.sender); return _requestWithdrawal(layer2, amount); } function processRequests(address layer2, uint256 n, bool receiveTON) external returns (bool) { for (uint256 i = 0; i < n; i++) { require(_processRequest(layer2, receiveTON)); } return true; } function numRequests(address layer2, address account) external view returns (uint256) { return _withdrawalRequests[layer2][account].length; } function numPendingRequests(address layer2, address account) external view returns (uint256) { uint256 numRequests = _withdrawalRequests[layer2][account].length; uint256 index = _withdrawalRequestIndex[layer2][account]; if (numRequests == 0) return 0; return numRequests - index; } function _isOperator(address layer2, address operator) internal view returns (bool) { return operator == Layer2I(layer2).operator(); } //////////////////// // Storage getters //////////////////// // solium-disable function wton() external view returns (address) { return address(_wton); } function registry() external view returns (address) { return address(_registry); } function seigManager() external view returns (address) { return address(_seigManager); } function accStaked(address layer2, address account) external view returns (uint256 wtonAmount) { return _accStaked[layer2][account]; } function accStakedLayer2(address layer2) external view returns (uint256 wtonAmount) { return _accStakedLayer2[layer2]; } function accStakedAccount(address account) external view returns (uint256 wtonAmount) { return _accStakedAccount[account]; } function pendingUnstaked(address layer2, address account) external view returns (uint256 wtonAmount) { return _pendingUnstaked[layer2][account]; } function pendingUnstakedLayer2(address layer2) external view returns (uint256 wtonAmount) { return _pendingUnstakedLayer2[layer2]; } function pendingUnstakedAccount(address account) external view returns (uint256 wtonAmount) { return _pendingUnstakedAccount[account]; } function accUnstaked(address layer2, address account) external view returns (uint256 wtonAmount) { return _accUnstaked[layer2][account]; } function accUnstakedLayer2(address layer2) external view returns (uint256 wtonAmount) { return _accUnstakedLayer2[layer2]; } function accUnstakedAccount(address account) external view returns (uint256 wtonAmount) { return _accUnstakedAccount[account]; } function withdrawalRequestIndex(address layer2, address account) external view returns (uint256 index) { return _withdrawalRequestIndex[layer2][account]; } function withdrawalRequest(address layer2, address account, uint256 index) external view returns (uint128 withdrawableBlockNumber, uint128 amount, bool processed ) { withdrawableBlockNumber = _withdrawalRequests[layer2][account][index].withdrawableBlockNumber; amount = _withdrawalRequests[layer2][account][index].amount; processed = _withdrawalRequests[layer2][account][index].processed; } // solium-enable }
File 4 of 8: AutoRefactorCoinage
// based on ERC20 implementation of openzeppelin-solidity: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/7552af95e4ec6fccd64a95b206f59a1b4ff91517/contracts/token/ERC20/ERC20.sol pragma solidity ^0.5.12; import { AutoRefactorCoinageI } from "AutoRefactorCoinageI.sol"; import { SafeMath } from "openzeppelin-solidity/SafeMath.sol"; import { Context } from "openzeppelin-solidity/Context.sol"; import { Ownable } from "openzeppelin-solidity/Ownable.sol"; import { IERC20 } from "openzeppelin-solidity/IERC20.sol"; import { ERC20Detailed } from "openzeppelin-solidity/ERC20Detailed.sol"; import { ERC20Mintable } from "openzeppelin-solidity/ERC20Mintable.sol"; import { ERC20Burnable } from "openzeppelin-solidity/ERC20Burnable.sol"; import { DSMath } from "DSMath.sol"; /** * @dev Implementation of coin age token based on ERC20 of openzeppelin-solidity * * AutoRefactorCoinage stores `_totalSupply` and `_balances` as RAY BASED value, * `_allowances` as RAY FACTORED value. * * This takes public function (including _approve) parameters as RAY FACTORED value * and internal function (including approve) parameters as RAY BASED value, and emits event in RAY FACTORED value. * * `RAY BASED` = `RAY FACTORED` / factor * * factor increases exponentially for each block mined. */ contract AutoRefactorCoinage is Context, IERC20, DSMath, Ownable, ERC20Detailed, ERC20Mintable, ERC20Burnable { using SafeMath for uint256; struct Balance { uint256 balance; uint256 refactoredCount; uint256 remain; } uint256 public REFACTOR_BOUNDARY = 10 ** 28; uint256 public REFACTOR_DIVIDER = 2; uint256 public refactorCount; mapping (address => Balance) public balances; Balance public _totalSupply; uint256 public _factor; bool internal _transfersEnabled; event FactorSet(uint256 previous, uint256 current, uint256 shiftCount); constructor ( string memory name, string memory symbol, uint256 factor ) public ERC20Detailed(name, symbol, 27) { _factor = factor; //_factorIncrement = factorIncrement; //_lastBlock = block.number; //_transfersEnabled = transfersEnabled; } function factor() public view returns (uint256) { uint256 result = _factor; for (uint256 i = 0; i < refactorCount; i++) { result = result.mul(REFACTOR_DIVIDER); } return result; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _applyFactor(_totalSupply.balance, _totalSupply.refactoredCount).add(_totalSupply.remain); } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view returns (uint256) { Balance storage b = balances[account]; return _applyFactor(b.balance, b.refactoredCount).add(b.remain); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal { require(account != address(0), "AutoRefactorCoinage: mint to the zero address"); Balance storage b = balances[account]; uint256 currentBalance = balanceOf(account); uint256 newBalance = currentBalance.add(amount); uint256 rbAmount = _toRAYBased(newBalance); b.balance = rbAmount; b.refactoredCount = refactorCount; addTotalSupply(amount); emit Transfer(address(0), account, _toRAYFactored(rbAmount)); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal { require(account != address(0), "AutoRefactorCoinage: burn from the zero address"); Balance storage b = balances[account]; uint256 currentBalance = balanceOf(account); uint256 newBalance = currentBalance.sub(amount); uint256 rbAmount = _toRAYBased(newBalance); b.balance = rbAmount; b.refactoredCount = refactorCount; subTotalSupply(amount); emit Transfer(account, address(0), _toRAYFactored(rbAmount)); } function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); } // helpers /** * @param v the value to be factored */ function _applyFactor(uint256 v, uint256 refactoredCount) internal view returns (uint256) { if (v == 0) { return 0; } v = rmul2(v, _factor); for (uint256 i = refactoredCount; i < refactorCount; i++) { v = v.mul(REFACTOR_DIVIDER); } return v; } /** * @dev Calculate RAY BASED from RAY FACTORED */ function _toRAYBased(uint256 rf) internal view returns (uint256 rb) { return rdiv2(rf, _factor); } /** * @dev Calculate RAY FACTORED from RAY BASED */ function _toRAYFactored(uint256 rb) internal view returns (uint256 rf) { return rmul2(rb, _factor); } // new function setFactor(uint256 factor) external onlyOwner returns (bool) { uint256 previous = _factor; uint256 count = 0; uint256 f = factor; for (; f >= REFACTOR_BOUNDARY; f = f.div(REFACTOR_DIVIDER)) { count = count.add(1); } refactorCount = count; _factor = f; emit FactorSet(previous, f, count); } function addTotalSupply(uint256 amount) internal { uint256 currentSupply = _applyFactor(_totalSupply.balance, _totalSupply.refactoredCount); uint256 newSupply = currentSupply.add(amount); uint256 rbAmount = _toRAYBased(newSupply); _totalSupply.balance = rbAmount; _totalSupply.refactoredCount = refactorCount; } function subTotalSupply(uint256 amount) internal { uint256 currentSupply = _applyFactor(_totalSupply.balance, _totalSupply.refactoredCount); uint256 newSupply = currentSupply.sub(amount); uint256 rbAmount = _toRAYBased(newSupply); _totalSupply.balance = rbAmount; _totalSupply.refactoredCount = refactorCount; } // unsupported functions function transfer(address recipient, uint256 amount) public returns (bool) { revert(); } function allowance(address owner, address spender) public view returns (uint256) { return 0; } function approve(address spender, uint256 amount) public returns (bool) { revert(); } function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { revert(); } } pragma solidity ^0.5.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: 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 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // https://github.com/dapphub/ds-math/blob/de45767/src/math.sol /// math.sol -- mixin for inline numerical wizardry // 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.4.13; contract DSMath { function add(uint x, uint y) internal pure returns (uint z) { require((z = x + y) >= x, "ds-math-add-overflow"); } function sub(uint x, uint y) internal pure returns (uint z) { require((z = x - y) <= x, "ds-math-sub-underflow"); } function mul(uint x, uint y) internal pure returns (uint z) { require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow"); } function min(uint x, uint y) internal pure returns (uint z) { return x <= y ? x : y; } function max(uint x, uint y) internal pure returns (uint z) { return x >= y ? x : y; } function imin(int x, int y) internal pure returns (int z) { return x <= y ? x : y; } function imax(int x, int y) internal pure returns (int z) { return x >= y ? x : y; } uint constant WAD = 10 ** 18; uint constant RAY = 10 ** 27; function wmul(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, y), WAD / 2) / WAD; } function rmul(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, y), RAY / 2) / RAY; } function wdiv(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, WAD), y / 2) / y; } function rdiv(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, RAY), y / 2) / y; } function wmul2(uint x, uint y) internal pure returns (uint z) { z = mul(x, y) / WAD; } function rmul2(uint x, uint y) internal pure returns (uint z) { z = mul(x, y) / RAY; } function wdiv2(uint x, uint y) internal pure returns (uint z) { z = mul(x, WAD) / y; } function rdiv2(uint x, uint y) internal pure returns (uint z) { z = mul(x, RAY) / y; } // This famous algorithm is called "exponentiation by squaring" // and calculates x^n with x as fixed-point and n as regular unsigned. // // It's O(log n), instead of O(n) for naive repeated multiplication. // // These facts are why it works: // // If n is even, then x^n = (x^2)^(n/2). // If n is odd, then x^n = x * x^(n-1), // and applying the equation for even x gives // x^n = x * (x^2)^((n-1) / 2). // // Also, EVM division is flooring and // floor[(n-1) / 2] = floor[n / 2]. // function wpow(uint x, uint n) internal pure returns (uint z) { z = n % 2 != 0 ? x : WAD; for (n /= 2; n != 0; n /= 2) { x = wmul(x, x); if (n % 2 != 0) { z = wmul(z, x); } } } function rpow(uint x, uint n) internal pure returns (uint z) { z = n % 2 != 0 ? x : RAY; for (n /= 2; n != 0; n /= 2) { x = rmul(x, x); if (n % 2 != 0) { z = rmul(z, x); } } } } pragma solidity ^0.5.0; import "openzeppelin-solidity/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } pragma solidity ^0.5.0; import "openzeppelin-solidity/ERC20.sol"; import "openzeppelin-solidity/MinterRole.sol"; /** * @dev Extension of {ERC20} that adds a set of accounts with the {MinterRole}, * which have permission to mint (create) new tokens as they see fit. * * At construction, the deployer of the contract is the only minter. */ contract ERC20Mintable is ERC20, MinterRole { /** * @dev See {ERC20-_mint}. * * Requirements: * * - the caller must have the {MinterRole}. */ function mint(address account, uint256 amount) public onlyMinter returns (bool) { _mint(account, amount); return true; } } pragma solidity ^0.5.0; import "openzeppelin-solidity/IERC20.sol"; /** * @dev Optional functions from the ERC20 standard. */ contract ERC20Detailed is IERC20 { string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of * these values are immutable: they can only be set once during * construction. */ constructor (string memory name, string memory symbol, uint8 decimals) public { _name = name; _symbol = symbol; _decimals = decimals; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } } pragma solidity ^0.5.0; import "openzeppelin-solidity/Context.sol"; import "openzeppelin-solidity/ERC20.sol"; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ contract ERC20Burnable is Context, ERC20 { /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 amount) public { _burn(_msgSender(), amount); } /** * @dev See {ERC20-_burnFrom}. */ function burnFrom(address account, uint256 amount) public { _burnFrom(account, amount); } } pragma solidity ^0.5.0; import "openzeppelin-solidity/Context.sol"; import "openzeppelin-solidity/IERC20.sol"; import "openzeppelin-solidity/SafeMath.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20Mintable}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for `sender`'s tokens of at least * `amount`. */ 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; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ 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); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ 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); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ 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); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ 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); } /** * @dev Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); } } pragma solidity ^0.5.0; import "openzeppelin-solidity/Context.sol"; import "openzeppelin-solidity/Roles.sol"; 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); } } pragma solidity ^0.5.0; /** * @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(!has(role, account), "Roles: account already has role"); role.bearer[account] = true; } /** * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { require(has(role, account), "Roles: account does not have role"); 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), "Roles: account is the zero address"); return role.bearer[account]; } } pragma solidity ^0.5.12; interface AutoRefactorCoinageI { function factor() external view returns (uint256); function setFactor(uint256 factor) external returns (bool); function burn(uint256 amount) external; function burnFrom(address account, uint256 amount) external; function mint(address account, uint256 amount) external returns (bool); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function addMinter(address account) external; function renounceMinter() external; function transferOwnership(address newOwner) external; } pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot 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-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
File 5 of 8: AutoRefactorCoinage
// based on ERC20 implementation of openzeppelin-solidity: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/7552af95e4ec6fccd64a95b206f59a1b4ff91517/contracts/token/ERC20/ERC20.sol pragma solidity ^0.5.12; import { AutoRefactorCoinageI } from "AutoRefactorCoinageI.sol"; import { SafeMath } from "openzeppelin-solidity/SafeMath.sol"; import { Context } from "openzeppelin-solidity/Context.sol"; import { Ownable } from "openzeppelin-solidity/Ownable.sol"; import { IERC20 } from "openzeppelin-solidity/IERC20.sol"; import { ERC20Detailed } from "openzeppelin-solidity/ERC20Detailed.sol"; import { ERC20Mintable } from "openzeppelin-solidity/ERC20Mintable.sol"; import { ERC20Burnable } from "openzeppelin-solidity/ERC20Burnable.sol"; import { DSMath } from "DSMath.sol"; /** * @dev Implementation of coin age token based on ERC20 of openzeppelin-solidity * * AutoRefactorCoinage stores `_totalSupply` and `_balances` as RAY BASED value, * `_allowances` as RAY FACTORED value. * * This takes public function (including _approve) parameters as RAY FACTORED value * and internal function (including approve) parameters as RAY BASED value, and emits event in RAY FACTORED value. * * `RAY BASED` = `RAY FACTORED` / factor * * factor increases exponentially for each block mined. */ contract AutoRefactorCoinage is Context, IERC20, DSMath, Ownable, ERC20Detailed, ERC20Mintable, ERC20Burnable { using SafeMath for uint256; struct Balance { uint256 balance; uint256 refactoredCount; uint256 remain; } uint256 public REFACTOR_BOUNDARY = 10 ** 28; uint256 public REFACTOR_DIVIDER = 2; uint256 public refactorCount; mapping (address => Balance) public balances; Balance public _totalSupply; uint256 public _factor; bool internal _transfersEnabled; event FactorSet(uint256 previous, uint256 current, uint256 shiftCount); constructor ( string memory name, string memory symbol, uint256 factor ) public ERC20Detailed(name, symbol, 27) { _factor = factor; //_factorIncrement = factorIncrement; //_lastBlock = block.number; //_transfersEnabled = transfersEnabled; } function factor() public view returns (uint256) { uint256 result = _factor; for (uint256 i = 0; i < refactorCount; i++) { result = result.mul(REFACTOR_DIVIDER); } return result; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _applyFactor(_totalSupply.balance, _totalSupply.refactoredCount).add(_totalSupply.remain); } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view returns (uint256) { Balance storage b = balances[account]; return _applyFactor(b.balance, b.refactoredCount).add(b.remain); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal { require(account != address(0), "AutoRefactorCoinage: mint to the zero address"); Balance storage b = balances[account]; uint256 currentBalance = balanceOf(account); uint256 newBalance = currentBalance.add(amount); uint256 rbAmount = _toRAYBased(newBalance); b.balance = rbAmount; b.refactoredCount = refactorCount; addTotalSupply(amount); emit Transfer(address(0), account, _toRAYFactored(rbAmount)); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal { require(account != address(0), "AutoRefactorCoinage: burn from the zero address"); Balance storage b = balances[account]; uint256 currentBalance = balanceOf(account); uint256 newBalance = currentBalance.sub(amount); uint256 rbAmount = _toRAYBased(newBalance); b.balance = rbAmount; b.refactoredCount = refactorCount; subTotalSupply(amount); emit Transfer(account, address(0), _toRAYFactored(rbAmount)); } function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); } // helpers /** * @param v the value to be factored */ function _applyFactor(uint256 v, uint256 refactoredCount) internal view returns (uint256) { if (v == 0) { return 0; } v = rmul2(v, _factor); for (uint256 i = refactoredCount; i < refactorCount; i++) { v = v.mul(REFACTOR_DIVIDER); } return v; } /** * @dev Calculate RAY BASED from RAY FACTORED */ function _toRAYBased(uint256 rf) internal view returns (uint256 rb) { return rdiv2(rf, _factor); } /** * @dev Calculate RAY FACTORED from RAY BASED */ function _toRAYFactored(uint256 rb) internal view returns (uint256 rf) { return rmul2(rb, _factor); } // new function setFactor(uint256 factor) external onlyOwner returns (bool) { uint256 previous = _factor; uint256 count = 0; uint256 f = factor; for (; f >= REFACTOR_BOUNDARY; f = f.div(REFACTOR_DIVIDER)) { count = count.add(1); } refactorCount = count; _factor = f; emit FactorSet(previous, f, count); } function addTotalSupply(uint256 amount) internal { uint256 currentSupply = _applyFactor(_totalSupply.balance, _totalSupply.refactoredCount); uint256 newSupply = currentSupply.add(amount); uint256 rbAmount = _toRAYBased(newSupply); _totalSupply.balance = rbAmount; _totalSupply.refactoredCount = refactorCount; } function subTotalSupply(uint256 amount) internal { uint256 currentSupply = _applyFactor(_totalSupply.balance, _totalSupply.refactoredCount); uint256 newSupply = currentSupply.sub(amount); uint256 rbAmount = _toRAYBased(newSupply); _totalSupply.balance = rbAmount; _totalSupply.refactoredCount = refactorCount; } // unsupported functions function transfer(address recipient, uint256 amount) public returns (bool) { revert(); } function allowance(address owner, address spender) public view returns (uint256) { return 0; } function approve(address spender, uint256 amount) public returns (bool) { revert(); } function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { revert(); } } pragma solidity ^0.5.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: 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 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // https://github.com/dapphub/ds-math/blob/de45767/src/math.sol /// math.sol -- mixin for inline numerical wizardry // 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.4.13; contract DSMath { function add(uint x, uint y) internal pure returns (uint z) { require((z = x + y) >= x, "ds-math-add-overflow"); } function sub(uint x, uint y) internal pure returns (uint z) { require((z = x - y) <= x, "ds-math-sub-underflow"); } function mul(uint x, uint y) internal pure returns (uint z) { require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow"); } function min(uint x, uint y) internal pure returns (uint z) { return x <= y ? x : y; } function max(uint x, uint y) internal pure returns (uint z) { return x >= y ? x : y; } function imin(int x, int y) internal pure returns (int z) { return x <= y ? x : y; } function imax(int x, int y) internal pure returns (int z) { return x >= y ? x : y; } uint constant WAD = 10 ** 18; uint constant RAY = 10 ** 27; function wmul(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, y), WAD / 2) / WAD; } function rmul(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, y), RAY / 2) / RAY; } function wdiv(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, WAD), y / 2) / y; } function rdiv(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, RAY), y / 2) / y; } function wmul2(uint x, uint y) internal pure returns (uint z) { z = mul(x, y) / WAD; } function rmul2(uint x, uint y) internal pure returns (uint z) { z = mul(x, y) / RAY; } function wdiv2(uint x, uint y) internal pure returns (uint z) { z = mul(x, WAD) / y; } function rdiv2(uint x, uint y) internal pure returns (uint z) { z = mul(x, RAY) / y; } // This famous algorithm is called "exponentiation by squaring" // and calculates x^n with x as fixed-point and n as regular unsigned. // // It's O(log n), instead of O(n) for naive repeated multiplication. // // These facts are why it works: // // If n is even, then x^n = (x^2)^(n/2). // If n is odd, then x^n = x * x^(n-1), // and applying the equation for even x gives // x^n = x * (x^2)^((n-1) / 2). // // Also, EVM division is flooring and // floor[(n-1) / 2] = floor[n / 2]. // function wpow(uint x, uint n) internal pure returns (uint z) { z = n % 2 != 0 ? x : WAD; for (n /= 2; n != 0; n /= 2) { x = wmul(x, x); if (n % 2 != 0) { z = wmul(z, x); } } } function rpow(uint x, uint n) internal pure returns (uint z) { z = n % 2 != 0 ? x : RAY; for (n /= 2; n != 0; n /= 2) { x = rmul(x, x); if (n % 2 != 0) { z = rmul(z, x); } } } } pragma solidity ^0.5.0; import "openzeppelin-solidity/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } pragma solidity ^0.5.0; import "openzeppelin-solidity/ERC20.sol"; import "openzeppelin-solidity/MinterRole.sol"; /** * @dev Extension of {ERC20} that adds a set of accounts with the {MinterRole}, * which have permission to mint (create) new tokens as they see fit. * * At construction, the deployer of the contract is the only minter. */ contract ERC20Mintable is ERC20, MinterRole { /** * @dev See {ERC20-_mint}. * * Requirements: * * - the caller must have the {MinterRole}. */ function mint(address account, uint256 amount) public onlyMinter returns (bool) { _mint(account, amount); return true; } } pragma solidity ^0.5.0; import "openzeppelin-solidity/IERC20.sol"; /** * @dev Optional functions from the ERC20 standard. */ contract ERC20Detailed is IERC20 { string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of * these values are immutable: they can only be set once during * construction. */ constructor (string memory name, string memory symbol, uint8 decimals) public { _name = name; _symbol = symbol; _decimals = decimals; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } } pragma solidity ^0.5.0; import "openzeppelin-solidity/Context.sol"; import "openzeppelin-solidity/ERC20.sol"; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ contract ERC20Burnable is Context, ERC20 { /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 amount) public { _burn(_msgSender(), amount); } /** * @dev See {ERC20-_burnFrom}. */ function burnFrom(address account, uint256 amount) public { _burnFrom(account, amount); } } pragma solidity ^0.5.0; import "openzeppelin-solidity/Context.sol"; import "openzeppelin-solidity/IERC20.sol"; import "openzeppelin-solidity/SafeMath.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20Mintable}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for `sender`'s tokens of at least * `amount`. */ 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; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ 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); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ 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); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ 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); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ 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); } /** * @dev Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); } } pragma solidity ^0.5.0; import "openzeppelin-solidity/Context.sol"; import "openzeppelin-solidity/Roles.sol"; 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); } } pragma solidity ^0.5.0; /** * @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(!has(role, account), "Roles: account already has role"); role.bearer[account] = true; } /** * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { require(has(role, account), "Roles: account does not have role"); 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), "Roles: account is the zero address"); return role.bearer[account]; } } pragma solidity ^0.5.12; interface AutoRefactorCoinageI { function factor() external view returns (uint256); function setFactor(uint256 factor) external returns (bool); function burn(uint256 amount) external; function burnFrom(address account, uint256 amount) external; function mint(address account, uint256 amount) external returns (bool); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function addMinter(address account) external; function renounceMinter() external; function transferOwnership(address newOwner) external; } pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot 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-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
File 6 of 8: PowerTON
// File: openzeppelin-solidity/contracts/GSN/Context.sol pragma solidity ^0.5.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: openzeppelin-solidity/contracts/ownership/Ownable.sol pragma solidity ^0.5.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: openzeppelin-solidity/contracts/access/Roles.sol pragma solidity ^0.5.0; /** * @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(!has(role, account), "Roles: account already has role"); role.bearer[account] = true; } /** * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { require(has(role, account), "Roles: account does not have role"); 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), "Roles: account is the zero address"); return role.bearer[account]; } } // File: openzeppelin-solidity/contracts/access/roles/PauserRole.sol pragma solidity ^0.5.0; contract PauserRole is Context { using Roles for Roles.Role; event PauserAdded(address indexed account); event PauserRemoved(address indexed account); Roles.Role private _pausers; constructor () internal { _addPauser(_msgSender()); } modifier onlyPauser() { require(isPauser(_msgSender()), "PauserRole: caller does not have the Pauser role"); _; } function isPauser(address account) public view returns (bool) { return _pausers.has(account); } function addPauser(address account) public onlyPauser { _addPauser(account); } function renouncePauser() public { _removePauser(_msgSender()); } function _addPauser(address account) internal { _pausers.add(account); emit PauserAdded(account); } function _removePauser(address account) internal { _pausers.remove(account); emit PauserRemoved(account); } } // File: openzeppelin-solidity/contracts/lifecycle/Pausable.sol pragma solidity ^0.5.0; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ contract Pausable is Context, PauserRole { /** * @dev Emitted when the pause is triggered by a pauser (`account`). */ event Paused(address account); /** * @dev Emitted when the pause is lifted by a pauser (`account`). */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. Assigns the Pauser role * to the deployer. */ constructor () internal { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPaused() { require(!_paused, "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. */ modifier whenPaused() { require(_paused, "Pausable: not paused"); _; } /** * @dev Called by a pauser to pause, triggers stopped state. */ function pause() public onlyPauser whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Called by a pauser to unpause, returns to normal state. */ function unpause() public onlyPauser whenPaused { _paused = false; emit Unpaused(_msgSender()); } } // File: openzeppelin-solidity/contracts/math/SafeMath.sol pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot 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-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: 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 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: openzeppelin-solidity/contracts/utils/Address.sol pragma solidity ^0.5.5; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Converts an `address` into `address payable`. Note that this is * simply a type cast: the actual underlying value is not changed. * * _Available since v2.4.0._ */ function toPayable(address account) internal pure returns (address payable) { return address(uint160(account)); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. * * _Available since v2.4.0._ */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-call-value (bool success, ) = recipient.call.value(amount)(""); require(success, "Address: unable to send value, recipient may have reverted"); } } // File: openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol pragma solidity ^0.5.0; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol pragma solidity ^0.5.0; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20Mintable}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for `sender`'s tokens of at least * `amount`. */ 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; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ 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); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ 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); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ 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); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ 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); } /** * @dev Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); } } // File: openzeppelin-solidity/contracts/access/roles/MinterRole.sol pragma solidity ^0.5.0; 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); } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol pragma solidity ^0.5.0; /** * @dev Extension of {ERC20} that adds a set of accounts with the {MinterRole}, * which have permission to mint (create) new tokens as they see fit. * * At construction, the deployer of the contract is the only minter. */ contract ERC20Mintable is ERC20, MinterRole { /** * @dev See {ERC20-_mint}. * * Requirements: * * - the caller must have the {MinterRole}. */ function mint(address account, uint256 amount) public onlyMinter returns (bool) { _mint(account, amount); return true; } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol pragma solidity ^0.5.0; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ contract ERC20Burnable is Context, ERC20 { /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 amount) public { _burn(_msgSender(), amount); } /** * @dev See {ERC20-_burnFrom}. */ function burnFrom(address account, uint256 amount) public { _burnFrom(account, amount); } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol pragma solidity ^0.5.0; /** * @dev Optional functions from the ERC20 standard. */ contract ERC20Detailed is IERC20 { string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of * these values are immutable: they can only be set once during * construction. */ constructor (string memory name, string memory symbol, uint8 decimals) public { _name = name; _symbol = symbol; _decimals = decimals; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } } // File: openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol pragma solidity ^0.5.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. * * _Since v2.5.0:_ this module is now much more gas efficient, given net gas * metering changes introduced in the Istanbul hardfork. */ contract ReentrancyGuard { bool private _notEntered; constructor () internal { // Storing an initial non-zero value makes deployment a bit more // expensive, but in exchange the refund on every call to nonReentrant // will be lower in amount. Since refunds are capped to a percetange of // the total transaction's gas, it is best to keep them low in cases // like this one, to increase the likelihood of the full refund coming // into effect. _notEntered = true; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_notEntered, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _notEntered = false; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _notEntered = true; } } // File: openzeppelin-solidity/contracts/introspection/IERC165.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File: openzeppelin-solidity/contracts/introspection/ERC165.sol pragma solidity ^0.5.0; /** * @dev Implementation of the {IERC165} interface. * * Contracts may inherit from this and call {_registerInterface} to declare * their support of an interface. */ contract ERC165 is IERC165 { /* * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 */ bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * @dev Mapping of interface ids to whether or not it's supported. */ mapping(bytes4 => bool) private _supportedInterfaces; constructor () internal { // Derived contracts need only register support for their own interfaces, // we register support for ERC165 itself here _registerInterface(_INTERFACE_ID_ERC165); } /** * @dev See {IERC165-supportsInterface}. * * Time complexity O(1), guaranteed to always use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool) { return _supportedInterfaces[interfaceId]; } /** * @dev Registers the contract as an implementer of the interface defined by * `interfaceId`. Support of the actual ERC165 interface is automatic and * registering its interface id is not required. * * See {IERC165-supportsInterface}. * * Requirements: * * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). */ function _registerInterface(bytes4 interfaceId) internal { require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); _supportedInterfaces[interfaceId] = true; } } // File: openzeppelin-solidity/contracts/introspection/ERC165Checker.sol pragma solidity ^0.5.10; /** * @dev Library used to query support of an interface declared via {IERC165}. * * Note that these functions return the actual result of the query: they do not * `revert` if an interface is not supported. It is up to the caller to decide * what to do in these cases. */ library ERC165Checker { // As per the EIP-165 spec, no interface should ever match 0xffffffff bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff; /* * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 */ bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * @dev Returns true if `account` supports the {IERC165} interface, */ function _supportsERC165(address account) internal view returns (bool) { // Any contract that implements ERC165 must explicitly indicate support of // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) && !_supportsERC165Interface(account, _INTERFACE_ID_INVALID); } /** * @dev Returns true if `account` supports the interface defined by * `interfaceId`. Support for {IERC165} itself is queried automatically. * * See {IERC165-supportsInterface}. */ function _supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { // query support of both ERC165 as per the spec and support of _interfaceId return _supportsERC165(account) && _supportsERC165Interface(account, interfaceId); } /** * @dev Returns true if `account` supports all the interfaces defined in * `interfaceIds`. Support for {IERC165} itself is queried automatically. * * Batch-querying can lead to gas savings by skipping repeated checks for * {IERC165} support. * * See {IERC165-supportsInterface}. */ function _supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { // query support of ERC165 itself if (!_supportsERC165(account)) { return false; } // query support of each interface in _interfaceIds for (uint256 i = 0; i < interfaceIds.length; i++) { if (!_supportsERC165Interface(account, interfaceIds[i])) { return false; } } // all interfaces supported return true; } /** * @notice Query if a contract implements an interface, does not check ERC165 support * @param account The address of the contract to query for support of an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @return true if the contract at account indicates support of the interface with * identifier interfaceId, false otherwise * @dev Assumes that account contains a contract that supports ERC165, otherwise * the behavior of this method is undefined. This precondition can be checked * with the `supportsERC165` method in this library. * Interface identification is specified in ERC-165. */ function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) { // success determines whether the staticcall succeeded and result determines // whether the contract at account indicates support of _interfaceId (bool success, bool result) = _callERC165SupportsInterface(account, interfaceId); return (success && result); } /** * @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw * @param account The address of the contract to query for support of an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @return success true if the STATICCALL succeeded, false otherwise * @return result true if the STATICCALL succeeded and the contract at account * indicates support of the interface with identifier interfaceId, false otherwise */ function _callERC165SupportsInterface(address account, bytes4 interfaceId) private view returns (bool, bool) { bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId); (bool success, bytes memory result) = account.staticcall.gas(30000)(encodedParams); if (result.length < 32) return (false, false); return (success, abi.decode(result, (bool))); } } // File: coinage-token/contracts/lib/DSMath.sol // https://github.com/dapphub/ds-math/blob/de45767/src/math.sol /// math.sol -- mixin for inline numerical wizardry // 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.4.13; contract DSMath { function add(uint x, uint y) internal pure returns (uint z) { require((z = x + y) >= x, "ds-math-add-overflow"); } function sub(uint x, uint y) internal pure returns (uint z) { require((z = x - y) <= x, "ds-math-sub-underflow"); } function mul(uint x, uint y) internal pure returns (uint z) { require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow"); } function min(uint x, uint y) internal pure returns (uint z) { return x <= y ? x : y; } function max(uint x, uint y) internal pure returns (uint z) { return x >= y ? x : y; } function imin(int x, int y) internal pure returns (int z) { return x <= y ? x : y; } function imax(int x, int y) internal pure returns (int z) { return x >= y ? x : y; } uint constant WAD = 10 ** 18; uint constant RAY = 10 ** 27; function wmul(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, y), WAD / 2) / WAD; } function rmul(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, y), RAY / 2) / RAY; } function wdiv(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, WAD), y / 2) / y; } function rdiv(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, RAY), y / 2) / y; } // This famous algorithm is called "exponentiation by squaring" // and calculates x^n with x as fixed-point and n as regular unsigned. // // It's O(log n), instead of O(n) for naive repeated multiplication. // // These facts are why it works: // // If n is even, then x^n = (x^2)^(n/2). // If n is odd, then x^n = x * x^(n-1), // and applying the equation for even x gives // x^n = x * (x^2)^((n-1) / 2). // // Also, EVM division is flooring and // floor[(n-1) / 2] = floor[n / 2]. // function wpow(uint x, uint n) internal pure returns (uint z) { z = n % 2 != 0 ? x : WAD; for (n /= 2; n != 0; n /= 2) { x = wmul(x, x); if (n % 2 != 0) { z = wmul(z, x); } } } function rpow(uint x, uint n) internal pure returns (uint z) { z = n % 2 != 0 ? x : RAY; for (n /= 2; n != 0; n /= 2) { x = rmul(x, x); if (n % 2 != 0) { z = rmul(z, x); } } } } // File: contracts/stake/interfaces/SeigManagerI.sol pragma solidity ^0.5.12; interface SeigManagerI { function registry() external view returns (address); function depositManager() external view returns (address); function ton() external view returns (address); function wton() external view returns (address); function powerton() external view returns (address); function tot() external view returns (address); function coinages(address layer2) external view returns (address); function commissionRates(address layer2) external view returns (uint256); function lastCommitBlock(address layer2) external view returns (uint256); function seigPerBlock() external view returns (uint256); function lastSeigBlock() external view returns (uint256); function pausedBlock() external view returns (uint256); function unpausedBlock() external view returns (uint256); function DEFAULT_FACTOR() external view returns (uint256); function deployCoinage(address layer2) external returns (bool); function setCommissionRate(address layer2, uint256 commission, bool isCommissionRateNegative) external returns (bool); function uncomittedStakeOf(address layer2, address account) external view returns (uint256); function stakeOf(address layer2, address account) external view returns (uint256); function additionalTotBurnAmount(address layer2, address account, uint256 amount) external view returns (uint256 totAmount); function onTransfer(address sender, address recipient, uint256 amount) external returns (bool); function updateSeigniorage() external returns (bool); function onDeposit(address layer2, address account, uint256 amount) external returns (bool); function onWithdraw(address layer2, address account, uint256 amount) external returns (bool); } // File: contracts/stake/tokens/OnApprove.sol pragma solidity ^0.5.12; contract OnApprove is ERC165 { constructor() public { _registerInterface(OnApprove(this).onApprove.selector); } function onApprove(address owner, address spender, uint256 amount, bytes calldata data) external returns (bool); } // File: contracts/stake/tokens/ERC20OnApprove.sol pragma solidity ^0.5.12; contract ERC20OnApprove is ERC20 { function approveAndCall(address spender, uint256 amount, bytes memory data) public returns (bool) { require(approve(spender, amount)); _callOnApprove(msg.sender, spender, amount, data); return true; } function _callOnApprove(address owner, address spender, uint256 amount, bytes memory data) internal { bytes4 onApproveSelector = OnApprove(spender).onApprove.selector; require(ERC165Checker._supportsInterface(spender, onApproveSelector), "ERC20OnApprove: spender doesn't support onApprove"); (bool ok, bytes memory res) = spender.call( abi.encodeWithSelector( onApproveSelector, owner, spender, amount, data ) ); // check if low-level call reverted or not require(ok, string(res)); assembly { ok := mload(add(res, 0x20)) } // check if OnApprove.onApprove returns true or false require(ok, "ERC20OnApprove: failed to call onApprove"); } } // File: contracts/stake/tokens/AuthController.sol pragma solidity ^0.5.12; interface MinterRoleRenounceTarget { function renounceMinter() external; } interface PauserRoleRenounceTarget { function renouncePauser() external; } interface OwnableTarget { function renounceOwnership() external; function transferOwnership(address newOwner) external; } contract AuthController is Ownable { function renounceMinter(address target) public onlyOwner { MinterRoleRenounceTarget(target).renounceMinter(); } function renouncePauser(address target) public onlyOwner { PauserRoleRenounceTarget(target).renouncePauser(); } function renounceOwnership(address target) public onlyOwner { OwnableTarget(target).renounceOwnership(); } function transferOwnership(address target, address newOwner) public onlyOwner { OwnableTarget(target).transferOwnership(newOwner); } } // File: contracts/stake/tokens/SeigToken.sol pragma solidity ^0.5.12; contract SeigToken is ERC20, Ownable, ERC20OnApprove, AuthController { SeigManagerI public seigManager; bool public callbackEnabled; function enableCallback(bool _callbackEnabled) external onlyOwner { callbackEnabled = _callbackEnabled; } function setSeigManager(SeigManagerI _seigManager) external onlyOwner { seigManager = _seigManager; } ////////////////////// // Override ERC20 functions ////////////////////// function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { return super.transferFrom(sender, recipient, amount); } function _transfer(address sender, address recipient, uint256 amount) internal { super._transfer(sender, recipient, amount); if (callbackEnabled && address(seigManager) != address(0)) { require(seigManager.onTransfer(sender, recipient, amount)); } } function _mint(address account, uint256 amount) internal { super._mint(account, amount); if (callbackEnabled && address(seigManager) != address(0)) { require(seigManager.onTransfer(address(0), account, amount)); } } function _burn(address account, uint256 amount) internal { super._burn(account, amount); if (callbackEnabled && address(seigManager) != address(0)) { require(seigManager.onTransfer(account, address(0), amount)); } } } // File: contracts/stake/tokens/WTON.sol pragma solidity ^0.5.12; contract WTON is DSMath, ReentrancyGuard, Ownable, ERC20Mintable, ERC20Burnable, ERC20Detailed, SeigToken, OnApprove { using SafeERC20 for ERC20Mintable; ERC20Mintable public ton; constructor ( ERC20Mintable _ton ) public ERC20Detailed("Wrapped TON", "WTON", 27) { require(ERC20Detailed(address(_ton)).decimals() == 18, "WTON: decimals of TON must be 18"); ton = _ton; } ////////////////////// // TON Approve callback ////////////////////// function onApprove( address owner, address spender, uint256 tonAmount, bytes calldata data ) external returns (bool) { require(msg.sender == address(ton), "WTON: only accept TON approve callback"); // swap owner's TON to WTON _swapFromTON(owner, owner, tonAmount); uint256 wtonAmount = _toRAY(tonAmount); (address depositManager, address layer2) = _decodeTONApproveData(data); // approve WTON to DepositManager _approve(owner, depositManager, wtonAmount); // call DepositManager.onApprove to deposit WTON bytes memory depositManagerOnApproveData = _encodeDepositManagerOnApproveData(layer2); _callOnApprove(owner, depositManager, wtonAmount, depositManagerOnApproveData); return true; } /** * @dev data is 64 bytes of 2 addresses in left-padded 32 bytes */ function _decodeTONApproveData( bytes memory data ) internal pure returns (address depositManager, address layer2) { require(data.length == 0x40); assembly { depositManager := mload(add(data, 0x20)) layer2 := mload(add(data, 0x40)) } } function _encodeDepositManagerOnApproveData( address layer2 ) internal pure returns (bytes memory data) { data = new bytes(0x20); assembly { mstore(add(data, 0x20), layer2) } } ////////////////////// // Override ERC20 functions ////////////////////// function burnFrom(address account, uint256 amount) public { if (isMinter(msg.sender)) { _burn(account, amount); return; } super.burnFrom(account, amount); } ////////////////////// // Swap functions ////////////////////// /** * @dev swap WTON to TON */ function swapToTON(uint256 wtonAmount) public nonReentrant returns (bool) { return _swapToTON(msg.sender, msg.sender, wtonAmount); } /** * @dev swap TON to WTON */ function swapFromTON(uint256 tonAmount) public nonReentrant returns (bool) { return _swapFromTON(msg.sender, msg.sender, tonAmount); } /** * @dev swap WTON to TON, and transfer TON * NOTE: TON's transfer event's `from` argument is not `msg.sender` but `WTON` address. */ function swapToTONAndTransfer(address to, uint256 wtonAmount) public nonReentrant returns (bool) { return _swapToTON(to, msg.sender, wtonAmount); } /** * @dev swap TON to WTON, and transfer WTON */ function swapFromTONAndTransfer(address to, uint256 tonAmount) public nonReentrant returns (bool) { return _swapFromTON(msg.sender, to, tonAmount); } function renounceTonMinter() external onlyOwner { ton.renounceMinter(); } ////////////////////// // Internal functions ////////////////////// function _swapToTON(address tonAccount, address wtonAccount, uint256 wtonAmount) internal returns (bool) { _burn(wtonAccount, wtonAmount); // mint TON if WTON contract has not enough TON to transfer uint256 tonAmount = _toWAD(wtonAmount); uint256 tonBalance = ton.balanceOf(address(this)); if (tonBalance < tonAmount) { ton.mint(address(this), tonAmount.sub(tonBalance)); } ton.safeTransfer(tonAccount, tonAmount); return true; } function _swapFromTON(address tonAccount, address wtonAccount, uint256 tonAmount) internal returns (bool) { _mint(wtonAccount, _toRAY(tonAmount)); ton.safeTransferFrom(tonAccount, address(this), tonAmount); return true; } /** * @dev transform WAD to RAY */ function _toRAY(uint256 v) internal pure returns (uint256) { return v * 10 ** 9; } /** * @dev transform RAY to WAD */ function _toWAD(uint256 v) internal pure returns (uint256) { return v / 10 ** 9; } } // File: contracts/lib/SortitionSumTreeFactory.sol // https://github.com/kleros/kleros/blob/683145a9e6de70f5be87599daaf7372578b9d110/contracts/data-structures/SortitionSumTreeFactory.sol /** * @reviewers: [@clesaege, @unknownunknown1, @ferittuncer] * @auditors: [] * @bounties: [<14 days 10 ETH max payout>] * @deployments: [] */ pragma solidity ^0.5.12; /** * @title SortitionSumTreeFactory * @author Enrique Piqueras - <[email protected]> * @dev A factory of trees that keep track of staked values for sortition. */ library SortitionSumTreeFactory { /* Structs */ struct SortitionSumTree { uint K; // The maximum number of childs per node. // We use this to keep track of vacant positions in the tree after removing a leaf. This is for keeping the tree as balanced as possible without spending gas on moving nodes around. uint[] stack; uint[] nodes; // Two-way mapping of IDs to node indexes. Note that node index 0 is reserved for the root node, and means the ID does not have a node. mapping(bytes32 => uint) IDsToNodeIndexes; mapping(uint => bytes32) nodeIndexesToIDs; } /* Storage */ struct SortitionSumTrees { mapping(bytes32 => SortitionSumTree) sortitionSumTrees; } /* Public */ /** * @dev Create a sortition sum tree at the specified key. * @param _key The key of the new tree. * @param _K The number of children each node in the tree should have. */ function createTree(SortitionSumTrees storage self, bytes32 _key, uint _K) internal { SortitionSumTree storage tree = self.sortitionSumTrees[_key]; require(tree.K == 0, "Tree already exists."); require(_K > 1, "K must be greater than one."); tree.K = _K; tree.stack.length = 0; tree.nodes.length = 0; tree.nodes.push(0); } /** * @dev Set a value of a tree. * @param _key The key of the tree. * @param _value The new value. * @param _ID The ID of the value. * `O(log_k(n))` where * `k` is the maximum number of childs per node in the tree, * and `n` is the maximum number of nodes ever appended. */ function set(SortitionSumTrees storage self, bytes32 _key, uint _value, bytes32 _ID) internal { SortitionSumTree storage tree = self.sortitionSumTrees[_key]; uint treeIndex = tree.IDsToNodeIndexes[_ID]; if (treeIndex == 0) { // No existing node. if (_value != 0) { // Non zero value. // Append. // Add node. if (tree.stack.length == 0) { // No vacant spots. // Get the index and append the value. treeIndex = tree.nodes.length; tree.nodes.push(_value); // Potentially append a new node and make the parent a sum node. if (treeIndex != 1 && (treeIndex - 1) % tree.K == 0) { // Is first child. uint parentIndex = treeIndex / tree.K; bytes32 parentID = tree.nodeIndexesToIDs[parentIndex]; uint newIndex = treeIndex + 1; tree.nodes.push(tree.nodes[parentIndex]); delete tree.nodeIndexesToIDs[parentIndex]; tree.IDsToNodeIndexes[parentID] = newIndex; tree.nodeIndexesToIDs[newIndex] = parentID; } } else { // Some vacant spot. // Pop the stack and append the value. treeIndex = tree.stack[tree.stack.length - 1]; tree.stack.length--; tree.nodes[treeIndex] = _value; } // Add label. tree.IDsToNodeIndexes[_ID] = treeIndex; tree.nodeIndexesToIDs[treeIndex] = _ID; updateParents(self, _key, treeIndex, true, _value); } } else { // Existing node. if (_value == 0) { // Zero value. // Remove. // Remember value and set to 0. uint value = tree.nodes[treeIndex]; tree.nodes[treeIndex] = 0; // Push to stack. tree.stack.push(treeIndex); // Clear label. delete tree.IDsToNodeIndexes[_ID]; delete tree.nodeIndexesToIDs[treeIndex]; updateParents(self, _key, treeIndex, false, value); } else if (_value != tree.nodes[treeIndex]) { // New, non zero value. // Set. bool plusOrMinus = tree.nodes[treeIndex] <= _value; uint plusOrMinusValue = plusOrMinus ? _value - tree.nodes[treeIndex] : tree.nodes[treeIndex] - _value; tree.nodes[treeIndex] = _value; updateParents(self, _key, treeIndex, plusOrMinus, plusOrMinusValue); } } } /* Public Views */ /** * @dev Query the leaves of a tree. Note that if `startIndex == 0`, the tree is empty and the root node will be returned. * @param _key The key of the tree to get the leaves from. * @param _cursor The pagination cursor. * @param _count The number of items to return. * @return The index at which leaves start, the values of the returned leaves, and whether there are more for pagination. * `O(n)` where * `n` is the maximum number of nodes ever appended. */ function queryLeafs( SortitionSumTrees storage self, bytes32 _key, uint _cursor, uint _count ) internal view returns(uint startIndex, uint[] memory values, bool hasMore) { SortitionSumTree storage tree = self.sortitionSumTrees[_key]; // Find the start index. for (uint i = 0; i < tree.nodes.length; i++) { if ((tree.K * i) + 1 >= tree.nodes.length) { startIndex = i; break; } } // Get the values. uint loopStartIndex = startIndex + _cursor; values = new uint[](loopStartIndex + _count > tree.nodes.length ? tree.nodes.length - loopStartIndex : _count); uint valuesIndex = 0; for (uint j = loopStartIndex; j < tree.nodes.length; j++) { if (valuesIndex < _count) { values[valuesIndex] = tree.nodes[j]; valuesIndex++; } else { hasMore = true; break; } } } /** * @dev Draw an ID from a tree using a number. Note that this function reverts if the sum of all values in the tree is 0. * @param _key The key of the tree. * @param _drawnNumber The drawn number. * @return The drawn ID. * `O(k * log_k(n))` where * `k` is the maximum number of childs per node in the tree, * and `n` is the maximum number of nodes ever appended. */ function draw(SortitionSumTrees storage self, bytes32 _key, uint _drawnNumber) internal view returns(bytes32 ID) { SortitionSumTree storage tree = self.sortitionSumTrees[_key]; uint treeIndex = 0; uint currentDrawnNumber = _drawnNumber % tree.nodes[0]; while ((tree.K * treeIndex) + 1 < tree.nodes.length) // While it still has children. for (uint i = 1; i <= tree.K; i++) { // Loop over children. uint nodeIndex = (tree.K * treeIndex) + i; uint nodeValue = tree.nodes[nodeIndex]; if (currentDrawnNumber >= nodeValue) currentDrawnNumber -= nodeValue; // Go to the next child. else { // Pick this child. treeIndex = nodeIndex; break; } } ID = tree.nodeIndexesToIDs[treeIndex]; } /** @dev Gets a specified ID's associated value. * @param _key The key of the tree. * @param _ID The ID of the value. * @return The associated value. */ function stakeOf(SortitionSumTrees storage self, bytes32 _key, bytes32 _ID) internal view returns(uint value) { SortitionSumTree storage tree = self.sortitionSumTrees[_key]; uint treeIndex = tree.IDsToNodeIndexes[_ID]; if (treeIndex == 0) value = 0; else value = tree.nodes[treeIndex]; } /* Private */ /** * @dev Update all the parents of a node. * @param _key The key of the tree to update. * @param _treeIndex The index of the node to start from. * @param _plusOrMinus Wether to add (true) or substract (false). * @param _value The value to add or substract. * `O(log_k(n))` where * `k` is the maximum number of childs per node in the tree, * and `n` is the maximum number of nodes ever appended. */ function updateParents(SortitionSumTrees storage self, bytes32 _key, uint _treeIndex, bool _plusOrMinus, uint _value) private { SortitionSumTree storage tree = self.sortitionSumTrees[_key]; uint parentIndex = _treeIndex; while (parentIndex != 0) { parentIndex = (parentIndex - 1) / tree.K; tree.nodes[parentIndex] = _plusOrMinus ? tree.nodes[parentIndex] + _value : tree.nodes[parentIndex] - _value; } } } // File: contracts/stake/interfaces/DepositManagerI.sol pragma solidity ^0.5.12; interface DepositManagerI { function owner() external view returns (address); function wton() external view returns (address); function registry() external view returns (address); function seigManager() external view returns (address); function accStaked(address layer2, address account) external view returns (uint256 wtonAmount); function accStakedLayer2(address layer2) external view returns (uint256 wtonAmount); function accStakedAccount(address account) external view returns (uint256 wtonAmount); function pendingUnstaked(address layer2, address account) external view returns (uint256 wtonAmount); function pendingUnstakedLayer2(address layer2) external view returns (uint256 wtonAmount); function pendingUnstakedAccount(address account) external view returns (uint256 wtonAmount); function accUnstaked(address layer2, address account) external view returns (uint256 wtonAmount); function accUnstakedLayer2(address layer2) external view returns (uint256 wtonAmount); function accUnstakedAccount(address account) external view returns (uint256 wtonAmount); function withdrawalRequestIndex(address layer2, address account) external view returns (uint256 index); function withdrawalRequest(address layer2, address account, uint256 index) external view returns (uint128 withdrawableBlockNumber, uint128 amount, bool processed ); function WITHDRAWAL_DELAY() external view returns (uint256); function setSeigManager(address seigManager) external; function deposit(address layer2, uint256 amount) external returns (bool); function requestWithdrawal(address layer2, uint256 amount) external returns (bool); function processRequest(address layer2) external returns (bool); function requestWithdrawalAll(address layer2) external returns (bool); function processRequests(address layer2, uint256 n) external returns (bool); function numRequests(address layer2, address account) external view returns (uint256); function numPendingRequests(address layer2, address account) external view returns (uint256); function slash(address layer2, address recipient, uint256 amount) external returns (bool); } // File: contracts/stake/interfaces/PowerTONI.sol pragma solidity ^0.5.12; interface PowerTONI { function seigManager() external view returns (address); function wton() external view returns (address); function currentRound() external view returns (uint256); function roundDuration() external view returns (uint256); function totalDeposits() external view returns (uint256); function winnerOf(uint256 round) external view returns (address); function powerOf(address account) external view returns (uint256); function init() external; function start() external; function endRound() external; function onDeposit(address layer2, address account, uint256 amount) external; function onWithdraw(address layer2, address account, uint256 amount) external; } // File: contracts/stake/powerton/PowerTON.sol pragma solidity ^0.5.12; pragma experimental ABIEncoderV2; contract PowerTON is Ownable, Pausable, AuthController, PowerTONI { using SafeMath for *; using SafeERC20 for IERC20; using SortitionSumTreeFactory for SortitionSumTreeFactory.SortitionSumTrees; struct Round { uint64 startTime; uint64 endTime; uint256 reward; address winner; } // contracts address internal _seigManager; address internal _wton; // rounds uint256 internal _currentRound; // TODO: consider block nubmer uint256 internal _roundDuration; // unix timestamp mapping(uint256 => Round) public rounds; // sortition SortitionSumTreeFactory.SortitionSumTrees internal sortitionSumTrees; bool public initialized; bytes32 constant internal TREE_KEY = keccak256("power-balances"); bytes32 constant internal TREE_KEY_PREFIX = keccak256("power-balances"); uint256 constant internal TREE_NUM_CHILDREN = 16; // balances uint256 internal _totalDeposits; // randomness uint256 internal constant maskLast8Bits = uint256(0xff); uint256 internal constant maskFirst248Bits = uint256(~0xff); ////////////////////////////// // Modifiers ////////////////////////////// modifier checkRound() { if (currentRoundFinished()) { _endRound(); } _; } ////////////////////////////// // Events ////////////////////////////// event RoundStart(uint256 round, uint256 startTime, uint256 endTime); event RoundEnd(uint256 round, address winner, uint256 reward); event PowerIncreased(address indexed account, uint256 amount); event PowerDecreased(address indexed account, uint256 amount); ////////////////////////////// // Constructor ////////////////////////////// constructor ( address seigManager, address wton, uint256 roundDuration ) public { require(roundDuration > 0); _seigManager = seigManager; _wton = wton; _roundDuration = roundDuration; } /** * @dev set SeigManager contract, only by owner. */ function setSeigManager(address seigManager) external onlyOwner { _seigManager = seigManager; } function init() external onlyOwner { require(!initialized); sortitionSumTrees.createTree(TREE_KEY, TREE_NUM_CHILDREN); initialized = true; } function start() external onlyOwner { require(_currentRound == 0, "PowerTON: current round is not zero"); require(rounds[_currentRound].startTime == 0 && rounds[_currentRound].endTime == 0, "PowerTON: round already started"); _startRound(0); } function powerOf(address account) external view returns (uint256) { return sortitionSumTrees.stakeOf(TREE_KEY, _getID(account)); } /** * @dev end current round */ function endRound() external { require(currentRoundFinished(), "PowerTON: round not finished"); _endRound(); } function roundStarted(uint256 round) public view returns (bool) { return rounds[round].startTime != 0 && rounds[round].endTime != 0; } function roundFinished(uint256 round) public view returns (bool) { return roundStarted(round) && rounds[round].endTime < block.timestamp && rounds[round].winner == address(0); } function currentRoundFinished() public view returns (bool) { return roundFinished(_currentRound); } function _endRound() internal { // short circuit in case of no deposit if (_totalDeposits == 0) { return; } uint256 round = _currentRound; Round storage r = rounds[round]; uint256 n = _seed(block.number - 1) % _totalDeposits; address winner = _recoverID(sortitionSumTrees.draw(TREE_KEY, n)); require(winner != address(0), "PowerTON: no winner"); r.winner = winner; uint256 reward = IERC20(_wton).balanceOf(address(this)); r.reward = reward; emit RoundEnd(round, winner, reward); _currentRound += 1; _startRound(_currentRound); WTON(_wton).swapToTONAndTransfer(winner, reward); } ////////////////////////////// // SeigManager ////////////////////////////// function onDeposit( address layer2, address account, uint256 amount ) external checkRound { require(msg.sender == _seigManager); _increaseEffectiveBalance(account, amount); _totalDeposits = _totalDeposits.add(amount); emit PowerIncreased(account, amount); } function onWithdraw( address layer2, address account, uint256 amount ) external checkRound { require(msg.sender == _seigManager); uint256 v = _decreaseEffectiveBalance(account, amount); _totalDeposits = _totalDeposits.sub(v); emit PowerDecreased(account, v); } ////////////////////////////// // External storage getters ////////////////////////////// function seigManager() external view returns (address) { return _seigManager; } function wton() external view returns (address) { return _wton; } function currentRound() external view returns (uint256) { return _currentRound; } function roundDuration() external view returns (uint256) { return _roundDuration; } function totalDeposits() external view returns (uint256) { return _totalDeposits; } function winnerOf(uint256 round) external view returns (address) { return rounds[round].winner; } ////////////////////////////// // Internal functions ////////////////////////////// // TODO: enable upgradability // TODO: use other entrophy source // https://github.com/cryptocopycats/awesome-cryptokitties/blob/master/contracts/GeneScience.sol#L111-L133 function _seed(uint256 _targetBlock) internal view returns (uint256 randomN) { uint256 h = uint256(blockhash(_targetBlock)); if (h == 0) { _targetBlock = (block.number & maskFirst248Bits) + (_targetBlock & maskLast8Bits); if (_targetBlock >= block.number) _targetBlock -= 256; h = uint256(blockhash(_targetBlock)); } randomN = (h + block.number + uint256(blockhash(block.number - 1))) * h * h * _totalDeposits; } function _startRound(uint256 round) internal { require( round == 0 || (rounds[round - 1].endTime < block.timestamp && rounds[round - 1].winner != address(0)) ); Round storage r = rounds[round]; require(r.startTime == 0 && r.endTime == 0 && r.winner == address(0)); uint64 startTime = uint64(block.timestamp); uint64 endTime = uint64(block.timestamp + _roundDuration); r.startTime = startTime; r.endTime = endTime; emit RoundStart(round, startTime, endTime); } function _increaseEffectiveBalance(address account, uint256 amount) internal { bytes32 id = _getID(account); uint256 value = sortitionSumTrees.stakeOf(TREE_KEY, id).add(amount); sortitionSumTrees.set(TREE_KEY, value, id); } function _decreaseEffectiveBalance(address account, uint256 amount) internal returns (uint256) { bytes32 id = _getID(account); uint256 stake = sortitionSumTrees.stakeOf(TREE_KEY, id); uint256 value = _sub0(stake, amount); sortitionSumTrees.set(TREE_KEY, value, id); return stake - value; } /** * @dev return a - b if a > b, otherwise 0 */ function _sub0(uint256 a, uint256 b) internal pure returns (uint256) { if (a > b) return a - b; return 0; } function _getID(address account) internal pure returns (bytes32) { return bytes32(uint256(account)); } function _recoverID(bytes32 id) internal pure returns (address) { return address(uint160(uint256(id))); } function _getTreeKey(uint256 round) internal pure returns (bytes32 k) { require(round < 2 ** 224); k = bytes32(TREE_KEY_PREFIX); assembly { k := add(k, round) } } }
File 7 of 8: Layer2Registry
// File: openzeppelin-solidity/contracts/GSN/Context.sol pragma solidity ^0.5.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: openzeppelin-solidity/contracts/ownership/Ownable.sol pragma solidity ^0.5.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: contracts/Layer2I.sol pragma solidity ^0.5.12; interface Layer2I { function operator() external view returns (address); function isLayer2() external view returns (bool); function currentFork() external view returns (uint); function lastEpoch(uint forkNumber) external view returns (uint); function changeOperator(address _operator) external; } // File: contracts/stake/interfaces/SeigManagerI.sol pragma solidity ^0.5.12; interface SeigManagerI { function registry() external view returns (address); function depositManager() external view returns (address); function ton() external view returns (address); function wton() external view returns (address); function powerton() external view returns (address); function tot() external view returns (address); function coinages(address layer2) external view returns (address); function commissionRates(address layer2) external view returns (uint256); function lastCommitBlock(address layer2) external view returns (uint256); function seigPerBlock() external view returns (uint256); function lastSeigBlock() external view returns (uint256); function pausedBlock() external view returns (uint256); function unpausedBlock() external view returns (uint256); function DEFAULT_FACTOR() external view returns (uint256); function deployCoinage(address layer2) external returns (bool); function setCommissionRate(address layer2, uint256 commission, bool isCommissionRateNegative) external returns (bool); function uncomittedStakeOf(address layer2, address account) external view returns (uint256); function stakeOf(address layer2, address account) external view returns (uint256); function additionalTotBurnAmount(address layer2, address account, uint256 amount) external view returns (uint256 totAmount); function onTransfer(address sender, address recipient, uint256 amount) external returns (bool); function updateSeigniorage() external returns (bool); function onDeposit(address layer2, address account, uint256 amount) external returns (bool); function onWithdraw(address layer2, address account, uint256 amount) external returns (bool); } // File: contracts/stake/interfaces/Layer2RegistryI.sol pragma solidity ^0.5.12; interface Layer2RegistryI { function layer2s(address layer2) external view returns (bool); function register(address layer2) external returns (bool); function numLayer2s() external view returns (uint256); function layer2ByIndex(uint256 index) external view returns (address); function deployCoinage(address layer2, address seigManager) external returns (bool); function registerAndDeployCoinage(address layer2, address seigManager) external returns (bool); function unregister(address layer2) external returns (bool); } // File: contracts/stake/Layer2Registry.sol pragma solidity ^0.5.12; // TODO: transfer coinages ownership to seig manager contract Layer2Registry is Layer2RegistryI, Ownable { // check whether the address is layer2 contract or not mapping (address => bool) internal _layer2s; // array-like storages // NOTE: unregistered layer2s could exists in that array. so, should check by layer2s(address) uint256 internal _numLayer2s; mapping (uint256 => address) internal _layer2ByIndex; modifier onlyOwnerOrOperator(address layer2) { require(isOwner() || Layer2I(layer2).operator() == msg.sender, "sender is neither operator nor operator"); _; } function layer2s(address layer2) external view returns (bool) { return _layer2s[layer2]; } function numLayer2s() external view returns (uint256) { return _numLayer2s; } function layer2ByIndex(uint256 index) external view returns (address) { return _layer2ByIndex[index]; } function register(address layer2) external onlyOwnerOrOperator(layer2) returns (bool) { return _register(layer2); } function _register(address layer2) internal returns (bool) { require(!_layer2s[layer2]); require(Layer2I(layer2).isLayer2()); _layer2s[layer2] = true; _layer2ByIndex[_numLayer2s] = layer2; _numLayer2s += 1; return true; } function deployCoinage( address layer2, address seigManager ) external onlyOwnerOrOperator(layer2) returns (bool) { return _deployCoinage(layer2, seigManager); } function _deployCoinage( address layer2, address seigManager ) internal returns (bool) { return SeigManagerI(seigManager).deployCoinage(layer2); } function registerAndDeployCoinage( address layer2, address seigManager ) external onlyOwnerOrOperator(layer2) returns (bool) { require(_register(layer2)); require(_deployCoinage(layer2, seigManager)); return true; } function registerAndDeployCoinageAndSetCommissionRate( address layer2, address seigManager, uint256 commissionRate, bool isCommissionRateNegative ) external onlyOwnerOrOperator(layer2) returns (bool) { require(_register(layer2)); require(_deployCoinage(layer2, seigManager)); require(_setCommissionRate(layer2, seigManager, commissionRate, isCommissionRateNegative)); return true; } function _setCommissionRate( address layer2, address seigManager, uint256 commissionRate, bool isCommissionRateNegative ) internal returns (bool) { return SeigManagerI(seigManager).setCommissionRate(layer2, commissionRate, isCommissionRateNegative); } function unregister(address layer2) external onlyOwner returns (bool) { require(_layer2s[layer2]); _layer2s[layer2] = false; } }
File 8 of 8: SeigManager
pragma solidity ^0.5.12; interface SeigManagerI { function registry() external view returns (address); function depositManager() external view returns (address); function ton() external view returns (address); function wton() external view returns (address); function powerton() external view returns (address); function tot() external view returns (address); function coinages(address layer2) external view returns (address); function commissionRates(address layer2) external view returns (uint256); function lastCommitBlock(address layer2) external view returns (uint256); function seigPerBlock() external view returns (uint256); function lastSeigBlock() external view returns (uint256); function pausedBlock() external view returns (uint256); function unpausedBlock() external view returns (uint256); function DEFAULT_FACTOR() external view returns (uint256); function deployCoinage(address layer2) external returns (bool); function setCommissionRate(address layer2, uint256 commission, bool isCommissionRateNegative) external returns (bool); function uncomittedStakeOf(address layer2, address account) external view returns (uint256); function stakeOf(address layer2, address account) external view returns (uint256); function additionalTotBurnAmount(address layer2, address account, uint256 amount) external view returns (uint256 totAmount); function onTransfer(address sender, address recipient, uint256 amount) external returns (bool); function updateSeigniorage() external returns (bool); function onDeposit(address layer2, address account, uint256 amount) external returns (bool); function onWithdraw(address layer2, address account, uint256 amount) external returns (bool); } // https://github.com/dapphub/ds-math/blob/de45767/src/math.sol /// math.sol -- mixin for inline numerical wizardry // 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.4.13; contract DSMath { function add(uint x, uint y) internal pure returns (uint z) { require((z = x + y) >= x, "ds-math-add-overflow"); } function sub(uint x, uint y) internal pure returns (uint z) { require((z = x - y) <= x, "ds-math-sub-underflow"); } function mul(uint x, uint y) internal pure returns (uint z) { require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow"); } function min(uint x, uint y) internal pure returns (uint z) { return x <= y ? x : y; } function max(uint x, uint y) internal pure returns (uint z) { return x >= y ? x : y; } function imin(int x, int y) internal pure returns (int z) { return x <= y ? x : y; } function imax(int x, int y) internal pure returns (int z) { return x >= y ? x : y; } uint constant WAD = 10 ** 18; uint constant RAY = 10 ** 27; function wmul(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, y), WAD / 2) / WAD; } function rmul(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, y), RAY / 2) / RAY; } function wdiv(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, WAD), y / 2) / y; } function rdiv(uint x, uint y) internal pure returns (uint z) { z = add(mul(x, RAY), y / 2) / y; } function wmul2(uint x, uint y) internal pure returns (uint z) { z = mul(x, y) / WAD; } function rmul2(uint x, uint y) internal pure returns (uint z) { z = mul(x, y) / RAY; } function wdiv2(uint x, uint y) internal pure returns (uint z) { z = mul(x, WAD) / y; } function rdiv2(uint x, uint y) internal pure returns (uint z) { z = mul(x, RAY) / y; } // This famous algorithm is called "exponentiation by squaring" // and calculates x^n with x as fixed-point and n as regular unsigned. // // It's O(log n), instead of O(n) for naive repeated multiplication. // // These facts are why it works: // // If n is even, then x^n = (x^2)^(n/2). // If n is odd, then x^n = x * x^(n-1), // and applying the equation for even x gives // x^n = x * (x^2)^((n-1) / 2). // // Also, EVM division is flooring and // floor[(n-1) / 2] = floor[n / 2]. // function wpow(uint x, uint n) internal pure returns (uint z) { z = n % 2 != 0 ? x : WAD; for (n /= 2; n != 0; n /= 2) { x = wmul(x, x); if (n % 2 != 0) { z = wmul(z, x); } } } function rpow(uint x, uint n) internal pure returns (uint z) { z = n % 2 != 0 ? x : RAY; for (n /= 2; n != 0; n /= 2) { x = rmul(x, x); if (n % 2 != 0) { z = rmul(z, x); } } } } pragma solidity ^0.5.0; import "Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } pragma solidity ^0.5.0; import "Context.sol"; import "PauserRole.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ contract Pausable is Context, PauserRole { /** * @dev Emitted when the pause is triggered by a pauser (`account`). */ event Paused(address account); /** * @dev Emitted when the pause is lifted by a pauser (`account`). */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. Assigns the Pauser role * to the deployer. */ constructor () internal { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPaused() { require(!_paused, "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. */ modifier whenPaused() { require(_paused, "Pausable: not paused"); _; } /** * @dev Called by a pauser to pause, triggers stopped state. */ function pause() public onlyPauser whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Called by a pauser to unpause, returns to normal state. */ function unpause() public onlyPauser whenPaused { _paused = false; emit Unpaused(_msgSender()); } } pragma solidity ^0.5.12; import { Ownable } from "Ownable.sol"; interface MinterRoleRenounceTarget { function renounceMinter() external; } interface PauserRoleRenounceTarget { function renouncePauser() external; } interface OwnableTarget { function renounceOwnership() external; function transferOwnership(address newOwner) external; } contract AuthController is Ownable { function renounceMinter(address target) public onlyOwner { MinterRoleRenounceTarget(target).renounceMinter(); } function renouncePauser(address target) public onlyOwner { PauserRoleRenounceTarget(target).renouncePauser(); } function renounceOwnership(address target) public onlyOwner { OwnableTarget(target).renounceOwnership(); } function transferOwnership(address target, address newOwner) public onlyOwner { OwnableTarget(target).transferOwnership(newOwner); } }pragma solidity ^0.5.12; import "lib/Roles.sol"; contract ChallengerRole { using Roles for Roles.Role; event ChallengerAdded(address indexed account); event ChallengerRemoved(address indexed account); Roles.Role private _challengers; constructor () internal { _addChallenger(msg.sender); } modifier onlyChallenger() { require(isChallenger(msg.sender)); _; } function isChallenger(address account) public view returns (bool) { return _challengers.has(account); } function addChallenger(address account) public onlyChallenger { _addChallenger(account); } function renounceChallenger() public { _removeChallenger(msg.sender); } function _addChallenger(address account) internal { _challengers.add(account); emit ChallengerAdded(account); } function _removeChallenger(address account) internal { _challengers.remove(account); emit ChallengerRemoved(account); } } pragma solidity ^0.5.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } pragma solidity ^0.5.0; import "Context.sol"; import "openzeppelin-solidity/Roles.sol"; contract PauserRole is Context { using Roles for Roles.Role; event PauserAdded(address indexed account); event PauserRemoved(address indexed account); Roles.Role private _pausers; constructor () internal { _addPauser(_msgSender()); } modifier onlyPauser() { require(isPauser(_msgSender()), "PauserRole: caller does not have the Pauser role"); _; } function isPauser(address account) public view returns (bool) { return _pausers.has(account); } function addPauser(address account) public onlyPauser { _addPauser(account); } function renouncePauser() public { _removePauser(_msgSender()); } function _addPauser(address account) internal { _pausers.add(account); emit PauserAdded(account); } function _removePauser(address account) internal { _pausers.remove(account); emit PauserRemoved(account); } } pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot 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-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } pragma solidity ^0.5.0; import "ERC20.sol"; import "MinterRole.sol"; /** * @dev Extension of {ERC20} that adds a set of accounts with the {MinterRole}, * which have permission to mint (create) new tokens as they see fit. * * At construction, the deployer of the contract is the only minter. */ contract ERC20Mintable is ERC20, MinterRole { /** * @dev See {ERC20-_mint}. * * Requirements: * * - the caller must have the {MinterRole}. */ function mint(address account, uint256 amount) public onlyMinter returns (bool) { _mint(account, amount); return true; } } pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: 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 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } pragma solidity ^0.5.0; import "IERC20.sol"; import "SafeMath.sol"; import "Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } pragma solidity ^0.5.12; interface AutoRefactorCoinageI { function factor() external view returns (uint256); function setFactor(uint256 factor) external returns (bool); function burn(uint256 amount) external; function burnFrom(address account, uint256 amount) external; function mint(address account, uint256 amount) external returns (bool); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function addMinter(address account) external; function renounceMinter() external; function transferOwnership(address newOwner) external; } pragma solidity ^0.5.12; interface CoinageFactoryI { function deploy() external returns (address); } pragma solidity ^0.5.12; interface Layer2I { function operator() external view returns (address); function isLayer2() external view returns (bool); function currentFork() external view returns (uint); function lastEpoch(uint forkNumber) external view returns (uint); function changeOperator(address _operator) external; } pragma solidity ^0.5.12; interface Layer2RegistryI { function layer2s(address layer2) external view returns (bool); function register(address layer2) external returns (bool); function numLayer2s() external view returns (uint256); function layer2ByIndex(uint256 index) external view returns (address); function deployCoinage(address layer2, address seigManager) external returns (bool); function registerAndDeployCoinage(address layer2, address seigManager) external returns (bool); function unregister(address layer2) external returns (bool); } pragma solidity ^0.5.12; interface DepositManagerI { function owner() external view returns (address); function wton() external view returns (address); function registry() external view returns (address); function seigManager() external view returns (address); function accStaked(address layer2, address account) external view returns (uint256 wtonAmount); function accStakedLayer2(address layer2) external view returns (uint256 wtonAmount); function accStakedAccount(address account) external view returns (uint256 wtonAmount); function pendingUnstaked(address layer2, address account) external view returns (uint256 wtonAmount); function pendingUnstakedLayer2(address layer2) external view returns (uint256 wtonAmount); function pendingUnstakedAccount(address account) external view returns (uint256 wtonAmount); function accUnstaked(address layer2, address account) external view returns (uint256 wtonAmount); function accUnstakedLayer2(address layer2) external view returns (uint256 wtonAmount); function accUnstakedAccount(address account) external view returns (uint256 wtonAmount); function withdrawalRequestIndex(address layer2, address account) external view returns (uint256 index); function withdrawalRequest(address layer2, address account, uint256 index) external view returns (uint128 withdrawableBlockNumber, uint128 amount, bool processed ); function WITHDRAWAL_DELAY() external view returns (uint256); function setSeigManager(address seigManager) external; function deposit(address layer2, uint256 amount) external returns (bool); function requestWithdrawal(address layer2, uint256 amount) external returns (bool); function processRequest(address layer2) external returns (bool); function requestWithdrawalAll(address layer2) external returns (bool); function processRequests(address layer2, uint256 n) external returns (bool); function numRequests(address layer2, address account) external view returns (uint256); function numPendingRequests(address layer2, address account) external view returns (uint256); function slash(address layer2, address recipient, uint256 amount) external returns (bool); } pragma solidity ^0.5.12; interface PowerTONI { function seigManager() external view returns (address); function wton() external view returns (address); function currentRound() external view returns (uint256); function roundDuration() external view returns (uint256); function totalDeposits() external view returns (uint256); function winnerOf(uint256 round) external view returns (address); function powerOf(address account) external view returns (uint256); function init() external; function start() external; function endRound() external; function onDeposit(address layer2, address account, uint256 amount) external; function onWithdraw(address layer2, address account, uint256 amount) external; } // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/67bca85/contracts/access/Roles.sol pragma solidity ^0.5.12; /** * @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(!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(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]; } } pragma solidity ^0.5.0; /** * @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(!has(role, account), "Roles: account already has role"); role.bearer[account] = true; } /** * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { require(has(role, account), "Roles: account does not have role"); 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), "Roles: account is the zero address"); return role.bearer[account]; } } pragma solidity ^0.5.0; import "Context.sol"; import "IERC20.sol"; import "SafeMath.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20Mintable}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for `sender`'s tokens of at least * `amount`. */ 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; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ 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); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ 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); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ 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); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ 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); } /** * @dev Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); } } pragma solidity ^0.5.0; import "Context.sol"; import "openzeppelin-solidity/Roles.sol"; 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); } } // https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/utils/Address.sol pragma solidity ^0.5.12; /** * Utility library of inline functions on addresses */ library Address { /** * Returns whether the target address is a contract * @dev This function will return false if invoked during the constructor of a contract, * as the code is not actually created until after the constructor finishes. * @param account address of the account to check * @return whether the target address is a contract */ function isContract(address account) internal view returns (bool) { uint256 size; // XXX Currently there is no better way to check if there is a contract in an address // than to check the size of the code at that address. // See https://ethereum.stackexchange.com/a/14016/36603 // for more details about how this works. // TODO Check this again before the Serenity release, because all addresses will be // contracts then. // solium-disable-next-line security/no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } } pragma solidity ^0.5.12; import { Ownable } from "Ownable.sol"; import { Pausable } from "Pausable.sol"; import { SafeMath } from "SafeMath.sol"; import { ERC20Mintable } from "ERC20Mintable.sol"; import { IERC20 } from "IERC20.sol"; import { SafeERC20 } from "SafeERC20.sol"; import { DSMath } from "DSMath.sol"; import { AutoRefactorCoinageI } from "AutoRefactorCoinageI.sol"; import { CoinageFactoryI } from "CoinageFactoryI.sol"; import { AuthController } from "AuthController.sol"; import { ChallengerRole } from "ChallengerRole.sol"; import { Layer2I } from "Layer2I.sol"; import { SeigManagerI } from "SeigManagerI.sol"; import { Layer2RegistryI } from "Layer2RegistryI.sol"; import { DepositManagerI } from "DepositManagerI.sol"; import { PowerTONI } from "PowerTONI.sol"; /** * @dev SeigManager gives seigniorage to operator and WTON holders. * For each commit by operator, operator (or user) will get seigniorage * in propotion to the staked (or delegated) amount of WTON. * * [Tokens] * - {tot} tracks total staked or delegated WTON of each Layer2 contract (and depositor?). * - {coinages[layer2]} tracks staked or delegated WTON of user or operator to a Layer2 contract. * * For each commit by operator, * 1. increases all layer2's balance of {tot} by (the staked amount of WTON) / * (total supply of TON and WTON) * (num blocks * seigniorage per block). * 2. increases all depositors' blanace of {coinages[layer2]} in proportion to the staked amount of WTON, * up to the increased amount in step (1). * 3. set the layer2's balance of {committed} as the layer2's {tot} balance. * * For each stake or delegate with amount of {v} to a Layer2, * 1. mint {v} {coinages[layer2]} tokens to the account * 2. mint {v} {tot} tokens to the layer2 contract * * For each unstake or undelegate (or get rewards) with amount of {v} to a Layer2, * 1. burn {v} {coinages[layer2]} tokens from the account * 2. burn {v + ⍺} {tot} tokens from the layer2 contract, * where ⍺ = SEIGS * staked ratio of the layer2 * withdrawal ratio of the account * - SEIGS = tot total supply - tot total supply at last commit from the layer2 * - staked ratio of the layer2 = tot balance of the layer2 / tot total supply * - withdrawal ratio of the account = amount to withdraw / total supply of coinage * */ contract SeigManager is SeigManagerI, DSMath, Ownable, Pausable, AuthController, ChallengerRole { using SafeMath for uint256; using SafeERC20 for ERC20Mintable; ////////////////////////////// // Common contracts ////////////////////////////// Layer2RegistryI internal _registry; DepositManagerI internal _depositManager; PowerTONI internal _powerton; address public dao; ////////////////////////////// // Token-related ////////////////////////////// // TON token contract IERC20 internal _ton; // WTON token contract ERC20Mintable internal _wton; // TODO: use mintable erc20! // contract factory CoinageFactoryI public factory; // track total deposits of each layer2. AutoRefactorCoinageI internal _tot; // coinage token for each layer2. mapping (address => AutoRefactorCoinageI) internal _coinages; // last commit block number for each layer2. mapping (address => uint256) internal _lastCommitBlock; // total seigniorage per block uint256 internal _seigPerBlock; // the block number when seigniorages are given uint256 internal _lastSeigBlock; // block number when paused or unpaused uint256 internal _pausedBlock; uint256 internal _unpausedBlock; // commission rates in RAY mapping (address => uint256) internal _commissionRates; // whether commission is negative or not (default=possitive) mapping (address => bool) internal _isCommissionRateNegative; // setting commissionrate delay uint256 public adjustCommissionDelay; mapping (address => uint256) public delayedCommissionBlock; mapping (address => uint256) public delayedCommissionRate; mapping (address => bool) public delayedCommissionRateNegative; // minimum deposit amount uint256 public minimumAmount; uint256 public powerTONSeigRate; uint256 public daoSeigRate; uint256 public relativeSeigRate; uint256 public accRelativeSeig; ////////////////////////////// // Constants ////////////////////////////// uint256 constant public RAY = 10 ** 27; // 1 RAY uint256 constant internal _DEFAULT_FACTOR = RAY; uint256 constant public MAX_VALID_COMMISSION = RAY; // 1 RAY uint256 constant public MIN_VALID_COMMISSION = 10 ** 25; // 0.01 RAY ////////////////////////////// // Modifiers ////////////////////////////// modifier onlyRegistry() { require(msg.sender == address(_registry)); _; } modifier onlyRegistryOrOperator(address layer2) { require(msg.sender == address(_registry) || msg.sender == Layer2I(layer2).operator()); _; } modifier onlyDepositManager() { require(msg.sender == address(_depositManager)); _; } modifier onlyLayer2(address layer2) { require(_registry.layer2s(layer2)); _; } modifier checkCoinage(address layer2) { require(address(_coinages[layer2]) != address(0), "SeigManager: coinage has not been deployed yet"); _; } ////////////////////////////// // Events ////////////////////////////// event CoinageCreated(address indexed layer2, address coinage); event SeigGiven(address indexed layer2, uint256 totalSeig, uint256 stakedSeig, uint256 unstakedSeig, uint256 powertonSeig, uint256 pseig); event Comitted(address indexed layer2); event CommissionRateSet(address indexed layer2, uint256 previousRate, uint256 newRate); ////////////////////////////// // Constuctor ////////////////////////////// constructor ( ERC20Mintable ton, ERC20Mintable wton, Layer2RegistryI registry, DepositManagerI depositManager, uint256 seigPerBlock, address factory_ ) public { _ton = ton; _wton = wton; _registry = registry; _depositManager = depositManager; _seigPerBlock = seigPerBlock; factory = CoinageFactoryI(factory_); address c = factory.deploy(); _tot = AutoRefactorCoinageI(c); _lastSeigBlock = block.number; } ////////////////////////////// // Override Pausable ////////////////////////////// function pause() public onlyPauser whenNotPaused { _pausedBlock = block.number; super.pause(); } /** * @dev Called by a pauser to unpause, returns to normal state. */ function unpause() public onlyPauser whenPaused { _unpausedBlock = block.number; super.unpause(); } ////////////////////////////// // External functions ////////////////////////////// /** * @dev set PowerTON contract, only by owner. */ function setPowerTON(PowerTONI powerton) external onlyOwner { _powerton = powerton; } function setDao(address daoAddress) external onlyOwner { dao = daoAddress; } /** * @dev deploy coinage token for the layer2. */ function deployCoinage(address layer2) external onlyRegistry returns (bool) { // create new coinage token for the layer2 contract if (address(_coinages[layer2]) == address(0)) { address c = factory.deploy(); _lastCommitBlock[layer2] = block.number; addChallenger(layer2); _coinages[layer2] = AutoRefactorCoinageI(c); emit CoinageCreated(layer2, c); } return true; } function setCommissionRate( address layer2, uint256 commissionRate, bool isCommissionRateNegative ) external onlyRegistryOrOperator(layer2) returns (bool) { // check commission range require( (commissionRate == 0) || (MIN_VALID_COMMISSION <= commissionRate && commissionRate <= MAX_VALID_COMMISSION), "SeigManager: commission rate must be 0 or between 1 RAY and 0.01 RAY" ); uint256 previous = _commissionRates[layer2]; if (adjustCommissionDelay == 0) { _commissionRates[layer2] = commissionRate; _isCommissionRateNegative[layer2] = isCommissionRateNegative; } else { delayedCommissionBlock[layer2] = block.number + adjustCommissionDelay; delayedCommissionRate[layer2] = commissionRate; delayedCommissionRateNegative[layer2] = isCommissionRateNegative; } emit CommissionRateSet(layer2, previous, commissionRate); return true; } function getOperatorAmount(address layer2) public view returns (uint256) { address operator = Layer2I(msg.sender).operator(); return _coinages[layer2].balanceOf(operator); } /** * @dev Callback for a new commit */ function updateSeigniorage() external checkCoinage(msg.sender) returns (bool) { // short circuit if paused if (paused()) { return true; } uint256 operatorAmount = getOperatorAmount(msg.sender); require(operatorAmount >= minimumAmount); _increaseTot(); _lastCommitBlock[msg.sender] = block.number; // 2. increase total supply of {coinages[layer2]} AutoRefactorCoinageI coinage = _coinages[msg.sender]; uint256 prevTotalSupply = coinage.totalSupply(); uint256 nextTotalSupply = _tot.balanceOf(msg.sender); // short circuit if there is no seigs for the layer2 if (prevTotalSupply >= nextTotalSupply) { emit Comitted(msg.sender); return true; } uint256 seigs = nextTotalSupply - prevTotalSupply; address operator = Layer2I(msg.sender).operator(); uint256 operatorSeigs; // calculate commission amount bool isCommissionRateNegative = _isCommissionRateNegative[msg.sender]; (nextTotalSupply, operatorSeigs) = _calcSeigsDistribution( msg.sender, coinage, prevTotalSupply, seigs, isCommissionRateNegative, operator ); // gives seigniorages to the layer2 as coinage coinage.setFactor( _calcNewFactor( prevTotalSupply, nextTotalSupply, coinage.factor() ) ); // give commission to operator or delegators if (operatorSeigs != 0) { if (isCommissionRateNegative) { // TODO: adjust arithmetic error // burn by ? coinage.burnFrom(operator, operatorSeigs); } else { coinage.mint(operator, operatorSeigs); } } _wton.mint(address(_depositManager), seigs); emit Comitted(msg.sender); return true; } function _calcSeigsDistribution( address layer2, AutoRefactorCoinageI coinage, uint256 prevTotalSupply, uint256 seigs, bool isCommissionRateNegative, address operator ) internal returns ( uint256 nextTotalSupply, uint256 operatorSeigs ) { if (block.number >= delayedCommissionBlock[layer2] && delayedCommissionBlock[layer2] != 0) { _commissionRates[layer2] = delayedCommissionRate[layer2]; _isCommissionRateNegative[layer2] = delayedCommissionRateNegative[layer2]; delayedCommissionBlock[layer2] = 0; } uint256 commissionRate = _commissionRates[msg.sender]; nextTotalSupply = prevTotalSupply + seigs; // short circuit if there is no commission rate if (commissionRate == 0) { return (nextTotalSupply, operatorSeigs); } // if commission rate is possitive if (!isCommissionRateNegative) { operatorSeigs = rmul(seigs, commissionRate); // additional seig for operator nextTotalSupply = nextTotalSupply.sub(operatorSeigs); return (nextTotalSupply, operatorSeigs); } // short circuit if there is no previous total deposit (meanning, there is no deposit) if (prevTotalSupply == 0) { return (nextTotalSupply, operatorSeigs); } // See negative commission distribution formular here: TBD uint256 operatorBalance = coinage.balanceOf(operator); // short circuit if there is no operator deposit if (operatorBalance == 0) { return (nextTotalSupply, operatorSeigs); } uint256 operatorRate = rdiv(operatorBalance, prevTotalSupply); // ɑ: insufficient seig for operator operatorSeigs = rmul( rmul(seigs, operatorRate), // seigs for operator commissionRate ); // β: uint256 delegatorSeigs = operatorRate == RAY ? operatorSeigs : rdiv(operatorSeigs, RAY - operatorRate); // ?: operatorSeigs = operatorRate == RAY ? operatorSeigs : operatorSeigs + rmul(delegatorSeigs, operatorRate); nextTotalSupply = nextTotalSupply.add(delegatorSeigs); return (nextTotalSupply, operatorSeigs); } /** * @dev Callback for a token transfer */ function onTransfer(address sender, address recipient, uint256 amount) external returns (bool) { require(msg.sender == address(_ton) || msg.sender == address(_wton), "SeigManager: only TON or WTON can call onTransfer"); if (!paused()) { _increaseTot(); } return true; } /** * @dev Callback for a new deposit */ function onDeposit(address layer2, address account, uint256 amount) external onlyDepositManager checkCoinage(layer2) returns (bool) { if (_isOperator(layer2, account)) { uint256 newAmount = _coinages[layer2].balanceOf(account).add(amount); require(newAmount >= minimumAmount, "minimum amount is required"); } _tot.mint(layer2, amount); _coinages[layer2].mint(account, amount); if (address(_powerton) != address(0)) { _powerton.onDeposit(layer2, account, amount); } return true; } // DEV ONLY event UnstakeLog(uint coinageBurnAmount, uint totBurnAmount); function onWithdraw(address layer2, address account, uint256 amount) external onlyDepositManager checkCoinage(layer2) returns (bool) { require(_coinages[layer2].balanceOf(account) >= amount, "SeigManager: insufficiant balance to unstake"); if (_isOperator(layer2, account)) { uint256 newAmount = _coinages[layer2].balanceOf(account).sub(amount); require(newAmount >= minimumAmount, "minimum amount is required"); } // burn {v + ⍺} {tot} tokens to the layer2 contract, uint256 totAmount = _additionalTotBurnAmount(layer2, account, amount); _tot.burnFrom(layer2, amount.add(totAmount)); // burn {v} {coinages[layer2]} tokens to the account _coinages[layer2].burnFrom(account, amount); if (address(_powerton) != address(0)) { _powerton.onWithdraw(layer2, account, amount); } emit UnstakeLog(amount, totAmount); return true; } function setPowerTONSeigRate(uint256 powerTONSeigRate_) external onlyOwner { require(powerTONSeigRate_ > 0 && powerTONSeigRate_ < RAY, "exceeded seigniorage rate"); powerTONSeigRate = powerTONSeigRate_; } function setDaoSeigRate(uint256 daoSeigRate_) external onlyOwner { require(daoSeigRate_ > 0 && daoSeigRate_ < RAY, "exceeded seigniorage rate"); daoSeigRate = daoSeigRate_; } function setPseigRate(uint256 PseigRate_) external onlyOwner { require(PseigRate_ > 0 && PseigRate_ < RAY, "exceeded seigniorage rate"); relativeSeigRate = PseigRate_; } function setCoinageFactory(address factory_) external onlyOwner { factory = CoinageFactoryI(factory_); } function addChallenger(address account) public onlyRegistry { _addChallenger(account); } function transferCoinageOwnership(address newSeigManager, address[] calldata coinages) external onlyOwner { for (uint256 i = 0; i < coinages.length; i++) { AutoRefactorCoinageI c = AutoRefactorCoinageI(coinages[i]); c.addMinter(newSeigManager); c.renounceMinter(); c.transferOwnership(newSeigManager); } } function renounceWTONMinter() external onlyOwner { _wton.renounceMinter(); } function slash(address layer2, address challenger) external onlyChallenger checkCoinage(layer2) returns (bool) { Layer2I(layer2).changeOperator(challenger); return true; } function additionalTotBurnAmount(address layer2, address account, uint256 amount) external view returns (uint256 totAmount) { return _additionalTotBurnAmount(layer2, account, amount); } // return ⍺, where ⍺ = (tot.balanceOf(layer2) - coinages[layer2].totalSupply()) * (amount / coinages[layer2].totalSupply()) function _additionalTotBurnAmount(address layer2, address account, uint256 amount) internal view returns (uint256 totAmount) { uint256 coinageTotalSupply = _coinages[layer2].totalSupply(); uint256 totBalalnce = _tot.balanceOf(layer2); // NOTE: arithamtic operations (mul and div) make some errors, so we gonna adjust them under 1e-9 WTON. // note that coinageTotalSupply and totBalalnce are RAY values. if (coinageTotalSupply > totBalalnce && coinageTotalSupply - totBalalnce < WAD) { return 0; } return rdiv( rmul( totBalalnce.sub(coinageTotalSupply), amount ), coinageTotalSupply ); } function setAdjustDelay(uint256 adjustDelay_) external onlyOwner { adjustCommissionDelay = adjustDelay_; } function setMinimumAmount(uint256 minimumAmount_) external onlyOwner { minimumAmount = minimumAmount_; } ////////////////////////////// // Public and internal functions ////////////////////////////// function uncomittedStakeOf(address layer2, address account) external view returns (uint256) { AutoRefactorCoinageI coinage = _coinages[layer2]; uint256 prevFactor = coinage.factor(); uint256 prevTotalSupply = coinage.totalSupply(); uint256 nextTotalSupply = _tot.balanceOf(layer2); uint256 newFactor = _calcNewFactor(prevTotalSupply, nextTotalSupply, prevFactor); uint256 uncomittedBalance = rmul( rdiv(coinage.balanceOf(account), prevFactor), newFactor ); return uncomittedBalance .sub(_coinages[layer2].balanceOf(account)); } function stakeOf(address layer2, address account) external view returns (uint256) { return _coinages[layer2].balanceOf(account); } function _calcNewFactor(uint256 source, uint256 target, uint256 oldFactor) internal pure returns (uint256) { return rdiv(rmul(target, oldFactor), source); } // DEV ONLY event CommitLog1(uint256 totalStakedAmount, uint256 totalSupplyOfWTON, uint256 prevTotalSupply, uint256 nextTotalSupply); function _increaseTot() internal returns (bool) { // short circuit if already seigniorage is given. if (block.number == _lastSeigBlock) { return false; } if (_tot.totalSupply() == 0) { _lastSeigBlock = block.number; return false; } uint256 prevTotalSupply; uint256 nextTotalSupply; // 1. increase total supply of {tot} by maximum seigniorages * staked rate // staked rate = total staked amount / total supply of (W)TON prevTotalSupply = _tot.totalSupply(); // maximum seigniorages uint256 maxSeig = _calcNumSeigBlocks().mul(_seigPerBlock); // total supply of (W)TON uint256 tos = _ton.totalSupply() .sub(_ton.balanceOf(address(_wton))) .mul(10 ** 9) // convert TON total supply into ray .add(_tot.totalSupply()); // consider additional TOT balance as total supply // maximum seigniorages * staked rate uint256 stakedSeig = rdiv( rmul( maxSeig, // total staked amount _tot.totalSupply() ), tos ); // pseig uint256 totalPseig = rmul(maxSeig.sub(stakedSeig), relativeSeigRate); nextTotalSupply = prevTotalSupply.add(stakedSeig).add(totalPseig); _lastSeigBlock = block.number; _tot.setFactor(_calcNewFactor(prevTotalSupply, nextTotalSupply, _tot.factor())); // TODO: reduce computation // DEV ONLY emit CommitLog1( _tot.totalSupply(), tos, prevTotalSupply, nextTotalSupply ); uint256 unstakedSeig = maxSeig.sub(stakedSeig); uint256 powertonSeig; uint256 daoSeig; uint256 relativeSeig; if (address(_powerton) != address(0)) { powertonSeig = rmul(unstakedSeig, powerTONSeigRate); _wton.mint(address(_powerton), powertonSeig); } if (dao != address(0)) { daoSeig = rmul(unstakedSeig, daoSeigRate); _wton.mint(address(dao), daoSeig); } if (relativeSeigRate != 0) { relativeSeig = totalPseig; accRelativeSeig = accRelativeSeig.add(relativeSeig); } emit SeigGiven(msg.sender, maxSeig, stakedSeig, unstakedSeig, powertonSeig, relativeSeig); return true; } function _calcNumSeigBlocks() internal view returns (uint256) { require(!paused()); uint256 span = block.number - _lastSeigBlock; if (_unpausedBlock < _lastSeigBlock) { return span; } return span - (_unpausedBlock - _pausedBlock); } function _isOperator(address layer2, address operator) internal view returns (bool) { return operator == Layer2I(layer2).operator(); } ////////////////////////////// // Storage getters ////////////////////////////// // solium-disable function registry() external view returns (address) { return address(_registry); } function depositManager() external view returns (address) { return address(_depositManager); } function ton() external view returns (address) { return address(_ton); } function wton() external view returns (address) { return address(_wton); } function powerton() external view returns (address) { return address(_powerton); } function tot() external view returns (address) { return address(_tot); } function coinages(address layer2) external view returns (address) { return address(_coinages[layer2]); } function commissionRates(address layer2) external view returns (uint256) { return _commissionRates[layer2]; } function isCommissionRateNegative(address layer2) external view returns (bool) { return _isCommissionRateNegative[layer2]; } function lastCommitBlock(address layer2) external view returns (uint256) { return _lastCommitBlock[layer2]; } function seigPerBlock() external view returns (uint256) { return _seigPerBlock; } function lastSeigBlock() external view returns (uint256) { return _lastSeigBlock; } function pausedBlock() external view returns (uint256) { return _pausedBlock; } function unpausedBlock() external view returns (uint256) { return _unpausedBlock; } function DEFAULT_FACTOR() external view returns (uint256) { return _DEFAULT_FACTOR; } // solium-enable }