Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 15,825 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Unbind Stake | 20195101 | 297 days ago | IN | 0 ETH | 0.00002781 | ||||
Withdraw | 16862156 | 765 days ago | IN | 0 ETH | 0.00054885 | ||||
Withdraw | 16506959 | 815 days ago | IN | 0 ETH | 0.0005708 | ||||
Withdraw | 16506959 | 815 days ago | IN | 0 ETH | 0.00052689 | ||||
Withdraw | 16506959 | 815 days ago | IN | 0 ETH | 0.00063666 | ||||
Withdraw | 16506958 | 815 days ago | IN | 0 ETH | 0.00064544 | ||||
Withdraw | 16506958 | 815 days ago | IN | 0 ETH | 0.0008562 | ||||
Withdraw | 16506958 | 815 days ago | IN | 0 ETH | 0.00074643 | ||||
Withdraw | 16506958 | 815 days ago | IN | 0 ETH | 0.00094402 | ||||
Withdraw | 16506958 | 815 days ago | IN | 0 ETH | 0.00111306 | ||||
Withdraw | 16506958 | 815 days ago | IN | 0 ETH | 0.00118551 | ||||
Withdraw | 16506958 | 815 days ago | IN | 0 ETH | 0.00131724 | ||||
Withdraw | 16506958 | 815 days ago | IN | 0 ETH | 0.00074643 | ||||
Withdraw | 16506957 | 815 days ago | IN | 0 ETH | 0.0007247 | ||||
Withdraw | 16506957 | 815 days ago | IN | 0 ETH | 0.00208563 | ||||
Withdraw | 16506957 | 815 days ago | IN | 0 ETH | 0.00153678 | ||||
Bind Stake | 15817230 | 911 days ago | IN | 0 ETH | 0.00071341 | ||||
Bind Stake | 15817230 | 911 days ago | IN | 0 ETH | 0.0007255 | ||||
Bind Stake | 15817230 | 911 days ago | IN | 0 ETH | 0.00071341 | ||||
Bind Stake | 15817230 | 911 days ago | IN | 0 ETH | 0.00079146 | ||||
Bind Stake | 15817230 | 911 days ago | IN | 0 ETH | 0.00096294 | ||||
Unbind Stake | 15192027 | 1005 days ago | IN | 0 ETH | 0.00010982 | ||||
Unbind Stake | 15190545 | 1005 days ago | IN | 0 ETH | 0.00083622 | ||||
Unbind Stake | 15190545 | 1005 days ago | IN | 0 ETH | 0.00093154 | ||||
Unbind Stake | 15190545 | 1005 days ago | IN | 0 ETH | 0.00127896 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
Staking
Compiler Version
v0.6.8+commit.0bbfe453
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion, Apache-2.0 license, Audited
Contract Source Code (Solidity)Audit Report
/** *Submitted for verification at Etherscan.io on 2020-10-15 */ // SPDX-License-Identifier: (Apache-2.0 AND MIT AND BSD-4-Clause) //------------------------------------------------------------------------------ // // Copyright 2020 Fetch.AI Limited // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //------------------------------------------------------------------------------ pragma solidity ^0.6.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ 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); } /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256` * (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping (bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { require(set._values.length > index, "EnumerableSet: index out of bounds"); return set._values[index]; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(value))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(value))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(value))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint256(_at(set._inner, index))); } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } } /** * @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 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]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return _functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); return _functionCallWithValue(target, data, value, errorMessage); } function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } /* * @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. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } /** * @dev Contract module that allows children to implement role-based access * control mechanisms. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context { using EnumerableSet for EnumerableSet.AddressSet; using Address for address; struct RoleData { EnumerableSet.AddressSet members; bytes32 adminRole; } mapping (bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view returns (bool) { return _roles[role].members.contains(account); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) public view returns (uint256) { return _roles[role].members.length(); } /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view returns (address) { return _roles[role].members.at(index); } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual { require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant"); _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual { require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke"); _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { emit RoleAdminChanged(role, _roles[role].adminRole, adminRole); _roles[role].adminRole = adminRole; } function _grantRole(bytes32 role, address account) private { if (_roles[role].members.add(account)) { emit RoleGranted(role, account, _msgSender()); } } function _revokeRole(bytes32 role, address account) private { if (_roles[role].members.remove(account)) { emit RoleRevoked(role, account, _msgSender()); } } } //------------------------------------------------------------------------------ // // Copyright 2020 Fetch.AI Limited // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //------------------------------------------------------------------------------ /* * ABDK Math 64.64 Smart Contract Library. Copyright © 2019 by ABDK Consulting. * Author: Mikhail Vladimirov <[email protected]> */ /** * Smart contract library of mathematical functions operating with signed * 64.64-bit fixed point numbers. Signed 64.64-bit fixed point number is * basically a simple fraction whose numerator is signed 128-bit integer and * denominator is 2^64. As long as denominator is always the same, there is no * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are * represented by int128 type holding only the numerator. */ library ABDKMath64x64 { /* * Minimum value signed 64.64-bit fixed point number may have. */ int128 private constant MIN_64x64 = -0x80000000000000000000000000000000; /* * Maximum value signed 64.64-bit fixed point number may have. */ int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; /** * Convert signed 256-bit integer number into signed 64.64-bit fixed point * number. Revert on overflow. * * @param x signed 256-bit integer number * @return signed 64.64-bit fixed point number */ function fromInt (int256 x) internal pure returns (int128) { require (x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF); return int128 (x << 64); } /** * Convert signed 64.64 fixed point number into signed 64-bit integer number * rounding down. * * @param x signed 64.64-bit fixed point number * @return signed 64-bit integer number */ function toInt (int128 x) internal pure returns (int64) { return int64 (x >> 64); } /** * Convert unsigned 256-bit integer number into signed 64.64-bit fixed point * number. Revert on overflow. * * @param x unsigned 256-bit integer number * @return signed 64.64-bit fixed point number */ function fromUInt (uint256 x) internal pure returns (int128) { require (x <= 0x7FFFFFFFFFFFFFFF); return int128 (x << 64); } /** * Convert signed 64.64 fixed point number into unsigned 64-bit integer * number rounding down. Revert on underflow. * * @param x signed 64.64-bit fixed point number * @return unsigned 64-bit integer number */ function toUInt (int128 x) internal pure returns (uint64) { require (x >= 0); return uint64 (x >> 64); } /** * Convert signed 128.128 fixed point number into signed 64.64-bit fixed point * number rounding down. Revert on overflow. * * @param x signed 128.128-bin fixed point number * @return signed 64.64-bit fixed point number */ function from128x128 (int256 x) internal pure returns (int128) { int256 result = x >> 64; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } /** * Convert signed 64.64 fixed point number into signed 128.128 fixed point * number. * * @param x signed 64.64-bit fixed point number * @return signed 128.128 fixed point number */ function to128x128 (int128 x) internal pure returns (int256) { return int256 (x) << 64; } /** * Calculate x + y. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function add (int128 x, int128 y) internal pure returns (int128) { int256 result = int256(x) + y; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } /** * Calculate x - y. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function sub (int128 x, int128 y) internal pure returns (int128) { int256 result = int256(x) - y; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } /** * Calculate x * y rounding down. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function mul (int128 x, int128 y) internal pure returns (int128) { int256 result = int256(x) * y >> 64; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } /** * Calculate x * y rounding towards zero, where x is signed 64.64 fixed point * number and y is signed 256-bit integer number. Revert on overflow. * * @param x signed 64.64 fixed point number * @param y signed 256-bit integer number * @return signed 256-bit integer number */ function muli (int128 x, int256 y) internal pure returns (int256) { if (x == MIN_64x64) { require (y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF && y <= 0x1000000000000000000000000000000000000000000000000); return -y << 63; } else { bool negativeResult = false; if (x < 0) { x = -x; negativeResult = true; } if (y < 0) { y = -y; // We rely on overflow behavior here negativeResult = !negativeResult; } uint256 absoluteResult = mulu (x, uint256 (y)); if (negativeResult) { require (absoluteResult <= 0x8000000000000000000000000000000000000000000000000000000000000000); return -int256 (absoluteResult); // We rely on overflow behavior here } else { require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int256 (absoluteResult); } } } /** * Calculate x * y rounding down, where x is signed 64.64 fixed point number * and y is unsigned 256-bit integer number. Revert on overflow. * * @param x signed 64.64 fixed point number * @param y unsigned 256-bit integer number * @return unsigned 256-bit integer number */ function mulu (int128 x, uint256 y) internal pure returns (uint256) { if (y == 0) return 0; require (x >= 0); uint256 lo = (uint256 (x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64; uint256 hi = uint256 (x) * (y >> 128); require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); hi <<= 64; require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo); return hi + lo; } /** * Calculate x / y rounding towards zero. Revert on overflow or when y is * zero. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function div (int128 x, int128 y) internal pure returns (int128) { require (y != 0); int256 result = (int256 (x) << 64) / y; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } /** * Calculate x / y rounding towards zero, where x and y are signed 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x signed 256-bit integer number * @param y signed 256-bit integer number * @return signed 64.64-bit fixed point number */ function divi (int256 x, int256 y) internal pure returns (int128) { require (y != 0); bool negativeResult = false; if (x < 0) { x = -x; // We rely on overflow behavior here negativeResult = true; } if (y < 0) { y = -y; // We rely on overflow behavior here negativeResult = !negativeResult; } uint128 absoluteResult = divuu (uint256 (x), uint256 (y)); if (negativeResult) { require (absoluteResult <= 0x80000000000000000000000000000000); return -int128 (absoluteResult); // We rely on overflow behavior here } else { require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int128 (absoluteResult); // We rely on overflow behavior here } } /** * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x unsigned 256-bit integer number * @param y unsigned 256-bit integer number * @return signed 64.64-bit fixed point number */ function divu (uint256 x, uint256 y) internal pure returns (int128) { require (y != 0); uint128 result = divuu (x, y); require (result <= uint128 (MAX_64x64)); return int128 (result); } /** * Calculate -x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function neg (int128 x) internal pure returns (int128) { require (x != MIN_64x64); return -x; } /** * Calculate |x|. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function abs (int128 x) internal pure returns (int128) { require (x != MIN_64x64); return x < 0 ? -x : x; } /** * Calculate 1 / x rounding towards zero. Revert on overflow or when x is * zero. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function inv (int128 x) internal pure returns (int128) { require (x != 0); int256 result = int256 (0x100000000000000000000000000000000) / x; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } /** * Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function avg (int128 x, int128 y) internal pure returns (int128) { return int128 ((int256 (x) + int256 (y)) >> 1); } /** * Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down. * Revert on overflow or in case x * y is negative. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function gavg (int128 x, int128 y) internal pure returns (int128) { int256 m = int256 (x) * int256 (y); require (m >= 0); require (m < 0x4000000000000000000000000000000000000000000000000000000000000000); return int128 (sqrtu (uint256 (m))); } /** * Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number * and y is unsigned 256-bit integer number. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y uint256 value * @return signed 64.64-bit fixed point number */ function pow (int128 x, uint256 y) internal pure returns (int128) { uint256 absoluteResult; bool negativeResult = false; if (x >= 0) { absoluteResult = powu (uint256 (x) << 63, y); } else { // We rely on overflow behavior here absoluteResult = powu (uint256 (uint128 (-x)) << 63, y); negativeResult = y & 1 > 0; } absoluteResult >>= 63; if (negativeResult) { require (absoluteResult <= 0x80000000000000000000000000000000); return -int128 (absoluteResult); // We rely on overflow behavior here } else { require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int128 (absoluteResult); // We rely on overflow behavior here } } /** * Calculate sqrt (x) rounding down. Revert if x < 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function sqrt (int128 x) internal pure returns (int128) { require (x >= 0); return int128 (sqrtu (uint256 (x) << 64)); } /** * Calculate binary logarithm of x. Revert if x <= 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function log_2 (int128 x) internal pure returns (int128) { require (x > 0); int256 msb = 0; int256 xc = x; if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; } if (xc >= 0x100000000) { xc >>= 32; msb += 32; } if (xc >= 0x10000) { xc >>= 16; msb += 16; } if (xc >= 0x100) { xc >>= 8; msb += 8; } if (xc >= 0x10) { xc >>= 4; msb += 4; } if (xc >= 0x4) { xc >>= 2; msb += 2; } if (xc >= 0x2) msb += 1; // No need to shift xc anymore int256 result = msb - 64 << 64; uint256 ux = uint256 (x) << uint256 (127 - msb); for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) { ux *= ux; uint256 b = ux >> 255; ux >>= 127 + b; result += bit * int256 (b); } return int128 (result); } /** * Calculate natural logarithm of x. Revert if x <= 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function ln (int128 x) internal pure returns (int128) { require (x > 0); return int128 ( uint256 (log_2 (x)) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF >> 128); } /** * Calculate binary exponent of x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function exp_2 (int128 x) internal pure returns (int128) { require (x < 0x400000000000000000); // Overflow if (x < -0x400000000000000000) return 0; // Underflow uint256 result = 0x80000000000000000000000000000000; if (x & 0x8000000000000000 > 0) result = result * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128; if (x & 0x4000000000000000 > 0) result = result * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128; if (x & 0x2000000000000000 > 0) result = result * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128; if (x & 0x1000000000000000 > 0) result = result * 0x10B5586CF9890F6298B92B71842A98363 >> 128; if (x & 0x800000000000000 > 0) result = result * 0x1059B0D31585743AE7C548EB68CA417FD >> 128; if (x & 0x400000000000000 > 0) result = result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128; if (x & 0x200000000000000 > 0) result = result * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128; if (x & 0x100000000000000 > 0) result = result * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128; if (x & 0x80000000000000 > 0) result = result * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128; if (x & 0x40000000000000 > 0) result = result * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128; if (x & 0x20000000000000 > 0) result = result * 0x100162F3904051FA128BCA9C55C31E5DF >> 128; if (x & 0x10000000000000 > 0) result = result * 0x1000B175EFFDC76BA38E31671CA939725 >> 128; if (x & 0x8000000000000 > 0) result = result * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128; if (x & 0x4000000000000 > 0) result = result * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128; if (x & 0x2000000000000 > 0) result = result * 0x1000162E525EE054754457D5995292026 >> 128; if (x & 0x1000000000000 > 0) result = result * 0x10000B17255775C040618BF4A4ADE83FC >> 128; if (x & 0x800000000000 > 0) result = result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128; if (x & 0x400000000000 > 0) result = result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128; if (x & 0x200000000000 > 0) result = result * 0x10000162E43F4F831060E02D839A9D16D >> 128; if (x & 0x100000000000 > 0) result = result * 0x100000B1721BCFC99D9F890EA06911763 >> 128; if (x & 0x80000000000 > 0) result = result * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128; if (x & 0x40000000000 > 0) result = result * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128; if (x & 0x20000000000 > 0) result = result * 0x100000162E430E5A18F6119E3C02282A5 >> 128; if (x & 0x10000000000 > 0) result = result * 0x1000000B1721835514B86E6D96EFD1BFE >> 128; if (x & 0x8000000000 > 0) result = result * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128; if (x & 0x4000000000 > 0) result = result * 0x10000002C5C8601CC6B9E94213C72737A >> 128; if (x & 0x2000000000 > 0) result = result * 0x1000000162E42FFF037DF38AA2B219F06 >> 128; if (x & 0x1000000000 > 0) result = result * 0x10000000B17217FBA9C739AA5819F44F9 >> 128; if (x & 0x800000000 > 0) result = result * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128; if (x & 0x400000000 > 0) result = result * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128; if (x & 0x200000000 > 0) result = result * 0x10000000162E42FF0999CE3541B9FFFCF >> 128; if (x & 0x100000000 > 0) result = result * 0x100000000B17217F80F4EF5AADDA45554 >> 128; if (x & 0x80000000 > 0) result = result * 0x10000000058B90BFBF8479BD5A81B51AD >> 128; if (x & 0x40000000 > 0) result = result * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128; if (x & 0x20000000 > 0) result = result * 0x100000000162E42FEFB2FED257559BDAA >> 128; if (x & 0x10000000 > 0) result = result * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128; if (x & 0x8000000 > 0) result = result * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128; if (x & 0x4000000 > 0) result = result * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128; if (x & 0x2000000 > 0) result = result * 0x1000000000162E42FEFA494F1478FDE05 >> 128; if (x & 0x1000000 > 0) result = result * 0x10000000000B17217F7D20CF927C8E94C >> 128; if (x & 0x800000 > 0) result = result * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128; if (x & 0x400000 > 0) result = result * 0x100000000002C5C85FDF477B662B26945 >> 128; if (x & 0x200000 > 0) result = result * 0x10000000000162E42FEFA3AE53369388C >> 128; if (x & 0x100000 > 0) result = result * 0x100000000000B17217F7D1D351A389D40 >> 128; if (x & 0x80000 > 0) result = result * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128; if (x & 0x40000 > 0) result = result * 0x1000000000002C5C85FDF4741BEA6E77E >> 128; if (x & 0x20000 > 0) result = result * 0x100000000000162E42FEFA39FE95583C2 >> 128; if (x & 0x10000 > 0) result = result * 0x1000000000000B17217F7D1CFB72B45E1 >> 128; if (x & 0x8000 > 0) result = result * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128; if (x & 0x4000 > 0) result = result * 0x10000000000002C5C85FDF473E242EA38 >> 128; if (x & 0x2000 > 0) result = result * 0x1000000000000162E42FEFA39F02B772C >> 128; if (x & 0x1000 > 0) result = result * 0x10000000000000B17217F7D1CF7D83C1A >> 128; if (x & 0x800 > 0) result = result * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128; if (x & 0x400 > 0) result = result * 0x100000000000002C5C85FDF473DEA871F >> 128; if (x & 0x200 > 0) result = result * 0x10000000000000162E42FEFA39EF44D91 >> 128; if (x & 0x100 > 0) result = result * 0x100000000000000B17217F7D1CF79E949 >> 128; if (x & 0x80 > 0) result = result * 0x10000000000000058B90BFBE8E7BCE544 >> 128; if (x & 0x40 > 0) result = result * 0x1000000000000002C5C85FDF473DE6ECA >> 128; if (x & 0x20 > 0) result = result * 0x100000000000000162E42FEFA39EF366F >> 128; if (x & 0x10 > 0) result = result * 0x1000000000000000B17217F7D1CF79AFA >> 128; if (x & 0x8 > 0) result = result * 0x100000000000000058B90BFBE8E7BCD6D >> 128; if (x & 0x4 > 0) result = result * 0x10000000000000002C5C85FDF473DE6B2 >> 128; if (x & 0x2 > 0) result = result * 0x1000000000000000162E42FEFA39EF358 >> 128; if (x & 0x1 > 0) result = result * 0x10000000000000000B17217F7D1CF79AB >> 128; result >>= uint256 (63 - (x >> 64)); require (result <= uint256 (MAX_64x64)); return int128 (result); } /** * Calculate natural exponent of x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function exp (int128 x) internal pure returns (int128) { require (x < 0x400000000000000000); // Overflow if (x < -0x400000000000000000) return 0; // Underflow return exp_2 ( int128 (int256 (x) * 0x171547652B82FE1777D0FFDA0D23A7D12 >> 128)); } /** * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x unsigned 256-bit integer number * @param y unsigned 256-bit integer number * @return unsigned 64.64-bit fixed point number */ function divuu (uint256 x, uint256 y) private pure returns (uint128) { require (y != 0); uint256 result; if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y; else { uint256 msb = 192; uint256 xc = x >> 192; if (xc >= 0x100000000) { xc >>= 32; msb += 32; } if (xc >= 0x10000) { xc >>= 16; msb += 16; } if (xc >= 0x100) { xc >>= 8; msb += 8; } if (xc >= 0x10) { xc >>= 4; msb += 4; } if (xc >= 0x4) { xc >>= 2; msb += 2; } if (xc >= 0x2) msb += 1; // No need to shift xc anymore result = (x << 255 - msb) / ((y - 1 >> msb - 191) + 1); require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); uint256 hi = result * (y >> 128); uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); uint256 xh = x >> 192; uint256 xl = x << 64; if (xl < lo) xh -= 1; xl -= lo; // We rely on overflow behavior here lo = hi << 128; if (xl < lo) xh -= 1; xl -= lo; // We rely on overflow behavior here assert (xh == hi >> 128); result += xl / y; } require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return uint128 (result); } /** * Calculate x^y assuming 0^0 is 1, where x is unsigned 129.127 fixed point * number and y is unsigned 256-bit integer number. Revert on overflow. * * @param x unsigned 129.127-bit fixed point number * @param y uint256 value * @return unsigned 129.127-bit fixed point number */ function powu (uint256 x, uint256 y) private pure returns (uint256) { if (y == 0) return 0x80000000000000000000000000000000; else if (x == 0) return 0; else { int256 msb = 0; uint256 xc = x; if (xc >= 0x100000000000000000000000000000000) { xc >>= 128; msb += 128; } if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; } if (xc >= 0x100000000) { xc >>= 32; msb += 32; } if (xc >= 0x10000) { xc >>= 16; msb += 16; } if (xc >= 0x100) { xc >>= 8; msb += 8; } if (xc >= 0x10) { xc >>= 4; msb += 4; } if (xc >= 0x4) { xc >>= 2; msb += 2; } if (xc >= 0x2) msb += 1; // No need to shift xc anymore int256 xe = msb - 127; if (xe > 0) x >>= uint256 (xe); else x <<= uint256 (-xe); uint256 result = 0x80000000000000000000000000000000; int256 re = 0; while (y > 0) { if (y & 1 > 0) { result = result * x; y -= 1; re += xe; if (result >= 0x8000000000000000000000000000000000000000000000000000000000000000) { result >>= 128; re += 1; } else result >>= 127; if (re < -127) return 0; // Underflow require (re < 128); // Overflow } else { x = x * x; y >>= 1; xe <<= 1; if (x >= 0x8000000000000000000000000000000000000000000000000000000000000000) { x >>= 128; xe += 1; } else x >>= 127; if (xe < -127) return 0; // Underflow require (xe < 128); // Overflow } } if (re > 0) result <<= uint256 (re); else if (re < 0) result >>= uint256 (-re); return result; } } /** * Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer * number. * * @param x unsigned 256-bit integer number * @return unsigned 128-bit integer number */ function sqrtu (uint256 x) private pure returns (uint128) { if (x == 0) return 0; else { uint256 xx = x; uint256 r = 1; if (xx >= 0x100000000000000000000000000000000) { xx >>= 128; r <<= 64; } if (xx >= 0x10000000000000000) { xx >>= 64; r <<= 32; } if (xx >= 0x100000000) { xx >>= 32; r <<= 16; } if (xx >= 0x10000) { xx >>= 16; r <<= 8; } if (xx >= 0x100) { xx >>= 8; r <<= 4; } if (xx >= 0x10) { xx >>= 4; r <<= 2; } if (xx >= 0x8) { r <<= 1; } r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; // Seven iterations should be enough uint256 r1 = x / r; return uint128 (r < r1 ? r : r1); } } } //------------------------------------------------------------------------------ // // Copyright 2020 Fetch.AI Limited // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //------------------------------------------------------------------------------ /** * @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. */ 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. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 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. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } library AssetLib { using SafeMath for uint256; struct Asset { uint256 principal; uint256 compoundInterest; } function composite(Asset storage asset) internal view returns(uint256) { return asset.principal.add(asset.compoundInterest); } function compositeM(Asset memory asset) internal pure returns(uint256) { return asset.principal.add(asset.compoundInterest); } function imAddS(Asset memory to, Asset storage amount) internal view { to.principal = to.principal.add(amount.principal); to.compoundInterest = to.compoundInterest.add(amount.compoundInterest); } function iAdd(Asset storage to, Asset memory amount) internal { to.principal = to.principal.add(amount.principal); to.compoundInterest = to.compoundInterest.add(amount.compoundInterest); } function imSubM(Asset memory from, Asset storage amount) internal view { from.principal = from.principal.sub(amount.principal); from.compoundInterest = from.compoundInterest.sub(amount.compoundInterest); } function iSub(Asset storage from, Asset memory amount) internal { from.principal = from.principal.sub(amount.principal); from.compoundInterest = from.compoundInterest.sub(amount.compoundInterest); } function iSubPrincipalFirst(Asset storage from, uint256 amount) internal returns(Asset memory _amount) { if (from.principal >= amount) { from.principal = from.principal.sub(amount); _amount.principal = amount; } else { _amount.compoundInterest = amount.sub(from.principal); // NOTE(pb): Fail as soon as possible (even though this ordering of lines makes code less readable): from.compoundInterest = from.compoundInterest.sub(_amount.compoundInterest); _amount.principal = from.principal; from.principal = 0; } } function iSubCompoundInterestFirst(Asset storage from, uint256 amount) internal returns(Asset memory _amount) { if (from.compoundInterest >= amount) { from.compoundInterest = from.compoundInterest.sub(amount); _amount.compoundInterest = amount; } else { _amount.principal = amount.sub(from.compoundInterest); // NOTE(pb): Fail as soon as possible (even though this ordering of lines makes code less readable): from.principal = from.principal.sub(_amount.principal); _amount.compoundInterest = from.compoundInterest; from.compoundInterest = 0; } } // NOTE(pb): This is a little bit more expensive version of the commented-out function bellow, // but it avoids copying the code by reusing (calling existing functions), and so // making code more reliable and readable. function iRelocatePrincipalFirst(Asset storage from, Asset storage to, uint256 amount) internal returns(Asset memory _amount) { _amount = iSubPrincipalFirst(from, amount); iAdd(to, _amount); } // NOTE(pb): This is a little bit more expensive version of the commented-out function bellow, // but it avoids copying the code by reusing (calling existing functions), and so // making code more reliable and readable. function iRelocateCompoundInterestFirst(Asset storage from, Asset storage to, uint256 amount) internal returns(Asset memory _amount) { _amount = iSubCompoundInterestFirst(from, amount); iAdd(to, _amount); } ////NOTE(pb): Whole Commented out code block bellow consumes less gas then variant above, however for the price //// of copy code which can be rather called (see notes in the commented out code): //function iRelocatePrincipalFirst(Asset storage from, Asset storage to, uint256 amount) // internal pure returns(Asset memory _amount) //{ // if (from.principal >= amount) { // from.principal = from.principal.sub(amount); // to.principal = to.principal.add(amount); // // NOTE(pb): Line bellow is enough - no necessity to call subtract for compound as it is called in // // uncommented variant of this function above. // _amount.principal = amount; // } else { // _amount.compoundInterest = amount.sub(from.principal); // // NOTE(pb): Fail as soon as possible (even though this ordering of lines makes code less readable): // from.compoundInterest = from.compoundInterest.sub(_amount.compoundInterest); // to.compoundInterest = to.compoundInterest.add(_amount.compoundInterest); // to.principal = to.principal.add(from.principal); // _amount.principal = from.principal; // // NOTE(pb): Line bellow is enough - no necessity to call subtract for principal as it is called in // // uncommented variant of this function above. // from.principal = 0; // } //} //function iRelocateCompoundInterestFirst(Asset storage from, Asset storage to, uint256 amount) // internal pure returns(Asset memory _amount) //{ // if (from.compoundInterest >= amount) { // from.compoundInterest = from.compoundInterest.sub(amount); // to.compoundInterest = to.compoundInterest.add(amount); // // NOTE(pb): Line bellow is enough - no necessity to call subtract for principal as it is called in // // uncommented variant of this function above. // _amount.compoundInterest = amount; // } else { // _amount.principal = amount.sub(from.compoundInterest); // // NOTE(pb): Fail as soon as possible (even though this ordering of lines makes code less readable): // from.principal = from.principal.sub(_amount.principal); // to.principal = to.principal.add(_amount.principal); // to.compoundInterest = to.compoundInterest.add(from.compoundInterest); // _amount.compoundInterest = from.compoundInterest; // // NOTE(pb): Line bellow is enough - no necessity to call subtract for compound as it is called in // // uncommented variant of this function above. // from.compoundInterest = 0; // } //} } library Finance { using SafeMath for uint256; using AssetLib for AssetLib.Asset; function pow (int128 x, uint256 n) internal pure returns (int128 r) { r = ABDKMath64x64.fromUInt (1); while (n != 0) { if ((n & 1) != 0) { r = ABDKMath64x64.mul (r, x); n -= 1; } else { x = ABDKMath64x64.mul (x, x); n >>= 1; } } } function compoundInterest (uint256 principal, uint256 ratio, uint256 n) internal pure returns (uint256) { return ABDKMath64x64.mulu ( pow ( ABDKMath64x64.add ( ABDKMath64x64.fromUInt (1), ABDKMath64x64.divu ( ratio, 10**18) ), n ), principal); } function compoundInterest (uint256 principal, int256 ratio, uint256 n) internal pure returns (uint256) { return ABDKMath64x64.mulu ( pow ( ABDKMath64x64.add ( ABDKMath64x64.fromUInt (1), ABDKMath64x64.divi ( ratio, 10**18) ), n ), principal); } function compoundInterest (AssetLib.Asset storage asset, uint256 interest, uint256 n) internal { uint256 composite = asset.composite(); composite = compoundInterest(composite, interest, n); asset.compoundInterest = composite.sub(asset.principal); } } // [Canonical ERC20-FET] = 10**(-18)x[ECR20-FET] contract Staking is AccessControl { using SafeMath for uint256; using AssetLib for AssetLib.Asset; struct InterestRatePerBlock { uint256 sinceBlock; // NOTE(pb): To simplify, interest rate value can *not* be negative uint256 rate; // Signed interest rate in [10**18] units => real_rate = rate / 10**18. //// Number of users who bound stake while this particular interest rate was still in effect. //// This enables to identify when we can delete interest rates which are no more used by anyone //// (continuously from the beginning). //uint256 numberOfRegisteredUsers; } struct Stake { uint256 sinceBlock; uint256 sinceInterestRateIndex; AssetLib.Asset asset; } struct LockedAsset { uint256 liquidSinceBlock; AssetLib.Asset asset; } struct Locked { AssetLib.Asset aggregate; LockedAsset[] assets; } // ******* EVENTS ******** event BindStake( address indexed stakerAddress , uint256 indexed sinceInterestRateIndex , uint256 principal , uint256 compoundInterest ); /** * @dev This event is triggered exclusivelly to recalculate the compount interest of ALREADY staked asset * for the poriod since it was calculated the last time. This means this event does *NOT* include *YET* * any added (resp. removed) asset user is currently binding (resp. unbinding). * The main motivation for this event is to give listener opportunity to get feedback what is the * user's staked asset value with compound interrest recalculated to *CURRENT* block *BEFORE* user's * action (binding resp. unbinding) affects user's staked asset value. */ event StakeCompoundInterest( address indexed stakerAddress , uint256 indexed sinceInterestRateIndex , uint256 principal // = previous_principal , uint256 compoundInterest // = previous_principal * (pow(1+interest, _getBlockNumber()-since_block) - 1) ); event LiquidityDeposited( address indexed stakerAddress , uint256 amount ); event LiquidityUnlocked( address indexed stakerAddress , uint256 principal , uint256 compoundInterest ); event UnbindStake( address indexed stakerAddress , uint256 indexed liquidSinceBlock , uint256 principal , uint256 compoundInterest ); event NewInterestRate( uint256 indexed index , uint256 rate // Signed interest rate in [10**18] units => real_rate = rate / 10**18 ); event Withdraw( address indexed stakerAddress , uint256 principal , uint256 compoundInterest ); event LockPeriod(uint64 numOfBlocks); event Pause(uint256 sinceBlock); event TokenWithdrawal(address targetAddress, uint256 amount); event ExcessTokenWithdrawal(address targetAddress, uint256 amount); event RewardsPoolTokenTopUp(address sender, uint256 amount); event RewardsPoolTokenWithdrawal(address targetAddress, uint256 amount); event DeleteContract(); bytes32 public constant DELEGATE_ROLE = keccak256("DELEGATE_ROLE"); uint256 public constant DELETE_PROTECTION_PERIOD = 370285;// 60*24*60*60[s] / (14[s/block]) = 370285[block]; IERC20 public _token; // NOTE(pb): This needs to be either completely replaced by multisig concept, // or at least joined with multisig. // This contract does not have, by-design on conceptual level, any clearly defined repeating // life-cycle behaviour (for instance: `initialise -> staking-period -> locked-period` cycle // with clear start & end of each life-cycle. Life-cycle of this contract is single monolithic // period `creation -> delete-contract`, where there is no clear place where to `update` the // earliest deletion block value, thus it would need to be set once at the contract creation // point what completely defeats the protection by time delay. uint256 public _earliestDelete; uint256 public _pausedSinceBlock; uint64 public _lockPeriodInBlocks; // Represents amount of reward funds which are dedicated to cover accrued compound interest during user withdrawals. uint256 public _rewardsPoolBalance; // Accumulated global value of all principals (from all users) currently held in this contract (liquid, bound and locked). uint256 public _accruedGlobalPrincipal; AssetLib.Asset public _accruedGlobalLiquidity; // Exact AssetLib.Asset public _accruedGlobalLocked; // Exact uint256 public _interestRatesStartIdx; uint256 public _interestRatesNextIdx; mapping(uint256 => InterestRatePerBlock) public _interestRates; mapping(address => Stake) _stakes; mapping(address => Locked) _locked; mapping(address => AssetLib.Asset) public _liquidity; /* Only callable by owner */ modifier onlyOwner() { require(_isOwner(), "Caller is not an owner"); _; } /* Only callable by owner or delegate */ modifier onlyDelegate() { require(_isOwner() || hasRole(DELEGATE_ROLE, msg.sender), "Caller is neither owner nor delegate"); _; } modifier verifyTxExpiration(uint256 expirationBlock) { require(_getBlockNumber() <= expirationBlock, "Transaction expired"); _; } modifier verifyNotPaused() { require(_pausedSinceBlock > _getBlockNumber(), "Contract has been paused"); _; } /******************* Contract start *******************/ /** * @param ERC20Address address of the ERC20 contract */ constructor( address ERC20Address , uint256 interestRatePerBlock , uint256 pausedSinceBlock , uint64 lockPeriodInBlocks) public { _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _token = IERC20(ERC20Address); _earliestDelete = _getBlockNumber().add(DELETE_PROTECTION_PERIOD); // NOTE(pb): Unnecessary initialisations, shall be done implicitly by VM //_interestRatesStartIdx = 0; //_interestRatesNextIdx = 0; //_rewardsPoolBalance = 0; //_accruedGlobalPrincipal = 0; //_accruedGlobalLiquidity = 0; //_accruedGlobalLocked = 0; _updateLockPeriod(lockPeriodInBlocks); _addInterestRate(interestRatePerBlock); _pauseSince(pausedSinceBlock /* uint256(0) */); } /** * @notice Add new interest rate in to the ordered container of previously added interest rates * @param rate - signed interest rate value in [10**18] units => real_rate [1] = rate [10**18] / 10**18 * @param expirationBlock - block number beyond which is the carrier Tx considered expired, and so rejected. * This is for protection of Tx sender to exactly define lifecycle length of the Tx, * and so avoiding uncertainty of how long Tx sender needs to wait for Tx processing. * Tx can be withheld * @dev expiration period */ function addInterestRate( uint256 rate, uint256 expirationBlock ) external onlyDelegate() verifyTxExpiration(expirationBlock) { _addInterestRate(rate); } function deposit( uint256 amount, uint256 txExpirationBlock ) external verifyTxExpiration(txExpirationBlock) verifyNotPaused { bool makeTransfer = amount != 0; if (makeTransfer) { require(_token.transferFrom(msg.sender, address(this), amount), "Transfer failed"); _accruedGlobalPrincipal = _accruedGlobalPrincipal.add(amount); _accruedGlobalLiquidity.principal = _accruedGlobalLiquidity.principal.add(amount); emit LiquidityDeposited(msg.sender, amount); } uint256 curr_block = _getBlockNumber(); (, AssetLib.Asset storage liquidity,) = _collectLiquidity(msg.sender, curr_block); if (makeTransfer) { liquidity.principal = liquidity.principal.add(amount); } } /** * @notice Withdraws amount from sender' available liquidity pool back to sender address, * preferring withdrawal from compound interest dimension of liquidity. * * @param amount - value to withdraw * * @dev public access */ function withdraw( uint256 amount, uint256 txExpirationBlock ) external verifyTxExpiration(txExpirationBlock) verifyNotPaused { address sender = msg.sender; uint256 curr_block = _getBlockNumber(); (, AssetLib.Asset storage liquidity,) = _collectLiquidity(sender, curr_block); AssetLib.Asset memory _amount = liquidity.iSubCompoundInterestFirst(amount); _finaliseWithdraw(sender, _amount, amount); } /** * @notice Withdraws *WHOLE* compound interest amount available to sender. * * @dev public access */ function withdrawPrincipal( uint256 txExpirationBlock ) external verifyTxExpiration(txExpirationBlock) verifyNotPaused { address sender = msg.sender; uint256 curr_block = _getBlockNumber(); (, AssetLib.Asset storage liquidity, ) = _collectLiquidity(sender, curr_block); AssetLib.Asset memory _amount; _amount.principal = liquidity.principal; liquidity.principal = 0; _finaliseWithdraw(sender, _amount, _amount.principal); } /** * @notice Withdraws *WHOLE* compound interest amount available to sender. * * @dev public access */ function withdrawCompoundInterest( uint256 txExpirationBlock ) external verifyTxExpiration(txExpirationBlock) verifyNotPaused { address sender = msg.sender; uint256 curr_block = _getBlockNumber(); (, AssetLib.Asset storage liquidity, ) = _collectLiquidity(sender, curr_block); AssetLib.Asset memory _amount; _amount.compoundInterest = liquidity.compoundInterest; liquidity.compoundInterest = 0; _finaliseWithdraw(sender, _amount, _amount.compoundInterest); } /** * @notice Withdraws whole liquidity available to sender back to sender' address, * * @dev public access */ function withdrawWholeLiquidity( uint256 txExpirationBlock ) external verifyTxExpiration(txExpirationBlock) verifyNotPaused { address sender = msg.sender; uint256 curr_block = _getBlockNumber(); (, AssetLib.Asset storage liquidity, ) = _collectLiquidity(sender, curr_block); _finaliseWithdraw(sender, liquidity, liquidity.composite()); liquidity.compoundInterest = 0; liquidity.principal = 0; } function bindStake( uint256 amount, uint256 txExpirationBlock ) external verifyTxExpiration(txExpirationBlock) verifyNotPaused { require(amount != 0, "Amount must be higher than zero"); uint256 curr_block = _getBlockNumber(); (, AssetLib.Asset storage liquidity, ) = _collectLiquidity(msg.sender, curr_block); //// NOTE(pb): Strictly speaking, the following check is not necessary, since the requirement will be checked //// during the `iRelocatePrincipalFirst(...)` method code flow (see bellow). //uint256 composite = liquidity.composite(); //require(amount <= composite, "Insufficient liquidity."); Stake storage stake = _updateStakeCompoundInterest(msg.sender, curr_block); AssetLib.Asset memory _amount = liquidity.iRelocatePrincipalFirst(stake.asset, amount); _accruedGlobalLiquidity.iSub(_amount); //// NOTE(pb): Emitting only info about Tx input `amount` value, decomposed to principal & compound interest //// coordinates based on liquidity available. //if (amount > 0) { emit BindStake(msg.sender, stake.sinceInterestRateIndex, _amount.principal, _amount.compoundInterest); //} } /** * @notice Unbinds amount from the stake of sender of the transaction, * and *LOCKS* it for number of blocks defined by value of the * `_lockPeriodInBlocks` state of this contract at the point * of this call. * The locked amount can *NOT* be withdrawn from the contract * *BEFORE* the lock period ends. * * Unbinding (=calling this method) also means, that compound * interest will be calculated for period since la. * * @param amount - value to un-bind from the stake * If `amount=0` then the **WHOLE** stake (including * compound interest) will be unbound. * * @dev public access */ function unbindStake( uint256 amount, //NOTE: If zero, then all stake is withdrawn uint256 txExpirationBlock ) external verifyTxExpiration(txExpirationBlock) verifyNotPaused { uint256 curr_block = _getBlockNumber(); address sender = msg.sender; Stake storage stake = _updateStakeCompoundInterest(sender, curr_block); uint256 stake_composite = stake.asset.composite(); AssetLib.Asset memory _amount; if (amount > 0) { // TODO(pb): Failing this way is expensive (causing rollback of state change). // It would be beneficial to retain newly calculated liquidity value // in to the state, thus the invested calculation would not come to wain. // However that comes with another implication - this would need // to return status/error code instead of reverting = caller MUST actually // check the return value, what might be trap for callers who do not expect // this behaviour (Tx execution passed , but in fact the essential feature // has not been fully executed). require(amount <= stake_composite, "Amount is higher than stake"); if (_lockPeriodInBlocks == 0) { _amount = stake.asset.iRelocateCompoundInterestFirst(_liquidity[sender], amount); _accruedGlobalLiquidity.iAdd(_amount); emit UnbindStake(sender, curr_block, _amount.principal, _amount.compoundInterest); emit LiquidityUnlocked(sender, _amount.principal, _amount.compoundInterest); } else { Locked storage locked = _locked[sender]; LockedAsset storage newLockedAsset = locked.assets.push(); newLockedAsset.liquidSinceBlock = curr_block.add(_lockPeriodInBlocks); _amount = stake.asset.iRelocateCompoundInterestFirst(newLockedAsset.asset, amount); _accruedGlobalLocked.iAdd(_amount); locked.aggregate.iAdd(_amount); // NOTE: Emitting only info about Tx input values, not resulting compound values emit UnbindStake(sender, newLockedAsset.liquidSinceBlock, _amount.principal, _amount.compoundInterest); } } else { if (stake_composite == 0) { // NOTE(pb): Nothing to do return; } _amount = stake.asset; stake.asset.principal = 0; stake.asset.compoundInterest = 0; if (_lockPeriodInBlocks == 0) { _liquidity[sender].iAdd(_amount); _accruedGlobalLiquidity.iAdd(_amount); emit UnbindStake(sender, curr_block, _amount.principal, _amount.compoundInterest); emit LiquidityUnlocked(sender, _amount.principal, _amount.compoundInterest); } else { Locked storage locked = _locked[sender]; LockedAsset storage newLockedAsset = locked.assets.push(); newLockedAsset.liquidSinceBlock = curr_block.add(_lockPeriodInBlocks); newLockedAsset.asset = _amount; _accruedGlobalLocked.iAdd(_amount); locked.aggregate.iAdd(_amount); // NOTE: Emitting only info about Tx input values, not resulting compound values emit UnbindStake(msg.sender, newLockedAsset.liquidSinceBlock, newLockedAsset.asset.principal, newLockedAsset.asset.compoundInterest); } } } function getRewardsPoolBalance() external view returns(uint256) { return _rewardsPoolBalance; } function getEarliestDeleteBlock() external view returns(uint256) { return _earliestDelete; } function getNumberOfLockedAssetsForUser(address forAddress) external view returns(uint256 length) { length = _locked[forAddress].assets.length; } function getLockedAssetsAggregateForUser(address forAddress) external view returns(uint256 principal, uint256 compoundInterest) { AssetLib.Asset storage aggregate = _locked[forAddress].aggregate; return (aggregate.principal, aggregate.compoundInterest); } /** * @dev Returns locked assets decomposed in to 3 separate arrays (principal, compound interest, liquid since block) * NOTE(pb): This method might be quite expensive, depending on size of locked assets */ function getLockedAssetsForUser(address forAddress) external view returns(uint256[] memory principal, uint256[] memory compoundInterest, uint256[] memory liquidSinceBlock) { LockedAsset[] storage lockedAssets = _locked[forAddress].assets; uint256 length = lockedAssets.length; if (length != 0) { principal = new uint256[](length); compoundInterest = new uint256[](length); liquidSinceBlock = new uint256[](length); for (uint256 i=0; i < length; ++i) { LockedAsset storage la = lockedAssets[i]; AssetLib.Asset storage a = la.asset; principal[i] = a.principal; compoundInterest[i] = a.compoundInterest; liquidSinceBlock[i] = la.liquidSinceBlock; } } } function getStakeForUser(address forAddress) external view returns(uint256 principal, uint256 compoundInterest, uint256 sinceBlock, uint256 sinceInterestRateIndex) { Stake storage stake = _stakes[forAddress]; principal = stake.asset.principal; compoundInterest = stake.asset.compoundInterest; sinceBlock = stake.sinceBlock; sinceInterestRateIndex = stake.sinceInterestRateIndex; } /** @dev Even though this is considered as administrative action (is not affected by by contract paused state, it can be executed by anyone who wishes to top-up the rewards pool (funds are sent in to contract, *not* the other way around). The Rewards Pool is exclusively dedicated to cover withdrawals of user' compound interest, which is effectively the reward. */ function topUpRewardsPool( uint256 amount, uint256 txExpirationBlock ) external verifyTxExpiration(txExpirationBlock) { if (amount == 0) { return; } require(_token.transferFrom(msg.sender, address(this), amount), "Transfer failed"); _rewardsPoolBalance = _rewardsPoolBalance.add(amount); emit RewardsPoolTokenTopUp(msg.sender, amount); } /** * @notice Updates Lock Period value * @param numOfBlocks length of the lock period * @dev Delegate only */ function updateLockPeriod(uint64 numOfBlocks, uint256 txExpirationBlock) external verifyTxExpiration(txExpirationBlock) onlyDelegate { _updateLockPeriod(numOfBlocks); } /** * @notice Pauses all NON-administrative interaction with the contract since the specidfed block number * @param blockNumber block number since which non-admin interaction will be paused (for all _getBlockNumber() >= blockNumber) * @dev Delegate only */ function pauseSince(uint256 blockNumber, uint256 txExpirationBlock) external verifyTxExpiration(txExpirationBlock) onlyDelegate { _pauseSince(blockNumber); } /** * @dev Withdraw tokens from rewards pool. * * @param amount : amount to withdraw. * If `amount == 0` then whole amount in rewards pool will be withdrawn. * @param targetAddress : address to send tokens to */ function withdrawFromRewardsPool(uint256 amount, address payable targetAddress, uint256 txExpirationBlock ) external verifyTxExpiration(txExpirationBlock) onlyOwner { if (amount == 0) { amount = _rewardsPoolBalance; } else { require(amount <= _rewardsPoolBalance, "Amount higher than rewards pool"); } // NOTE(pb): Strictly speaking, consistency check in following lines is not necessary, // the if-else code above guarantees that everything is alright: uint256 contractBalance = _token.balanceOf(address(this)); uint256 expectedMinContractBalance = _accruedGlobalPrincipal.add(amount); require(expectedMinContractBalance <= contractBalance, "Contract inconsistency."); require(_token.transfer(targetAddress, amount), "Not enough funds on contr. addr."); // NOTE(pb): No need for SafeMath.sub since the overflow is checked in the if-else code above. _rewardsPoolBalance -= amount; emit RewardsPoolTokenWithdrawal(targetAddress, amount); } /** * @dev Withdraw "excess" tokens, which were sent to contract directly via direct ERC20.transfer(...), * without interacting with API of this (Staking) contract, what could be done only by mistake. * Thus this method is meant to be used primarily for rescue purposes, enabling withdrawal of such * "excess" tokens out of contract. * @param targetAddress : address to send tokens to * @param txExpirationBlock : block number until which is the transaction valid (inclusive). * When transaction is processed after this block, it fails. */ function withdrawExcessTokens(address payable targetAddress, uint256 txExpirationBlock) external verifyTxExpiration(txExpirationBlock) onlyOwner { uint256 contractBalance = _token.balanceOf(address(this)); uint256 expectedMinContractBalance = _accruedGlobalPrincipal.add(_rewardsPoolBalance); // NOTE(pb): The following subtraction shall *fail* (revert) IF the contract is in *INCONSISTENT* state, // = when contract balance is less than minial expected balance: uint256 excessAmount = contractBalance.sub(expectedMinContractBalance); require(_token.transfer(targetAddress, excessAmount), "Not enough funds on contr. addr."); emit ExcessTokenWithdrawal(targetAddress, excessAmount); } /** * @notice Delete the contract, transfers the remaining token and ether balance to the specified payoutAddress * @param payoutAddress address to transfer the balances to. Ensure that this is able to handle ERC20 tokens * @dev owner only + only on or after `_earliestDelete` block */ function deleteContract(address payable payoutAddress, uint256 txExpirationBlock) external verifyTxExpiration(txExpirationBlock) onlyOwner { require(_earliestDelete >= _getBlockNumber(), "Earliest delete not reached"); uint256 contractBalance = _token.balanceOf(address(this)); require(_token.transfer(payoutAddress, contractBalance)); emit DeleteContract(); selfdestruct(payoutAddress); } // ********************************************************** // ****************** INTERNAL METHODS ***************** /** * @dev VIRTUAL Method returning bock number. Introduced for * testing purposes (allows mocking). */ function _getBlockNumber() internal view virtual returns(uint256) { return block.number; } function _isOwner() internal view returns(bool) { return hasRole(DEFAULT_ADMIN_ROLE, msg.sender); } /** * @notice Add new interest rate in to the ordered container of previously added interest rates * @param rate - signed interest rate value in [10**18] units => real_rate [1] = rate [10**18] / 10**18 */ function _addInterestRate(uint256 rate) internal { uint256 idx = _interestRatesNextIdx; _interestRates[idx] = InterestRatePerBlock({ sinceBlock: _getBlockNumber() , rate: rate //,numberOfRegisteredUsers: 0 }); _interestRatesNextIdx = _interestRatesNextIdx.add(1); emit NewInterestRate(idx, rate); } /** * @notice Updates Lock Period value * @param numOfBlocks length of the lock period */ function _updateLockPeriod(uint64 numOfBlocks) internal { _lockPeriodInBlocks = numOfBlocks; emit LockPeriod(numOfBlocks); } /** * @notice Pauses all NON-administrative interaction with the contract since the specidfed block number * @param blockNumber block number since which non-admin interaction will be paused (for all _getBlockNumber() >= blockNumber) */ function _pauseSince(uint256 blockNumber) internal { uint256 currentBlockNumber = _getBlockNumber(); _pausedSinceBlock = blockNumber < currentBlockNumber ? currentBlockNumber : blockNumber; emit Pause(_pausedSinceBlock); } /** * @notice Withdraws amount from sender' available liquidity pool back to sender address, * preferring withdrawal from compound interest dimension of liquidity. * * @param amount - value to withdraw * * @dev NOTE(pb): Passing redundant `uint256 amount` (on top of the `Asset _amount`) in the name * of performance to avoid calculating it again from `_amount` (or the other way around). * IMPLICATION: Caller **MUST** pass correct values, ensuring that `amount == _amount.composite()`, * since this private method is **NOT** verifying this condition due to performance reasons. */ function _finaliseWithdraw(address sender, AssetLib.Asset memory _amount, uint256 amount) internal { if (amount != 0) { require(_rewardsPoolBalance >= _amount.compoundInterest, "Not enough funds in rewards pool"); require(_token.transfer(sender, amount), "Transfer failed"); _rewardsPoolBalance = _rewardsPoolBalance.sub(_amount.compoundInterest); _accruedGlobalPrincipal = _accruedGlobalPrincipal.sub(_amount.principal); _accruedGlobalLiquidity.iSub(_amount); // NOTE(pb): Emitting only info about Tx input `amount` value, decomposed to principal & compound interest // coordinates based on liquidity available. emit Withdraw(msg.sender, _amount.principal, _amount.compoundInterest); } } function _updateStakeCompoundInterest(address sender, uint256 at_block) internal returns(Stake storage stake) { stake = _stakes[sender]; uint256 composite = stake.asset.composite(); if (composite != 0) { // TODO(pb): There is more effective algorithm than this. uint256 start_block = stake.sinceBlock; // NOTE(pb): Probability of `++i` or `j=i+1` overflowing is limitly approaching zero, // since we would need to create `(1<<256)-1`, resp `1<<256)-2`, number of interrest rates in order to reach the overflow for (uint256 i=stake.sinceInterestRateIndex; i < _interestRatesNextIdx; ++i) { InterestRatePerBlock storage interest = _interestRates[i]; // TODO(pb): It is not strictly necessary to do this assert, and rather fully rely // on correctness of `addInterestRate(...)` implementation. require(interest.sinceBlock <= start_block, "sinceBlock inconsistency"); uint256 end_block = at_block; uint256 j = i + 1; if (j < _interestRatesNextIdx) { InterestRatePerBlock storage next_interest = _interestRates[j]; end_block = next_interest.sinceBlock; } composite = Finance.compoundInterest(composite, interest.rate, end_block - start_block); start_block = end_block; } stake.asset.compoundInterest = composite.sub(stake.asset.principal); } stake.sinceBlock = at_block; stake.sinceInterestRateIndex = (_interestRatesNextIdx != 0 ? _interestRatesNextIdx - 1 : 0); // TODO(pb): Careful: The `StakeCompoundInterest` event doers not carry explicit block number value - it relies // on the fact that Event implicitly carries value block.number where the event has been triggered, // what however can be different than value of the `at_block` input parameter passed in. // Thus this method needs to be EITHER refactored to drop the `at_block` parameter (and so get the // value internally by calling the `_getBlockNumber()` method), OR the `StakeCompoundInterest` event // needs to be extended to include the `uint256 sinceBlock` attribute. // The original reason for passing the `at_block` parameter was to spare gas for calling the // `_getBlockNumber()` method twice (by the caller of this method + by this method), what might NOT be // relevant anymore (after refactoring), since caller might not need to use the block number value anymore. emit StakeCompoundInterest(sender, stake.sinceInterestRateIndex, stake.asset.principal, stake.asset.compoundInterest); } function _collectLiquidity(address sender, uint256 at_block) internal returns(AssetLib.Asset memory unlockedLiquidity, AssetLib.Asset storage liquidity, bool collected) { Locked storage locked = _locked[sender]; LockedAsset[] storage lockedAssets = locked.assets; liquidity = _liquidity[sender]; for (uint256 i=0; i < lockedAssets.length; ) { LockedAsset memory l = lockedAssets[i]; if (l.liquidSinceBlock > at_block) { ++i; // NOTE(pb): Probability of overflow is zero, what is ensured by condition in this for cycle. continue; } unlockedLiquidity.principal = unlockedLiquidity.principal.add(l.asset.principal); // NOTE(pb): The following can potentially overflow, since accrued compound interest can be high, depending on values on sequence of interest rates & length of compounding intervals involved. unlockedLiquidity.compoundInterest = unlockedLiquidity.compoundInterest.add(l.asset.compoundInterest); // Copying last element of the array in to the current one, // so that the last one can be popped out of the array. // NOTE(pb): Probability of overflow during `-` operation is zero, what is ensured by condition in this for cycle. uint256 last_idx = lockedAssets.length - 1; if (i != last_idx) { lockedAssets[i] = lockedAssets[last_idx]; } // TODO(pb): It will be cheaper (GAS consumption-wise) to simply leave // elements in array (do NOT delete them) and rather store "amortised" // size of the array in secondary separate store variable (= do NOT // use `array.length` as primary indication of array length). // Destruction of the array items is expensive. Excess of "allocated" // array storage can be left temporarily (or even permanently) unused. lockedAssets.pop(); } // TODO(pb): This should not be necessary. if (lockedAssets.length == 0) { delete _locked[sender]; } collected = unlockedLiquidity.principal != 0 || unlockedLiquidity.compoundInterest != 0; if (collected) { emit LiquidityUnlocked(sender, unlockedLiquidity.principal, unlockedLiquidity.compoundInterest); _accruedGlobalLocked.iSub(unlockedLiquidity); if (lockedAssets.length != 0) { locked.aggregate.iSub(unlockedLiquidity); } _accruedGlobalLiquidity.iAdd(unlockedLiquidity); liquidity.iAdd(unlockedLiquidity); } } }
Contract Security Audit
- Certik - October 15th, 2020 - Security Audit Report
Contract ABI
API[{"inputs":[{"internalType":"address","name":"ERC20Address","type":"address"},{"internalType":"uint256","name":"interestRatePerBlock","type":"uint256"},{"internalType":"uint256","name":"pausedSinceBlock","type":"uint256"},{"internalType":"uint64","name":"lockPeriodInBlocks","type":"uint64"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakerAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"sinceInterestRateIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"principal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"compoundInterest","type":"uint256"}],"name":"BindStake","type":"event"},{"anonymous":false,"inputs":[],"name":"DeleteContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"targetAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ExcessTokenWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakerAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LiquidityDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakerAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"principal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"compoundInterest","type":"uint256"}],"name":"LiquidityUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"numOfBlocks","type":"uint64"}],"name":"LockPeriod","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rate","type":"uint256"}],"name":"NewInterestRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"sinceBlock","type":"uint256"}],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsPoolTokenTopUp","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"targetAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsPoolTokenWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakerAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"sinceInterestRateIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"principal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"compoundInterest","type":"uint256"}],"name":"StakeCompoundInterest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"targetAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakerAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"liquidSinceBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"principal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"compoundInterest","type":"uint256"}],"name":"UnbindStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakerAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"principal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"compoundInterest","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DELEGATE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DELETE_PROTECTION_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_accruedGlobalLiquidity","outputs":[{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"compoundInterest","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_accruedGlobalLocked","outputs":[{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"compoundInterest","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_accruedGlobalPrincipal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_earliestDelete","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"_interestRates","outputs":[{"internalType":"uint256","name":"sinceBlock","type":"uint256"},{"internalType":"uint256","name":"rate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_interestRatesNextIdx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_interestRatesStartIdx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_liquidity","outputs":[{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"compoundInterest","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_lockPeriodInBlocks","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_pausedSinceBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_rewardsPoolBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rate","type":"uint256"},{"internalType":"uint256","name":"expirationBlock","type":"uint256"}],"name":"addInterestRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"txExpirationBlock","type":"uint256"}],"name":"bindStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"payoutAddress","type":"address"},{"internalType":"uint256","name":"txExpirationBlock","type":"uint256"}],"name":"deleteContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"txExpirationBlock","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getEarliestDeleteBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forAddress","type":"address"}],"name":"getLockedAssetsAggregateForUser","outputs":[{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"compoundInterest","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forAddress","type":"address"}],"name":"getLockedAssetsForUser","outputs":[{"internalType":"uint256[]","name":"principal","type":"uint256[]"},{"internalType":"uint256[]","name":"compoundInterest","type":"uint256[]"},{"internalType":"uint256[]","name":"liquidSinceBlock","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forAddress","type":"address"}],"name":"getNumberOfLockedAssetsForUser","outputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardsPoolBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forAddress","type":"address"}],"name":"getStakeForUser","outputs":[{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"compoundInterest","type":"uint256"},{"internalType":"uint256","name":"sinceBlock","type":"uint256"},{"internalType":"uint256","name":"sinceInterestRateIndex","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"txExpirationBlock","type":"uint256"}],"name":"pauseSince","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"txExpirationBlock","type":"uint256"}],"name":"topUpRewardsPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"txExpirationBlock","type":"uint256"}],"name":"unbindStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"numOfBlocks","type":"uint64"},{"internalType":"uint256","name":"txExpirationBlock","type":"uint256"}],"name":"updateLockPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"txExpirationBlock","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"txExpirationBlock","type":"uint256"}],"name":"withdrawCompoundInterest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"targetAddress","type":"address"},{"internalType":"uint256","name":"txExpirationBlock","type":"uint256"}],"name":"withdrawExcessTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"targetAddress","type":"address"},{"internalType":"uint256","name":"txExpirationBlock","type":"uint256"}],"name":"withdrawFromRewardsPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"txExpirationBlock","type":"uint256"}],"name":"withdrawPrincipal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"txExpirationBlock","type":"uint256"}],"name":"withdrawWholeLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506040516200391838038062003918833981810160405260808110156200003757600080fd5b5080516020820151604083015160609093015191929091620000646000336001600160e01b03620000ee16565b600180546001600160a01b0319166001600160a01b038616179055620000a56205a66d6200009162000107565b6200010b60201b620023d81790919060201c565b600255620000bc816001600160e01b036200016f16565b620000d0836001600160e01b03620001c316565b620000e4826001600160e01b036200025f16565b50505050620003d8565b6200010382826001600160e01b03620002c216565b5050565b4390565b60008282018381101562000166576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b600480546001600160401b0383166001600160401b0319909116811790915560408051918252517f6b24ea7c7a8ce7fd2e6a6cb675dbabcd38a90f83ddd581c4435610ce90456e8f9181900360200190a150565b600c546040805180820190915280620001e46001600160e01b036200010716565b815260209081018490526000838152600d8252604090208251815591810151600192830155600c5462000222929091620023d86200010b821b17901c565b600c5560408051838152905182917fbcd200f406c53d9438c6cdc2966a1e99c35f336588c95bc3639e539df21c2f53919081900360200190a25050565b6000620002746001600160e01b036200010716565b905080821062000285578162000287565b805b600381905560408051918252517f68b095021b1f40fe513109f513c66692f0b3219aee674a69f4efc57badb8201d9181900360200190a15050565b600082815260208181526040909120620002e79183906200243262000344821b17901c565b156200010357620003006001600160e01b036200036416565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600062000166836001600160a01b0384166001600160e01b036200036816565b3390565b60006200037f83836001600160e01b03620003c016565b620003b75750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000169565b50600062000169565b60009081526001919091016020526040902054151590565b61353080620003e86000396000f3fe608060405234801561001057600080fd5b506004361061025e5760003560e01c80639010d07c11610146578063c8984ab2116100c3578063d9d8e78311610087578063d9d8e783146107bf578063dca2aa5c146107c7578063e2bbb158146107e4578063ecd0c0c314610807578063f0895e521461080f578063f1209ef71461083c5761025e565b8063c8984ab214610749578063ca15c87314610751578063d547741f1461076e578063d8cd39991461079a578063d9b202c9146107b75761025e565b8063aa700ff21161010a578063aa700ff2146106ad578063adf55101146106ca578063ba92a4c5146106d2578063c0ba241b146106f5578063c30f75cf146106fd5761025e565b80639010d07c146105d457806391d14854146106135780639608df4b14610653578063a217fddf1461067f578063a8f1b4c4146106875761025e565b8063372646bb116101df57806353e052ac116101a357806353e052ac146103f35780635f208f341461041f578063658e28a41461052357806367ce50c01461054057806368bccfcf1461057f57806388cedd5e146105b15761025e565b8063372646bb1461037757806340e979031461037f5780634164b001146103a5578063441a3e70146103ad57806352885d8d146103d05761025e565b8063292911fb11610226578063292911fb146102ec5780632f2ff15d146102f457806332a1bd7014610320578063347908df1461032857806336568abe1461034b5761025e565b8063085313ec146102635780630c450f9d1461027d5780631338403914610285578063248a9ca3146102aa5780632514c50a146102c7575b600080fd5b61026b610844565b60408051918252519081900360200190f35b61026b61084b565b6102a86004803603604081101561029b57600080fd5b5080359060200135610851565b005b61026b600480360360208110156102c057600080fd5b503561091f565b6102cf610934565b6040805167ffffffffffffffff9092168252519081900360200190f35b61026b610944565b6102a86004803603604081101561030a57600080fd5b50803590602001356001600160a01b031661094a565b61026b6109b6565b6102a86004803603604081101561033e57600080fd5b50803590602001356109bc565b6102a86004803603604081101561036157600080fd5b50803590602001356001600160a01b0316610a85565b61026b610ae6565b61026b6004803603602081101561039557600080fd5b50356001600160a01b0316610aed565b61026b610b0b565b6102a8600480360360408110156103c357600080fd5b5080359060200135610b11565b6102a8600480360360408110156103e657600080fd5b5080359060200135610bf2565b6102a86004803603604081101561040957600080fd5b506001600160a01b03813516906020013561108b565b6104456004803603602081101561043557600080fd5b50356001600160a01b03166112ef565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b8381101561048d578181015183820152602001610475565b50505050905001848103835286818151815260200191508051906020019060200280838360005b838110156104cc5781810151838201526020016104b4565b50505050905001848103825285818151815260200191508051906020019060200280838360005b8381101561050b5781810151838201526020016104f3565b50505050905001965050505050505060405180910390f35b6102a86004803603602081101561053957600080fd5b5035611482565b6105666004803603602081101561055657600080fd5b50356001600160a01b031661155b565b6040805192835260208301919091528051918290030190f35b6102a86004803603606081101561059557600080fd5b508035906001600160a01b036020820135169060400135611574565b6102a8600480360360408110156105c757600080fd5b5080359060200135611886565b6105f7600480360360408110156105ea57600080fd5b5080359060200135611a15565b604080516001600160a01b039092168252519081900360200190f35b61063f6004803603604081101561062957600080fd5b50803590602001356001600160a01b0316611a3c565b604080519115158252519081900360200190f35b6102a86004803603604081101561066957600080fd5b506001600160a01b038135169060200135611a5a565b61026b611c8e565b6105666004803603602081101561069d57600080fd5b50356001600160a01b0316611c93565b610566600480360360208110156106c357600080fd5b5035611cb6565b61026b611ccf565b6102a8600480360360408110156106e857600080fd5b5080359060200135611cd5565b61026b611e49565b6107236004803603602081101561071357600080fd5b50356001600160a01b0316611e6e565b604080519485526020850193909352838301919091526060830152519081900360800190f35b610566611e9f565b61026b6004803603602081101561076757600080fd5b5035611ea8565b6102a86004803603604081101561078457600080fd5b50803590602001356001600160a01b0316611ebf565b6102a8600480360360208110156107b057600080fd5b5035611f18565b610566611ff2565b61026b611ffb565b6102a8600480360360208110156107dd57600080fd5b5035612001565b6102a8600480360360408110156107fa57600080fd5b50803590602001356120f2565b6105f76122fa565b6102a86004803603604081101561082557600080fd5b5067ffffffffffffffff8135169060200135612309565b61026b6123d2565b6002545b90565b60055481565b610859612447565b8061088b5750604080516c44454c45474154455f524f4c4560981b8152905190819003600d01902061088b9033611a3c565b6108c65760405162461bcd60e51b81526004018080602001828103825260248152602001806134186024913960400191505060405180910390fd5b80806108d0612458565b1115610911576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b61091a8361245c565b505050565b60009081526020819052604090206002015490565b60045467ffffffffffffffff1681565b60065481565b60008281526020819052604090206002015461096d906109686124e5565b611a3c565b6109a85760405162461bcd60e51b815260040180806020018281038252602f8152602001806133e9602f913960400191505060405180910390fd5b6109b282826124e9565b5050565b60025481565b80806109c6612458565b1115610a07576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b610a0f612447565b80610a415750604080516c44454c45474154455f524f4c4560981b8152905190819003600d019020610a419033611a3c565b610a7c5760405162461bcd60e51b81526004018080602001828103825260248152602001806134186024913960400191505060405180910390fd5b61091a83612558565b610a8d6124e5565b6001600160a01b0316816001600160a01b031614610adc5760405162461bcd60e51b815260040180806020018281038252602f8152602001806134cc602f913960400191505060405180910390fd5b6109b282826125ae565b6205a66d81565b6001600160a01b03166000908152600f602052604090206002015490565b600c5481565b8080610b1b612458565b1115610b5c576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b610b64612458565b60035411610ba7576040805162461bcd60e51b815260206004820152601860248201526000805160206134ac833981519152604482015290519081900360640190fd5b336000610bb2612458565b90506000610bc0838361261d565b50915050610bcc61333e565b610bdc828863ffffffff61287b16565b9050610be98482896128f4565b50505050505050565b8080610bfc612458565b1115610c3d576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b610c45612458565b60035411610c88576040805162461bcd60e51b815260206004820152601860248201526000805160206134ac833981519152604482015290519081900360640190fd5b6000610c92612458565b9050336000610ca18284612aa1565b90506000610cb182600201612c1a565b9050610cbb61333e565b8715610ebd5781881115610d16576040805162461bcd60e51b815260206004820152601b60248201527f416d6f756e7420697320686967686572207468616e207374616b650000000000604482015290519081900360640190fd5b60045467ffffffffffffffff16610dee576001600160a01b0384166000908152601060205260409020610d549060028501908a63ffffffff612c3416565b9050610d6760078263ffffffff612c5916565b80516020808301516040805193845291830152805187926001600160a01b0388169260008051602061348c83398151915292918290030190a38051602080830151604080519384529183015280516001600160a01b038716927fa219ed960eef85ed4cd072d3a9f240ea94727c0d6fb15e9a91a8cd4bf18ee3a692908290030190a2610eb8565b6001600160a01b0384166000908152600f6020908152604082206002810180546001810182559084529190922060045460039092020190610e4090889067ffffffffffffffff1663ffffffff6123d816565b8155610e5960028601600183018c63ffffffff612c3416565b9250610e6c60098463ffffffff612c5916565b610e7c828463ffffffff612c5916565b80548351602080860151604080519384529183015280516001600160a01b038a169260008051602061348c83398151915292908290030190a350505b611081565b81610ecc57505050505061091a565b5060408051808201909152600283018054825260038401805460208401526000918290555560045467ffffffffffffffff16610fc2576001600160a01b0384166000908152601060205260409020610f2a908263ffffffff612c5916565b610f3b60078263ffffffff612c5916565b80516020808301516040805193845291830152805187926001600160a01b0388169260008051602061348c83398151915292918290030190a38051602080830151604080519384529183015280516001600160a01b038716927fa219ed960eef85ed4cd072d3a9f240ea94727c0d6fb15e9a91a8cd4bf18ee3a692908290030190a2611081565b6001600160a01b0384166000908152600f602090815260408220600281018054600181018255908452919092206004546003909202019061101490889067ffffffffffffffff1663ffffffff6123d816565b8155825160018201556020830151600282015561103860098463ffffffff612c5916565b611048828463ffffffff612c5916565b8054600182015460028301546040805192835260208301919091528051339260008051602061348c83398151915292908290030190a350505b5050505050505050565b8080611095612458565b11156110d6576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b6110de612447565b611128576040805162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1030b71037bbb732b960511b604482015290519081900360640190fd5b600154604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561117357600080fd5b505afa158015611187573d6000803e3d6000fd5b505050506040513d602081101561119d57600080fd5b50516005546006549192506000916111ba9163ffffffff6123d816565b905060006111ce838363ffffffff612c9316565b6001546040805163a9059cbb60e01b81526001600160a01b038a8116600483015260248201859052915193945091169163a9059cbb916044808201926020929091908290030181600087803b15801561122657600080fd5b505af115801561123a573d6000803e3d6000fd5b505050506040513d602081101561125057600080fd5b50516112a3576040805162461bcd60e51b815260206004820181905260248201527f4e6f7420656e6f7567682066756e6473206f6e20636f6e74722e20616464722e604482015290519081900360640190fd5b604080516001600160a01b03881681526020810183905281517f7f66376a5ef2f39ab4ee2ee6e400606624e66929dba5d82df5b14dd0070a8a87929181900390910190a1505050505050565b6001600160a01b0381166000908152600f60205260409020600201805460609182918291908015611479578067ffffffffffffffff8111801561133157600080fd5b5060405190808252806020026020018201604052801561135b578160200160208202803683370190505b5094508067ffffffffffffffff8111801561137557600080fd5b5060405190808252806020026020018201604052801561139f578160200160208202803683370190505b5093508067ffffffffffffffff811180156113b957600080fd5b506040519080825280602002602001820160405280156113e3578160200160208202803683370190505b50925060005b818110156114775760008382815481106113ff57fe5b906000526020600020906003020190506000816001019050806000015488848151811061142857fe5b602002602001018181525050806001015487848151811061144557fe5b602002602001018181525050816000015486848151811061146257fe5b602090810291909101015250506001016113e9565b505b50509193909250565b808061148c612458565b11156114cd576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b6114d5612458565b60035411611518576040805162461bcd60e51b815260206004820152601860248201526000805160206134ac833981519152604482015290519081900360640190fd5b336000611523612458565b90506000611531838361261d565b5091505061153d61333e565b81548082526000835561155390859083906128f4565b505050505050565b6010602052600090815260409020805460019091015482565b808061157e612458565b11156115bf576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b6115c7612447565b611611576040805162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1030b71037bbb732b960511b604482015290519081900360640190fd5b83611620576005549350611677565b600554841115611677576040805162461bcd60e51b815260206004820152601f60248201527f416d6f756e7420686967686572207468616e207265776172647320706f6f6c00604482015290519081900360640190fd5b600154604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156116c257600080fd5b505afa1580156116d6573d6000803e3d6000fd5b505050506040513d60208110156116ec57600080fd5b5051600654909150600090611707908763ffffffff6123d816565b90508181111561175e576040805162461bcd60e51b815260206004820152601760248201527f436f6e747261637420696e636f6e73697374656e63792e000000000000000000604482015290519081900360640190fd5b6001546040805163a9059cbb60e01b81526001600160a01b038881166004830152602482018a90529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156117b457600080fd5b505af11580156117c8573d6000803e3d6000fd5b505050506040513d60208110156117de57600080fd5b5051611831576040805162461bcd60e51b815260206004820181905260248201527f4e6f7420656e6f7567682066756e6473206f6e20636f6e74722e20616464722e604482015290519081900360640190fd5b600580548790039055604080516001600160a01b03871681526020810188905281517f8a652d32cc9efc0a4f0fc3708c9fb81d5a924a7b9af2a37c46e9e4910d0dc325929181900390910190a1505050505050565b8080611890612458565b11156118d1576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b6118d9612458565b6003541161191c576040805162461bcd60e51b815260206004820152601860248201526000805160206134ac833981519152604482015290519081900360640190fd5b8261196e576040805162461bcd60e51b815260206004820152601f60248201527f416d6f756e74206d75737420626520686967686572207468616e207a65726f00604482015290519081900360640190fd5b6000611978612458565b90506000611986338361261d565b5091505060006119963384612aa1565b90506119a061333e565b6119b483600284018963ffffffff612cd516565b90506119c760078263ffffffff612ce716565b600182015481516020808401516040805193845291830152805133927f0fb741c5ad2cad8215be7b4cab4e3f202f907d4540668ebf954f8e742efd89cf92908290030190a350505050505050565b6000828152602081905260408120611a33908363ffffffff612d1516565b90505b92915050565b6000828152602081905260408120611a33908363ffffffff612d2116565b8080611a64612458565b1115611aa5576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b611aad612447565b611af7576040805162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1030b71037bbb732b960511b604482015290519081900360640190fd5b611aff612458565b6002541015611b55576040805162461bcd60e51b815260206004820152601b60248201527f4561726c696573742064656c657465206e6f7420726561636865640000000000604482015290519081900360640190fd5b600154604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611ba057600080fd5b505afa158015611bb4573d6000803e3d6000fd5b505050506040513d6020811015611bca57600080fd5b50516001546040805163a9059cbb60e01b81526001600160a01b03888116600483015260248201859052915193945091169163a9059cbb916044808201926020929091908290030181600087803b158015611c2457600080fd5b505af1158015611c38573d6000803e3d6000fd5b505050506040513d6020811015611c4e57600080fd5b5051611c5957600080fd5b6040517fe4dedc7f698868c432fb679313d1381b06601dfb7174d9b18b2e35378b67633390600090a1836001600160a01b0316ff5b600081565b6001600160a01b03166000908152600f6020526040902080546001909101549091565b600d602052600090815260409020805460019091015482565b60055490565b8080611cdf612458565b1115611d20576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b82611d2a5761091a565b600154604080516323b872dd60e01b81523360048201523060248201526044810186905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b158015611d8457600080fd5b505af1158015611d98573d6000803e3d6000fd5b505050506040513d6020811015611dae57600080fd5b5051611df3576040805162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b600554611e06908463ffffffff6123d816565b600555604080513381526020810185905281517fb562e06b275d420e5848bb9083041a1c68466a478df92491b473ce99a4c68f68929181900390910190a1505050565b604080516c44454c45474154455f524f4c4560981b8152905190819003600d01902081565b6001600160a01b03166000908152600e60205260409020600281015460038201548254600190930154919390929190565b60075460085482565b6000818152602081905260408120611a3690612d36565b600082815260208190526040902060020154611edd906109686124e5565b610adc5760405162461bcd60e51b815260040180806020018281038252603081526020018061343c6030913960400191505060405180910390fd5b8080611f22612458565b1115611f63576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b611f6b612458565b60035411611fae576040805162461bcd60e51b815260206004820152601860248201526000805160206134ac833981519152604482015290519081900360640190fd5b336000611fb9612458565b90506000611fc7838361261d565b50915050611fd361333e565b60018201805460208301819052600090915561155390859083906128f4565b600954600a5482565b600b5481565b808061200b612458565b111561204c576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b612054612458565b60035411612097576040805162461bcd60e51b815260206004820152601860248201526000805160206134ac833981519152604482015290519081900360640190fd5b3360006120a2612458565b905060006120b0838361261d565b506040805180820190915281548152600182015460208201529092506120e1915084906120dc84612c1a565b6128f4565b600060018201819055905550505050565b80806120fc612458565b111561213d576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b612145612458565b60035411612188576040805162461bcd60e51b815260206004820152601860248201526000805160206134ac833981519152604482015290519081900360640190fd5b82158015906122bd57600154604080516323b872dd60e01b81523360048201523060248201526044810187905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b1580156121eb57600080fd5b505af11580156121ff573d6000803e3d6000fd5b505050506040513d602081101561221557600080fd5b505161225a576040805162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b60065461226d908563ffffffff6123d816565b600655600754612283908563ffffffff6123d816565b60075560408051858152905133917f7ff07ce9a287649537e4b012e45cf012d90228b12e2b56bb03515a6b5436fcdf919081900360200190a25b60006122c7612458565b905060006122d5338361261d565b5091505082156115535780546122f1908763ffffffff6123d816565b90555050505050565b6001546001600160a01b031681565b8080612313612458565b1115612354576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b61235c612447565b8061238e5750604080516c44454c45474154455f524f4c4560981b8152905190819003600d01902061238e9033611a3c565b6123c95760405162461bcd60e51b81526004018080602001828103825260248152602001806134186024913960400191505060405180910390fd5b61091a83612d41565b60035481565b600082820183811015611a33576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000611a33836001600160a01b038416612d97565b60006124538133611a3c565b905090565b4390565b600c546040805180820190915280612472612458565b815260209081018490526000838152600d82526040902082518155910151600191820155600c546124a89163ffffffff6123d816565b600c5560408051838152905182917fbcd200f406c53d9438c6cdc2966a1e99c35f336588c95bc3639e539df21c2f53919081900360200190a25050565b3390565b6000828152602081905260409020612507908263ffffffff61243216565b156109b2576125146124e5565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000612562612458565b90508082106125715781612573565b805b600381905560408051918252517f68b095021b1f40fe513109f513c66692f0b3219aee674a69f4efc57badb8201d9181900360200190a15050565b60008281526020819052604090206125cc908263ffffffff612de116565b156109b2576125d96124e5565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b61262561333e565b6001600160a01b0383166000908152600f6020908152604080832060109092528220919060028101825b815481101561278c57612660613358565b82828154811061266c57fe5b600091825260209182902060408051808201825260039093029091018054835281518083019092526001810154825260020154818401529181019190915280519091508810156126bf5750600101612787565b60208101515187516126d69163ffffffff6123d816565b8752602080820151810151908801516126f49163ffffffff6123d816565b60208801528254600019018281146127555783818154811061271257fe5b906000526020600020906003020184848154811061272c57fe5b600091825260209091208254600390920201908155600180830154908201556002918201549101555b8380548061275f57fe5b6000828152602081206003600019909301928302018181556001810182905560020155905550505b61264f565b5080546127c6576001600160a01b0387166000908152600f6020526040812081815560018101829055906127c36002830182613377565b50505b84511515806127d85750602085015115155b92508215612872578451602080870151604080519384529183015280516001600160a01b038a16927fa219ed960eef85ed4cd072d3a9f240ea94727c0d6fb15e9a91a8cd4bf18ee3a692908290030190a261283a60098663ffffffff612ce716565b80541561285157612851828663ffffffff612ce716565b61286260078663ffffffff612c5916565b612872848663ffffffff612c5916565b50509250925092565b61288361333e565b818360010154106128b45760018301546128a3908363ffffffff612c9316565b600184015560208101829052611a36565b60018301546128ca90839063ffffffff612c9316565b80825283546128de9163ffffffff612c9316565b8355600190920180546020840152600090555090565b801561091a5781602001516005541015612955576040805162461bcd60e51b815260206004820181905260248201527f4e6f7420656e6f7567682066756e647320696e207265776172647320706f6f6c604482015290519081900360640190fd5b6001546040805163a9059cbb60e01b81526001600160a01b038681166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156129ab57600080fd5b505af11580156129bf573d6000803e3d6000fd5b505050506040513d60208110156129d557600080fd5b5051612a1a576040805162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b6020820151600554612a319163ffffffff612c9316565b6005558151600654612a489163ffffffff612c9316565b600655612a5c60078363ffffffff612ce716565b81516020808401516040805193845291830152805133927ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56892908290030190a2505050565b6001600160a01b0382166000908152600e6020526040812090612ac660028301612c1a565b90508015612ba557815460018301545b600c54811015612b87576000818152600d602052604090208054831015612b44576040805162461bcd60e51b815260206004820152601860248201527f73696e6365426c6f636b20696e636f6e73697374656e63790000000000000000604482015290519081900360640190fd5b600c5486906001840190811015612b67576000818152600d602052604090205491505b612b78868460010154878503612df6565b95509093505050600101612ad6565b506002830154612b9e90839063ffffffff612c9316565b6003840155505b828255600c54612bb6576000612bbd565b6001600c54035b600183018190556002830154600384015460408051928352602083019190915280516001600160a01b038816927f6b6b43cdaf8f2ae06bdc6f6be433bb374b703ce8c88db4adce9dd8aefe44fe6d92908290030190a35092915050565b60018101548154600091611a36919063ffffffff6123d816565b612c3c61333e565b612c46848361287b565b9050612c528382612c59565b9392505050565b80518254612c6c9163ffffffff6123d816565b825560208101516001830154612c879163ffffffff6123d816565b82600101819055505050565b6000611a3383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612e36565b612cdd61333e565b612c468483612ecd565b80518254612cfa9163ffffffff612c9316565b825560208101516001830154612c879163ffffffff612c9316565b6000611a338383612f39565b6000611a33836001600160a01b038416612f9d565b6000611a3682612fb5565b6004805467ffffffffffffffff831667ffffffffffffffff19909116811790915560408051918252517f6b24ea7c7a8ce7fd2e6a6cb675dbabcd38a90f83ddd581c4435610ce90456e8f9181900360200190a150565b6000612da38383612f9d565b612dd957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611a36565b506000611a36565b6000611a33836001600160a01b038416612fb9565b6000612e2e612e28612e22612e0b600161307f565b612e1d87670de0b6b3a764000061309d565b6130d4565b84613108565b85613156565b949350505050565b60008184841115612ec55760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612e8a578181015183820152602001612e72565b50505050905090810190601f168015612eb75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b612ed561333e565b82548211612ef9578254612eef908363ffffffff612c9316565b8355818152611a36565b8254612f0c90839063ffffffff612c9316565b602082018190526001840154612f279163ffffffff612c9316565b60018401558254815260009092555090565b81546000908210612f7b5760405162461bcd60e51b81526004018080602001828103825260228152602001806133c76022913960400191505060405180910390fd5b826000018281548110612f8a57fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b5490565b600081815260018301602052604081205480156130755783546000198083019190810190600090879083908110612fec57fe5b906000526020600020015490508087600001848154811061300957fe5b60009182526020808320909101929092558281526001898101909252604090209084019055865487908061303957fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050611a36565b6000915050611a36565b6000677fffffffffffffff82111561309657600080fd5b5060401b90565b6000816130a957600080fd5b60006130b584846131be565b905060016001607f1b036001600160801b0382161115611a3357600080fd5b6000600f83810b9083900b0160016001607f1b031981128015906130ff575060016001607f1b038113155b611a3357600080fd5b6000613114600161307f565b90505b8115611a3657600182161561313d576131308184613308565b9050600182039150613151565b6131478384613308565b9250600182901c91505b613117565b60008161316557506000611a36565b600083600f0b121561317657600080fd5b600f83900b6001600160801b038316810260401c90608084901c026001600160c01b038111156131a557600080fd5b60401b81198111156131b657600080fd5b019392505050565b6000816131ca57600080fd5b60006001600160c01b0384116131ef5782604085901b816131e757fe5b0490506132f4565b60c084811c6401000000008110613208576020918201911c5b62010000811061321a576010918201911c5b610100811061322b576008918201911c5b6010811061323b576004918201911c5b6004811061324b576002918201911c5b6002811061325a576001820191505b60bf820360018603901c6001018260ff0387901b8161327557fe5b0492506001600160801b0383111561328c57600080fd5b608085901c83026001600160801b038616840260c088901c604089901b828110156132b8576001820391505b608084901b929003828110156132cf576001820391505b829003608084901c82146132df57fe5b8881816132e857fe5b04870196505050505050505b6001600160801b03811115611a3357600080fd5b6000600f83810b9083900b0260401d60016001607f1b031981128015906130ff575060016001607f1b03811315611a3357600080fd5b604051806040016040528060008152602001600081525090565b60405180604001604052806000815260200161337261333e565b905290565b5080546000825560030290600052602060002090810190613398919061339b565b50565b61084891905b808211156133c25760008082556001820181905560028201556003016133a1565b509056fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e6473416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f206772616e7443616c6c6572206973206e656974686572206f776e6572206e6f722064656c6567617465416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f207265766f6b655472616e73616374696f6e2065787069726564000000000000000000000000005bfe1e16d75ca1fa001989652cd88c5b8ee8a59b5df6df99836337def4d1c82d436f6e747261637420686173206265656e207061757365640000000000000000416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636520726f6c657320666f722073656c66a26469706673582212205436678265352631f897e2cef39869cf23c267c4a2f500784a8480a5ff10f77664736f6c63430006080033000000000000000000000000aea46a60368a7bd060eec7df8cba43b7ef41ad850000000000000000000000000000000000000000000000000000000944754ca900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021a27
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061025e5760003560e01c80639010d07c11610146578063c8984ab2116100c3578063d9d8e78311610087578063d9d8e783146107bf578063dca2aa5c146107c7578063e2bbb158146107e4578063ecd0c0c314610807578063f0895e521461080f578063f1209ef71461083c5761025e565b8063c8984ab214610749578063ca15c87314610751578063d547741f1461076e578063d8cd39991461079a578063d9b202c9146107b75761025e565b8063aa700ff21161010a578063aa700ff2146106ad578063adf55101146106ca578063ba92a4c5146106d2578063c0ba241b146106f5578063c30f75cf146106fd5761025e565b80639010d07c146105d457806391d14854146106135780639608df4b14610653578063a217fddf1461067f578063a8f1b4c4146106875761025e565b8063372646bb116101df57806353e052ac116101a357806353e052ac146103f35780635f208f341461041f578063658e28a41461052357806367ce50c01461054057806368bccfcf1461057f57806388cedd5e146105b15761025e565b8063372646bb1461037757806340e979031461037f5780634164b001146103a5578063441a3e70146103ad57806352885d8d146103d05761025e565b8063292911fb11610226578063292911fb146102ec5780632f2ff15d146102f457806332a1bd7014610320578063347908df1461032857806336568abe1461034b5761025e565b8063085313ec146102635780630c450f9d1461027d5780631338403914610285578063248a9ca3146102aa5780632514c50a146102c7575b600080fd5b61026b610844565b60408051918252519081900360200190f35b61026b61084b565b6102a86004803603604081101561029b57600080fd5b5080359060200135610851565b005b61026b600480360360208110156102c057600080fd5b503561091f565b6102cf610934565b6040805167ffffffffffffffff9092168252519081900360200190f35b61026b610944565b6102a86004803603604081101561030a57600080fd5b50803590602001356001600160a01b031661094a565b61026b6109b6565b6102a86004803603604081101561033e57600080fd5b50803590602001356109bc565b6102a86004803603604081101561036157600080fd5b50803590602001356001600160a01b0316610a85565b61026b610ae6565b61026b6004803603602081101561039557600080fd5b50356001600160a01b0316610aed565b61026b610b0b565b6102a8600480360360408110156103c357600080fd5b5080359060200135610b11565b6102a8600480360360408110156103e657600080fd5b5080359060200135610bf2565b6102a86004803603604081101561040957600080fd5b506001600160a01b03813516906020013561108b565b6104456004803603602081101561043557600080fd5b50356001600160a01b03166112ef565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b8381101561048d578181015183820152602001610475565b50505050905001848103835286818151815260200191508051906020019060200280838360005b838110156104cc5781810151838201526020016104b4565b50505050905001848103825285818151815260200191508051906020019060200280838360005b8381101561050b5781810151838201526020016104f3565b50505050905001965050505050505060405180910390f35b6102a86004803603602081101561053957600080fd5b5035611482565b6105666004803603602081101561055657600080fd5b50356001600160a01b031661155b565b6040805192835260208301919091528051918290030190f35b6102a86004803603606081101561059557600080fd5b508035906001600160a01b036020820135169060400135611574565b6102a8600480360360408110156105c757600080fd5b5080359060200135611886565b6105f7600480360360408110156105ea57600080fd5b5080359060200135611a15565b604080516001600160a01b039092168252519081900360200190f35b61063f6004803603604081101561062957600080fd5b50803590602001356001600160a01b0316611a3c565b604080519115158252519081900360200190f35b6102a86004803603604081101561066957600080fd5b506001600160a01b038135169060200135611a5a565b61026b611c8e565b6105666004803603602081101561069d57600080fd5b50356001600160a01b0316611c93565b610566600480360360208110156106c357600080fd5b5035611cb6565b61026b611ccf565b6102a8600480360360408110156106e857600080fd5b5080359060200135611cd5565b61026b611e49565b6107236004803603602081101561071357600080fd5b50356001600160a01b0316611e6e565b604080519485526020850193909352838301919091526060830152519081900360800190f35b610566611e9f565b61026b6004803603602081101561076757600080fd5b5035611ea8565b6102a86004803603604081101561078457600080fd5b50803590602001356001600160a01b0316611ebf565b6102a8600480360360208110156107b057600080fd5b5035611f18565b610566611ff2565b61026b611ffb565b6102a8600480360360208110156107dd57600080fd5b5035612001565b6102a8600480360360408110156107fa57600080fd5b50803590602001356120f2565b6105f76122fa565b6102a86004803603604081101561082557600080fd5b5067ffffffffffffffff8135169060200135612309565b61026b6123d2565b6002545b90565b60055481565b610859612447565b8061088b5750604080516c44454c45474154455f524f4c4560981b8152905190819003600d01902061088b9033611a3c565b6108c65760405162461bcd60e51b81526004018080602001828103825260248152602001806134186024913960400191505060405180910390fd5b80806108d0612458565b1115610911576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b61091a8361245c565b505050565b60009081526020819052604090206002015490565b60045467ffffffffffffffff1681565b60065481565b60008281526020819052604090206002015461096d906109686124e5565b611a3c565b6109a85760405162461bcd60e51b815260040180806020018281038252602f8152602001806133e9602f913960400191505060405180910390fd5b6109b282826124e9565b5050565b60025481565b80806109c6612458565b1115610a07576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b610a0f612447565b80610a415750604080516c44454c45474154455f524f4c4560981b8152905190819003600d019020610a419033611a3c565b610a7c5760405162461bcd60e51b81526004018080602001828103825260248152602001806134186024913960400191505060405180910390fd5b61091a83612558565b610a8d6124e5565b6001600160a01b0316816001600160a01b031614610adc5760405162461bcd60e51b815260040180806020018281038252602f8152602001806134cc602f913960400191505060405180910390fd5b6109b282826125ae565b6205a66d81565b6001600160a01b03166000908152600f602052604090206002015490565b600c5481565b8080610b1b612458565b1115610b5c576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b610b64612458565b60035411610ba7576040805162461bcd60e51b815260206004820152601860248201526000805160206134ac833981519152604482015290519081900360640190fd5b336000610bb2612458565b90506000610bc0838361261d565b50915050610bcc61333e565b610bdc828863ffffffff61287b16565b9050610be98482896128f4565b50505050505050565b8080610bfc612458565b1115610c3d576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b610c45612458565b60035411610c88576040805162461bcd60e51b815260206004820152601860248201526000805160206134ac833981519152604482015290519081900360640190fd5b6000610c92612458565b9050336000610ca18284612aa1565b90506000610cb182600201612c1a565b9050610cbb61333e565b8715610ebd5781881115610d16576040805162461bcd60e51b815260206004820152601b60248201527f416d6f756e7420697320686967686572207468616e207374616b650000000000604482015290519081900360640190fd5b60045467ffffffffffffffff16610dee576001600160a01b0384166000908152601060205260409020610d549060028501908a63ffffffff612c3416565b9050610d6760078263ffffffff612c5916565b80516020808301516040805193845291830152805187926001600160a01b0388169260008051602061348c83398151915292918290030190a38051602080830151604080519384529183015280516001600160a01b038716927fa219ed960eef85ed4cd072d3a9f240ea94727c0d6fb15e9a91a8cd4bf18ee3a692908290030190a2610eb8565b6001600160a01b0384166000908152600f6020908152604082206002810180546001810182559084529190922060045460039092020190610e4090889067ffffffffffffffff1663ffffffff6123d816565b8155610e5960028601600183018c63ffffffff612c3416565b9250610e6c60098463ffffffff612c5916565b610e7c828463ffffffff612c5916565b80548351602080860151604080519384529183015280516001600160a01b038a169260008051602061348c83398151915292908290030190a350505b611081565b81610ecc57505050505061091a565b5060408051808201909152600283018054825260038401805460208401526000918290555560045467ffffffffffffffff16610fc2576001600160a01b0384166000908152601060205260409020610f2a908263ffffffff612c5916565b610f3b60078263ffffffff612c5916565b80516020808301516040805193845291830152805187926001600160a01b0388169260008051602061348c83398151915292918290030190a38051602080830151604080519384529183015280516001600160a01b038716927fa219ed960eef85ed4cd072d3a9f240ea94727c0d6fb15e9a91a8cd4bf18ee3a692908290030190a2611081565b6001600160a01b0384166000908152600f602090815260408220600281018054600181018255908452919092206004546003909202019061101490889067ffffffffffffffff1663ffffffff6123d816565b8155825160018201556020830151600282015561103860098463ffffffff612c5916565b611048828463ffffffff612c5916565b8054600182015460028301546040805192835260208301919091528051339260008051602061348c83398151915292908290030190a350505b5050505050505050565b8080611095612458565b11156110d6576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b6110de612447565b611128576040805162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1030b71037bbb732b960511b604482015290519081900360640190fd5b600154604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561117357600080fd5b505afa158015611187573d6000803e3d6000fd5b505050506040513d602081101561119d57600080fd5b50516005546006549192506000916111ba9163ffffffff6123d816565b905060006111ce838363ffffffff612c9316565b6001546040805163a9059cbb60e01b81526001600160a01b038a8116600483015260248201859052915193945091169163a9059cbb916044808201926020929091908290030181600087803b15801561122657600080fd5b505af115801561123a573d6000803e3d6000fd5b505050506040513d602081101561125057600080fd5b50516112a3576040805162461bcd60e51b815260206004820181905260248201527f4e6f7420656e6f7567682066756e6473206f6e20636f6e74722e20616464722e604482015290519081900360640190fd5b604080516001600160a01b03881681526020810183905281517f7f66376a5ef2f39ab4ee2ee6e400606624e66929dba5d82df5b14dd0070a8a87929181900390910190a1505050505050565b6001600160a01b0381166000908152600f60205260409020600201805460609182918291908015611479578067ffffffffffffffff8111801561133157600080fd5b5060405190808252806020026020018201604052801561135b578160200160208202803683370190505b5094508067ffffffffffffffff8111801561137557600080fd5b5060405190808252806020026020018201604052801561139f578160200160208202803683370190505b5093508067ffffffffffffffff811180156113b957600080fd5b506040519080825280602002602001820160405280156113e3578160200160208202803683370190505b50925060005b818110156114775760008382815481106113ff57fe5b906000526020600020906003020190506000816001019050806000015488848151811061142857fe5b602002602001018181525050806001015487848151811061144557fe5b602002602001018181525050816000015486848151811061146257fe5b602090810291909101015250506001016113e9565b505b50509193909250565b808061148c612458565b11156114cd576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b6114d5612458565b60035411611518576040805162461bcd60e51b815260206004820152601860248201526000805160206134ac833981519152604482015290519081900360640190fd5b336000611523612458565b90506000611531838361261d565b5091505061153d61333e565b81548082526000835561155390859083906128f4565b505050505050565b6010602052600090815260409020805460019091015482565b808061157e612458565b11156115bf576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b6115c7612447565b611611576040805162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1030b71037bbb732b960511b604482015290519081900360640190fd5b83611620576005549350611677565b600554841115611677576040805162461bcd60e51b815260206004820152601f60248201527f416d6f756e7420686967686572207468616e207265776172647320706f6f6c00604482015290519081900360640190fd5b600154604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156116c257600080fd5b505afa1580156116d6573d6000803e3d6000fd5b505050506040513d60208110156116ec57600080fd5b5051600654909150600090611707908763ffffffff6123d816565b90508181111561175e576040805162461bcd60e51b815260206004820152601760248201527f436f6e747261637420696e636f6e73697374656e63792e000000000000000000604482015290519081900360640190fd5b6001546040805163a9059cbb60e01b81526001600160a01b038881166004830152602482018a90529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156117b457600080fd5b505af11580156117c8573d6000803e3d6000fd5b505050506040513d60208110156117de57600080fd5b5051611831576040805162461bcd60e51b815260206004820181905260248201527f4e6f7420656e6f7567682066756e6473206f6e20636f6e74722e20616464722e604482015290519081900360640190fd5b600580548790039055604080516001600160a01b03871681526020810188905281517f8a652d32cc9efc0a4f0fc3708c9fb81d5a924a7b9af2a37c46e9e4910d0dc325929181900390910190a1505050505050565b8080611890612458565b11156118d1576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b6118d9612458565b6003541161191c576040805162461bcd60e51b815260206004820152601860248201526000805160206134ac833981519152604482015290519081900360640190fd5b8261196e576040805162461bcd60e51b815260206004820152601f60248201527f416d6f756e74206d75737420626520686967686572207468616e207a65726f00604482015290519081900360640190fd5b6000611978612458565b90506000611986338361261d565b5091505060006119963384612aa1565b90506119a061333e565b6119b483600284018963ffffffff612cd516565b90506119c760078263ffffffff612ce716565b600182015481516020808401516040805193845291830152805133927f0fb741c5ad2cad8215be7b4cab4e3f202f907d4540668ebf954f8e742efd89cf92908290030190a350505050505050565b6000828152602081905260408120611a33908363ffffffff612d1516565b90505b92915050565b6000828152602081905260408120611a33908363ffffffff612d2116565b8080611a64612458565b1115611aa5576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b611aad612447565b611af7576040805162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1030b71037bbb732b960511b604482015290519081900360640190fd5b611aff612458565b6002541015611b55576040805162461bcd60e51b815260206004820152601b60248201527f4561726c696573742064656c657465206e6f7420726561636865640000000000604482015290519081900360640190fd5b600154604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611ba057600080fd5b505afa158015611bb4573d6000803e3d6000fd5b505050506040513d6020811015611bca57600080fd5b50516001546040805163a9059cbb60e01b81526001600160a01b03888116600483015260248201859052915193945091169163a9059cbb916044808201926020929091908290030181600087803b158015611c2457600080fd5b505af1158015611c38573d6000803e3d6000fd5b505050506040513d6020811015611c4e57600080fd5b5051611c5957600080fd5b6040517fe4dedc7f698868c432fb679313d1381b06601dfb7174d9b18b2e35378b67633390600090a1836001600160a01b0316ff5b600081565b6001600160a01b03166000908152600f6020526040902080546001909101549091565b600d602052600090815260409020805460019091015482565b60055490565b8080611cdf612458565b1115611d20576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b82611d2a5761091a565b600154604080516323b872dd60e01b81523360048201523060248201526044810186905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b158015611d8457600080fd5b505af1158015611d98573d6000803e3d6000fd5b505050506040513d6020811015611dae57600080fd5b5051611df3576040805162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b600554611e06908463ffffffff6123d816565b600555604080513381526020810185905281517fb562e06b275d420e5848bb9083041a1c68466a478df92491b473ce99a4c68f68929181900390910190a1505050565b604080516c44454c45474154455f524f4c4560981b8152905190819003600d01902081565b6001600160a01b03166000908152600e60205260409020600281015460038201548254600190930154919390929190565b60075460085482565b6000818152602081905260408120611a3690612d36565b600082815260208190526040902060020154611edd906109686124e5565b610adc5760405162461bcd60e51b815260040180806020018281038252603081526020018061343c6030913960400191505060405180910390fd5b8080611f22612458565b1115611f63576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b611f6b612458565b60035411611fae576040805162461bcd60e51b815260206004820152601860248201526000805160206134ac833981519152604482015290519081900360640190fd5b336000611fb9612458565b90506000611fc7838361261d565b50915050611fd361333e565b60018201805460208301819052600090915561155390859083906128f4565b600954600a5482565b600b5481565b808061200b612458565b111561204c576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b612054612458565b60035411612097576040805162461bcd60e51b815260206004820152601860248201526000805160206134ac833981519152604482015290519081900360640190fd5b3360006120a2612458565b905060006120b0838361261d565b506040805180820190915281548152600182015460208201529092506120e1915084906120dc84612c1a565b6128f4565b600060018201819055905550505050565b80806120fc612458565b111561213d576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b612145612458565b60035411612188576040805162461bcd60e51b815260206004820152601860248201526000805160206134ac833981519152604482015290519081900360640190fd5b82158015906122bd57600154604080516323b872dd60e01b81523360048201523060248201526044810187905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b1580156121eb57600080fd5b505af11580156121ff573d6000803e3d6000fd5b505050506040513d602081101561221557600080fd5b505161225a576040805162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b60065461226d908563ffffffff6123d816565b600655600754612283908563ffffffff6123d816565b60075560408051858152905133917f7ff07ce9a287649537e4b012e45cf012d90228b12e2b56bb03515a6b5436fcdf919081900360200190a25b60006122c7612458565b905060006122d5338361261d565b5091505082156115535780546122f1908763ffffffff6123d816565b90555050505050565b6001546001600160a01b031681565b8080612313612458565b1115612354576040805162461bcd60e51b8152602060048201526013602482015260008051602061346c833981519152604482015290519081900360640190fd5b61235c612447565b8061238e5750604080516c44454c45474154455f524f4c4560981b8152905190819003600d01902061238e9033611a3c565b6123c95760405162461bcd60e51b81526004018080602001828103825260248152602001806134186024913960400191505060405180910390fd5b61091a83612d41565b60035481565b600082820183811015611a33576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000611a33836001600160a01b038416612d97565b60006124538133611a3c565b905090565b4390565b600c546040805180820190915280612472612458565b815260209081018490526000838152600d82526040902082518155910151600191820155600c546124a89163ffffffff6123d816565b600c5560408051838152905182917fbcd200f406c53d9438c6cdc2966a1e99c35f336588c95bc3639e539df21c2f53919081900360200190a25050565b3390565b6000828152602081905260409020612507908263ffffffff61243216565b156109b2576125146124e5565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000612562612458565b90508082106125715781612573565b805b600381905560408051918252517f68b095021b1f40fe513109f513c66692f0b3219aee674a69f4efc57badb8201d9181900360200190a15050565b60008281526020819052604090206125cc908263ffffffff612de116565b156109b2576125d96124e5565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b61262561333e565b6001600160a01b0383166000908152600f6020908152604080832060109092528220919060028101825b815481101561278c57612660613358565b82828154811061266c57fe5b600091825260209182902060408051808201825260039093029091018054835281518083019092526001810154825260020154818401529181019190915280519091508810156126bf5750600101612787565b60208101515187516126d69163ffffffff6123d816565b8752602080820151810151908801516126f49163ffffffff6123d816565b60208801528254600019018281146127555783818154811061271257fe5b906000526020600020906003020184848154811061272c57fe5b600091825260209091208254600390920201908155600180830154908201556002918201549101555b8380548061275f57fe5b6000828152602081206003600019909301928302018181556001810182905560020155905550505b61264f565b5080546127c6576001600160a01b0387166000908152600f6020526040812081815560018101829055906127c36002830182613377565b50505b84511515806127d85750602085015115155b92508215612872578451602080870151604080519384529183015280516001600160a01b038a16927fa219ed960eef85ed4cd072d3a9f240ea94727c0d6fb15e9a91a8cd4bf18ee3a692908290030190a261283a60098663ffffffff612ce716565b80541561285157612851828663ffffffff612ce716565b61286260078663ffffffff612c5916565b612872848663ffffffff612c5916565b50509250925092565b61288361333e565b818360010154106128b45760018301546128a3908363ffffffff612c9316565b600184015560208101829052611a36565b60018301546128ca90839063ffffffff612c9316565b80825283546128de9163ffffffff612c9316565b8355600190920180546020840152600090555090565b801561091a5781602001516005541015612955576040805162461bcd60e51b815260206004820181905260248201527f4e6f7420656e6f7567682066756e647320696e207265776172647320706f6f6c604482015290519081900360640190fd5b6001546040805163a9059cbb60e01b81526001600160a01b038681166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156129ab57600080fd5b505af11580156129bf573d6000803e3d6000fd5b505050506040513d60208110156129d557600080fd5b5051612a1a576040805162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b6020820151600554612a319163ffffffff612c9316565b6005558151600654612a489163ffffffff612c9316565b600655612a5c60078363ffffffff612ce716565b81516020808401516040805193845291830152805133927ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56892908290030190a2505050565b6001600160a01b0382166000908152600e6020526040812090612ac660028301612c1a565b90508015612ba557815460018301545b600c54811015612b87576000818152600d602052604090208054831015612b44576040805162461bcd60e51b815260206004820152601860248201527f73696e6365426c6f636b20696e636f6e73697374656e63790000000000000000604482015290519081900360640190fd5b600c5486906001840190811015612b67576000818152600d602052604090205491505b612b78868460010154878503612df6565b95509093505050600101612ad6565b506002830154612b9e90839063ffffffff612c9316565b6003840155505b828255600c54612bb6576000612bbd565b6001600c54035b600183018190556002830154600384015460408051928352602083019190915280516001600160a01b038816927f6b6b43cdaf8f2ae06bdc6f6be433bb374b703ce8c88db4adce9dd8aefe44fe6d92908290030190a35092915050565b60018101548154600091611a36919063ffffffff6123d816565b612c3c61333e565b612c46848361287b565b9050612c528382612c59565b9392505050565b80518254612c6c9163ffffffff6123d816565b825560208101516001830154612c879163ffffffff6123d816565b82600101819055505050565b6000611a3383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612e36565b612cdd61333e565b612c468483612ecd565b80518254612cfa9163ffffffff612c9316565b825560208101516001830154612c879163ffffffff612c9316565b6000611a338383612f39565b6000611a33836001600160a01b038416612f9d565b6000611a3682612fb5565b6004805467ffffffffffffffff831667ffffffffffffffff19909116811790915560408051918252517f6b24ea7c7a8ce7fd2e6a6cb675dbabcd38a90f83ddd581c4435610ce90456e8f9181900360200190a150565b6000612da38383612f9d565b612dd957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611a36565b506000611a36565b6000611a33836001600160a01b038416612fb9565b6000612e2e612e28612e22612e0b600161307f565b612e1d87670de0b6b3a764000061309d565b6130d4565b84613108565b85613156565b949350505050565b60008184841115612ec55760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612e8a578181015183820152602001612e72565b50505050905090810190601f168015612eb75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b612ed561333e565b82548211612ef9578254612eef908363ffffffff612c9316565b8355818152611a36565b8254612f0c90839063ffffffff612c9316565b602082018190526001840154612f279163ffffffff612c9316565b60018401558254815260009092555090565b81546000908210612f7b5760405162461bcd60e51b81526004018080602001828103825260228152602001806133c76022913960400191505060405180910390fd5b826000018281548110612f8a57fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b5490565b600081815260018301602052604081205480156130755783546000198083019190810190600090879083908110612fec57fe5b906000526020600020015490508087600001848154811061300957fe5b60009182526020808320909101929092558281526001898101909252604090209084019055865487908061303957fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050611a36565b6000915050611a36565b6000677fffffffffffffff82111561309657600080fd5b5060401b90565b6000816130a957600080fd5b60006130b584846131be565b905060016001607f1b036001600160801b0382161115611a3357600080fd5b6000600f83810b9083900b0160016001607f1b031981128015906130ff575060016001607f1b038113155b611a3357600080fd5b6000613114600161307f565b90505b8115611a3657600182161561313d576131308184613308565b9050600182039150613151565b6131478384613308565b9250600182901c91505b613117565b60008161316557506000611a36565b600083600f0b121561317657600080fd5b600f83900b6001600160801b038316810260401c90608084901c026001600160c01b038111156131a557600080fd5b60401b81198111156131b657600080fd5b019392505050565b6000816131ca57600080fd5b60006001600160c01b0384116131ef5782604085901b816131e757fe5b0490506132f4565b60c084811c6401000000008110613208576020918201911c5b62010000811061321a576010918201911c5b610100811061322b576008918201911c5b6010811061323b576004918201911c5b6004811061324b576002918201911c5b6002811061325a576001820191505b60bf820360018603901c6001018260ff0387901b8161327557fe5b0492506001600160801b0383111561328c57600080fd5b608085901c83026001600160801b038616840260c088901c604089901b828110156132b8576001820391505b608084901b929003828110156132cf576001820391505b829003608084901c82146132df57fe5b8881816132e857fe5b04870196505050505050505b6001600160801b03811115611a3357600080fd5b6000600f83810b9083900b0260401d60016001607f1b031981128015906130ff575060016001607f1b03811315611a3357600080fd5b604051806040016040528060008152602001600081525090565b60405180604001604052806000815260200161337261333e565b905290565b5080546000825560030290600052602060002090810190613398919061339b565b50565b61084891905b808211156133c25760008082556001820181905560028201556003016133a1565b509056fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e6473416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f206772616e7443616c6c6572206973206e656974686572206f776e6572206e6f722064656c6567617465416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e2061646d696e20746f207265766f6b655472616e73616374696f6e2065787069726564000000000000000000000000005bfe1e16d75ca1fa001989652cd88c5b8ee8a59b5df6df99836337def4d1c82d436f6e747261637420686173206265656e207061757365640000000000000000416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636520726f6c657320666f722073656c66a26469706673582212205436678265352631f897e2cef39869cf23c267c4a2f500784a8480a5ff10f77664736f6c63430006080033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000aea46a60368a7bd060eec7df8cba43b7ef41ad850000000000000000000000000000000000000000000000000000000944754ca900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021a27
-----Decoded View---------------
Arg [0] : ERC20Address (address): 0xaea46A60368A7bD060eec7DF8CBa43b7EF41Ad85
Arg [1] : interestRatePerBlock (uint256): 39803243689
Arg [2] : pausedSinceBlock (uint256): 0
Arg [3] : lockPeriodInBlocks (uint64): 137767
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000aea46a60368a7bd060eec7df8cba43b7ef41ad85
Arg [1] : 0000000000000000000000000000000000000000000000000000000944754ca9
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [3] : 0000000000000000000000000000000000000000000000000000000000021a27
Deployed Bytecode Sourcemap
66825:34088:0:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;66825:34088:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;84168:106:0;;;:::i;:::-;;;;;;;;;;;;;;;;71336:34;;;:::i;74255:226::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;74255:226:0;;;;;;;:::i;:::-;;22875:114;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;22875:114:0;;:::i;71172:33::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;71505:38;;;:::i;23251:227::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;23251:227:0;;;;;;-1:-1:-1;;;;;23251:227:0;;:::i;71090:30::-;;;:::i;87842:203::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;87842:203:0;;;;;;;:::i;24460:209::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;24460:209:0;;;;;;-1:-1:-1;;;;;24460:209:0;;:::i;70190:57::-;;;:::i;84284:159::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;84284:159:0;-1:-1:-1;;;;;84284:159:0;;:::i;71715:36::-;;;:::i;75637:509::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;75637:509:0;;;;;;;:::i;80328:3711::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;80328:3711:0;;;;;;;:::i;90114:794::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;90114:794:0;;;;;;;;:::i;84976:865::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;84976:865:0;-1:-1:-1;;;;;84976:865:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;84976:865:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;84976:865:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;84976:865:0;;;;;;;;;;;;;;;;;;;;;76289:545;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;76289:545:0;;:::i;71910:52::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;71910:52:0;-1:-1:-1;;;;;71910:52:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;88324:1145;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;88324:1145:0;;;-1:-1:-1;;;;;88324:1145:0;;;;;;;;;;:::i;78222:1319::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;78222:1319:0;;;;;;;:::i;22548:138::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;22548:138:0;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;22548:138:0;;;;;;;;;;;;;;21509:139;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;21509:139:0;;;;;;-1:-1:-1;;;;;21509:139:0;;:::i;:::-;;;;;;;;;;;;;;;;;;91241:459;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;91241:459:0;;;;;;;;:::i;20254:49::-;;;:::i;84453:278::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;84453:278:0;-1:-1:-1;;;;;84453:278:0;;:::i;71758:62::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;71758:62:0;;:::i;84049:109::-;;;:::i;86728:452::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;86728:452:0;;;;;;;:::i;70117:66::-;;;:::i;85851:430::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;85851:430:0;-1:-1:-1;;;;;85851:430:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71550:45;;;:::i;21822:127::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;21822:127:0;;:::i;23723:230::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;23723:230:0;;;;;;-1:-1:-1;;;;;23723:230:0;;:::i;76977:580::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;76977:580:0;;:::i;71611:42::-;;;:::i;71671:37::-;;;:::i;77707:505::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;77707:505:0;;:::i;74491:853::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;74491:853:0;;;;;;;:::i;70306:20::-;;;:::i;87331:214::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;87331:214:0;;;;;;;;;:::i;71133:32::-;;;:::i;84168:106::-;84251:15;;84168:106;;:::o;71336:34::-;;;;:::o;74255:226::-;72201:10;:8;:10::i;:::-;:48;;;-1:-1:-1;70157:26:0;;;-1:-1:-1;;;70157:26:0;;;;;;;;;;;;72215:34;;72238:10;72215:7;:34::i;:::-;72193:97;;;;-1:-1:-1;;;72193:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74418:15:::1;72411;72390:17;:15;:17::i;:::-;:36;;72382:68;;;::::0;;-1:-1:-1;;;72382:68:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;;;;;;;72382:68:0;;;;;;;;;;;;;::::1;;74451:22:::2;74468:4;74451:16;:22::i;:::-;72301:1:::1;74255:226:::0;;:::o;22875:114::-;22932:7;22959:12;;;;;;;;;;:22;;;;22875:114::o;71172:33::-;;;;;;:::o;71505:38::-;;;;:::o;23251:227::-;23343:6;:12;;;;;;;;;;:22;;;23335:45;;23367:12;:10;:12::i;:::-;23335:7;:45::i;:::-;23327:105;;;;-1:-1:-1;;;23327:105:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23445:25;23456:4;23462:7;23445:10;:25::i;:::-;23251:227;;:::o;71090:30::-;;;;:::o;87842:203::-;87956:17;72411:15;72390:17;:15;:17::i;:::-;:36;;72382:68;;;;;-1:-1:-1;;;72382:68:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;72382:68:0;;;;;;;;;;;;;;;72201:10:::1;:8;:10::i;:::-;:48;;;-1:-1:-1::0;70157:26:0::1;::::0;;-1:-1:-1;;;70157:26:0;;;;;;;;::::1;::::0;;;72215:34:::1;::::0;72238:10:::1;72215:7;:34::i;:::-;72193:97;;;;-1:-1:-1::0;;;72193:97:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88013:24:::2;88025:11;88013;:24::i;24460:209::-:0;24558:12;:10;:12::i;:::-;-1:-1:-1;;;;;24547:23:0;:7;-1:-1:-1;;;;;24547:23:0;;24539:83;;;;-1:-1:-1;;;24539:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24635:26;24647:4;24653:7;24635:11;:26::i;70190:57::-;70241:6;70190:57;:::o;84284:159::-;-1:-1:-1;;;;;84402:19:0;84366:14;84402:19;;;:7;:19;;;;;:26;;:33;;84284:159::o;71715:36::-;;;;:::o;75637:509::-;75773:17;72411:15;72390:17;:15;:17::i;:::-;:36;;72382:68;;;;;-1:-1:-1;;;72382:68:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;72382:68:0;;;;;;;;;;;;;;;72544:17:::1;:15;:17::i;:::-;72524;;:37;72516:74;;;::::0;;-1:-1:-1;;;72516:74:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;;;;;;;72516:74:0;;;;;;;;;;;;;::::1;;75850:10:::2;75833:14;75892:17;:15;:17::i;:::-;75871:38;;75923:32;75960:37;75978:6;75986:10;75960:17;:37::i;:::-;75920:77;;;;76010:29;;:::i;:::-;76042:43;:9:::0;76078:6;76042:43:::2;:35;:43;:::i;:::-;76010:75;;76096:42;76114:6;76122:7;76131:6;76096:17;:42::i;:::-;72601:1;;;;75637:509:::0;;;:::o;80328:3711::-;80512:17;72411:15;72390:17;:15;:17::i;:::-;:36;;72382:68;;;;;-1:-1:-1;;;72382:68:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;72382:68:0;;;;;;;;;;;;;;;72544:17:::1;:15;:17::i;:::-;72524;;:37;72516:74;;;::::0;;-1:-1:-1;;;72516:74:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;;;;;;;72516:74:0;;;;;;;;;;;;;::::1;;80572:18:::2;80593:17;:15;:17::i;:::-;80572:38:::0;-1:-1:-1;80638:10:0::2;80621:14;80681:48;80638:10:::0;80572:38;80681:28:::2;:48::i;:::-;80659:70;;80742:23;80768;:5;:11;;:21;:23::i;:::-;80742:49;;80802:29;;:::i;:::-;80848:10:::0;;80844:3188:::2;;81613:15;81603:6;:25;;81595:65;;;::::0;;-1:-1:-1;;;81595:65:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;81681:19;::::0;::::2;;81677:1065;;-1:-1:-1::0;;;;;81779:18:0;::::2;;::::0;;;:10:::2;:18;::::0;;;;81736:70:::2;::::0;:11:::2;::::0;::::2;::::0;81799:6;81736:70:::2;:42;:70;:::i;:::-;81726:80:::0;-1:-1:-1;81825:37:0::2;:23;81726:80:::0;81825:37:::2;:28;:37;:::i;:::-;81918:17:::0;;81937:24:::2;::::0;;::::2;::::0;81886:76:::2;::::0;;;;;;;::::2;::::0;;;81906:10;;-1:-1:-1;;;;;81886:76:0;::::2;::::0;-1:-1:-1;;;;;;;;;;;81886:76:0;;;;;;;::::2;82012:17:::0;;82031:24:::2;::::0;;::::2;::::0;81986:70:::2;::::0;;;;;;;::::2;::::0;;;-1:-1:-1;;;;;81986:70:0;::::2;::::0;::::2;::::0;;;;;;;::::2;81677:1065;;;-1:-1:-1::0;;;;;82121:15:0;::::2;82097:21;82121:15:::0;;;:7:::2;:15;::::0;;;;;;82192:13:::2;::::0;::::2;27:10:-1::0;;82192:20:0::2;23:18:-1::0;::::2;45:23:::0;;82192:20:0;;;;;;;82280:19:::2;::::0;82192:20:::2;::::0;;::::2;;::::0;82265:35:::2;::::0;:10;;82280:19:::2;;82265:35;:14;:35;:::i;:::-;82231:69:::0;;82329:72:::2;:11;::::0;::::2;82372:20;::::0;::::2;82394:6:::0;82329:72:::2;:42;:72;:::i;:::-;82319:82:::0;-1:-1:-1;82422:34:0::2;:20;82319:82:::0;82422:34:::2;:25;:34;:::i;:::-;82475:30;:6:::0;82497:7;82475:30:::2;:21;:30;:::i;:::-;82649:31:::0;;82682:17;;82701:24:::2;::::0;;::::2;::::0;82629:97:::2;::::0;;;;;;;::::2;::::0;;;-1:-1:-1;;;;;82629:97:0;::::2;::::0;-1:-1:-1;;;;;;;;;;;82629:97:0;;;;;;;::::2;81677:1065;;;80844:3188;;;82778:20:::0;82774:111:::2;;82863:7;;;;;;;82774:111;-1:-1:-1::0;82901:21:0::2;::::0;;;;::::2;::::0;;;82911:11:::2;::::0;::::2;82901:21:::0;;;;;;;;;::::2;::::0;::::2;::::0;-1:-1:-1;82937:25:0;;;;82977:32;83030:19:::2;::::0;::::2;;83026:995;;-1:-1:-1::0;;;;;83075:18:0;::::2;;::::0;;;:10:::2;:18;::::0;;;;:32:::2;::::0;83099:7;83075:32:::2;:23;:32;:::i;:::-;83126:37;:23;83155:7:::0;83126:37:::2;:28;:37;:::i;:::-;83219:17:::0;;83238:24:::2;::::0;;::::2;::::0;83187:76:::2;::::0;;;;;;;::::2;::::0;;;83207:10;;-1:-1:-1;;;;;83187:76:0;::::2;::::0;-1:-1:-1;;;;;;;;;;;83187:76:0;;;;;;;::::2;83313:17:::0;;83332:24:::2;::::0;;::::2;::::0;83287:70:::2;::::0;;;;;;;::::2;::::0;;;-1:-1:-1;;;;;83287:70:0;::::2;::::0;::::2;::::0;;;;;;;::::2;83026:995;;;-1:-1:-1::0;;;;;83422:15:0;::::2;83398:21;83422:15:::0;;;:7:::2;:15;::::0;;;;;;83493:13:::2;::::0;::::2;27:10:-1::0;;83493:20:0::2;23:18:-1::0;::::2;45:23:::0;;83493:20:0;;;;;;;83581:19:::2;::::0;83493:20:::2;::::0;;::::2;;::::0;83566:35:::2;::::0;:10;;83581:19:::2;;83566:35;:14;:35;:::i;:::-;83532:69:::0;;83620:30;;:20:::2;::::0;::::2;:30:::0;::::2;::::0;::::2;::::0;;;;;83671:34:::2;:20;83643:7:::0;83671:34:::2;:25;:34;:::i;:::-;83724:30;:6:::0;83746:7;83724:30:::2;:21;:30;:::i;:::-;83902:31:::0;;83935:20:::2;::::0;::::2;:30:::0;83967:37;;;;83878:127:::2;::::0;;;;;::::2;::::0;::::2;::::0;;;;;;83890:10:::2;::::0;-1:-1:-1;;;;;;;;;;;83878:127:0;;;;;;;::::2;83026:995;;;72601:1;;;;;80328:3711:::0;;;:::o;90114:794::-;90248:17;72411:15;72390:17;:15;:17::i;:::-;:36;;72382:68;;;;;-1:-1:-1;;;72382:68:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;72382:68:0;;;;;;;;;;;;;;;72047:10:::1;:8;:10::i;:::-;72039:45;;;::::0;;-1:-1:-1;;;72039:45:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;72039:45:0;;;;;;;;;;;;;::::1;;90328:6:::2;::::0;:31:::2;::::0;;-1:-1:-1;;;90328:31:0;;90353:4:::2;90328:31;::::0;::::2;::::0;;;90302:23:::2;::::0;-1:-1:-1;;;;;90328:6:0::2;::::0;:16:::2;::::0;:31;;;;;::::2;::::0;;;;;;;;:6;:31;::::2;;2:2:-1::0;::::2;;;27:1;24::::0;17:12:::2;2:2;90328:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;90328:31:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::2;4:2;-1:-1:::0;90328:31:0;90435:19:::2;::::0;90407:23:::2;::::0;90328:31;;-1:-1:-1;90370:34:0::2;::::0;90407:48:::2;::::0;::::2;:27;:48;:::i;:::-;90370:85:::0;-1:-1:-1;90664:20:0::2;90687:47;:15:::0;90370:85;90687:47:::2;:19;:47;:::i;:::-;90753:6;::::0;:44:::2;::::0;;-1:-1:-1;;;90753:44:0;;-1:-1:-1;;;;;90753:44:0;;::::2;;::::0;::::2;::::0;;;;;;;;;90664:70;;-1:-1:-1;90753:6:0;::::2;::::0;:15:::2;::::0;:44;;;;;::::2;::::0;;;;;;;;;:6:::2;::::0;:44;::::2;;2:2:-1::0;::::2;;;27:1;24::::0;17:12:::2;2:2;90753:44:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;90753:44:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::2;4:2;-1:-1:::0;90753:44:0;90745:89:::2;;;::::0;;-1:-1:-1;;;90745:89:0;;::::2;;::::0;::::2;::::0;;;;;;;::::2;::::0;;;;;;;;;;;;;::::2;;90850:50;::::0;;-1:-1:-1;;;;;90850:50:0;::::2;::::0;;::::2;::::0;::::2;::::0;;;;;::::2;::::0;;;;;;;;;::::2;72095:1;;;90114:794:::0;;;:::o;84976:865::-;-1:-1:-1;;;;;85219:19:0;;85182:34;85219:19;;;:7;:19;;;;;:26;;85273:19;;85068:26;;;;;;85219;85307:11;;85303:531;;85361:6;85347:21;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;85347:21:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;85347:21:0;;85335:33;;85416:6;85402:21;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;85402:21:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;85402:21:0;;85383:40;;85471:6;85457:21;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;85457:21:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;85457:21:0;-1:-1:-1;85438:40:0;-1:-1:-1;85500:9:0;85495:328;85517:6;85513:1;:10;85495:328;;;85549:22;85574:12;85587:1;85574:15;;;;;;;;;;;;;;;;;;85549:40;;85608:24;85635:2;:8;;85608:35;;85677:1;:11;;;85662:9;85672:1;85662:12;;;;;;;;;;;;;:26;;;;;85729:1;:18;;;85707:16;85724:1;85707:19;;;;;;;;;;;;;:40;;;;;85788:2;:19;;;85766:16;85783:1;85766:19;;;;;;;;;;;;;;;;;:41;-1:-1:-1;;85525:3:0;;85495:328;;;;85303:531;84976:865;;;;;;;:::o;76289:545::-;76409:17;72411:15;72390:17;:15;:17::i;:::-;:36;;72382:68;;;;;-1:-1:-1;;;72382:68:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;72382:68:0;;;;;;;;;;;;;;;72544:17:::1;:15;:17::i;:::-;72524;;:37;72516:74;;;::::0;;-1:-1:-1;;;72516:74:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;;;;;;;72516:74:0;;;;;;;;;;;;;::::1;;76486:10:::2;76469:14;76528:17;:15;:17::i;:::-;76507:38;;76559:32;76597:37;76615:6;76623:10;76597:17;:37::i;:::-;76556:78;;;;76647:29;;:::i;:::-;76707:19:::0;;76687:39;;;76707:19:::2;76737:23:::0;;76773:53:::2;::::0;76791:6;;76687:7;;76773:17:::2;:53::i;:::-;72601:1;;;;76289:545:::0;;:::o;71910:52::-;;;;;;;;;;;;;;;;;;;:::o;88324:1145::-;88496:17;72411:15;72390:17;:15;:17::i;:::-;:36;;72382:68;;;;;-1:-1:-1;;;72382:68:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;72382:68:0;;;;;;;;;;;;;;;72047:10:::1;:8;:10::i;:::-;72039:45;;;::::0;;-1:-1:-1;;;72039:45:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;72039:45:0;;;;;;;;;;;;;::::1;;88554:11:::0;88550:178:::2;;88591:19;;88582:28;;88550:178;;;88661:19;;88651:6;:29;;88643:73;;;::::0;;-1:-1:-1;;;88643:73:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;88946:6;::::0;:31:::2;::::0;;-1:-1:-1;;;88946:31:0;;88971:4:::2;88946:31;::::0;::::2;::::0;;;88920:23:::2;::::0;-1:-1:-1;;;;;88946:6:0::2;::::0;:16:::2;::::0;:31;;;;;::::2;::::0;;;;;;;;:6;:31;::::2;;2:2:-1::0;::::2;;;27:1;24::::0;17:12:::2;2:2;88946:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;88946:31:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::2;4:2;-1:-1:::0;88946:31:0;89025:23:::2;::::0;88946:31;;-1:-1:-1;88988:34:0::2;::::0;89025:35:::2;::::0;89053:6;89025:35:::2;:27;:35;:::i;:::-;88988:72;;89109:15;89079:26;:45;;89071:81;;;::::0;;-1:-1:-1;;;89071:81:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;89173:6;::::0;:38:::2;::::0;;-1:-1:-1;;;89173:38:0;;-1:-1:-1;;;;;89173:38:0;;::::2;;::::0;::::2;::::0;;;;;;;;;:6;;;::::2;::::0;:15:::2;::::0;:38;;;;;::::2;::::0;;;;;;;;:6:::2;::::0;:38;::::2;;2:2:-1::0;::::2;;;27:1;24::::0;17:12:::2;2:2;89173:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;89173:38:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::2;4:2;-1:-1:::0;89173:38:0;89165:83:::2;;;::::0;;-1:-1:-1;;;89165:83:0;;::::2;;::::0;::::2;::::0;;;;;;;::::2;::::0;;;;;;;;;;;;;::::2;;89365:19;:29:::0;;;;::::2;::::0;;89412:49:::2;::::0;;-1:-1:-1;;;;;89412:49:0;::::2;::::0;;::::2;::::0;::::2;::::0;;;;;::::2;::::0;;;;;;;;;::::2;72095:1;;88324:1145:::0;;;;:::o;78222:1319::-;78359:17;72411:15;72390:17;:15;:17::i;:::-;:36;;72382:68;;;;;-1:-1:-1;;;72382:68:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;72382:68:0;;;;;;;;;;;;;;;72544:17:::1;:15;:17::i;:::-;72524;;:37;72516:74;;;::::0;;-1:-1:-1;;;72516:74:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;;;;;;;72516:74:0;;;;;;;;;;;;;::::1;;78427:11:::0;78419:55:::2;;;::::0;;-1:-1:-1;;;78419:55:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;78487:18;78508:17;:15;:17::i;:::-;78487:38;;78541:32;78579:41;78597:10;78609;78579:17;:41::i;:::-;78538:82;;;;78973:19;78995:52;79024:10;79036;78995:28;:52::i;:::-;78973:74;;79058:29;;:::i;:::-;79090:54;:9:::0;79124:11:::2;::::0;::::2;79137:6:::0;79090:54:::2;:33;:54;:::i;:::-;79058:86:::0;-1:-1:-1;79155:37:0::2;:23;79058:86:::0;79155:37:::2;:28;:37;:::i;:::-;79446:28;::::0;::::2;::::0;79476:17;;79495:24:::2;::::0;;::::2;::::0;79424:96:::2;::::0;;;;;;;::::2;::::0;;;79434:10:::2;::::0;79424:96:::2;::::0;;;;;;;::::2;72601:1;;;;78222:1319:::0;;;:::o;22548:138::-;22621:7;22648:12;;;;;;;;;;:30;;22672:5;22648:30;:23;:30;:::i;:::-;22641:37;;22548:138;;;;;:::o;21509:139::-;21578:4;21602:12;;;;;;;;;;:38;;21632:7;21602:38;:29;:38;:::i;91241:459::-;91361:17;72411:15;72390:17;:15;:17::i;:::-;:36;;72382:68;;;;;-1:-1:-1;;;72382:68:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;72382:68:0;;;;;;;;;;;;;;;72047:10:::1;:8;:10::i;:::-;72039:45;;;::::0;;-1:-1:-1;;;72039:45:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;72039:45:0;;;;;;;;;;;;;::::1;;91438:17:::2;:15;:17::i;:::-;91419:15;;:36;;91411:76;;;::::0;;-1:-1:-1;;;91411:76:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;91524:6;::::0;:31:::2;::::0;;-1:-1:-1;;;91524:31:0;;91549:4:::2;91524:31;::::0;::::2;::::0;;;91498:23:::2;::::0;-1:-1:-1;;;;;91524:6:0::2;::::0;:16:::2;::::0;:31;;;;;::::2;::::0;;;;;;;;:6;:31;::::2;;2:2:-1::0;::::2;;;27:1;24::::0;17:12:::2;2:2;91524:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;91524:31:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::2;4:2;-1:-1:::0;91524:31:0;91574:6:::2;::::0;:47:::2;::::0;;-1:-1:-1;;;91574:47:0;;-1:-1:-1;;;;;91574:47:0;;::::2;;::::0;::::2;::::0;;;;;;;;;91524:31;;-1:-1:-1;91574:6:0;::::2;::::0;:15:::2;::::0;:47;;;;;91524:31:::2;::::0;91574:47;;;;;;;;:6:::2;::::0;:47;::::2;;2:2:-1::0;::::2;;;27:1;24::::0;17:12:::2;2:2;91574:47:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;91574:47:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::2;4:2;-1:-1:::0;91574:47:0;91566:56:::2;;12:1:-1;9::::0;2:12:::2;91566:56:0;91638:16;::::0;::::2;::::0;;;::::2;91678:13;-1:-1:-1::0;;;;;91665:27:0::2;;20254:49:::0;20299:4;20254:49;:::o;84453:278::-;-1:-1:-1;;;;;84627:19:0;84536:17;84627:19;;;:7;:19;;;;;84675;;84696:26;;;;;84675:19;;84453:278::o;71758:62::-;;;;;;;;;;;;;;;;;;;:::o;84049:109::-;84131:19;;84049:109;:::o;86728:452::-;86872:17;72411:15;72390:17;:15;:17::i;:::-;:36;;72382:68;;;;;-1:-1:-1;;;72382:68:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;72382:68:0;;;;;;;;;;;;;;;86911:11;86907:50:::1;;86939:7;;86907:50;86977:6;::::0;:54:::1;::::0;;-1:-1:-1;;;86977:54:0;;86997:10:::1;86977:54;::::0;::::1;::::0;87017:4:::1;86977:54:::0;;;;;;;;;;;;-1:-1:-1;;;;;86977:6:0;;::::1;::::0;:19:::1;::::0;:54;;;;;::::1;::::0;;;;;;;;;:6:::1;::::0;:54;::::1;;2:2:-1::0;::::1;;;27:1;24::::0;17:12:::1;2:2;86977:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;86977:54:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::1;4:2;-1:-1:::0;86977:54:0;86969:82:::1;;;::::0;;-1:-1:-1;;;86969:82:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;86969:82:0;;;;;;;;;;;;;::::1;;87084:19;::::0;:31:::1;::::0;87108:6;87084:31:::1;:23;:31;:::i;:::-;87062:19;:53:::0;87131:41:::1;::::0;;87153:10:::1;87131:41:::0;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;;;;;;;;;::::1;86728:452:::0;;;:::o;70117:66::-;70157:26;;;-1:-1:-1;;;70157:26:0;;;;;;;;;;;;70117:66;:::o;85851:430::-;-1:-1:-1;;;;;86048:19:0;85918:17;86048:19;;;:7;:19;;;;;86090:11;;;:21;86141:28;;;;86193:16;;86141:28;86245;;;;86090:21;;86141:28;;86193:16;86245:28;85851:430::o;71550:45::-;;;;;;:::o;21822:127::-;21885:7;21912:12;;;;;;;;;;:29;;:27;:29::i;23723:230::-;23816:6;:12;;;;;;;;;;:22;;;23808:45;;23840:12;:10;:12::i;23808:45::-;23800:106;;;;-1:-1:-1;;;23800:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76977:580;77104:17;72411:15;72390:17;:15;:17::i;:::-;:36;;72382:68;;;;;-1:-1:-1;;;72382:68:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;72382:68:0;;;;;;;;;;;;;;;72544:17:::1;:15;:17::i;:::-;72524;;:37;72516:74;;;::::0;;-1:-1:-1;;;72516:74:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;;;;;;;72516:74:0;;;;;;;;;;;;;::::1;;77181:10:::2;77164:14;77223:17;:15;:17::i;:::-;77202:38;;77254:32;77292:37;77310:6;77318:10;77292:17;:37::i;:::-;77251:78;;;;77342:29;;:::i;:::-;77409:26;::::0;::::2;::::0;;77382:24:::2;::::0;::::2;:53:::0;;;77475:1:::2;77446:30:::0;;;77489:60:::2;::::0;77507:6;;77382:7;;77489:17:::2;:60::i;71611:42::-:0;;;;;;:::o;71671:37::-;;;;:::o;77707:505::-;77832:17;72411:15;72390:17;:15;:17::i;:::-;:36;;72382:68;;;;;-1:-1:-1;;;72382:68:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;72382:68:0;;;;;;;;;;;;;;;72544:17:::1;:15;:17::i;:::-;72524;;:37;72516:74;;;::::0;;-1:-1:-1;;;72516:74:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;;;;;;;72516:74:0;;;;;;;;;;;;;::::1;;77909:10:::2;77892:14;77951:17;:15;:17::i;:::-;77930:38;;77982:32;78020:37;78038:6;78046:10;78020:17;:37::i;:::-;-1:-1:-1::0;78070:59:0::2;::::0;;;;::::2;::::0;;;;;;;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;77979:78;;-1:-1:-1;78070:59:0::2;::::0;-1:-1:-1;78088:6:0;;78107:21:::2;77979:78:::0;78107:19:::2;:21::i;:::-;78070:17;:59::i;:::-;78169:1;78140:26;::::0;::::2;:30:::0;;;78181:23;;-1:-1:-1;;;;77707:505:0:o;74491:853::-;74626:17;72411:15;72390:17;:15;:17::i;:::-;:36;;72382:68;;;;;-1:-1:-1;;;72382:68:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;72382:68:0;;;;;;;;;;;;;;;72544:17:::1;:15;:17::i;:::-;72524;;:37;72516:74;;;::::0;;-1:-1:-1;;;72516:74:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;;;;;;;72516:74:0;;;;;;;;;;;;;::::1;;74706:11:::0;;;::::2;::::0;74728:357:::2;;74769:6;::::0;:54:::2;::::0;;-1:-1:-1;;;74769:54:0;;74789:10:::2;74769:54;::::0;::::2;::::0;74809:4:::2;74769:54:::0;;;;;;;;;;;;-1:-1:-1;;;;;74769:6:0;;::::2;::::0;:19:::2;::::0;:54;;;;;::::2;::::0;;;;;;;;;:6:::2;::::0;:54;::::2;;2:2:-1::0;::::2;;;27:1;24::::0;17:12:::2;2:2;74769:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;74769:54:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::2;4:2;-1:-1:::0;74769:54:0;74761:82:::2;;;::::0;;-1:-1:-1;;;74761:82:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;74761:82:0;;;;;;;;;;;;;::::2;;74884:23;::::0;:35:::2;::::0;74912:6;74884:35:::2;:27;:35;:::i;:::-;74858:23;:61:::0;74970:23:::2;:33:::0;:45:::2;::::0;75008:6;74970:45:::2;:37;:45;:::i;:::-;74934:23;:81:::0;75035:38:::2;::::0;;;;;;;75054:10:::2;::::0;75035:38:::2;::::0;;;;;::::2;::::0;;::::2;74728:357;75097:18;75118:17;:15;:17::i;:::-;75097:38;;75149:32;75186:41;75204:10;75216;75186:17;:41::i;:::-;75146:81;;;;75244:12;75240:97;;;75295:19:::0;;:31:::2;::::0;75319:6;75295:31:::2;:23;:31;:::i;:::-;75273:53:::0;;-1:-1:-1;;;;;74491:853:0:o;70306:20::-;;;-1:-1:-1;;;;;70306:20:0;;:::o;87331:214::-;87450:17;72411:15;72390:17;:15;:17::i;:::-;:36;;72382:68;;;;;-1:-1:-1;;;72382:68:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;72382:68:0;;;;;;;;;;;;;;;72201:10:::1;:8;:10::i;:::-;:48;;;-1:-1:-1::0;70157:26:0::1;::::0;;-1:-1:-1;;;70157:26:0;;;;;;;;::::1;::::0;;;72215:34:::1;::::0;72238:10:::1;72215:7;:34::i;:::-;72193:97;;;;-1:-1:-1::0;;;72193:97:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87507:30:::2;87525:11;87507:17;:30::i;71133:32::-:0;;;;:::o;53885:181::-;53943:7;53975:5;;;53999:6;;;;53991:46;;;;;-1:-1:-1;;;53991:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;8565:143;8635:4;8659:41;8664:3;-1:-1:-1;;;;;8684:14:0;;8659:4;:41::i;92101:113::-;92143:4;92167:39;92143:4;92195:10;92167:7;:39::i;:::-;92160:46;;92101:113;:::o;91982:109::-;92071:12;91982:109;:::o;92452:401::-;92532:21;;92586:152;;;;;;;;;;92636:17;:15;:17::i;:::-;92586:152;;;;;;;;;-1:-1:-1;92564:19:0;;;:14;:19;;;;;:174;;;;;;;;;;;;92773:21;;:28;;;:25;:28;:::i;:::-;92749:21;:52;92819:26;;;;;;;;92835:3;;92819:26;;;;;;;;;;92452:401;;:::o;18293:106::-;18381:10;18293:106;:::o;25703:188::-;25777:6;:12;;;;;;;;;;:33;;25802:7;25777:33;:24;:33;:::i;:::-;25773:111;;;25859:12;:10;:12::i;:::-;-1:-1:-1;;;;;25832:40:0;25850:7;-1:-1:-1;;;;;25832:40:0;25844:4;25832:40;;;;;;;;;;25703:188;;:::o;93399:260::-;93467:26;93496:17;:15;:17::i;:::-;93467:46;;93558:18;93544:11;:32;:67;;93600:11;93544:67;;;93579:18;93544:67;93524:17;:87;;;93627:24;;;;;;;;;;;;;;;;93399:260;;:::o;25899:192::-;25974:6;:12;;;;;;;;;;:36;;26002:7;25974:36;:27;:36;:::i;:::-;25970:114;;;26059:12;:10;:12::i;:::-;-1:-1:-1;;;;;26032:40:0;26050:7;-1:-1:-1;;;;;26032:40:0;26044:4;26032:40;;;;;;;;;;25899:192;;:::o;98160:2748::-;98256:39;;:::i;:::-;-1:-1:-1;;;;;98387:15:0;;98297:32;98387:15;;;:7;:15;;;;;;;;98486:10;:18;;;;;;98297:32;98450:13;;;98297:32;98517:1699;98539:19;;98535:23;;98517:1699;;;98577:20;;:::i;:::-;98600:12;98613:1;98600:15;;;;;;;;;;;;;;;;;98577:38;;;;;;;;98600:15;;;;;;;98577:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98636:18;;98577:38;;-1:-1:-1;98636:29:0;-1:-1:-1;98632:194:0;;;-1:-1:-1;98686:3:0;;98802:8;;98632:194;98904:7;;;;:17;98872:27;;:50;;;:31;:50;:::i;:::-;98842:80;;99218:7;;;;;:24;;;99179:34;;;;:64;;;:38;:64;:::i;:::-;99142:34;;;:101;99549:19;;-1:-1:-1;;99549:23:0;99591:13;;;99587:94;;99643:12;99656:8;99643:22;;;;;;;;;;;;;;;;;;99625:12;99638:1;99625:15;;;;;;;;;;;;;;;;:40;;:15;;;;;:40;;;;;;;;;;;;;;;;;;;;99587:94;100186:12;:18;;;;;;;;;;;;;;;-1:-1:-1;;100186:18:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;98517:1699:0;;;;-1:-1:-1;100284:19:0;;100280:79;;-1:-1:-1;;;;;100332:15:0;;;;;;:7;:15;;;;;100325:22;;;;;;;;;100332:15;100325:22;;;;100332:15;100325:22;:::i;:::-;;;100280:79;100383:27;;:32;;;:75;;-1:-1:-1;100419:34:0;;;;:39;;100383:75;100371:87;;100473:9;100469:432;;;100531:27;;100560:34;;;;;100505:90;;;;;;;;;;;;-1:-1:-1;;;;;100505:90:0;;;;;;;;;;;;100612:44;:20;100638:17;100612:44;:25;:44;:::i;:::-;100675:19;;:24;100671:105;;100720:40;:6;100742:17;100720:40;:21;:40;:::i;:::-;100792:47;:23;100821:17;100792:47;:28;:47;:::i;:::-;100856:33;:9;100871:17;100856:33;:14;:33;:::i;:::-;98160:2748;;;;;;;:::o;60463:685::-;60560:20;;:::i;:::-;60627:6;60602:4;:21;;;:31;60598:543;;60674:21;;;;:33;;60700:6;60674:33;:25;:33;:::i;:::-;60650:21;;;:57;60722:24;;;:33;;;60598:543;;;60819:21;;;;60808:33;;:6;;:33;:10;:33;:::i;:::-;60788:53;;;60987:14;;:37;;;:18;:37;:::i;:::-;60970:54;;61068:21;;;;;;61041:24;;;:48;60970:14;61104:25;;-1:-1:-1;61041:24:0;60463:685::o;94370:831::-;94485:11;;94481:713;;94544:7;:24;;;94521:19;;:47;;94513:92;;;;;-1:-1:-1;;;94513:92:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94628:6;;:31;;;-1:-1:-1;;;94628:31:0;;-1:-1:-1;;;;;94628:31:0;;;;;;;;;;;;;;;:6;;;;;:15;;:31;;;;;;;;;;;;;;:6;;:31;;;2:2:-1;;;;27:1;24;17:12;2:2;94628:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;94628:31:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;94628:31:0;94620:59;;;;;-1:-1:-1;;;94620:59:0;;;;;;;;;;;;-1:-1:-1;;;94620:59:0;;;;;;;;;;;;;;;94742:24;;;;94718:19;;:49;;;:23;:49;:::i;:::-;94696:19;:71;94836:17;;94808:23;;:46;;;:27;:46;:::i;:::-;94782:23;:72;94869:37;:23;94898:7;94869:37;:28;:37;:::i;:::-;95137:17;;95156:24;;;;;95116:65;;;;;;;;;;;;95125:10;;95116:65;;;;;;;;;94370:831;;;:::o;95211:2939::-;-1:-1:-1;;;;;95363:15:0;;95318:19;95363:15;;;:7;:15;;;;;;95409:23;:11;;;:21;:23::i;:::-;95389:43;-1:-1:-1;95447:14:0;;95443:1393;;95580:16;;95862:28;;;;95847:894;95896:21;;95892:1;:25;95847:894;;;95943:37;95983:17;;;:14;:17;;;;;96214:19;;:34;-1:-1:-1;96214:34:0;96206:71;;;;;-1:-1:-1;;;96206:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;96389:21;;96316:8;;96361:1;96357:5;;;96385:25;;96381:195;;;96435:42;96480:17;;;:14;:17;;;;;96532:24;;-1:-1:-1;96381:195:0;96608:75;96633:9;96644:8;:13;;;96671:11;96659:9;:23;96608:24;:75::i;:::-;96596:87;-1:-1:-1;96716:9:0;;-1:-1:-1;;;95919:3:0;;95847:894;;;-1:-1:-1;96802:11:0;;;:21;96788:36;;:9;;:36;:13;:36;:::i;:::-;96757:28;;;:67;-1:-1:-1;95443:1393:0;96848:27;;;96918:21;;:58;;96975:1;96918:58;;;96971:1;96947:21;;:25;96918:58;96886:28;;;:91;;;98090:11;;;:21;98113:28;;;;98030:112;;;;;;;;;;;;;;;-1:-1:-1;;;;;98030:112:0;;;;;;;;;;;;95211:2939;;;;;:::o;58502:154::-;58625:22;;;;58605:15;;58573:7;;58605:43;;:15;:43;:19;:43;:::i;61903:243::-;62023:20;;:::i;:::-;62071:39;62097:4;62103:6;62071:25;:39::i;:::-;62061:49;;62121:17;62126:2;62130:7;62121:4;:17::i;:::-;61903:243;;;;;:::o;59072:225::-;59191:16;;59174:12;;:34;;;:16;:34;:::i;:::-;59159:49;;59265:23;;;;59241:19;;;;:48;;;:23;:48;:::i;:::-;59219:2;:19;;:70;;;;59072:225;;:::o;54349:136::-;54407:7;54434:43;54438:1;54441;54434:43;;;;;;;;;;;;;;;;;:3;:43::i;61411:229::-;61524:20;;:::i;:::-;61572:32;61591:4;61597:6;61572:18;:32::i;59559:235::-;59684:16;;59665:14;;:36;;;:18;:36;:::i;:::-;59648:53;;59762:23;;;;59736:21;;;;:50;;;:25;:50;:::i;9824:149::-;9898:7;9941:22;9945:3;9957:5;9941:3;:22::i;9119:158::-;9199:4;9223:46;9233:3;-1:-1:-1;;;;;9253:14:0;;9223:9;:46::i;9363:117::-;9426:7;9453:19;9461:3;9453:7;:19::i;92977:152::-;93049:19;:33;;;;;-1:-1:-1;;93049:33:0;;;;;;;;93098:23;;;;;;;;;;;;;;;;92977:152;:::o;5219:414::-;5282:4;5304:21;5314:3;5319:5;5304:9;:21::i;:::-;5299:327;;-1:-1:-1;27:10;;39:1;23:18;;;45:23;;5342:11:0;:23;;;;;;;;;;;;;5525:18;;5503:19;;;:12;;;:19;;;;;;:40;;;;5558:11;;5299:327;-1:-1:-1;5609:5:0;5602:12;;8884:149;8957:4;8981:44;8989:3;-1:-1:-1;;;;;9009:14:0;;8981:7;:44::i;65509:471::-;65613:7;65645:327;65679:268;65702:202;65743:26;65767:1;65743:22;:26::i;:::-;65792:89;65840:5;65874:6;65792:18;:89::i;:::-;65702:17;:202::i;:::-;65927:1;65679:3;:268::i;:::-;65962:9;65645:18;:327::i;:::-;65638:334;65509:471;-1:-1:-1;;;;65509:471:0:o;54788:192::-;54874:7;54910:12;54902:6;;;;54894:29;;;;-1:-1:-1;;;54894:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;54894:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;54946:5:0;;;54788:192::o;59804:649::-;59894:20;;:::i;:::-;59936:14;;:24;-1:-1:-1;59932:514:0;;59994:14;;:26;;60013:6;59994:26;:18;:26;:::i;:::-;59977:43;;60035:26;;;59932:514;;;60131:14;;60120:26;;:6;;:26;:10;:26;:::i;:::-;60093:24;;;:53;;;60299:21;;;;:51;;;:25;:51;:::i;:::-;60275:21;;;:75;60387:14;;60367:34;;60387:14;60416:18;;;-1:-1:-1;60367:34:0;59804:649::o;8107:204::-;8202:18;;8174:7;;8202:26;-1:-1:-1;8194:73:0;;;;-1:-1:-1;;;8194:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8285:3;:11;;8297:5;8285:18;;;;;;;;;;;;;;;;8278:25;;8107:204;;;;:::o;7439:129::-;7512:4;7536:19;;;:12;;;;;:19;;;;;;:24;;;7439:129::o;7654:109::-;7737:18;;7654:109::o;5809:1544::-;5875:4;6014:19;;;:12;;;:19;;;;;;6050:15;;6046:1300;;6485:18;;-1:-1:-1;;6436:14:0;;;;6485:22;;;;6412:21;;6485:3;;:22;;6772;;;;;;;;;;;;;;6752:42;;6918:9;6889:3;:11;;6901:13;6889:26;;;;;;;;;;;;;;;;;;;:38;;;;6995:23;;;7037:1;6995:12;;;:23;;;;;;7021:17;;;6995:43;;7147:17;;6995:3;;7147:17;;;;;;;;;;;;;;;;;;;;;;7242:3;:12;;:19;7255:5;7242:19;;;;;;;;;;;7235:26;;;7285:4;7278:11;;;;;;;;6046:1300;7329:5;7322:12;;;;;28795:137;28848:6;28877:18;28872:1;:23;;28863:33;;12:1:-1;9;2:12;28863:33:0;-1:-1:-1;28923:2:0;28918:7;;28795:137::o;35294:208::-;35354:6;35378;35369:16;;12:1:-1;9;2:12;35369:16:0;35392:14;35409:12;35416:1;35419;35409:5;:12::i;:::-;35392:29;-1:-1:-1;;;;;;;;;;;35437:29:0;;;;35428:39;;12:1:-1;9;2:12;30279:195:0;30336:6;30367:13;:9;;;:13;;;;;-1:-1:-1;;;;;;30396:19:0;;;;;:42;;-1:-1:-1;;;;;;30419:19:0;;;30396:42;30387:52;;12:1:-1;9;2:12;65114:385:0;65181:8;65211:26;65235:1;65211:22;:26::i;:::-;65207:30;;65250:242;65257:6;;65250:242;;65289:1;65285:5;;65284:12;65280:201;;65321:24;65340:1;65343;65321:17;:24::i;:::-;65317:28;;65369:1;65364:6;;;;65280:201;;;65415:24;65434:1;65437;65415:17;:24::i;:::-;65411:28;;65464:1;65458:7;;;;;65280:201;65250:242;;32949:469;33008:7;33028:6;33024:20;;-1:-1:-1;33043:1:0;33036:8;;33024:20;33067:1;33062;:6;;;;33053:16;;12:1:-1;9;2:12;33053:16:0;33092:11;;;;-1:-1:-1;;;;;33107:38:0;;33092:54;;33151:2;33091:62;;33193:3;33188:8;;;33173:24;-1:-1:-1;;;;;33215:56:0;;;33206:66;;12:1:-1;9;2:12;33206:66:0;33286:2;33279:9;33319:71;;33306:84;;;33297:94;;12:1:-1;9;2:12;33297:94:0;33405:7;;32949:469;-1:-1:-1;;;32949:469:0:o;47833:1257::-;47893:7;47918:6;47909:16;;12:1:-1;9;2:12;47909:16:0;47934:14;-1:-1:-1;;;;;47961:1:0;:55;47957:1035;;48046:1;48040:2;48035:1;:7;;48034:13;;;;;;48025:22;;47957:1035;;;48082:3;48107:8;;;48134:11;48128:17;;48124:48;;48156:2;48160:9;;;;48149;48124:48;48190:7;48184:2;:13;48180:44;;48208:2;48212:9;;;;48201;48180:44;48242:5;48236:2;:11;48232:40;;48258:1;48261:8;;;;48251;48232:40;48290:4;48284:2;:10;48280:39;;48305:1;48308:8;;;;48298;48280:39;48337:3;48331:2;:9;48327:38;;48351:1;48354:8;;;;48344;48327:38;48383:3;48377:2;:9;48373:23;;48395:1;48388:8;;;;48373:23;48484:3;48478;:9;48473:1;48469;:5;:18;;48491:1;48468:24;48460:3;48454;:9;48449:1;:14;;48448:45;;;;;;48439:54;;-1:-1:-1;;;;;48511:6:0;:44;;48502:54;;12:1:-1;9;2:12;48502:54:0;48595:3;48590:8;;;48580:19;;-1:-1:-1;;;;;48631:38:0;;48621:49;;48699:3;48694:8;;;48729:2;48724:7;;;48746;;;48742:20;;;48761:1;48755:7;;;;48742:20;48836:3;48830:9;;;;48771:8;;48852:7;;;48848:20;;;48867:1;48861:7;;;;48848:20;48877:8;;;48953:3;48947:9;;;48941:15;;48933:24;;;;48983:1;48978:2;:6;;;;;;48968:16;;;;47957:1035;;;;;;;-1:-1:-1;;;;;49009:6:0;:44;;49000:54;;12:1:-1;9;2:12;31127:201:0;31184:6;31215:13;:9;;;:13;;;;;31232:2;31215:19;-1:-1:-1;;;;;;31250:19:0;;;;;:42;;-1:-1:-1;;;;;;31273:19:0;;;31241:52;;12:1:-1;9;2:12;-1:-1;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Swarm Source
ipfs://5436678265352631f897e2cef39869cf23c267c4a2f500784a8480a5ff10f776
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.