More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 4,948 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Claim Reward | 19219510 | 197 days ago | IN | 0 ETH | 0.12878812 | ||||
Claim Reward | 16614632 | 563 days ago | IN | 0 ETH | 0.0035093 | ||||
Claim Reward | 16614624 | 563 days ago | IN | 0 ETH | 0.00324479 | ||||
Claim Reward | 16614624 | 563 days ago | IN | 0 ETH | 0.00291837 | ||||
Claim Reward | 16614610 | 563 days ago | IN | 0 ETH | 0.00568886 | ||||
Claim Reward | 16266624 | 611 days ago | IN | 0 ETH | 0.00258772 | ||||
Unstake | 16238320 | 615 days ago | IN | 0 ETH | 0.00316453 | ||||
Claim Reward | 16238312 | 615 days ago | IN | 0 ETH | 0.00576708 | ||||
Claim Reward | 16059454 | 640 days ago | IN | 0 ETH | 0.0021585 | ||||
Claim Reward | 16016340 | 646 days ago | IN | 0 ETH | 0.00612839 | ||||
Claim Reward | 15706141 | 690 days ago | IN | 0 ETH | 0.00675709 | ||||
Claim Reward | 15706140 | 690 days ago | IN | 0 ETH | 0.00675709 | ||||
Claim Reward | 15704833 | 690 days ago | IN | 0 ETH | 0.00242086 | ||||
Claim Reward | 15704833 | 690 days ago | IN | 0 ETH | 0.00242086 | ||||
Claim Reward | 15704825 | 690 days ago | IN | 0 ETH | 0.00150785 | ||||
Claim Reward | 15704825 | 690 days ago | IN | 0 ETH | 0.00239013 | ||||
Claim Reward | 15704809 | 690 days ago | IN | 0 ETH | 0.00281545 | ||||
Claim Reward | 15704768 | 690 days ago | IN | 0 ETH | 0.00279043 | ||||
Claim Reward | 15704758 | 690 days ago | IN | 0 ETH | 0.0059827 | ||||
Claim Reward | 15629457 | 700 days ago | IN | 0 ETH | 0.00219319 | ||||
Claim Reward | 15616523 | 702 days ago | IN | 0 ETH | 0.00394615 | ||||
Claim Reward | 15423037 | 732 days ago | IN | 0 ETH | 0.00348594 | ||||
Claim Reward | 15422910 | 732 days ago | IN | 0 ETH | 0.00162163 | ||||
Claim Reward | 15409064 | 734 days ago | IN | 0 ETH | 0.00225279 | ||||
Unstake | 15330066 | 747 days ago | IN | 0 ETH | 0.00548007 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
12072324 | 1258 days ago | 1.8 ETH | ||||
12072310 | 1258 days ago | 0.1 ETH | ||||
12060043 | 1259 days ago | 1.9 ETH | ||||
12059908 | 1259 days ago | 1.9 ETH | ||||
12004574 | 1268 days ago | 1.7 ETH | ||||
12004553 | 1268 days ago | 0.1 ETH | ||||
11868908 | 1289 days ago | 1.9 ETH | ||||
11868875 | 1289 days ago | 1.9 ETH | ||||
11523795 | 1342 days ago | 1.9 ETH | ||||
11515606 | 1343 days ago | 0.2 ETH | ||||
11515542 | 1343 days ago | 0.5 ETH | ||||
11477732 | 1349 days ago | 0.75 ETH | ||||
11477713 | 1349 days ago | 1 ETH | ||||
11474099 | 1350 days ago | 1.1 ETH | ||||
11474090 | 1350 days ago | 0.8 ETH | ||||
11473988 | 1350 days ago | 0.1 ETH | ||||
11473731 | 1350 days ago | 0.05 ETH | ||||
11467758 | 1350 days ago | 1 ETH | ||||
11467496 | 1351 days ago | 0.75 ETH | ||||
11453628 | 1353 days ago | 0.73 ETH | ||||
11451424 | 1353 days ago | 1.17 ETH | ||||
11445117 | 1354 days ago | 1.6 ETH | ||||
11444914 | 1354 days ago | 0.3 ETH | ||||
11407170 | 1360 days ago | 1 ETH | ||||
11406848 | 1360 days ago | 0.5 ETH |
Loading...
Loading
Contract Name:
DigitalaxGenesisStaking
Compiler Version
v0.6.12+commit.27d51765
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-11-29 */ // File @openzeppelin/contracts/math/[email protected] // SPDX-License-Identifier: GPLv2 pragma solidity ^0.6.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ 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; } } // File @openzeppelin/contracts/utils/[email protected] pragma solidity ^0.6.0; /** * @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)); } } // File @openzeppelin/contracts/utils/[email protected] pragma solidity ^0.6.2; /** * @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) { // This method relies in extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @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); } } } } // File @openzeppelin/contracts/GSN/[email protected] pragma solidity ^0.6.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ 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; } } // File @openzeppelin/contracts/access/[email protected] pragma solidity ^0.6.0; /** * @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()); } } } // File contracts/DigitalaxAccessControls.sol pragma solidity 0.6.12; /** * @notice Access Controls contract for the Digitalax Platform * @author BlockRocket.tech */ contract DigitalaxAccessControls is AccessControl { /// @notice Role definitions bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant SMART_CONTRACT_ROLE = keccak256("SMART_CONTRACT_ROLE"); /// @notice Events for adding and removing various roles event AdminRoleGranted( address indexed beneficiary, address indexed caller ); event AdminRoleRemoved( address indexed beneficiary, address indexed caller ); event MinterRoleGranted( address indexed beneficiary, address indexed caller ); event MinterRoleRemoved( address indexed beneficiary, address indexed caller ); event SmartContractRoleGranted( address indexed beneficiary, address indexed caller ); event SmartContractRoleRemoved( address indexed beneficiary, address indexed caller ); /** * @notice The deployer is automatically given the admin role which will allow them to then grant roles to other addresses */ constructor() public { _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); } ///////////// // Lookups // ///////////// /** * @notice Used to check whether an address has the admin role * @param _address EOA or contract being checked * @return bool True if the account has the role or false if it does not */ function hasAdminRole(address _address) external view returns (bool) { return hasRole(DEFAULT_ADMIN_ROLE, _address); } /** * @notice Used to check whether an address has the minter role * @param _address EOA or contract being checked * @return bool True if the account has the role or false if it does not */ function hasMinterRole(address _address) external view returns (bool) { return hasRole(MINTER_ROLE, _address); } /** * @notice Used to check whether an address has the smart contract role * @param _address EOA or contract being checked * @return bool True if the account has the role or false if it does not */ function hasSmartContractRole(address _address) external view returns (bool) { return hasRole(SMART_CONTRACT_ROLE, _address); } /////////////// // Modifiers // /////////////// /** * @notice Grants the admin role to an address * @dev The sender must have the admin role * @param _address EOA or contract receiving the new role */ function addAdminRole(address _address) external { grantRole(DEFAULT_ADMIN_ROLE, _address); emit AdminRoleGranted(_address, _msgSender()); } /** * @notice Removes the admin role from an address * @dev The sender must have the admin role * @param _address EOA or contract affected */ function removeAdminRole(address _address) external { revokeRole(DEFAULT_ADMIN_ROLE, _address); emit AdminRoleRemoved(_address, _msgSender()); } /** * @notice Grants the minter role to an address * @dev The sender must have the admin role * @param _address EOA or contract receiving the new role */ function addMinterRole(address _address) external { grantRole(MINTER_ROLE, _address); emit MinterRoleGranted(_address, _msgSender()); } /** * @notice Removes the minter role from an address * @dev The sender must have the admin role * @param _address EOA or contract affected */ function removeMinterRole(address _address) external { revokeRole(MINTER_ROLE, _address); emit MinterRoleRemoved(_address, _msgSender()); } /** * @notice Grants the smart contract role to an address * @dev The sender must have the admin role * @param _address EOA or contract receiving the new role */ function addSmartContractRole(address _address) external { grantRole(SMART_CONTRACT_ROLE, _address); emit SmartContractRoleGranted(_address, _msgSender()); } /** * @notice Removes the smart contract role from an address * @dev The sender must have the admin role * @param _address EOA or contract affected */ function removeSmartContractRole(address _address) external { revokeRole(SMART_CONTRACT_ROLE, _address); emit SmartContractRoleRemoved(_address, _msgSender()); } } // File @openzeppelin/contracts/introspection/[email protected] pragma solidity ^0.6.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File @openzeppelin/contracts/token/ERC721/[email protected] pragma solidity ^0.6.2; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; } // File @openzeppelin/contracts/token/ERC721/[email protected] pragma solidity ^0.6.2; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); } // File @openzeppelin/contracts/token/ERC721/[email protected] pragma solidity ^0.6.2; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); } // File @openzeppelin/contracts/token/ERC721/[email protected] pragma solidity ^0.6.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. */ function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4); } // File @openzeppelin/contracts/introspection/[email protected] pragma solidity ^0.6.0; /** * @dev Implementation of the {IERC165} interface. * * Contracts may inherit from this and call {_registerInterface} to declare * their support of an interface. */ contract ERC165 is IERC165 { /* * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 */ bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * @dev Mapping of interface ids to whether or not it's supported. */ mapping(bytes4 => bool) private _supportedInterfaces; constructor () internal { // Derived contracts need only register support for their own interfaces, // we register support for ERC165 itself here _registerInterface(_INTERFACE_ID_ERC165); } /** * @dev See {IERC165-supportsInterface}. * * Time complexity O(1), guaranteed to always use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) public view override returns (bool) { return _supportedInterfaces[interfaceId]; } /** * @dev Registers the contract as an implementer of the interface defined by * `interfaceId`. Support of the actual ERC165 interface is automatic and * registering its interface id is not required. * * See {IERC165-supportsInterface}. * * Requirements: * * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). */ function _registerInterface(bytes4 interfaceId) internal virtual { require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); _supportedInterfaces[interfaceId] = true; } } // File @openzeppelin/contracts/utils/[email protected] pragma solidity ^0.6.0; /** * @dev Library for managing an enumerable variant of Solidity's * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] * type. * * Maps have the following properties: * * - Entries are added, removed, and checked for existence in constant time * (O(1)). * - Entries are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableMap for EnumerableMap.UintToAddressMap; * * // Declare a set state variable * EnumerableMap.UintToAddressMap private myMap; * } * ``` * * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are * supported. */ library EnumerableMap { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Map type with // bytes32 keys and values. // The Map implementation uses private functions, and user-facing // implementations (such as Uint256ToAddressMap) are just wrappers around // the underlying Map. // This means that we can only create new EnumerableMaps for types that fit // in bytes32. struct MapEntry { bytes32 _key; bytes32 _value; } struct Map { // Storage of map keys and values MapEntry[] _entries; // Position of the entry defined by a key in the `entries` array, plus 1 // because index 0 means a key is not in the map. mapping (bytes32 => uint256) _indexes; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) { // We read and store the key's index to prevent multiple reads from the same storage slot uint256 keyIndex = map._indexes[key]; if (keyIndex == 0) { // Equivalent to !contains(map, key) map._entries.push(MapEntry({ _key: key, _value: value })); // The entry is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value map._indexes[key] = map._entries.length; return true; } else { map._entries[keyIndex - 1]._value = value; return false; } } /** * @dev Removes a key-value pair from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function _remove(Map storage map, bytes32 key) private returns (bool) { // We read and store the key's index to prevent multiple reads from the same storage slot uint256 keyIndex = map._indexes[key]; if (keyIndex != 0) { // Equivalent to contains(map, key) // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one // in the array, and then remove the last entry (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = keyIndex - 1; uint256 lastIndex = map._entries.length - 1; // When the entry 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. MapEntry storage lastEntry = map._entries[lastIndex]; // Move the last entry to the index where the entry to delete is map._entries[toDeleteIndex] = lastEntry; // Update the index for the moved entry map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based // Delete the slot where the moved entry was stored map._entries.pop(); // Delete the index for the deleted slot delete map._indexes[key]; return true; } else { return false; } } /** * @dev Returns true if the key is in the map. O(1). */ function _contains(Map storage map, bytes32 key) private view returns (bool) { return map._indexes[key] != 0; } /** * @dev Returns the number of key-value pairs in the map. O(1). */ function _length(Map storage map) private view returns (uint256) { return map._entries.length; } /** * @dev Returns the key-value pair stored at position `index` in the map. O(1). * * Note that there are no guarantees on the ordering of entries inside the * array, and it may change when more entries are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) { require(map._entries.length > index, "EnumerableMap: index out of bounds"); MapEntry storage entry = map._entries[index]; return (entry._key, entry._value); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function _get(Map storage map, bytes32 key) private view returns (bytes32) { return _get(map, key, "EnumerableMap: nonexistent key"); } /** * @dev Same as {_get}, with a custom error message when `key` is not in the map. */ function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) { uint256 keyIndex = map._indexes[key]; require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key) return map._entries[keyIndex - 1]._value; // All indexes are 1-based } // UintToAddressMap struct UintToAddressMap { Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) { return _set(map._inner, bytes32(key), bytes32(uint256(value))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { return _remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { return _contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToAddressMap storage map) internal view returns (uint256) { return _length(map._inner); } /** * @dev Returns the element 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(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { (bytes32 key, bytes32 value) = _at(map._inner, index); return (uint256(key), address(uint256(value))); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { return address(uint256(_get(map._inner, bytes32(key)))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. */ function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) { return address(uint256(_get(map._inner, bytes32(key), errorMessage))); } } // File @openzeppelin/contracts/utils/[email protected] pragma solidity ^0.6.0; /** * @dev String operations. */ library Strings { /** * @dev Converts a `uint256` to its ASCII `string` representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); uint256 index = digits - 1; temp = value; while (temp != 0) { buffer[index--] = byte(uint8(48 + temp % 10)); temp /= 10; } return string(buffer); } } // File contracts/ERC721/ERC721WithSameTokenURIForAllTokens.sol pragma solidity 0.6.12; /** * @title ERC721 Non-Fungible Token Standard basic implementation * @dev see https://eips.ethereum.org/EIPS/eip-721 * @dev This is a modified OZ ERC721 base contract with one change where all tokens have the same token URI */ contract ERC721WithSameTokenURIForAllTokens is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable { using SafeMath for uint256; using Address for address; using EnumerableSet for EnumerableSet.UintSet; using EnumerableMap for EnumerableMap.UintToAddressMap; using Strings for uint256; // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; // Mapping from holder address to their (enumerable) set of owned tokens mapping (address => EnumerableSet.UintSet) private _holderTokens; // Enumerable mapping from token ids to their owners EnumerableMap.UintToAddressMap private _tokenOwners; // Mapping from token ID to approved address mapping (uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping (address => mapping (address => bool)) private _operatorApprovals; // Token name string private _name; // Token symbol string private _symbol; // Single token URI for all tokens string public tokenURI_; /* * bytes4(keccak256('balanceOf(address)')) == 0x70a08231 * bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e * bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3 * bytes4(keccak256('getApproved(uint256)')) == 0x081812fc * bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465 * bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5 * bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde * * => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^ * 0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd */ bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd; /* * bytes4(keccak256('name()')) == 0x06fdde03 * bytes4(keccak256('symbol()')) == 0x95d89b41 * bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd * * => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f */ bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f; /* * bytes4(keccak256('totalSupply()')) == 0x18160ddd * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59 * bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7 * * => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63 */ bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor (string memory name, string memory symbol) public { _name = name; _symbol = symbol; // register the supported interfaces to conform to ERC721 via ERC165 _registerInterface(_INTERFACE_ID_ERC721); _registerInterface(_INTERFACE_ID_ERC721_METADATA); _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view override returns (uint256) { require(owner != address(0), "ERC721: balance query for the zero address"); return _holderTokens[owner].length(); } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view override returns (address) { return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token"); } /** * @dev See {IERC721Metadata-name}. */ function name() public view override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view override returns (string memory) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); return tokenURI_; } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) { return _holderTokens[owner].at(index); } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view override returns (uint256) { // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds return _tokenOwners.length(); } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view override returns (uint256) { (uint256 tokenId, ) = _tokenOwners.at(index); return tokenId; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view override returns (address) { require(_exists(tokenId), "ERC721: approved query for nonexistent token"); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { require(operator != _msgSender(), "ERC721: approve to caller"); _operatorApprovals[_msgSender()][operator] = approved; emit ApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom(address from, address to, uint256 tokenId) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _safeTransfer(from, to, tokenId, _data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `_data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view returns (bool) { return _tokenOwners.contains(tokenId); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) { require(_exists(tokenId), "ERC721: operator query for nonexistent token"); address owner = ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: d* * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual { _mint(to, tokenId); require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId); _holderTokens[to].add(tokenId); _tokenOwners.set(tokenId, to); emit Transfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _holderTokens[owner].remove(tokenId); _tokenOwners.remove(tokenId); emit Transfer(owner, address(0), tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer(address from, address to, uint256 tokenId) internal virtual { require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _holderTokens[from].remove(tokenId); _holderTokens[to].add(tokenId); _tokenOwners.set(tokenId, to); emit Transfer(from, to, tokenId); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) private returns (bool) { if (!to.isContract()) { return true; } bytes memory returndata = to.functionCall(abi.encodeWithSelector( IERC721Receiver(to).onERC721Received.selector, _msgSender(), from, tokenId, _data ), "ERC721: transfer to non ERC721Receiver implementer"); bytes4 retval = abi.decode(returndata, (bytes4)); return (retval == _ERC721_RECEIVED); } function _approve(address to, uint256 tokenId) private { _tokenApprovals[tokenId] = to; emit Approval(ownerOf(tokenId), to, tokenId); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` cannot be the zero address. * - `to` cannot be the zero address. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { } } // File contracts/DigitalaxGenesisNFT.sol pragma solidity 0.6.12; /** * @title Digitalax Genesis NFT * @dev To facilitate the genesis sale for the Digitialax platform */ contract DigitalaxGenesisNFT is ERC721WithSameTokenURIForAllTokens("DigitalaxGenesis", "DXG") { using SafeMath for uint256; // @notice event emitted upon construction of this contract, used to bootstrap external indexers event DigitalaxGenesisNFTContractDeployed(); // @notice event emitted when a contributor buys a Genesis NFT event GenesisPurchased( address indexed buyer, uint256 indexed tokenId, uint256 contribution ); // @notice event emitted when a admin mints a Genesis NFT event AdminGenesisMinted( address indexed beneficiary, address indexed admin, uint256 indexed tokenId ); // @notice event emitted when a contributors amount is increased event ContributionIncreased( address indexed buyer, uint256 contribution ); // @notice event emitted when end date is changed event GenesisEndUpdated( uint256 genesisEndTimestamp, address indexed admin ); // @notice event emitted when DigitalaxAccessControls is updated event AccessControlsUpdated( address indexed newAdress ); // @notice responsible for enforcing admin access DigitalaxAccessControls public accessControls; // @notice all funds will be sent to this address pon purchase of a Genesis NFT address payable public fundsMultisig; // @notice start date for them the Genesis sale is open to the public, before this data no purchases can be made uint256 public genesisStartTimestamp; // @notice end date for them the Genesis sale is closed, no more purchased can be made after this point uint256 public genesisEndTimestamp; // @notice set after end time has been changed once, prevents further changes to end timestamp bool public genesisEndTimestampLocked; // @notice the minimum amount a buyer can contribute in a single go uint256 public constant minimumContributionAmount = 0.1 ether; // @notice the maximum accumulative amount a user can contribute to the genesis sale uint256 public constant maximumContributionAmount = 2 ether; // @notice accumulative => contribution total mapping(address => uint256) public contribution; // @notice global accumulative contribution amount uint256 public totalContributions; // @notice max number of paid contributions to the genesis sale uint256 public constant maxGenesisContributionTokens = 460; uint256 public totalAdminMints; constructor( DigitalaxAccessControls _accessControls, address payable _fundsMultisig, uint256 _genesisStartTimestamp, uint256 _genesisEndTimestamp, string memory _tokenURI ) public { accessControls = _accessControls; fundsMultisig = _fundsMultisig; genesisStartTimestamp = _genesisStartTimestamp; genesisEndTimestamp = _genesisEndTimestamp; tokenURI_ = _tokenURI; emit DigitalaxGenesisNFTContractDeployed(); } /** * @dev Proxy method for facilitating a single point of entry to either buy or contribute additional value to the Genesis sale * @dev Cannot contribute less than minimumContributionAmount * @dev Cannot contribute accumulative more than than maximumContributionAmount */ function buyOrIncreaseContribution() external payable { if (contribution[_msgSender()] == 0) { buy(); } else { increaseContribution(); } } /** * @dev Facilitating the initial purchase of a Genesis NFT * @dev Cannot contribute less than minimumContributionAmount * @dev Cannot contribute accumulative more than than maximumContributionAmount * @dev Reverts if already owns an genesis token * @dev Buyer receives a NFT on success * @dev All funds move to fundsMultisig */ function buy() public payable { require(contribution[_msgSender()] == 0, "DigitalaxGenesisNFT.buy: You already own a genesis NFT"); require( _getNow() >= genesisStartTimestamp && _getNow() <= genesisEndTimestamp, "DigitalaxGenesisNFT.buy: No genesis are available outside of the genesis window" ); uint256 _contributionAmount = msg.value; require( _contributionAmount >= minimumContributionAmount, "DigitalaxGenesisNFT.buy: Contribution does not meet minimum requirement" ); require( _contributionAmount <= maximumContributionAmount, "DigitalaxGenesisNFT.buy: You cannot exceed the maximum contribution amount" ); require(remainingGenesisTokens() > 0, "DigitalaxGenesisNFT.buy: Total number of genesis token holders reached"); contribution[_msgSender()] = _contributionAmount; totalContributions = totalContributions.add(_contributionAmount); (bool fundsTransferSuccess,) = fundsMultisig.call{value : _contributionAmount}(""); require(fundsTransferSuccess, "DigitalaxGenesisNFT.buy: Unable to send contribution to funds multisig"); uint256 tokenId = totalSupply().add(1); _safeMint(_msgSender(), tokenId); emit GenesisPurchased(_msgSender(), tokenId, _contributionAmount); } /** * @dev Facilitates an owner to increase there contribution * @dev Cannot contribute less than minimumContributionAmount * @dev Cannot contribute accumulative more than than maximumContributionAmount * @dev Reverts if caller does not already owns an genesis token * @dev All funds move to fundsMultisig */ function increaseContribution() public payable { require( _getNow() >= genesisStartTimestamp && _getNow() <= genesisEndTimestamp, "DigitalaxGenesisNFT.increaseContribution: No increases are possible outside of the genesis window" ); require( contribution[_msgSender()] > 0, "DigitalaxGenesisNFT.increaseContribution: You do not own a genesis NFT" ); uint256 _amountToIncrease = msg.value; contribution[_msgSender()] = contribution[_msgSender()].add(_amountToIncrease); require( contribution[_msgSender()] <= maximumContributionAmount, "DigitalaxGenesisNFT.increaseContribution: You cannot exceed the maximum contribution amount" ); totalContributions = totalContributions.add(_amountToIncrease); (bool fundsTransferSuccess,) = fundsMultisig.call{value : _amountToIncrease}(""); require( fundsTransferSuccess, "DigitalaxGenesisNFT.increaseContribution: Unable to send contribution to funds multisig" ); emit ContributionIncreased(_msgSender(), _amountToIncrease); } // Admin /** * @dev Allows a whitelisted admin to mint a token and issue it to a beneficiary * @dev One token per holder * @dev All holders contribution as set o zero on creation */ function adminBuy(address _beneficiary) external { require( accessControls.hasAdminRole(_msgSender()), "DigitalaxGenesisNFT.adminBuy: Sender must be admin" ); require(_beneficiary != address(0), "DigitalaxGenesisNFT.adminBuy: Beneficiary cannot be ZERO"); require(balanceOf(_beneficiary) == 0, "DigitalaxGenesisNFT.adminBuy: Beneficiary already owns a genesis NFT"); uint256 tokenId = totalSupply().add(1); _safeMint(_beneficiary, tokenId); // Increase admin mint counts totalAdminMints = totalAdminMints.add(1); emit AdminGenesisMinted(_beneficiary, _msgSender(), tokenId); } /** * @dev Allows a whitelisted admin to update the end date of the genesis */ function updateGenesisEnd(uint256 _end) external { require( accessControls.hasAdminRole(_msgSender()), "DigitalaxGenesisNFT.updateGenesisEnd: Sender must be admin" ); // If already passed, dont allow opening again require(genesisEndTimestamp > _getNow(), "DigitalaxGenesisNFT.updateGenesisEnd: End time already passed"); // Only allow setting this once require(!genesisEndTimestampLocked, "DigitalaxGenesisNFT.updateGenesisEnd: End time locked"); genesisEndTimestamp = _end; // Lock future end time modifications genesisEndTimestampLocked = true; emit GenesisEndUpdated(genesisEndTimestamp, _msgSender()); } /** * @dev Allows a whitelisted admin to update the start date of the genesis */ function updateAccessControls(DigitalaxAccessControls _accessControls) external { require( accessControls.hasAdminRole(_msgSender()), "DigitalaxGenesisNFT.updateAccessControls: Sender must be admin" ); require(address(_accessControls) != address(0), "DigitalaxGenesisNFT.updateAccessControls: Zero Address"); accessControls = _accessControls; emit AccessControlsUpdated(address(_accessControls)); } /** * @dev Returns total remaining number of tokens available in the Genesis sale */ function remainingGenesisTokens() public view returns (uint256) { return _getMaxGenesisContributionTokens() - (totalSupply() - totalAdminMints); } // Internal function _getNow() internal virtual view returns (uint256) { return block.timestamp; } function _getMaxGenesisContributionTokens() internal virtual view returns (uint256) { return maxGenesisContributionTokens; } /** * @dev Before token transfer hook to enforce that no token can be moved to another address until the genesis sale has ended */ function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override { if (from != address(0) && _getNow() <= genesisEndTimestamp) { revert("DigitalaxGenesisNFT._beforeTokenTransfer: Transfers are currently locked at this time"); } } } // File interfaces/IERC20.sol pragma solidity ^0.6.2; interface IERC20 { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint256); function balanceOf(address owner) external view returns (uint256); function transfer(address to, uint256 amount) external returns (bool); function transferFrom(address from, address to, uint256 amount) external returns (bool); function approve(address spender, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); } // File interfaces/IDigitalaxRewards.sol pragma solidity 0.6.12; /// @dev an interface to interact with the Genesis MONA NFT that will interface IDigitalaxRewards { function updateRewards() external returns (bool); function genesisRewards(uint256 _from, uint256 _to) external view returns(uint256); function parentRewards(uint256 _from, uint256 _to) external view returns(uint256); function LPRewards(uint256 _from, uint256 _to) external view returns(uint256); function lastRewardTime() external view returns (uint256); } // File interfaces/IDigitalaxGenesisNFT.sol pragma solidity 0.6.12; /// @dev an interface to interact with the Genesis MONA NFT that will interface IDigitalaxGenesisNFT { function contribution(address user) external view returns (uint256); function totalContributions() external view returns (uint256); function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); function balanceOf(address owner) external view returns (uint256); function safeTransferFrom(address from, address to, uint256 tokenId) external; } // File contracts/DigitalaxGenesisStaking.sol pragma solidity 0.6.12; /** * @title Digitalax Staking * @dev Stake NFTs, earn tokens on the Digitialax platform * @author Adrian Guerrera (deepyr) */ contract DigitalaxGenesisStaking { using SafeMath for uint256; bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; IERC20 public rewardsToken; IDigitalaxGenesisNFT public genesisNFT; DigitalaxAccessControls public accessControls; IDigitalaxRewards public rewardsContract; /// @notice all funds will be sent to this address pon purchase of a Genesis NFT address payable public fundsMultisig; /// @notice total ethereum staked currently in the gensesis staking contract uint256 public stakedEthTotal; uint256 public lastUpdateTime; uint256 public rewardsPerTokenPoints; uint256 public totalUnclaimedRewards; uint256 constant pointMultiplier = 10e32; /** @notice Struct to track what user is staking which tokens @dev tokenIds are all the tokens staked by the staker @dev balance is the current ether balance of the staker @dev rewardsEarned is the total reward for the staker till now @dev rewardsReleased is how much reward has been paid to the staker */ struct Staker { uint256[] tokenIds; mapping (uint256 => uint256) tokenIndex; uint256 balance; uint256 lastRewardPoints; uint256 rewardsEarned; uint256 rewardsReleased; } /// @notice mapping of a staker to its current properties mapping (address => Staker) public stakers; // Mapping from token ID to owner address mapping (uint256 => address) public tokenOwner; /// @notice tokenId => amount contributed mapping (uint256 => uint256) public contribution; uint256 public totalContributions; // @notice the maximum accumulative amount a user can contribute to the genesis sale uint256 public constant maximumContributionAmount = 2 ether; /// @notice sets the token to be claimable or not, cannot claim if it set to false bool public tokensClaimable; bool initialised; /// @notice event emitted when a user has staked a token event Staked(address owner, uint256 amount); /// @notice event emitted when a user has unstaked a token event Unstaked(address owner, uint256 amount); /// @notice event emitted when a user claims reward event RewardPaid(address indexed user, uint256 reward); /// @notice Allows reward tokens to be claimed event ClaimableStatusUpdated(bool status); /// @notice Emergency unstake tokens without rewards event EmergencyUnstake(address indexed user, uint256 tokenId); // @notice event emitted when a contributors amount is increased event ContributionIncreased( uint256 indexed tokenId, uint256 contribution ); constructor() public { } /** * @dev Single gateway to intialize the staking contract after deploying * @dev Sets the contract with the MONA genesis NFT and MONA reward token */ function initGenesisStaking( address payable _fundsMultisig, IERC20 _rewardsToken, IDigitalaxGenesisNFT _genesisNFT, DigitalaxAccessControls _accessControls ) public { require(!initialised, "Already initialised"); fundsMultisig = _fundsMultisig; rewardsToken = _rewardsToken; genesisNFT = _genesisNFT; accessControls = _accessControls; lastUpdateTime = block.timestamp; initialised = true; } function setRewardsContract( address _addr ) external { require( accessControls.hasAdminRole(msg.sender), "DigitalaxGenesisStaking.setRewardsContract: Sender must be admin" ); require(_addr != address(0)); rewardsContract = IDigitalaxRewards(_addr); } function setTokensClaimable( bool _enabled ) external { require( accessControls.hasAdminRole(msg.sender), "DigitalaxGenesisStaking.setTokensClaimable: Sender must be admin" ); tokensClaimable = _enabled; emit ClaimableStatusUpdated(_enabled); } /// @dev Getter functions for Staking contract /// @dev Get the tokens staked by a user function getStakedTokens( address _user ) external view returns (uint256[] memory tokenIds) { return stakers[_user].tokenIds; } /// @dev Get the amount a staked nft is valued at ie bought at function getGenesisContribution ( uint256 _tokenId ) public view returns (uint256 amount) { return contribution[_tokenId]; } /// @notice Stake Genesis MONA NFT and earn reward tokens. function stake( uint256 tokenId ) external { _stake(msg.sender, tokenId); } /// @notice Stake multiple MONA NFTs and earn reward tokens. function stakeBatch(uint256[] memory tokenIds) external { for (uint i = 0; i < tokenIds.length; i++) { _stake(msg.sender, tokenIds[i]); } } /// @notice Stake all your MONA NFTs and earn reward tokens. function stakeAll() external { uint256 balance = genesisNFT.balanceOf(msg.sender); for (uint i = 0; i < balance; i++) { _stake(msg.sender, genesisNFT.tokenOfOwnerByIndex(msg.sender,i)); } } /** * @dev All the staking goes through this function * @dev Rewards to be given out is calculated * @dev Balance of stakers are updated as they stake the nfts based on ether price */ function _stake( address _user, uint256 _tokenId ) internal { Staker storage staker = stakers[_user]; if (staker.balance == 0 && staker.lastRewardPoints == 0 ) { staker.lastRewardPoints = rewardsPerTokenPoints; } updateReward(_user); uint256 amount = getGenesisContribution(_tokenId); staker.balance = staker.balance.add(amount); stakedEthTotal = stakedEthTotal.add(amount); staker.tokenIds.push(_tokenId); staker.tokenIndex[staker.tokenIds.length - 1]; tokenOwner[_tokenId] = _user; genesisNFT.safeTransferFrom( _user, address(this), _tokenId ); emit Staked(_user, _tokenId); } /// @notice Unstake Genesis MONA NFTs. function unstake( uint256 _tokenId ) external { require( tokenOwner[_tokenId] == msg.sender, "DigitalaxGenesisStaking._unstake: Sender must have staked tokenID" ); claimReward(msg.sender); _unstake(msg.sender, _tokenId); } /// @notice Stake multiple Genesis NFTs and claim reward tokens. function unstakeBatch( uint256[] memory tokenIds ) external { claimReward(msg.sender); for (uint i = 0; i < tokenIds.length; i++) { if (tokenOwner[i] == msg.sender) { _unstake(msg.sender, tokenIds[i]); } } } /** * @dev All the unstaking goes through this function * @dev Rewards to be given out is calculated * @dev Balance of stakers are updated as they unstake the nfts based on ether price */ function _unstake( address _user, uint256 _tokenId ) internal { Staker storage staker = stakers[_user]; uint256 amount = getGenesisContribution(_tokenId); staker.balance = staker.balance.sub(amount); stakedEthTotal = stakedEthTotal.sub(amount); uint256 lastIndex = staker.tokenIds.length - 1; uint256 lastIndexKey = staker.tokenIds[lastIndex]; staker.tokenIds[staker.tokenIndex[_tokenId]] = lastIndexKey; if (staker.tokenIds.length > 0) { staker.tokenIds.pop(); delete staker.tokenIndex[_tokenId]; } if (staker.balance == 0) { delete stakers[_user]; } delete tokenOwner[_tokenId]; genesisNFT.safeTransferFrom( address(this), _user, _tokenId ); emit Unstaked(_user, _tokenId); } // Unstake without caring about rewards. EMERGENCY ONLY. function emergencyUnstake(uint256 _tokenId) external { require( tokenOwner[_tokenId] == msg.sender, "DigitalaxGenesisStaking._unstake: Sender must have staked tokenID" ); _unstake(msg.sender, _tokenId); emit EmergencyUnstake(msg.sender, _tokenId); } /// @dev Updates the amount of rewards owed for each user before any tokens are moved function updateReward( address _user ) public { rewardsContract.updateRewards(); uint256 genesisRewards = rewardsContract.genesisRewards(lastUpdateTime, block.timestamp); if (stakedEthTotal > 0) { rewardsPerTokenPoints = rewardsPerTokenPoints.add(genesisRewards .mul(1e18) .mul(pointMultiplier) .div(stakedEthTotal)); } lastUpdateTime = block.timestamp; uint256 rewards = rewardsOwing(_user); Staker storage staker = stakers[_user]; if (_user != address(0)) { staker.rewardsEarned = staker.rewardsEarned.add(rewards); staker.lastRewardPoints = rewardsPerTokenPoints; } } /// @notice Returns the rewards owing for a user /// @dev The rewards are dynamic and normalised from the other pools /// @dev This gets the rewards from each of the periods as one multiplier function rewardsOwing( address _user ) public view returns(uint256) { uint256 newRewardPerToken = rewardsPerTokenPoints.sub(stakers[_user].lastRewardPoints); uint256 rewards = stakers[_user].balance.mul(newRewardPerToken) .div(1e18) .div(pointMultiplier); return rewards; } /// @notice Lets a user with rewards owing to claim tokens function claimReward( address _user ) public { require( tokensClaimable == true, "Tokens cannnot be claimed yet" ); updateReward(_user); Staker storage staker = stakers[_user]; uint256 payableAmount = staker.rewardsEarned.sub(staker.rewardsReleased); staker.rewardsReleased = staker.rewardsReleased.add(payableAmount); rewardsToken.transfer(_user, payableAmount); emit RewardPaid(_user, payableAmount); } /// @notice Returns the about of rewards yet to be claimed function unclaimedRewards( address _user ) external view returns(uint256) { if (stakedEthTotal == 0) { return 0; } uint256 genesisRewards = rewardsContract.genesisRewards(lastUpdateTime, block.timestamp); uint256 newRewardPerToken = rewardsPerTokenPoints.add(genesisRewards .mul(1e18) .mul(pointMultiplier) .div(stakedEthTotal)) .sub(stakers[_user].lastRewardPoints); uint256 rewards = stakers[_user].balance.mul(newRewardPerToken) .div(1e18) .div(pointMultiplier); return rewards.add(stakers[_user].rewardsEarned).sub(stakers[_user].rewardsReleased); } // Set contribution amounts for NFTs ///@dev So the genesis contracts did not have any way to check how much was contributed ///@dev So instead we put in the amounts using this function function setContributions( uint256[] memory tokens, uint256[] memory amounts ) external { require( accessControls.hasAdminRole(msg.sender), "DigitalaxGenesisStaking.setContributions: Sender must be admin" ); for (uint256 i = 0; i < tokens.length; i++) { uint256 token = tokens[i]; uint256 amount = amounts[i]; contribution[token] = amount; totalContributions = totalContributions.add(amount); } } /** * @notice Facilitates an owner to increase there contribution * @dev Cannot contribute less than minimumContributionAmount * @dev Cannot contribute accumulative more than than maximumContributionAmount * @dev Reverts if caller does not already owns an genesis token * @dev All funds move to fundsMultisig */ function increaseContribution(uint256 _tokenId) external payable { updateReward(tokenOwner[_tokenId]); require( contribution[_tokenId] > 0, "DigitalaxGenesisStaking.increaseContribution: genesis NFT was not contribibuted" ); uint256 _amountToIncrease = msg.value; contribution[_tokenId] = contribution[_tokenId].add(_amountToIncrease); require( contribution[_tokenId] <= maximumContributionAmount, "DigitalaxGenesisStaking.increaseContribution: You cannot exceed the maximum contribution amount" ); totalContributions = totalContributions.add(_amountToIncrease); (bool fundsTransferSuccess,) = fundsMultisig.call{value : _amountToIncrease}(""); require( fundsTransferSuccess, "DigitalaxGenesisStaking.increaseContribution: Unable to send contribution to funds multisig" ); Staker storage staker = stakers[tokenOwner[_tokenId]]; /// @dev Update staked balance if (staker.tokenIds[staker.tokenIndex[_tokenId]] == _tokenId ) { staker.balance = staker.balance.add(_amountToIncrease); stakedEthTotal = stakedEthTotal.add(_amountToIncrease); } emit ContributionIncreased(_tokenId, _amountToIncrease); } function onERC721Received( address, address, uint256, bytes calldata data ) public returns(bytes4) { return _ERC721_RECEIVED; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"ClaimableStatusUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"contribution","type":"uint256"}],"name":"ContributionIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"EmergencyUnstake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstaked","type":"event"},{"inputs":[],"name":"accessControls","outputs":[{"internalType":"contract DigitalaxAccessControls","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"claimReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"contribution","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"emergencyUnstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fundsMultisig","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"genesisNFT","outputs":[{"internalType":"contract IDigitalaxGenesisNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getGenesisContribution","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getStakedTokens","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"increaseContribution","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_fundsMultisig","type":"address"},{"internalType":"contract IERC20","name":"_rewardsToken","type":"address"},{"internalType":"contract IDigitalaxGenesisNFT","name":"_genesisNFT","type":"address"},{"internalType":"contract DigitalaxAccessControls","name":"_accessControls","type":"address"}],"name":"initGenesisStaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maximumContributionAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardsContract","outputs":[{"internalType":"contract IDigitalaxRewards","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"rewardsOwing","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsPerTokenPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokens","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"setContributions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"setRewardsContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setTokensClaimable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakeAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"stakeBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakedEthTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakers","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"lastRewardPoints","type":"uint256"},{"internalType":"uint256","name":"rewardsEarned","type":"uint256"},{"internalType":"uint256","name":"rewardsReleased","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensClaimable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalContributions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalUnclaimedRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"unclaimedRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"unstakeBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"updateReward","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50612135806100206000396000f3fe6080604052600436106101ee5760003560e01c8063748365ef1161010d578063aadee22d116100a0578063dbeb61c71161006f578063dbeb61c7146108c2578063dfa0dfa5146108d7578063e3ca00861461090a578063e64a21f31461091f578063e8709c40146109cd576101ee565b8063aadee22d14610850578063c8f33c9114610865578063d1af0c7d1461087a578063d279c1911461088f576101ee565b8063949813b8116100dc578063949813b81461069057806397d5ede5146106c3578063a2010956146106f6578063a694fc3a14610826576101ee565b8063748365ef146105f85780638dcb40611461060d5780638dd4916b146106225780639168ae7214610637576101ee565b80632e17de7811610185578063542360fd11610154578063542360fd14610501578063632447c91461052d57806363c28db11461056057806369f066a3146105e3576101ee565b80632e17de781461046f57806331f684c01461049957806337c08923146104c2578063494f67c2146104d7576101ee565b8063220cce97116101c1578063220cce9714610344578063230f436d146103595780632af59b9e146104075780632cb4836c14610424576101ee565b8063012ce501146101f35780630dc85f541461021f578063150b7a02146102465780631caaa487146102fe575b600080fd5b3480156101ff57600080fd5b5061021d6004803603602081101561021657600080fd5b50356109f7565b005b34801561022b57600080fd5b50610234610a8f565b60408051918252519081900360200190f35b34801561025257600080fd5b506102e16004803603608081101561026957600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156102a357600080fd5b8201836020820111156102b557600080fd5b803590602001918460018302840111600160201b831117156102d657600080fd5b509092509050610a9b565b604080516001600160e01b03199092168252519081900360200190f35b34801561030a57600080fd5b506103286004803603602081101561032157600080fd5b5035610aac565b604080516001600160a01b039092168252519081900360200190f35b34801561035057600080fd5b50610328610ac7565b34801561036557600080fd5b5061021d6004803603602081101561037c57600080fd5b810190602081018135600160201b81111561039657600080fd5b8201836020820111156103a857600080fd5b803590602001918460208302840111600160201b831117156103c957600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610ad6945050505050565b61021d6004803603602081101561041d57600080fd5b5035610b0b565b34801561043057600080fd5b5061021d6004803603608081101561044757600080fd5b506001600160a01b038135811691602081013582169160408201358116916060013516610d3c565b34801561047b57600080fd5b5061021d6004803603602081101561049257600080fd5b5035610df2565b3480156104a557600080fd5b506104ae610e5d565b604080519115158252519081900360200190f35b3480156104ce57600080fd5b50610234610e66565b3480156104e357600080fd5b50610234600480360360208110156104fa57600080fd5b5035610e6c565b34801561050d57600080fd5b5061021d6004803603602081101561052457600080fd5b50351515610e81565b34801561053957600080fd5b5061021d6004803603602081101561055057600080fd5b50356001600160a01b0316610f7a565b34801561056c57600080fd5b506105936004803603602081101561058357600080fd5b50356001600160a01b031661111c565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105cf5781810151838201526020016105b7565b505050509050019250505060405180910390f35b3480156105ef57600080fd5b50610234611188565b34801561060457600080fd5b5061032861118e565b34801561061957600080fd5b5061021d61119d565b34801561062e57600080fd5b506103286112af565b34801561064357600080fd5b5061066a6004803603602081101561065a57600080fd5b50356001600160a01b03166112be565b604080519485526020850193909352838301919091526060830152519081900360800190f35b34801561069c57600080fd5b50610234600480360360208110156106b357600080fd5b50356001600160a01b03166112e8565b3480156106cf57600080fd5b50610234600480360360208110156106e657600080fd5b50356001600160a01b0316611461565b34801561070257600080fd5b5061021d6004803603604081101561071957600080fd5b810190602081018135600160201b81111561073357600080fd5b82018360208201111561074557600080fd5b803590602001918460208302840111600160201b8311171561076657600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b8111156107b557600080fd5b8201836020820111156107c757600080fd5b803590602001918460208302840111600160201b831117156107e857600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506114de945050505050565b34801561083257600080fd5b5061021d6004803603602081101561084957600080fd5b503561160b565b34801561085c57600080fd5b50610234611615565b34801561087157600080fd5b5061023461161b565b34801561088657600080fd5b50610328611621565b34801561089b57600080fd5b5061021d600480360360208110156108b257600080fd5b50356001600160a01b0316611630565b3480156108ce57600080fd5b506103286117a3565b3480156108e357600080fd5b5061021d600480360360208110156108fa57600080fd5b50356001600160a01b03166117b2565b34801561091657600080fd5b50610234611899565b34801561092b57600080fd5b5061021d6004803603602081101561094257600080fd5b810190602081018135600160201b81111561095c57600080fd5b82018360208201111561096e57600080fd5b803590602001918460208302840111600160201b8311171561098f57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061189f945050505050565b3480156109d957600080fd5b50610234600480360360208110156109f057600080fd5b50356118f8565b6000818152600a60205260409020546001600160a01b03163314610a4c5760405162461bcd60e51b81526004018080602001828103825260418152602001806120816041913960600191505060405180910390fd5b610a56338261190a565b60408051828152905133917f571394674ec9d9e81517060110f8f894ce912af2b2febc091bee0cdea68adf00919081900360200190a250565b671bc16d674ec8000081565b630a85bd0160e11b95945050505050565b600a602052600090815260409020546001600160a01b031681565b6003546001600160a01b031681565b60005b8151811015610b0757610aff33838381518110610af257fe5b6020026020010151611b04565b600101610ad9565b5050565b6000818152600a6020526040902054610b2c906001600160a01b0316610f7a565b6000818152600b6020526040902054610b765760405162461bcd60e51b815260040180806020018281038252604f815260200180612032604f913960600191505060405180910390fd5b6000818152600b60205260409020543490610b919082611c68565b6000838152600b60205260409020819055671bc16d674ec800001015610be85760405162461bcd60e51b815260040180806020018281038252605f815260200180611fb2605f913960600191505060405180910390fd5b600c54610bf59082611c68565b600c556004546040516000916001600160a01b03169083908381818185875af1925050503d8060008114610c45576040519150601f19603f3d011682016040523d82523d6000602084013e610c4a565b606091505b5050905080610c8a5760405162461bcd60e51b815260040180806020018281038252605b815260200180611ed7605b913960600191505060405180910390fd5b6000838152600a60209081526040808320546001600160a01b031683526009825280832086845260018101909252909120548154859183918110610cca57fe5b90600052602060002001541415610d00576002810154610cea9084611c68565b6002820155600554610cfc9084611c68565b6005555b60408051848152905185917f80f327f9c1db6dfe75b98bc5424a9e88b2713c0de0c0553394d0158feaa5080b919081900360200190a250505050565b600d54610100900460ff1615610d8f576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5cd959606a1b604482015290519081900360640190fd5b600480546001600160a01b039586166001600160a01b031991821617909155600080549486169482169490941790935560018054928516928416929092179091556002805491909316911617905542600655600d805461ff001916610100179055565b6000818152600a60205260409020546001600160a01b03163314610e475760405162461bcd60e51b81526004018080602001828103825260418152602001806120816041913960600191505060405180910390fd5b610e5033611630565b610e5a338261190a565b50565b600d5460ff1681565b600c5481565b6000818152600b60205260409020545b919050565b6002546040805163c395fcb360e01b815233600482015290516001600160a01b039092169163c395fcb391602480820192602092909190829003018186803b158015610ecc57600080fd5b505afa158015610ee0573d6000803e3d6000fd5b505050506040513d6020811015610ef657600080fd5b5051610f335760405162461bcd60e51b8152600401808060200182810382526040815260200180611f326040913960400191505060405180910390fd5b600d805482151560ff19909116811790915560408051918252517f4a113b1b56ac87c884bce0b1715ef967c43f546e247aa746d79d92335fe9f8259181900360200190a150565b600360009054906101000a90046001600160a01b03166001600160a01b0316633e158b0c6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610fca57600080fd5b505af1158015610fde573d6000803e3d6000fd5b505050506040513d6020811015610ff457600080fd5b505060035460065460408051633bc22b5d60e11b81526004810192909252426024830152516000926001600160a01b03169163778456ba916044808301926020929190829003018186803b15801561104b57600080fd5b505afa15801561105f573d6000803e3d6000fd5b505050506040513d602081101561107557600080fd5b5051600554909150156110ca576005546110c6906110bd906110b76d314dc6448d9338c15b0a000000006110b186670de0b6b3a7640000611ccb565b90611ccb565b90611d24565b60075490611c68565b6007555b4260065560006110d983611461565b6001600160a01b0384166000818152600960205260409020919250156111165760048101546111089083611c68565b600482015560075460038201555b50505050565b6001600160a01b03811660009081526009602090815260409182902080548351818402810184019094528084526060939283018282801561117c57602002820191906000526020600020905b815481526020019060010190808311611168575b50505050509050919050565b60085481565b6002546001600160a01b031681565b600154604080516370a0823160e01b815233600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156111e857600080fd5b505afa1580156111fc573d6000803e3d6000fd5b505050506040513d602081101561121257600080fd5b5051905060005b81811015610b075760015460408051632f745c5960e01b815233600482018190526024820185905291516112a7936001600160a01b031691632f745c59916044808301926020929190829003018186803b15801561127657600080fd5b505afa15801561128a573d6000803e3d6000fd5b505050506040513d60208110156112a057600080fd5b5051611b04565b600101611219565b6001546001600160a01b031681565b60096020526000908152604090206002810154600382015460048301546005909301549192909184565b6000600554600014156112fd57506000610e7c565b60035460065460408051633bc22b5d60e11b81526004810192909252426024830152516000926001600160a01b03169163778456ba916044808301926020929190829003018186803b15801561135257600080fd5b505afa158015611366573d6000803e3d6000fd5b505050506040513d602081101561137c57600080fd5b50516001600160a01b03841660009081526009602052604081206003015460055492935090916113d991906113d3906110bd906110b76d314dc6448d9338c15b0a000000006110b189670de0b6b3a7640000611ccb565b90611d66565b6001600160a01b03851660009081526009602052604081206002015491925090611423906d314dc6448d9338c15b0a00000000906110b790670de0b6b3a764000090829087611ccb565b6001600160a01b03861660009081526009602052604090206005810154600490910154919250611458916113d3908490611c68565b95945050505050565b6001600160a01b038116600090815260096020526040812060030154600754829161148c9190611d66565b6001600160a01b038416600090815260096020526040812060020154919250906114d6906d314dc6448d9338c15b0a00000000906110b790670de0b6b3a764000090829087611ccb565b949350505050565b6002546040805163c395fcb360e01b815233600482015290516001600160a01b039092169163c395fcb391602480820192602092909190829003018186803b15801561152957600080fd5b505afa15801561153d573d6000803e3d6000fd5b505050506040513d602081101561155357600080fd5b50516115905760405162461bcd60e51b815260040180806020018281038252603e8152602001806120c2603e913960400191505060405180910390fd5b60005b82518110156116065760008382815181106115aa57fe5b6020026020010151905060008383815181106115c257fe5b6020026020010151905080600b6000848152602001908152602001600020819055506115f981600c54611c6890919063ffffffff16565b600c555050600101611593565b505050565b610e5a3382611b04565b60055481565b60065481565b6000546001600160a01b031681565b600d5460ff16151560011461168c576040805162461bcd60e51b815260206004820152601d60248201527f546f6b656e732063616e6e6e6f7420626520636c61696d656420796574000000604482015290519081900360640190fd5b61169581610f7a565b6001600160a01b0381166000908152600960205260408120600581015460048201549192916116c391611d66565b60058301549091506116d59082611c68565b6005830155600080546040805163a9059cbb60e01b81526001600160a01b038781166004830152602482018690529151919092169263a9059cbb92604480820193602093909283900390910190829087803b15801561173357600080fd5b505af1158015611747573d6000803e3d6000fd5b505050506040513d602081101561175d57600080fd5b50506040805182815290516001600160a01b038516917fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e0486919081900360200190a2505050565b6004546001600160a01b031681565b6002546040805163c395fcb360e01b815233600482015290516001600160a01b039092169163c395fcb391602480820192602092909190829003018186803b1580156117fd57600080fd5b505afa158015611811573d6000803e3d6000fd5b505050506040513d602081101561182757600080fd5b50516118645760405162461bcd60e51b8152600401808060200182810382526040815260200180611f726040913960400191505060405180910390fd5b6001600160a01b03811661187757600080fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60075481565b6118a833611630565b60005b8151811015610b07576000818152600a60205260409020546001600160a01b03163314156118f0576118f0338383815181106118e357fe5b602002602001015161190a565b6001016118ab565b600b6020526000908152604090205481565b6001600160a01b03821660009081526009602052604081209061192c83610e6c565b600283015490915061193e9082611d66565b60028301556005546119509082611d66565b600555815460001981019060009084908390811061196a57fe5b906000526020600020015490508084600001856001016000888152602001908152602001600020548154811061199c57fe5b6000918252602090912001558354156119e45783548490806119ba57fe5b60008281526020808220830160001990810183905590920190925586825260018601905260408120555b6002840154611a2f576001600160a01b038616600090815260096020526040812090611a108282611ea4565b5060006002820181905560038201819055600482018190556005909101555b6000858152600a602052604080822080546001600160a01b03191690556001548151632142170760e11b81523060048201526001600160a01b038a81166024830152604482018a9052925192909116926342842e0e9260648084019382900301818387803b158015611aa057600080fd5b505af1158015611ab4573d6000803e3d6000fd5b5050604080516001600160a01b038a1681526020810189905281517f0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f759450908190039091019150a1505050505050565b6001600160a01b03821660009081526009602052604090206002810154158015611b3057506003810154155b15611b3e5760075460038201555b611b4783610f7a565b6000611b5283610e6c565b6002830154909150611b649082611c68565b6002830155600554611b769082611c68565b60055581546001808201845560008481526020808220909301869055858152600a909252604080832080546001600160a01b0319166001600160a01b0389811691821790925592548251632142170760e11b815260048101949094523060248501526044840188905291519116926342842e0e926064808201939182900301818387803b158015611c0657600080fd5b505af1158015611c1a573d6000803e3d6000fd5b5050604080516001600160a01b03881681526020810187905281517f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d9450908190039091019150a150505050565b600082820183811015611cc2576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b600082611cda57506000611cc5565b82820282848281611ce757fe5b0414611cc25760405162461bcd60e51b81526004018080602001828103825260218152602001806120116021913960400191505060405180910390fd5b6000611cc283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611da8565b6000611cc283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611e4a565b60008183611e345760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611df9578181015183820152602001611de1565b50505050905090810190601f168015611e265780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581611e4057fe5b0495945050505050565b60008184841115611e9c5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611df9578181015183820152602001611de1565b505050900390565b5080546000825590600052602060002090810190610e5a91905b80821115611ed25760008155600101611ebe565b509056fe4469676974616c617847656e657369735374616b696e672e696e637265617365436f6e747269627574696f6e3a20556e61626c6520746f2073656e6420636f6e747269627574696f6e20746f2066756e6473206d756c74697369674469676974616c617847656e657369735374616b696e672e736574546f6b656e73436c61696d61626c653a2053656e646572206d7573742062652061646d696e4469676974616c617847656e657369735374616b696e672e73657452657761726473436f6e74726163743a2053656e646572206d7573742062652061646d696e4469676974616c617847656e657369735374616b696e672e696e637265617365436f6e747269627574696f6e3a20596f752063616e6e6f742065786365656420746865206d6178696d756d20636f6e747269627574696f6e20616d6f756e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774469676974616c617847656e657369735374616b696e672e696e637265617365436f6e747269627574696f6e3a2067656e65736973204e465420776173206e6f7420636f6e747269626962757465644469676974616c617847656e657369735374616b696e672e5f756e7374616b653a2053656e646572206d7573742068617665207374616b656420746f6b656e49444469676974616c617847656e657369735374616b696e672e736574436f6e747269627574696f6e733a2053656e646572206d7573742062652061646d696ea26469706673582212209e8bbf28c4312267905dbe2456074b732ffb7fd8dd6388e9e90aec6062c6699864736f6c634300060c0033
Deployed Bytecode
0x6080604052600436106101ee5760003560e01c8063748365ef1161010d578063aadee22d116100a0578063dbeb61c71161006f578063dbeb61c7146108c2578063dfa0dfa5146108d7578063e3ca00861461090a578063e64a21f31461091f578063e8709c40146109cd576101ee565b8063aadee22d14610850578063c8f33c9114610865578063d1af0c7d1461087a578063d279c1911461088f576101ee565b8063949813b8116100dc578063949813b81461069057806397d5ede5146106c3578063a2010956146106f6578063a694fc3a14610826576101ee565b8063748365ef146105f85780638dcb40611461060d5780638dd4916b146106225780639168ae7214610637576101ee565b80632e17de7811610185578063542360fd11610154578063542360fd14610501578063632447c91461052d57806363c28db11461056057806369f066a3146105e3576101ee565b80632e17de781461046f57806331f684c01461049957806337c08923146104c2578063494f67c2146104d7576101ee565b8063220cce97116101c1578063220cce9714610344578063230f436d146103595780632af59b9e146104075780632cb4836c14610424576101ee565b8063012ce501146101f35780630dc85f541461021f578063150b7a02146102465780631caaa487146102fe575b600080fd5b3480156101ff57600080fd5b5061021d6004803603602081101561021657600080fd5b50356109f7565b005b34801561022b57600080fd5b50610234610a8f565b60408051918252519081900360200190f35b34801561025257600080fd5b506102e16004803603608081101561026957600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156102a357600080fd5b8201836020820111156102b557600080fd5b803590602001918460018302840111600160201b831117156102d657600080fd5b509092509050610a9b565b604080516001600160e01b03199092168252519081900360200190f35b34801561030a57600080fd5b506103286004803603602081101561032157600080fd5b5035610aac565b604080516001600160a01b039092168252519081900360200190f35b34801561035057600080fd5b50610328610ac7565b34801561036557600080fd5b5061021d6004803603602081101561037c57600080fd5b810190602081018135600160201b81111561039657600080fd5b8201836020820111156103a857600080fd5b803590602001918460208302840111600160201b831117156103c957600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610ad6945050505050565b61021d6004803603602081101561041d57600080fd5b5035610b0b565b34801561043057600080fd5b5061021d6004803603608081101561044757600080fd5b506001600160a01b038135811691602081013582169160408201358116916060013516610d3c565b34801561047b57600080fd5b5061021d6004803603602081101561049257600080fd5b5035610df2565b3480156104a557600080fd5b506104ae610e5d565b604080519115158252519081900360200190f35b3480156104ce57600080fd5b50610234610e66565b3480156104e357600080fd5b50610234600480360360208110156104fa57600080fd5b5035610e6c565b34801561050d57600080fd5b5061021d6004803603602081101561052457600080fd5b50351515610e81565b34801561053957600080fd5b5061021d6004803603602081101561055057600080fd5b50356001600160a01b0316610f7a565b34801561056c57600080fd5b506105936004803603602081101561058357600080fd5b50356001600160a01b031661111c565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105cf5781810151838201526020016105b7565b505050509050019250505060405180910390f35b3480156105ef57600080fd5b50610234611188565b34801561060457600080fd5b5061032861118e565b34801561061957600080fd5b5061021d61119d565b34801561062e57600080fd5b506103286112af565b34801561064357600080fd5b5061066a6004803603602081101561065a57600080fd5b50356001600160a01b03166112be565b604080519485526020850193909352838301919091526060830152519081900360800190f35b34801561069c57600080fd5b50610234600480360360208110156106b357600080fd5b50356001600160a01b03166112e8565b3480156106cf57600080fd5b50610234600480360360208110156106e657600080fd5b50356001600160a01b0316611461565b34801561070257600080fd5b5061021d6004803603604081101561071957600080fd5b810190602081018135600160201b81111561073357600080fd5b82018360208201111561074557600080fd5b803590602001918460208302840111600160201b8311171561076657600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b8111156107b557600080fd5b8201836020820111156107c757600080fd5b803590602001918460208302840111600160201b831117156107e857600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506114de945050505050565b34801561083257600080fd5b5061021d6004803603602081101561084957600080fd5b503561160b565b34801561085c57600080fd5b50610234611615565b34801561087157600080fd5b5061023461161b565b34801561088657600080fd5b50610328611621565b34801561089b57600080fd5b5061021d600480360360208110156108b257600080fd5b50356001600160a01b0316611630565b3480156108ce57600080fd5b506103286117a3565b3480156108e357600080fd5b5061021d600480360360208110156108fa57600080fd5b50356001600160a01b03166117b2565b34801561091657600080fd5b50610234611899565b34801561092b57600080fd5b5061021d6004803603602081101561094257600080fd5b810190602081018135600160201b81111561095c57600080fd5b82018360208201111561096e57600080fd5b803590602001918460208302840111600160201b8311171561098f57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061189f945050505050565b3480156109d957600080fd5b50610234600480360360208110156109f057600080fd5b50356118f8565b6000818152600a60205260409020546001600160a01b03163314610a4c5760405162461bcd60e51b81526004018080602001828103825260418152602001806120816041913960600191505060405180910390fd5b610a56338261190a565b60408051828152905133917f571394674ec9d9e81517060110f8f894ce912af2b2febc091bee0cdea68adf00919081900360200190a250565b671bc16d674ec8000081565b630a85bd0160e11b95945050505050565b600a602052600090815260409020546001600160a01b031681565b6003546001600160a01b031681565b60005b8151811015610b0757610aff33838381518110610af257fe5b6020026020010151611b04565b600101610ad9565b5050565b6000818152600a6020526040902054610b2c906001600160a01b0316610f7a565b6000818152600b6020526040902054610b765760405162461bcd60e51b815260040180806020018281038252604f815260200180612032604f913960600191505060405180910390fd5b6000818152600b60205260409020543490610b919082611c68565b6000838152600b60205260409020819055671bc16d674ec800001015610be85760405162461bcd60e51b815260040180806020018281038252605f815260200180611fb2605f913960600191505060405180910390fd5b600c54610bf59082611c68565b600c556004546040516000916001600160a01b03169083908381818185875af1925050503d8060008114610c45576040519150601f19603f3d011682016040523d82523d6000602084013e610c4a565b606091505b5050905080610c8a5760405162461bcd60e51b815260040180806020018281038252605b815260200180611ed7605b913960600191505060405180910390fd5b6000838152600a60209081526040808320546001600160a01b031683526009825280832086845260018101909252909120548154859183918110610cca57fe5b90600052602060002001541415610d00576002810154610cea9084611c68565b6002820155600554610cfc9084611c68565b6005555b60408051848152905185917f80f327f9c1db6dfe75b98bc5424a9e88b2713c0de0c0553394d0158feaa5080b919081900360200190a250505050565b600d54610100900460ff1615610d8f576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5cd959606a1b604482015290519081900360640190fd5b600480546001600160a01b039586166001600160a01b031991821617909155600080549486169482169490941790935560018054928516928416929092179091556002805491909316911617905542600655600d805461ff001916610100179055565b6000818152600a60205260409020546001600160a01b03163314610e475760405162461bcd60e51b81526004018080602001828103825260418152602001806120816041913960600191505060405180910390fd5b610e5033611630565b610e5a338261190a565b50565b600d5460ff1681565b600c5481565b6000818152600b60205260409020545b919050565b6002546040805163c395fcb360e01b815233600482015290516001600160a01b039092169163c395fcb391602480820192602092909190829003018186803b158015610ecc57600080fd5b505afa158015610ee0573d6000803e3d6000fd5b505050506040513d6020811015610ef657600080fd5b5051610f335760405162461bcd60e51b8152600401808060200182810382526040815260200180611f326040913960400191505060405180910390fd5b600d805482151560ff19909116811790915560408051918252517f4a113b1b56ac87c884bce0b1715ef967c43f546e247aa746d79d92335fe9f8259181900360200190a150565b600360009054906101000a90046001600160a01b03166001600160a01b0316633e158b0c6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610fca57600080fd5b505af1158015610fde573d6000803e3d6000fd5b505050506040513d6020811015610ff457600080fd5b505060035460065460408051633bc22b5d60e11b81526004810192909252426024830152516000926001600160a01b03169163778456ba916044808301926020929190829003018186803b15801561104b57600080fd5b505afa15801561105f573d6000803e3d6000fd5b505050506040513d602081101561107557600080fd5b5051600554909150156110ca576005546110c6906110bd906110b76d314dc6448d9338c15b0a000000006110b186670de0b6b3a7640000611ccb565b90611ccb565b90611d24565b60075490611c68565b6007555b4260065560006110d983611461565b6001600160a01b0384166000818152600960205260409020919250156111165760048101546111089083611c68565b600482015560075460038201555b50505050565b6001600160a01b03811660009081526009602090815260409182902080548351818402810184019094528084526060939283018282801561117c57602002820191906000526020600020905b815481526020019060010190808311611168575b50505050509050919050565b60085481565b6002546001600160a01b031681565b600154604080516370a0823160e01b815233600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156111e857600080fd5b505afa1580156111fc573d6000803e3d6000fd5b505050506040513d602081101561121257600080fd5b5051905060005b81811015610b075760015460408051632f745c5960e01b815233600482018190526024820185905291516112a7936001600160a01b031691632f745c59916044808301926020929190829003018186803b15801561127657600080fd5b505afa15801561128a573d6000803e3d6000fd5b505050506040513d60208110156112a057600080fd5b5051611b04565b600101611219565b6001546001600160a01b031681565b60096020526000908152604090206002810154600382015460048301546005909301549192909184565b6000600554600014156112fd57506000610e7c565b60035460065460408051633bc22b5d60e11b81526004810192909252426024830152516000926001600160a01b03169163778456ba916044808301926020929190829003018186803b15801561135257600080fd5b505afa158015611366573d6000803e3d6000fd5b505050506040513d602081101561137c57600080fd5b50516001600160a01b03841660009081526009602052604081206003015460055492935090916113d991906113d3906110bd906110b76d314dc6448d9338c15b0a000000006110b189670de0b6b3a7640000611ccb565b90611d66565b6001600160a01b03851660009081526009602052604081206002015491925090611423906d314dc6448d9338c15b0a00000000906110b790670de0b6b3a764000090829087611ccb565b6001600160a01b03861660009081526009602052604090206005810154600490910154919250611458916113d3908490611c68565b95945050505050565b6001600160a01b038116600090815260096020526040812060030154600754829161148c9190611d66565b6001600160a01b038416600090815260096020526040812060020154919250906114d6906d314dc6448d9338c15b0a00000000906110b790670de0b6b3a764000090829087611ccb565b949350505050565b6002546040805163c395fcb360e01b815233600482015290516001600160a01b039092169163c395fcb391602480820192602092909190829003018186803b15801561152957600080fd5b505afa15801561153d573d6000803e3d6000fd5b505050506040513d602081101561155357600080fd5b50516115905760405162461bcd60e51b815260040180806020018281038252603e8152602001806120c2603e913960400191505060405180910390fd5b60005b82518110156116065760008382815181106115aa57fe5b6020026020010151905060008383815181106115c257fe5b6020026020010151905080600b6000848152602001908152602001600020819055506115f981600c54611c6890919063ffffffff16565b600c555050600101611593565b505050565b610e5a3382611b04565b60055481565b60065481565b6000546001600160a01b031681565b600d5460ff16151560011461168c576040805162461bcd60e51b815260206004820152601d60248201527f546f6b656e732063616e6e6e6f7420626520636c61696d656420796574000000604482015290519081900360640190fd5b61169581610f7a565b6001600160a01b0381166000908152600960205260408120600581015460048201549192916116c391611d66565b60058301549091506116d59082611c68565b6005830155600080546040805163a9059cbb60e01b81526001600160a01b038781166004830152602482018690529151919092169263a9059cbb92604480820193602093909283900390910190829087803b15801561173357600080fd5b505af1158015611747573d6000803e3d6000fd5b505050506040513d602081101561175d57600080fd5b50506040805182815290516001600160a01b038516917fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e0486919081900360200190a2505050565b6004546001600160a01b031681565b6002546040805163c395fcb360e01b815233600482015290516001600160a01b039092169163c395fcb391602480820192602092909190829003018186803b1580156117fd57600080fd5b505afa158015611811573d6000803e3d6000fd5b505050506040513d602081101561182757600080fd5b50516118645760405162461bcd60e51b8152600401808060200182810382526040815260200180611f726040913960400191505060405180910390fd5b6001600160a01b03811661187757600080fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60075481565b6118a833611630565b60005b8151811015610b07576000818152600a60205260409020546001600160a01b03163314156118f0576118f0338383815181106118e357fe5b602002602001015161190a565b6001016118ab565b600b6020526000908152604090205481565b6001600160a01b03821660009081526009602052604081209061192c83610e6c565b600283015490915061193e9082611d66565b60028301556005546119509082611d66565b600555815460001981019060009084908390811061196a57fe5b906000526020600020015490508084600001856001016000888152602001908152602001600020548154811061199c57fe5b6000918252602090912001558354156119e45783548490806119ba57fe5b60008281526020808220830160001990810183905590920190925586825260018601905260408120555b6002840154611a2f576001600160a01b038616600090815260096020526040812090611a108282611ea4565b5060006002820181905560038201819055600482018190556005909101555b6000858152600a602052604080822080546001600160a01b03191690556001548151632142170760e11b81523060048201526001600160a01b038a81166024830152604482018a9052925192909116926342842e0e9260648084019382900301818387803b158015611aa057600080fd5b505af1158015611ab4573d6000803e3d6000fd5b5050604080516001600160a01b038a1681526020810189905281517f0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f759450908190039091019150a1505050505050565b6001600160a01b03821660009081526009602052604090206002810154158015611b3057506003810154155b15611b3e5760075460038201555b611b4783610f7a565b6000611b5283610e6c565b6002830154909150611b649082611c68565b6002830155600554611b769082611c68565b60055581546001808201845560008481526020808220909301869055858152600a909252604080832080546001600160a01b0319166001600160a01b0389811691821790925592548251632142170760e11b815260048101949094523060248501526044840188905291519116926342842e0e926064808201939182900301818387803b158015611c0657600080fd5b505af1158015611c1a573d6000803e3d6000fd5b5050604080516001600160a01b03881681526020810187905281517f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d9450908190039091019150a150505050565b600082820183811015611cc2576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b600082611cda57506000611cc5565b82820282848281611ce757fe5b0414611cc25760405162461bcd60e51b81526004018080602001828103825260218152602001806120116021913960400191505060405180910390fd5b6000611cc283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611da8565b6000611cc283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611e4a565b60008183611e345760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611df9578181015183820152602001611de1565b50505050905090810190601f168015611e265780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581611e4057fe5b0495945050505050565b60008184841115611e9c5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611df9578181015183820152602001611de1565b505050900390565b5080546000825590600052602060002090810190610e5a91905b80821115611ed25760008155600101611ebe565b509056fe4469676974616c617847656e657369735374616b696e672e696e637265617365436f6e747269627574696f6e3a20556e61626c6520746f2073656e6420636f6e747269627574696f6e20746f2066756e6473206d756c74697369674469676974616c617847656e657369735374616b696e672e736574546f6b656e73436c61696d61626c653a2053656e646572206d7573742062652061646d696e4469676974616c617847656e657369735374616b696e672e73657452657761726473436f6e74726163743a2053656e646572206d7573742062652061646d696e4469676974616c617847656e657369735374616b696e672e696e637265617365436f6e747269627574696f6e3a20596f752063616e6e6f742065786365656420746865206d6178696d756d20636f6e747269627574696f6e20616d6f756e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774469676974616c617847656e657369735374616b696e672e696e637265617365436f6e747269627574696f6e3a2067656e65736973204e465420776173206e6f7420636f6e747269626962757465644469676974616c617847656e657369735374616b696e672e5f756e7374616b653a2053656e646572206d7573742068617665207374616b656420746f6b656e49444469676974616c617847656e657369735374616b696e672e736574436f6e747269627574696f6e733a2053656e646572206d7573742062652061646d696ea26469706673582212209e8bbf28c4312267905dbe2456074b732ffb7fd8dd6388e9e90aec6062c6699864736f6c634300060c0033
Deployed Bytecode Sourcemap
80409:15050:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88933:318;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;88933:318:0;;:::i;:::-;;82172:59;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;95254:196;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;95254:196:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;95254:196:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;95254:196:0;;;;;;;;;;-1:-1:-1;95254:196:0;;-1:-1:-1;95254:196:0;-1:-1:-1;95254:196:0;:::i;:::-;;;;-1:-1:-1;;;;;;95254:196:0;;;;;;;;;;;;;;81885:46;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;81885:46:0;;:::i;:::-;;;;-1:-1:-1;;;;;81885:46:0;;;;;;;;;;;;;;80674:40;;;;;;;;;;;;;:::i;85400:189::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;85400:189:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;85400:189:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85400:189:0;;-1:-1:-1;85400:189:0;;-1:-1:-1;;;;;85400:189:0:i;93854:1390::-;;;;;;;;;;;;;;;;-1:-1:-1;93854:1390:0;;:::i;83363:514::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;83363:514:0;;;;;;;;;;;;;;;;;;;;;;;;:::i;86980:319::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;86980:319:0;;:::i;82328:27::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;82042:33;;;;;;;;;;;;;:::i;84949:185::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;84949:185:0;;:::i;84239:339::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;84239:339:0;;;;:::i;89352:875::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;89352:875:0;-1:-1:-1;;;;;89352:875:0;;:::i;84684:187::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;84684:187:0;-1:-1:-1;;;;;84684:187:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81053:36;;;;;;;;;;;;;:::i;80622:45::-;;;;;;;;;;;;;:::i;85664:248::-;;;;;;;;;;;;;:::i;80577:38::-;;;;;;;;;;;;;:::i;81787:42::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;81787:42:0;-1:-1:-1;;;;;81787:42:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91588:1142;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;91588:1142:0;-1:-1:-1;;;;;91588:1142:0;;:::i;90444:449::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;90444:449:0;-1:-1:-1;;;;;90444:449:0;;:::i;92939:554::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;92939:554:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;92939:554:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;92939:554:0;;;;;;;;-1:-1:-1;92939:554:0;;-1:-1:-1;;;;;92939:554:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;92939:554:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;92939:554:0;;-1:-1:-1;92939:554:0;;-1:-1:-1;;;;;92939:554:0:i;85207:117::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85207:117:0;;:::i;80936:29::-;;;;;;;;;;;;;:::i;80972:::-;;;;;;;;;;;;;:::i;80544:26::-;;;;;;;;;;;;;:::i;90969:545::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;90969:545:0;-1:-1:-1;;;;;90969:545:0;;:::i;80809:36::-;;;;;;;;;;;;;:::i;83885:346::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;83885:346:0;-1:-1:-1;;;;;83885:346:0;;:::i;81010:36::-;;;;;;;;;;;;;:::i;87378:310::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;87378:310:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;87378:310:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;87378:310:0;;-1:-1:-1;87378:310:0;;-1:-1:-1;;;;;87378:310:0:i;81987:48::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;81987:48:0;;:::i;88933:318::-;89019:20;;;;:10;:20;;;;;;-1:-1:-1;;;;;89019:20:0;89043:10;89019:34;88997:149;;;;-1:-1:-1;;;88997:149:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89157:30;89166:10;89178:8;89157;:30::i;:::-;89203:38;;;;;;;;89220:10;;89203:38;;;;;;;;;;88933:318;:::o;82172:59::-;82224:7;82172:59;:::o;95254:196::-;-1:-1:-1;;;95254:196:0;;;;;;;:::o;81885:46::-;;;;;;;;;;;;-1:-1:-1;;;;;81885:46:0;;:::o;80674:40::-;;;-1:-1:-1;;;;;80674:40:0;;:::o;85400:189::-;85486:6;85481:101;85502:8;:15;85498:1;:19;85481:101;;;85539:31;85546:10;85558:8;85567:1;85558:11;;;;;;;;;;;;;;85539:6;:31::i;:::-;85519:3;;85481:101;;;;85400:189;:::o;93854:1390::-;93966:20;;;;:10;:20;;;;;;93953:34;;-1:-1:-1;;;;;93966:20:0;93953:12;:34::i;:::-;94045:1;94020:22;;;:12;:22;;;;;;93998:155;;;;-1:-1:-1;;;93998:155:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94166:25;94239:22;;;:12;:22;;;;;;94194:9;;94239:45;;94194:9;94239:26;:45::i;:::-;94214:22;;;;:12;:22;;;;;:70;;;82224:7;-1:-1:-1;94319:51:0;94297:196;;;;-1:-1:-1;;;94297:196:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94527:18;;:41;;94550:17;94527:22;:41::i;:::-;94506:18;:62;94612:13;;:49;;94582:25;;-1:-1:-1;;;;;94612:13:0;;94639:17;;94582:25;94612:49;94582:25;94612:49;94639:17;94612:13;:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94581:80;;;94694:20;94672:161;;;;-1:-1:-1;;;94672:161:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94854:21;94886:20;;;:10;:20;;;;;;;;;-1:-1:-1;;;;;94886:20:0;94878:29;;:7;:29;;;;;94978:27;;;94886:20;94978:17;;:27;;;;;;;94962:44;;94897:8;;94878:29;;94962:44;;;;;;;;;;;;;;:56;94958:213;;;95053:14;;;;:37;;95072:17;95053:18;:37::i;:::-;95036:14;;;:54;95122:14;;:37;;95141:17;95122:18;:37::i;:::-;95105:14;:54;94958:213;95186:50;;;;;;;;95208:8;;95186:50;;;;;;;;;;93854:1390;;;;:::o;83363:514::-;83604:11;;;;;;;83603:12;83595:44;;;;;-1:-1:-1;;;83595:44:0;;;;;;;;;;;;-1:-1:-1;;;83595:44:0;;;;;;;;;;;;;;;83650:13;:30;;-1:-1:-1;;;;;83650:30:0;;;-1:-1:-1;;;;;;83650:30:0;;;;;;;:13;83691:28;;;;;;;;;;;;;;;83650:30;83730:24;;;;;;;;;;;;;;;83765:14;:32;;;;;;;;;;;83825:15;83808:14;:32;83851:11;:18;;-1:-1:-1;;83851:18:0;83650:30;83851:18;;;83363:514::o;86980:319::-;87089:20;;;;:10;:20;;;;;;-1:-1:-1;;;;;87089:20:0;87113:10;87089:34;87067:149;;;;-1:-1:-1;;;87067:149:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87227:23;87239:10;87227:11;:23::i;:::-;87261:30;87270:10;87282:8;87261;:30::i;:::-;86980:319;:::o;82328:27::-;;;;;;:::o;82042:33::-;;;;:::o;84949:185::-;85065:14;85104:22;;;:12;:22;;;;;;84949:185;;;;:::o;84239:339::-;84354:14;;:39;;;-1:-1:-1;;;84354:39:0;;84382:10;84354:39;;;;;;-1:-1:-1;;;;;84354:14:0;;;;:27;;:39;;;;;;;;;;;;;;;:14;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;84354:39:0;84332:153;;;;-1:-1:-1;;;84332:153:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84496:15;:26;;;;;-1:-1:-1;;84496:26:0;;;;;;;;84538:32;;;;;;;;;;;;;;;;84239:339;:::o;89352:875::-;89439:15;;;;;;;;;-1:-1:-1;;;;;89439:15:0;-1:-1:-1;;;;;89439:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;89506:15:0;;89537:14;;89506:63;;;-1:-1:-1;;;89506:63:0;;;;;;;;;89553:15;89506:63;;;;;89481:22;;-1:-1:-1;;;;;89506:15:0;;:30;;:63;;;;;89439:31;;89506:63;;;;;;;:15;:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;89506:63:0;89586:14;;89506:63;;-1:-1:-1;89586:18:0;89582:305;;89859:14;;89645:230;;89671:203;;:137;81133:5;89671:70;:14;89736:4;89671:64;:70::i;:::-;:120;;:137::i;:::-;:187;;:203::i;:::-;89645:21;;;:25;:230::i;:::-;89621:21;:254;89582:305;89924:15;89907:14;:32;89950:15;89968:19;89981:5;89968:12;:19::i;:::-;-1:-1:-1;;;;;90024:14:0;;90000:21;90024:14;;;:7;:14;;;;;89950:37;;-1:-1:-1;90053:19:0;90049:171;;90112:20;;;;:33;;90137:7;90112:24;:33::i;:::-;90089:20;;;:56;90186:21;;90160:23;;;:47;90049:171;89352:875;;;;:::o;84684:187::-;-1:-1:-1;;;;;84840:14:0;;;;;;:7;:14;;;;;;;;;84833:30;;;;;;;;;;;;;;;;;84790:25;;84833:30;;;84840:14;84833:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84684:187;;;:::o;81053:36::-;;;;:::o;80622:45::-;;;-1:-1:-1;;;;;80622:45:0;;:::o;85664:248::-;85736:10;;:32;;;-1:-1:-1;;;85736:32:0;;85757:10;85736:32;;;;;;85718:15;;-1:-1:-1;;;;;85736:10:0;;:20;;:32;;;;;;;;;;;;;;:10;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85736:32:0;;-1:-1:-1;85784:6:0;85779:126;85800:7;85796:1;:11;85779:126;;;85848:10;;:44;;;-1:-1:-1;;;85848:44:0;;85836:10;85848:44;;;;;;;;;;;;;;85829:64;;-1:-1:-1;;;;;85848:10:0;;:30;;:44;;;;;;;;;;;;;;:10;:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85848:44:0;85829:6;:64::i;:::-;85809:3;;85779:126;;80577:38;;;-1:-1:-1;;;;;80577:38:0;;:::o;81787:42::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;91588:1142::-;91694:7;91723:14;;91741:1;91723:19;91719:60;;;-1:-1:-1;91766:1:0;91759:8;;91719:60;91816:15;;91847:14;;91816:120;;;-1:-1:-1;;;91816:120:0;;;;;;;;;91920:15;91816:120;;;;;91791:22;;-1:-1:-1;;;;;91816:15:0;;:30;;:120;;;;;;;;;;;;;;:15;:120;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;91816:120:0;-1:-1:-1;;;;;92331:14:0;;91949:25;92331:14;;;:7;91816:120;92331:14;;;;:31;;;92251:14;;91816:120;;-1:-1:-1;91949:25:0;;91977:386;;92331:31;91977:290;;92003:263;;:177;81133:5;92003:90;91816:120;92088:4;92003:84;:90::i;91977:290::-;:353;;:386::i;:::-;-1:-1:-1;;;;;92451:14:0;;92433:15;92451:14;;;:7;:14;;;;;:22;;;91949:414;;-1:-1:-1;92433:15:0;92451:176;;81133:5;;92451:105;;92551:4;;92451:105;;91949:414;92451:26;:45::i;:176::-;-1:-1:-1;;;;;92691:14:0;;;;;;:7;:14;;;;;:30;;;;92657:28;;;;;92433:194;;-1:-1:-1;92645:77:0;;:41;;92433:194;;92645:11;:41::i;:77::-;92638:84;91588:1142;-1:-1:-1;;;;;91588:1142:0:o;90444:449::-;-1:-1:-1;;;;;90623:14:0;;90544:7;90623:14;;;:7;:14;;;;;:31;;;90597:21;;90544:7;;90597:58;;:21;:25;:58::i;:::-;-1:-1:-1;;;;;90684:14:0;;90666:15;90684:14;;;:7;:14;;;;;:22;;;90569:86;;-1:-1:-1;90666:15:0;90684:176;;81133:5;;90684:105;;90784:4;;90684:105;;90569:86;90684:26;:45::i;:176::-;90666:194;90444:449;-1:-1:-1;;;;90444:449:0:o;92939:554::-;93097:14;;:39;;;-1:-1:-1;;;93097:39:0;;93125:10;93097:39;;;;;;-1:-1:-1;;;;;93097:14:0;;;;:27;;:39;;;;;;;;;;;;;;;:14;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;93097:39:0;93075:151;;;;-1:-1:-1;;;93075:151:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93242:9;93237:249;93261:6;:13;93257:1;:17;93237:249;;;93296:13;93312:6;93319:1;93312:9;;;;;;;;;;;;;;93296:25;;93336:14;93353:7;93361:1;93353:10;;;;;;;;;;;;;;93336:27;;93400:6;93378:12;:19;93391:5;93378:19;;;;;;;;;;;:28;;;;93442:30;93465:6;93442:18;;:22;;:30;;;;:::i;:::-;93421:18;:51;-1:-1:-1;;93276:3:0;;93237:249;;;;92939:554;;:::o;85207:117::-;85289:27;85296:10;85308:7;85289:6;:27::i;80936:29::-;;;;:::o;80972:::-;;;;:::o;80544:26::-;;;-1:-1:-1;;;;;80544:26:0;;:::o;90969:545::-;91075:15;;;;:23;;:15;:23;91053:102;;;;;-1:-1:-1;;;91053:102:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;91166:19;91179:5;91166:12;:19::i;:::-;-1:-1:-1;;;;;91222:14:0;;91198:21;91222:14;;;:7;:14;;;;;91302:22;;;;91277:20;;;;91222:14;;91198:21;91277:48;;:24;:48::i;:::-;91361:22;;;;91253:72;;-1:-1:-1;91361:41:0;;91253:72;91361:26;:41::i;:::-;91336:22;;;:66;91415:12;;;:43;;;-1:-1:-1;;;91415:43:0;;-1:-1:-1;;;;;91415:43:0;;;;;;;;;;;;;;;:12;;;;;:21;;:43;;;;;;;;;;;;;;;;;;:12;:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;91474:32:0;;;;;;;;-1:-1:-1;;;;;91474:32:0;;;;;;;;;91415:43;91474:32;;;90969:545;;;:::o;80809:36::-;;;-1:-1:-1;;;;;80809:36:0;;:::o;83885:346::-;84000:14;;:39;;;-1:-1:-1;;;84000:39:0;;84028:10;84000:39;;;;;;-1:-1:-1;;;;;84000:14:0;;;;:27;;:39;;;;;;;;;;;;;;;:14;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;84000:39:0;83978:153;;;;-1:-1:-1;;;83978:153:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;84150:19:0;;84142:28;;;;;;84181:15;:42;;-1:-1:-1;;;;;;84181:42:0;-1:-1:-1;;;;;84181:42:0;;;;;;;;;;83885:346::o;81010:36::-;;;;:::o;87378:310::-;87477:23;87489:10;87477:11;:23::i;:::-;87516:6;87511:170;87532:8;:15;87528:1;:19;87511:170;;;87573:13;;;;:10;:13;;;;;;-1:-1:-1;;;;;87573:13:0;87590:10;87573:27;87569:101;;;87621:33;87630:10;87642:8;87651:1;87642:11;;;;;;;;;;;;;;87621:8;:33::i;:::-;87549:3;;87511:170;;81987:48;;;;;;;;;;;;;:::o;87915:948::-;-1:-1:-1;;;;;88053:14:0;;88029:21;88053:14;;;:7;:14;;;;;;88097:32;88120:8;88097:22;:32::i;:::-;88157:14;;;;88080:49;;-1:-1:-1;88157:26:0;;88080:49;88157:18;:26::i;:::-;88140:14;;;:43;88211:14;;:26;;88230:6;88211:18;:26::i;:::-;88194:14;:43;88270:22;;-1:-1:-1;;88270:26:0;;;88250:17;;88270:6;;:26;;88330;;;;;;;;;;;;;;88307:49;;88414:12;88367:6;:15;;88383:6;:17;;:27;88401:8;88383:27;;;;;;;;;;;;88367:44;;;;;;;;;;;;;;;;;:59;88441:22;;:26;88437:129;;88484:21;;:6;;:21;;;;;;;;;;;;;;;-1:-1:-1;;88484:21:0;;;;;;;;;;;;88527:27;;;88484:21;88527:17;;:27;;;;;88520:34;88437:129;88582:14;;;;88578:73;;-1:-1:-1;;;;;88625:14:0;;;;;;:7;:14;;;;;;88618:21;88625:14;;88618:21;:::i;:::-;-1:-1:-1;88618:21:0;;;;;;;;;;;;;;;;;;;;;;;;88578:73;88668:20;;;;:10;:20;;;;;;88661:27;;-1:-1:-1;;;;;;88661:27:0;;;-1:-1:-1;88701:10:0;:109;;-1:-1:-1;;;88701:109:0;;88751:4;88701:109;;;;-1:-1:-1;;;;;88701:109:0;;;;;;;;;;;;;;;:10;;;;;:27;;:109;;;;;;;;;;88668:20;88701:10;:109;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;88828:25:0;;;-1:-1:-1;;;;;88828:25:0;;;;;;;;;;;;;;-1:-1:-1;88828:25:0;;;;;;;;-1:-1:-1;88828:25:0;87915:948;;;;;;:::o;86134:793::-;-1:-1:-1;;;;;86266:14:0;;86242:21;86266:14;;;:7;:14;;;;;86297;;;;:19;:51;;;;-1:-1:-1;86320:23:0;;;;:28;86297:51;86293:130;;;86390:21;;86364:23;;;:47;86293:130;86435:19;86448:5;86435:12;:19::i;:::-;86465:14;86482:32;86505:8;86482:22;:32::i;:::-;86542:14;;;;86465:49;;-1:-1:-1;86542:26:0;;86465:49;86542:18;:26::i;:::-;86525:14;;;:43;86596:14;;:26;;86615:6;86596:18;:26::i;:::-;86579:14;:43;86633:30;;;;;;;;-1:-1:-1;86633:30:0;;;;;;;;;;;;;86730:20;;;:10;:20;;;86674:45;86730:20;;;:28;;-1:-1:-1;;;;;;86730:28:0;-1:-1:-1;;;;;86730:28:0;;;;;;;;;86769:10;;:109;;-1:-1:-1;;;86769:109:0;;;;;;;;;86839:4;86769:109;;;;;;;;;;;;:10;;;:27;;:109;;;;;;;;;;;-1:-1:-1;86769:10:0;:109;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;86896:23:0;;;-1:-1:-1;;;;;86896:23:0;;;;;;;;;;;;;;-1:-1:-1;86896:23:0;;;;;;;;-1:-1:-1;86896:23:0;86134:793;;;;:::o;964:181::-;1022:7;1054:5;;;1078:6;;;;1070:46;;;;;-1:-1:-1;;;1070:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;1136:1;-1:-1:-1;964:181:0;;;;;:::o;2318:471::-;2376:7;2621:6;2617:47;;-1:-1:-1;2651:1:0;2644:8;;2617:47;2688:5;;;2692:1;2688;:5;:1;2712:5;;;;;:10;2704:56;;;;-1:-1:-1;;;2704:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3265:132;3323:7;3350:39;3354:1;3357;3350:39;;;;;;;;;;;;;;;;;:3;:39::i;1428:136::-;1486:7;1513:43;1517:1;1520;1513:43;;;;;;;;;;;;;;;;;:3;:43::i;3893:278::-;3979:7;4014:12;4007:5;3999:28;;;;-1:-1:-1;;;3999:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4038:9;4054:1;4050;:5;;;;;;;3893:278;-1:-1:-1;;;;;3893:278:0:o;1867:192::-;1953:7;1989:12;1981:6;;;;1973:29;;;;-1:-1:-1;;;1973:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;2025:5:0;;;1867:192::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o
Swarm Source
ipfs://9e8bbf28c4312267905dbe2456074b732ffb7fd8dd6388e9e90aec6062c66998
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $82.84 | 134.9976 | $11,183.2 |
Loading...
Loading
[ Download: CSV Export ]
[ 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.