More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 1,069,802 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Receive V2 | 99559203 | 5 secs ago | IN | 0 FTM | 0.00615286 | ||||
Receive V2 | 99559201 | 6 secs ago | IN | 0 FTM | 0.00442583 | ||||
Receive V2 | 99559194 | 13 secs ago | IN | 0 FTM | 0.00584619 | ||||
Receive V2 | 99559193 | 14 secs ago | IN | 0 FTM | 0.00405533 | ||||
Receive V2 | 99559170 | 45 secs ago | IN | 0 FTM | 0.00433928 | ||||
Receive V2 | 99559169 | 47 secs ago | IN | 0 FTM | 0.00172623 | ||||
Receive V2 | 99559160 | 56 secs ago | IN | 0 FTM | 0.00414345 | ||||
Receive V2 | 99559158 | 1 mins ago | IN | 0 FTM | 0.00410777 | ||||
Receive V2 | 99559151 | 1 min ago | IN | 0 FTM | 0.00427078 | ||||
Receive V2 | 99559148 | 1 min ago | IN | 0 FTM | 0.00409417 | ||||
Receive V2 | 99559145 | 1 min ago | IN | 0 FTM | 0.00417537 | ||||
Receive V2 | 99559143 | 1 min ago | IN | 0 FTM | 0.00410078 | ||||
Receive V2 | 99559137 | 1 min ago | IN | 0 FTM | 0.00500678 | ||||
Receive V2 | 99559133 | 1 min ago | IN | 0 FTM | 0.00429038 | ||||
Receive V2 | 99559117 | 1 min ago | IN | 0 FTM | 0.00428048 | ||||
Receive V2 | 99559110 | 1 min ago | IN | 0 FTM | 0.00418106 | ||||
Receive V2 | 99559108 | 1 min ago | IN | 0 FTM | 0.00430477 | ||||
Receive V2 | 99559098 | 1 min ago | IN | 0 FTM | 0.00407277 | ||||
Receive V2 | 99559092 | 1 min ago | IN | 0 FTM | 0.00174172 | ||||
Receive V2 | 99559078 | 2 mins ago | IN | 0 FTM | 0.00419331 | ||||
Receive V2 | 99559070 | 2 mins ago | IN | 0 FTM | 0.00419621 | ||||
Receive V2 | 99559056 | 2 mins ago | IN | 0 FTM | 0.004417 | ||||
Receive V2 | 99559042 | 2 mins ago | IN | 0 FTM | 0.00411164 | ||||
Receive V2 | 99559030 | 3 mins ago | IN | 0 FTM | 0.00413779 | ||||
Receive V2 | 99559022 | 3 mins ago | IN | 0 FTM | 0.00431025 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
99195647 | 4 days ago | Contract Creation | 0 FTM | |||
99195647 | 4 days ago | 0 FTM | ||||
99012974 | 5 days ago | Contract Creation | 0 FTM | |||
99012974 | 5 days ago | 0 FTM | ||||
97888014 | 18 days ago | Contract Creation | 0 FTM | |||
97888014 | 18 days ago | 0 FTM | ||||
97168748 | 26 days ago | Contract Creation | 0 FTM | |||
97168748 | 26 days ago | 0 FTM | ||||
96318238 | 36 days ago | Contract Creation | 0 FTM | |||
96318238 | 36 days ago | 0 FTM | ||||
96038731 | 39 days ago | Contract Creation | 0 FTM | |||
96038731 | 39 days ago | 0 FTM | ||||
91970598 | 81 days ago | Contract Creation | 0 FTM | |||
91970598 | 81 days ago | 0 FTM | ||||
82801210 | 178 days ago | Contract Creation | 0 FTM | |||
82801210 | 178 days ago | 0 FTM | ||||
82683552 | 180 days ago | Contract Creation | 0 FTM | |||
82683552 | 180 days ago | 0 FTM | ||||
80307422 | 221 days ago | Contract Creation | 0 FTM | |||
80307422 | 221 days ago | 0 FTM | ||||
80060101 | 226 days ago | Contract Creation | 0 FTM | |||
80060101 | 226 days ago | 0 FTM | ||||
79885101 | 228 days ago | Contract Creation | 0 FTM | |||
79885101 | 228 days ago | 0 FTM | ||||
79884198 | 228 days ago | Contract Creation | 0 FTM |
Loading...
Loading
Contract Name:
GovBridgeV2PoS
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED // Copyright (c) Eywa.Fi, 2021-2023 - all rights reserved pragma solidity ^0.8.17; import "./GovBridgeV2.sol"; /** * @notice [WIP] GovBridge PoS version. */ contract GovBridgeV2PoS is GovBridgeV2 { mapping(bytes32 => bool) private _processed; event EpochRatingsApplied( bytes32 epochHash, bytes32[] teamCollaterals, uint256[] teamRatings, uint8 ratingsDiff, uint32 epochNum, uint64 version ); function setRatings(ReceiveParams calldata params) external { verifyEpoch(currentEpoch, params); bytes memory payload = Merkle.prove(params.merkleProof, Block.txRootHash(params.blockHeader)); // TODO payload different with receiveparams - epoch hash should be on fixed position bytes32 epochHash; assembly { epochHash := mload(add(payload, add(0, 0x20))) // get first 32 bytes from 0 element } require(_processed[epochHash] == false, "GovBridgeV2PoS: raitings already set"); _processed[epochHash] = true; // Emulate raiting calculation... uint256 size = 24; // amount oracles on cdp stand (20 in epoch + 4) bytes32[] memory teamCollaterals = new bytes32[](size); uint256[] memory teamRatings = new uint256[](size); uint8 ratingsDiff = 1; for (uint256 i = 0; i<size; i++) { teamCollaterals[i] = bytes32(uint(keccak256(abi.encodePacked(i, msg.sender, block.number))) % (20000000000000000000-10000000000000000)); teamRatings[i] = uint(keccak256(abi.encodePacked(i, msg.sender, block.number))) % (20-10); // random btw 10 - 20 } emit EpochRatingsApplied(epochHash, teamCollaterals, teamRatings, ratingsDiff, currentEpoch.epochNum, nextProtocolVersion); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * 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, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(account), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @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 virtual override 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. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _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. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _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 revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { 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. * * May emit a {RoleGranted} event. * * [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}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ 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 { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControlEnumerable.sol"; import "./AccessControl.sol"; import "../utils/structs/EnumerableSet.sol"; /** * @dev Extension of {AccessControl} that allows enumerating the members of each role. */ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { using EnumerableSet for EnumerableSet.AddressSet; mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @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 virtual override returns (address) { return _roleMembers[role].at(index); } /** * @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 virtual override returns (uint256) { return _roleMembers[role].length(); } /** * @dev Overload {_grantRole} to track enumerable memberships */ function _grantRole(bytes32 role, address account) internal virtual override { super._grantRole(role, account); _roleMembers[role].add(account); } /** * @dev Overload {_revokeRole} to track enumerable memberships */ function _revokeRole(bytes32 role, address account) internal virtual override { super._revokeRole(role, account); _roleMembers[role].remove(account); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @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 {AccessControl-_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) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @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) external; /** * @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) external; /** * @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) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; /** * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. */ interface IAccessControlEnumerable is IAccessControl { /** * @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) external view returns (address); /** * @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) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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"); (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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.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 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) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.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.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ 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; if (lastIndex != toDeleteIndex) { 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] = valueIndex; // Replace lastValue's index to valueIndex } // 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) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { 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(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, 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(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set 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(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // 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(uint160(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(uint160(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(uint160(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(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // 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 in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: UNLICENSED // Copyright (c) Eywa.Fi, 2021-2023 - all rights reserved pragma solidity ^0.8.17; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "../interfaces/IBridgeV2.sol"; import "../utils/Block.sol"; import "../utils/Bls.sol"; import "../utils/Merkle.sol"; import "../utils/RequestIdChecker.sol"; import "../utils/Typecast.sol"; contract BridgeV2 is IBridgeV2, AccessControlEnumerable, Typecast, ReentrancyGuard { using Address for address; using Bls for Bls.Epoch; /// @dev gate keeper role id bytes32 public constant GATEKEEPER_ROLE = keccak256("GATEKEEPER_ROLE"); /// @dev validator role id bytes32 public constant VALIDATOR_ROLE = keccak256("VALIDATOR_ROLE"); /// @dev operator role id bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); /// @dev human readable version string public version; /// @dev current state Active\Inactive State public state; /// @dev nonces mapping(address => uint256) public nonces; /// @dev received request IDs against relay RequestIdChecker public currentRequestIdChecker; /// @dev received request IDs against relay RequestIdChecker public previousRequestIdChecker; // current epoch Bls.Epoch internal currentEpoch; // previous epoch Bls.Epoch internal previousEpoch; event EpochUpdated(bytes key, uint32 epochNum, uint64 protocolVersion); event RequestSent( bytes32 requestId, bytes data, address to, uint64 chainIdTo ); event RequestReceived(bytes32 requestId, string error); event StateSet(State state); constructor() { _grantRole(DEFAULT_ADMIN_ROLE, _msgSender()); version = "2.2.3"; currentRequestIdChecker = new RequestIdChecker(); previousRequestIdChecker = new RequestIdChecker(); state = State.Inactive; } /** * @dev Get current epoch. */ function getCurrentEpoch() public view returns (bytes memory, uint8, uint32) { return (abi.encode(currentEpoch.publicKey), currentEpoch.participantsCount, currentEpoch.epochNum); } /** * @dev Get previous epoch. */ function getPreviousEpoch() public view returns (bytes memory, uint8, uint32) { return (abi.encode(previousEpoch.publicKey), previousEpoch.participantsCount, previousEpoch.epochNum); } /** * @dev Updates current epoch. * * @param params ReceiveParams struct. */ function updateEpoch(ReceiveParams calldata params) external onlyRole(VALIDATOR_ROLE) { // TODO ensure that new epoch really next one after previous (by hash) bytes memory payload = Merkle.prove(params.merkleProof, Block.txRootHash(params.blockHeader)); (uint64 newEpochProtocolVersion, uint32 newEpochNum, bytes memory newKey, uint8 newParticipantsCount) = Block .decodeEpochUpdate(payload); require(currentEpoch.epochNum + 1 == newEpochNum, "Bridge: wrong epoch number"); // TODO remove if when resetEpoch will be removed if (currentEpoch.isSet()) { verifyEpoch(currentEpoch, params); rotateEpoch(); } // TODO ensure that new epoch really next one after previous (prev hash + params.blockHeader) bytes32 newHash = sha256(params.blockHeader); currentEpoch.update(newKey, newParticipantsCount, newEpochNum, newHash); onEpochStart(newEpochProtocolVersion); } /** * @dev Forcefully reset epoch on all chains. */ function resetEpoch() public onlyRole(OPERATOR_ROLE) { // TODO consider to remove any possible manipulations from protocol if (currentEpoch.isSet()) { rotateEpoch(); currentEpoch.epochNum = previousEpoch.epochNum + 1; } else { currentEpoch.epochNum = currentEpoch.epochNum + 1; } onEpochStart(0); } /** * @dev Send crosschain request v2. * * @param params struct with requestId, data, receiver and opposite cahinId * @param from sender's address * @param nonce sender's nonce */ function sendV2( SendParams calldata params, address from, uint256 nonce ) external override onlyRole(GATEKEEPER_ROLE) returns (bool) { require(state == State.Active, "Bridge: state inactive"); require(previousEpoch.isSet() || currentEpoch.isSet(), "Bridge: epoch not set"); verifyAndUpdateNonce(from, nonce); emit RequestSent( params.requestId, params.data, params.to, uint64(params.chainIdTo) ); return true; } /** * @dev Receive (batch) crosschain request v2. * * @param params array with ReceiveParams structs. */ function receiveV2(ReceiveParams[] calldata params) external override onlyRole(VALIDATOR_ROLE) nonReentrant returns (bool) { require(state != State.Inactive, "Bridge: state inactive"); for (uint256 i = 0; i < params.length; ++i) { bytes32 epochHash = Block.epochHash(params[i].blockHeader); // verify the block signature if (epochHash == currentEpoch.epochHash) { require(currentEpoch.isSet(), "Bridge: epoch not set"); verifyEpoch(currentEpoch, params[i]); } else if (epochHash == previousEpoch.epochHash) { require(previousEpoch.isSet(), "Bridge: epoch not set"); verifyEpoch(previousEpoch, params[i]); } else { revert("Bridge: wrong epoch"); } // verify that the transaction is really in the block bytes memory payload = Merkle.prove(params[i].merkleProof, Block.txRootHash(params[i].blockHeader)); // get call data (bytes32 requestId, bytes memory receivedData, address to, uint64 chainIdTo) = Block.decodeRequest(payload); require(chainIdTo == block.chainid, "Bridge: wrong chain id"); require(to.isContract(), "Bridge: receiver is not a contract"); bool isRequestIdUniq; if (epochHash == currentEpoch.epochHash) { isRequestIdUniq = currentRequestIdChecker.check(requestId); } else { isRequestIdUniq = previousRequestIdChecker.check(requestId); } string memory err; if (isRequestIdUniq) { (bytes memory data, bytes memory check) = abi.decode(receivedData, (bytes, bytes)); bytes memory result = to.functionCall(check); require(abi.decode(result, (bool)), "Bridge: check failed"); to.functionCall(data, "Bridge: receive failed"); } else { revert("Bridge: request id already seen"); } emit RequestReceived(requestId, err); } return true; } /** * @dev Set new state. * * @param state_ Active\Inactive state */ function setState(State state_) external onlyRole(OPERATOR_ROLE) { state = state_; emit StateSet(state); } /** * @dev Verifies epoch. * * @param epoch current or previous epoch; * @param params oracle tx params */ function verifyEpoch(Bls.Epoch storage epoch, ReceiveParams calldata params) internal view { Block.verify( epoch, params.blockHeader, params.votersPubKey, params.votersSignature, params.votersMask ); } /** * @dev Verifies and updates the sender's nonce. * * @param from sender's address * @param nonce provided nonce */ function verifyAndUpdateNonce(address from, uint256 nonce) internal { require(nonces[from]++ == nonce, "Bridge: nonce mismatch"); } /** * @dev Moves current epoch and current request filter to previous. */ function rotateEpoch() internal { previousEpoch = currentEpoch; Bls.Epoch memory epoch; currentEpoch = epoch; previousRequestIdChecker.destroy(); previousRequestIdChecker = currentRequestIdChecker; currentRequestIdChecker = new RequestIdChecker(); } /** * @dev Hook on start new epoch. */ function onEpochStart(uint64 protocolVersion_) internal virtual { emit EpochUpdated(abi.encode(currentEpoch.publicKey), currentEpoch.epochNum, protocolVersion_); } }
// SPDX-License-Identifier: UNLICENSED // Copyright (c) Eywa.Fi, 2021-2023 - all rights reserved pragma solidity ^0.8.17; import "./BridgeV2.sol"; contract GovBridgeV2 is BridgeV2 { /// @dev current protocol version uint64 public protocolVersion; /// @dev next protocol version, will be accepted fron next epoch uint64 public nextProtocolVersion; /// @dev current epoch start time uint256 public epochStartTime; /// @dev epoch min duration uint256 public epochMinDuration; /// @dev last request epoch update time uint256 public lastRequestEpochUpdateTime; /// @dev epoch min request update duration uint256 public epochMinRequestUpdateDuration; /// @dev node registry contract address address public nodeRegistry; event EpochUpdateRequested(uint32 currentEpochNum, uint64 protocolVersion); event ProtocolVersionUpdateRequested(uint64 version, uint64 nextVersion); event NodeRegistrySet(address nodeRegistry); event EpochMinDurationSet(uint256 epochMinDuration); event EpochMinRequestUpdateDurationSet(uint256 epochMinRequestUpdateDuration); constructor() { protocolVersion = 1; nextProtocolVersion = 1; epochMinDuration = 2 hours; epochMinRequestUpdateDuration = 30 minutes; } /** * @dev Changes node registry address. * * Controlled by DAO. */ function setNodeRegistry(address nodeRegistry_) external onlyRole(DEFAULT_ADMIN_ROLE) { require(nodeRegistry_ != address(0), "GovBridge: zero address given"); nodeRegistry = nodeRegistry_; emit NodeRegistrySet(nodeRegistry); } /** * @dev Request to update epoch. Anyone may call it after epochMinDuration passed. */ function requestEpochUpdate() external { require(block.timestamp > lastRequestEpochUpdateTime, "GovBridge: not enough time after retry"); require(block.timestamp > epochStartTime + epochMinDuration, "GovBridge: not enough time after epoch"); lastRequestEpochUpdateTime = block.timestamp + epochMinRequestUpdateDuration; emit EpochUpdateRequested(currentEpoch.epochNum, protocolVersion); } /** * @dev Request to update protocol version. * * Controlled by Operator. */ function requestProtocolVersionUpdate(uint64 version) external onlyRole(OPERATOR_ROLE) { require(version - 1 == protocolVersion, "GovBridge: wrong protocol version"); nextProtocolVersion = version; emit ProtocolVersionUpdateRequested(version, nextProtocolVersion); } /** * @dev Set epoch min duration. Only DAO may call this. * * Controlled by DAO. */ function setEpochMinDuration(uint256 epochMinDuration_) external onlyRole(DEFAULT_ADMIN_ROLE) { epochMinDuration = epochMinDuration_; emit EpochMinDurationSet(epochMinDuration); } /** * @dev Set epoch min request update duration. Only DAO may call this. * * Controlled by DAO. */ function setEpochMinRequestUpdateDuration(uint256 epochMinRequestUpdateDuration_) external onlyRole(DEFAULT_ADMIN_ROLE) { epochMinRequestUpdateDuration = epochMinRequestUpdateDuration_; emit EpochMinRequestUpdateDurationSet(epochMinRequestUpdateDuration); } /** * @dev Hook on start new epoch. */ function onEpochStart(uint64 protocolVersion_) internal override { uint64 prevProtocolVersion = protocolVersion; if (protocolVersion_ != 0) { protocolVersion = protocolVersion_; } else { protocolVersion = nextProtocolVersion; } require(protocolVersion >= prevProtocolVersion, "GovBridge: wrong protocol version"); epochStartTime = block.timestamp; emit EpochUpdated(abi.encode(currentEpoch.publicKey), currentEpoch.epochNum, protocolVersion); } }
// SPDX-License-Identifier: UNLICENSED // Copyright (c) Eywa.Fi, 2021-2023 - all rights reserved pragma solidity ^0.8.17; interface IBridgeV2 { enum State { Active, // data send and receive possible Inactive, // data send and receive impossible Limited // only data receive possible } struct SendParams { /// @param requestId unique request ID bytes32 requestId; /// @param data call data bytes data; /// @param to receiver contract address address to; /// @param chainIdTo destination chain ID uint256 chainIdTo; } struct ReceiveParams { /// @param blockHeader block header serialization bytes blockHeader; /// @param merkleProof OracleRequest transaction payload and its Merkle audit path bytes merkleProof; /// @param votersPubKey aggregated public key of the old epoch participants, who voted for the block bytes votersPubKey; /// @param votersSignature aggregated signature of the old epoch participants, who voted for the block bytes votersSignature; /// @param votersMask bitmask of epoch participants, who voted, among all participants uint256 votersMask; } function sendV2( SendParams calldata params, address sender, uint256 nonce ) external returns (bool); function receiveV2(ReceiveParams[] calldata params) external returns (bool); function nonces(address from) external view returns (uint256); }
// SPDX-License-Identifier: UNLICENSED // Copyright (c) Eywa.Fi, 2021-2023 - all rights reserved pragma solidity 0.8.17; import "../utils/Bls.sol"; import "../utils/Utils.sol"; import "../utils/ZeroCopySource.sol"; library Block { function txRootHash(bytes calldata payload) internal pure returns (bytes32 txRootHash_) { txRootHash_ = Utils.bytesToBytes32(payload[72:104]); } function epochHash(bytes calldata payload) internal pure returns (bytes32 epochHash_) { epochHash_ = Utils.bytesToBytes32(payload[40:72]); } function decodeRequest(bytes memory payload) internal pure returns ( bytes32 requestId, bytes memory data, address to, uint64 chainIdTo ) { uint256 off = 0; (requestId, off) = ZeroCopySource.NextHash(payload, off); (chainIdTo, off) = ZeroCopySource.NextUint64(payload, off); (to, off) = ZeroCopySource.NextAddress(payload, off); (data, off) = ZeroCopySource.NextVarBytes(payload, off); } function decodeEpochUpdate(bytes memory payload) internal pure returns ( uint64 newEpochVersion, uint32 newEpochNum, bytes memory newKey, uint8 newEpochParticipantsCount ) { uint256 off = 0; (newEpochVersion, off) = ZeroCopySource.NextUint64(payload, off); (newEpochNum, off) = ZeroCopySource.NextUint32(payload, off); (newEpochParticipantsCount, off) = ZeroCopySource.NextUint8(payload, off); (newKey, off) = ZeroCopySource.NextVarBytes(payload, off); } function verify( Bls.Epoch memory epoch, bytes calldata blockHeader, bytes calldata votersPubKey, bytes calldata votersSignature, uint256 votersMask ) internal view { require(popcnt(votersMask) > (uint256(epoch.participantsCount) * 2) / 3, "Block: not enough participants"); require(epoch.participantsCount == 255 || votersMask < (1 << epoch.participantsCount), "Block: bitmask too big"); require( Bls.verifyMultisig(epoch, votersPubKey, blockHeader, votersSignature, votersMask), "Block: multisig mismatch" ); } function popcnt(uint256 mask) internal pure returns (uint256 cnt) { cnt = 0; while (mask != 0) { mask = mask & (mask - 1); cnt++; } } }
// SPDX-License-Identifier: UNLICENSED // Copyright (c) ConsenSys // Copyright (c) Eywa.Fi, 2021-2023 - all rights reserved pragma solidity 0.8.17; import "./ModUtils.sol"; /** * @title Verify BLS Threshold Signed values. * * Much of the code in this file is derived from here: * https://github.com/ConsenSys/gpact/blob/main/common/common/src/main/solidity/BlsSignatureVerification.sol * https://github.com/ConsenSys/gpact/blob/main/contracts/contracts/src/common/BlsSignatureVerification.sol */ library Bls { using ModUtils for uint256; struct E1Point { uint256 x; uint256 y; } /** * @dev Note that the ordering of the elements in each array needs to be the reverse of what you would * normally have, to match the ordering expected by the precompile. */ struct E2Point { uint256[2] x; uint256[2] y; } /** * @dev P is a prime over which we form a basic field; * taken from go-ethereum/crypto/bn256/cloudflare/constants.go. */ uint256 constant P = 21888242871839275222246405745257275088696311157297823662689037894645226208583; struct Epoch { /// @param sum of all participant public keys E2Point publicKey; /// @param // sum of H(Pub, i) hashes of all participants indexes E1Point precomputedSum; /// @param // participants count contributed to the epochKey uint8 participantsCount; /// @param epoch number uint32 epochNum; /// @param epoch hash bytes32 epochHash; } /** * @dev Tests that epoch is set or zero. */ function isSet(Epoch memory epoch) internal pure returns (bool) { return epoch.publicKey.x[0] != 0 || epoch.publicKey.x[1] != 0; } /** * @dev Reset the epoch. */ function reset(Epoch storage epoch) internal { epoch.publicKey.x[0] = 0; epoch.publicKey.x[1] = 0; epoch.precomputedSum.x = 0; epoch.epochHash = 0; epoch.participantsCount = 0; } /** * @dev Update epoch and precompute epoch sum as if all participants signed. * * @param epoch_ current epoch to update; * @param epochPublicKey sum of all participant public keys; * @param epochParticipantsCount number of participants; * @param epochNum number of participants; * @param epochHash epoch hash. */ function update( Epoch storage epoch_, bytes memory epochPublicKey, uint8 epochParticipantsCount, uint32 epochNum, bytes32 epochHash ) internal { E2Point memory pub = decodeE2Point(epochPublicKey); E1Point memory sum = E1Point(0, 0); uint256 index = 0; bytes memory buf = abi.encodePacked(pub.x, pub.y, index); while (index < epochParticipantsCount) { assembly { mstore(add(buf, 160), index) } // overwrite index field, same as buf[128] = index sum = addCurveE1(sum, hashToCurveE1(buf)); index++; } epoch_.publicKey = pub; epoch_.precomputedSum = sum; epoch_.participantsCount = epochParticipantsCount; epoch_.epochNum = epochNum; epoch_.epochHash = epochHash; } /** * @dev Checks if the BLS multisignature is valid in the current epoch. * * @param epoch_ current epoch; * @param partPublicKey Sum of participated public keys; * @param message Message that was signed; * @param partSignature Signature over the message; * @param signersBitmask Bitmask of participants in this signature; * @return True if the message was correctly signed by the given participants. */ function verifyMultisig( Epoch memory epoch_, bytes memory partPublicKey, bytes memory message, bytes memory partSignature, uint256 signersBitmask ) internal view returns (bool) { E1Point memory sum = epoch_.precomputedSum; uint256 index = 0; uint256 mask = 1; bytes memory buf = abi.encodePacked(epoch_.publicKey.x, epoch_.publicKey.y, index); while (index < epoch_.participantsCount) { if (signersBitmask & mask == 0) { assembly { mstore(add(buf, 160), index) } // overwrite index field, same as buf[128] = index sum = addCurveE1(sum, negate(hashToCurveE1(buf))); } mask <<= 1; index++; } E1Point[] memory e1points = new E1Point[](3); E2Point[] memory e2points = new E2Point[](3); e1points[0] = negate(decodeE1Point(partSignature)); e1points[1] = hashToCurveE1(abi.encodePacked(epoch_.publicKey.x, epoch_.publicKey.y, message)); e1points[2] = sum; e2points[0] = G2(); e2points[1] = decodeE2Point(partPublicKey); e2points[2] = epoch_.publicKey; return pairing(e1points, e2points); } /** * @return The generator of E1. */ function G1() private pure returns (E1Point memory) { return E1Point(1, 2); } /** * @return The generator of E2. */ function G2() private pure returns (E2Point memory) { return E2Point({ x: [ 11559732032986387107991004021392285783925812861821192530917403151452391805634, 10857046999023057135944570762232829481370756359578518086990519993285655852781 ], y: [ 4082367875863433681332203403145435568316851327593401208105741076214120093531, 8495653923123431417604973247489272438418190587263600148770280649306958101930 ] }); } /** * Negate a point: Assuming the point isn't at infinity, the negation is same x value with -y. * * @dev Negates a point in E1; * @param _point Point to negate; * @return The negated point. */ function negate(E1Point memory _point) private pure returns (E1Point memory) { if (isAtInfinity(_point)) { return E1Point(0, 0); } return E1Point(_point.x, P - (_point.y % P)); } /** * Computes the pairing check e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1 * * @param _e1points List of points in E1; * @param _e2points List of points in E2; * @return True if pairing check succeeds. */ function pairing(E1Point[] memory _e1points, E2Point[] memory _e2points) private view returns (bool) { require(_e1points.length == _e2points.length, "Bls: point count mismatch"); uint256 elements = _e1points.length; uint256 inputSize = elements * 6; uint256[] memory input = new uint256[](inputSize); for (uint256 i = 0; i < elements; i++) { input[i * 6 + 0] = _e1points[i].x; input[i * 6 + 1] = _e1points[i].y; input[i * 6 + 2] = _e2points[i].x[0]; input[i * 6 + 3] = _e2points[i].x[1]; input[i * 6 + 4] = _e2points[i].y[0]; input[i * 6 + 5] = _e2points[i].y[1]; } uint256[1] memory out; bool success; assembly { // Start at memory offset 0x20 rather than 0 as input is a variable length array. // Location 0 is the length field. success := staticcall(sub(gas(), 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) } // The pairing operation will fail if the input data isn't the correct size (this won't happen // given the code above), or if one of the points isn't on the curve. require(success, "Bls: pairing operation failed"); return out[0] != 0; } /** * @dev Checks if the point is the point at infinity. * * @param _point a point on E1; * @return true if the point is the point at infinity. */ function isAtInfinity(E1Point memory _point) private pure returns (bool) { return (_point.x == 0 && _point.y == 0); } /** * @dev Hash a byte array message, m, and map it deterministically to a point on G1. * Note that this approach was chosen for its simplicity / * lower gas cost on the EVM, rather than good distribution of points on G1. */ function hashToCurveE1(bytes memory m) internal view returns (E1Point memory) { bytes32 h = sha256(m); uint256 x = uint256(h) % P; uint256 y; while (true) { y = YFromX(x); if (y > 0) { return E1Point(x, y); } x += 1; } revert("hashToCurveE1: unreachable end point"); } /** * @dev g1YFromX computes a Y value for a G1 point based on an X value. * This computation is simply evaluating the curve equation for Y on a given X, * and allows a point on the curve to be represented by just an X value + a sign bit. */ function YFromX(uint256 x) internal view returns (uint256) { return ((x.modExp(3, P) + 3) % P).modSqrt(P); } /** * @dev return the sum of two points of G1. */ function addCurveE1(E1Point memory _p1, E1Point memory _p2) internal view returns (E1Point memory res) { uint256[4] memory input; input[0] = _p1.x; input[1] = _p1.y; input[2] = _p2.x; input[3] = _p2.y; bool success; assembly { success := staticcall(sub(gas(), 2000), 6, input, 0x80, res, 0x40) } require(success, "Bls: add points failed"); } function decodeE1Point(bytes memory _sig) internal pure returns (E1Point memory signature) { uint256 sigx; uint256 sigy; assembly { sigx := mload(add(_sig, 0x20)) sigy := mload(add(_sig, 0x40)) } signature.x = sigx; signature.y = sigy; } function decodeE2Point(bytes memory _pubKey) internal pure returns (E2Point memory pubKey) { uint256 x1; uint256 x2; uint256 y1; uint256 y2; assembly { x1 := mload(add(_pubKey, 0x20)) x2 := mload(add(_pubKey, 0x40)) y1 := mload(add(_pubKey, 0x60)) y2 := mload(add(_pubKey, 0x80)) } pubKey.x[0] = x1; pubKey.x[1] = x2; pubKey.y[0] = y1; pubKey.y[1] = y2; } }
// SPDX-License-Identifier: UNLICENSED // Copyright (c) Eywa.Fi, 2021-2023 - all rights reserved pragma solidity 0.8.17; import "./ZeroCopySource.sol"; library Merkle { /** @notice Do hash leaf as the multi-chain does. * * @param data_ Data in bytes format; * @return result Hashed value in bytes32 format. */ function hashLeaf(bytes memory data_) internal pure returns (bytes32 result) { result = sha256(abi.encodePacked(uint8(0x0), data_)); } /** @notice Do hash children as the multi-chain does. * * @param l_ Left node; * @param r_ Right node; * @return result Hashed value in bytes32 format. */ function hashChildren(bytes32 l_, bytes32 r_) internal pure returns (bytes32 result) { result = sha256(abi.encodePacked(bytes1(0x01), l_, r_)); } /** @notice Verify merkle proove. * * @param auditPath_ Merkle path; * @param root_ Merkle tree root; * @return The verified value included in auditPath_. */ function prove(bytes memory auditPath_, bytes32 root_) internal pure returns (bytes memory) { uint256 off = 0; bytes memory value; (value, off) = ZeroCopySource.NextVarBytes(auditPath_, off); bytes32 hash = hashLeaf(value); uint256 size = (auditPath_.length - off) / 33; // 33 = sizeof(uint256) + 1 bytes32 nodeHash; uint8 pos; for (uint256 i = 0; i < size; i++) { (pos, off) = ZeroCopySource.NextUint8(auditPath_, off); (nodeHash, off) = ZeroCopySource.NextHash(auditPath_, off); if (pos == 0x00) { hash = hashChildren(nodeHash, hash); } else if (pos == 0x01) { hash = hashChildren(hash, nodeHash); } else { revert("Merkle: prove eod"); } } require(hash == root_, "Merkle: prove root"); return value; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; library ModUtils { /** * @dev Wrap the modular exponent pre-compile introduced in Byzantium. * Returns base^exponent mod p. */ function modExp( uint256 base, uint256 exponent, uint256 p ) internal view returns (uint256 o) { /* solium-disable-next-line */ assembly { // Args for the precompile: [<length_of_BASE> <length_of_EXPONENT> // <length_of_MODULUS> <BASE> <EXPONENT> <MODULUS>] let output := mload(0x40) let args := add(output, 0x20) mstore(args, 0x20) mstore(add(args, 0x20), 0x20) mstore(add(args, 0x40), 0x20) mstore(add(args, 0x60), base) mstore(add(args, 0x80), exponent) mstore(add(args, 0xa0), p) // 0x05 is the modular exponent contract address if iszero(staticcall(not(0), 0x05, args, 0xc0, output, 0x20)) { revert(0, 0) } o := mload(output) } } /** * @dev Calculates and returns the square root of a mod p if such a square * root exists. The modulus p must be an odd prime. If a square root does * not exist, function returns 0. */ function modSqrt(uint256 a, uint256 p) internal view returns (uint256) { if (legendre(a, p) != 1) { return 0; } if (a == 0) { return 0; } if (p % 4 == 3) { return modExp(a, (p + 1) / 4, p); } uint256 s = p - 1; uint256 e = 0; while (s % 2 == 0) { s = s / 2; e = e + 1; } // Note the smaller int- finding n with Legendre symbol or -1 // should be quick uint256 n = 2; while (legendre(n, p) != -1) { n = n + 1; } uint256 x = modExp(a, (s + 1) / 2, p); uint256 b = modExp(a, s, p); uint256 g = modExp(n, s, p); uint256 r = e; uint256 gs = 0; uint256 m = 0; uint256 t = b; while (true) { t = b; m = 0; for (m = 0; m < r; m++) { if (t == 1) { break; } t = modExp(t, 2, p); } if (m == 0) { return x; } gs = modExp(g, uint256(2)**(r - m - 1), p); g = (gs * gs) % p; x = (x * gs) % p; b = (b * g) % p; r = m; } revert("modSqrt: unreachable end point"); } /** * @dev Calculates the Legendre symbol of the given a mod p. * @return Returns 1 if a is a quadratic residue mod p, -1 if it is * a non-quadratic residue, and 0 if a is 0. */ function legendre(uint256 a, uint256 p) internal view returns (int256) { uint256 raised = modExp(a, (p - 1) / uint256(2), p); if (raised == 0 || raised == 1) { return int256(raised); } else if (raised == p - 1) { return -1; } revert("Failed to calculate legendre."); } }
// SPDX-License-Identifier: UNLICENSED // Copyright (c) Eywa.Fi, 2021-2023 - all rights reserved pragma solidity 0.8.17; contract RequestIdChecker { /// mapping(bytes32 => bool) public checks; /// address public owner; modifier onlyOwner() { require(msg.sender == owner, "RequestIdChecker: caller is not the owner"); _; } constructor() { owner = msg.sender; } function check(bytes32 id) public onlyOwner returns (bool) { if (checks[id] == false) { checks[id] = true; return true; } return false; } function destroy() public onlyOwner { selfdestruct(payable(owner)); } }
// SPDX-License-Identifier: UNLICENSED // Copyright (c) Eywa.Fi, 2021-2023 - all rights reserved pragma solidity 0.8.17; abstract contract Typecast { function castToAddress(bytes32 x) public pure returns (address) { return address(uint160(uint256(x))); } function castToBytes32(address a) public pure returns (bytes32) { return bytes32(uint256(uint160(a))); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import "solidity-bytes-utils/contracts/BytesLib.sol"; library Utils { /* @notice Convert the bytes array to bytes32 type, the bytes array length must be 32 * @param _bs Source bytes array * @return bytes32 */ function bytesToBytes32(bytes memory _bs) internal pure returns (bytes32 value) { require(_bs.length == 32, "bytes length is not 32."); assembly { // load 32 bytes from memory starting from position _bs + 0x20 since the first 0x20 bytes stores _bs length value := mload(add(_bs, 0x20)) } } /* @notice Convert bytes to uint256 * @param _b Source bytes should have length of 32 * @return uint256 */ function bytesToUint256(bytes memory _bs) internal pure returns (uint256 value) { require(_bs.length == 32, "bytes length is not 32."); assembly { // load 32 bytes from memory starting from position _bs + 32 value := mload(add(_bs, 0x20)) } require(value <= 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, "Value exceeds the range"); } /* @notice Convert uint256 to bytes * @param _b uint256 that needs to be converted * @return bytes */ function uint256ToBytes(uint256 _value) internal pure returns (bytes memory bs) { require( _value <= 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, "Value exceeds the range" ); assembly { // Get a location of some free memory and store it in result as // Solidity does for memory variables. bs := mload(0x40) // Put 0x20 at the first word, the length of bytes for uint256 value mstore(bs, 0x20) //In the next word, put value in bytes format to the next 32 bytes mstore(add(bs, 0x20), _value) // Update the free-memory pointer by padding our last write location to 32 bytes mstore(0x40, add(bs, 0x40)) } } /* @notice Convert bytes to address * @param _bs Source bytes: bytes length must be 20 * @return Converted address from source bytes */ function bytesToAddress(bytes memory _bs) internal pure returns (address addr) { require(_bs.length == 20, "bytes length does not match address"); assembly { // for _bs, first word store _bs.length, second word store _bs.value // load 32 bytes from mem[_bs+20], convert it into Uint160, meaning we take last 20 bytes as addr (address). addr := mload(add(_bs, 0x14)) } } /* @notice Convert address to bytes * @param _addr Address need to be converted * @return Converted bytes from address */ function addressToBytes(address _addr) internal pure returns (bytes memory bs) { assembly { // Get a location of some free memory and store it in result as // Solidity does for memory variables. bs := mload(0x40) // Put 20 (address byte length) at the first word, the length of bytes for uint256 value mstore(bs, 0x14) // logical shift left _a by 12 bytes, change _a from right-aligned to left-aligned mstore(add(bs, 0x20), shl(96, _addr)) // Update the free-memory pointer by padding our last write location to 32 bytes mstore(0x40, add(bs, 0x40)) } } /* @notice Compare if two bytes are equal, which are in storage and memory, seperately Refer from https://github.com/summa-tx/bitcoin-spv/blob/master/solidity/contracts/BytesLib.sol#L368 * @param _preBytes The bytes stored in storage * @param _postBytes The bytes stored in memory * @return Bool type indicating if they are equal */ function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // fslot can contain both the length and contents of the array // if slength < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage // slength != 0 if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint(mc < end) + cb == 2) for { } eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } /* @notice Slice the _bytes from _start index till the result has length of _length Refer from https://github.com/summa-tx/bitcoin-spv/blob/master/solidity/contracts/BytesLib.sol#L246 * @param _bytes The original bytes needs to be sliced * @param _start The index of _bytes for the start of sliced bytes * @param _length The index of _bytes for the end of sliced bytes * @return The sliced bytes */ function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_bytes.length >= (_start + _length)); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. // lengthmod <= _length % 32 let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } /* @notice Check if the elements number of _signers within _keepers array is no less than _m * @param _keepers The array consists of serveral address * @param _signers Some specific addresses to be looked into * @param _m The number requirement paramter * @return True means containment, false meansdo do not contain. */ function containMAddresses( address[] memory _keepers, address[] memory _signers, uint256 _m ) internal pure returns (bool) { uint256 m = 0; for (uint256 i = 0; i < _signers.length; i++) { for (uint256 j = 0; j < _keepers.length; j++) { if (_signers[i] == _keepers[j]) { m++; delete _keepers[j]; } } } return m >= _m; } /* @notice TODO * @param key * @return */ function compressMCPubKey(bytes memory key) internal pure returns (bytes memory newkey) { require(key.length >= 67, "key lenggh is too short"); newkey = slice(key, 0, 35); if (uint8(key[66]) % 2 == 0) { newkey[2] = 0x02; } else { newkey[2] = 0x03; } return newkey; } /** * @dev Returns true if `account` is a contract. * Refer from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol#L18 * * This test is non-exhaustive, and there may be false-negatives: during the * execution of a contract's constructor, its address will be reported as * not containing 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. */ 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. // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != 0x0 && codehash != accountHash); } /** * @dev Extracts error from the returned data of inter-contract call */ function extractErrorMessage(bytes memory data) internal pure returns (string memory) { if (data.length < 68) return "unknown error"; bytes memory revertData = BytesLib.slice(data, 4, data.length - 4); return abi.decode(revertData, (string)); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; /** * @dev Wrappers over decoding and deserialization operation from bytes into bassic types in Solidity for PolyNetwork cross chain utility. * * Decode into basic types in Solidity from bytes easily. It's designed to be used * for PolyNetwork cross chain application, and the decoding rules on Ethereum chain * and the encoding rule on other chains should be consistent, and . Here we * follow the underlying deserialization rule with implementation found here: * https://github.com/polynetwork/poly/blob/master/common/zero_copy_source.go * * Using this library instead of the unchecked serialization method can help reduce * the risk of serious bugs and handfule, so it's recommended to use it. * * Please note that risk can be minimized, yet not eliminated. */ library ZeroCopySource { /* @notice Read next byte as boolean type starting at offset from buff * @param buff Source bytes array * @param offset The position from where we read the boolean value * @return The the read boolean value and new offset */ function NextBool(bytes memory buff, uint256 offset) internal pure returns (bool, uint256) { require(offset + 1 <= buff.length && offset < offset + 1, "Offset exceeds limit"); // byte === bytes1 uint8 v; assembly { v := mload(add(add(buff, 0x20), offset)) } bool value; if (v == 0x01) { value = true; } else if (v == 0x00) { value = false; } else { revert("NextBool value error"); } return (value, offset + 1); } /* @notice Read next byte as uint8 starting at offset from buff * @param buff Source bytes array * @param offset The position from where we read the byte value * @return The read uint8 value and new offset */ function NextUint8(bytes memory buff, uint256 offset) internal pure returns (uint8, uint256) { require(offset + 1 <= buff.length && offset < offset + 1, "NextUint8, Offset exceeds maximum"); uint8 v; assembly { let tmpbytes := mload(0x40) let bvalue := mload(add(add(buff, 0x20), offset)) mstore8(tmpbytes, byte(0, bvalue)) mstore(0x40, add(tmpbytes, 0x01)) v := mload(sub(tmpbytes, 0x1f)) } return (v, offset + 1); } /* @notice Read next two bytes as uint16 type starting from offset * @param buff Source bytes array * @param offset The position from where we read the uint16 value * @return The read uint16 value and updated offset */ function NextUint16(bytes memory buff, uint256 offset) internal pure returns (uint16, uint256) { require(offset + 2 <= buff.length && offset < offset + 2, "NextUint16, offset exceeds maximum"); uint16 v; assembly { let tmpbytes := mload(0x40) let bvalue := mload(add(add(buff, 0x20), offset)) mstore8(tmpbytes, byte(0x01, bvalue)) mstore8(add(tmpbytes, 0x01), byte(0, bvalue)) mstore(0x40, add(tmpbytes, 0x02)) v := mload(sub(tmpbytes, 0x1e)) } return (v, offset + 2); } /* @notice Read next four bytes as uint32 type starting from offset * @param buff Source bytes array * @param offset The position from where we read the uint32 value * @return The read uint32 value and updated offset */ function NextUint32(bytes memory buff, uint256 offset) internal pure returns (uint32, uint256) { require(offset + 4 <= buff.length && offset < offset + 4, "NextUint32, offset exceeds maximum"); uint32 v; assembly { let tmpbytes := mload(0x40) let byteLen := 0x04 for { let tindex := 0x00 let bindex := sub(byteLen, 0x01) let bvalue := mload(add(add(buff, 0x20), offset)) } lt(tindex, byteLen) { tindex := add(tindex, 0x01) bindex := sub(bindex, 0x01) } { mstore8(add(tmpbytes, tindex), byte(bindex, bvalue)) } mstore(0x40, add(tmpbytes, byteLen)) v := mload(sub(tmpbytes, sub(0x20, byteLen))) } return (v, offset + 4); } /* @notice Read next eight bytes as uint64 type starting from offset * @param buff Source bytes array * @param offset The position from where we read the uint64 value * @return The read uint64 value and updated offset */ function NextUint64(bytes memory buff, uint256 offset) internal pure returns (uint64, uint256) { require(offset + 8 <= buff.length && offset < offset + 8, "NextUint64, offset exceeds maximum"); uint64 v; assembly { let tmpbytes := mload(0x40) let byteLen := 0x08 for { let tindex := 0x00 let bindex := sub(byteLen, 0x01) let bvalue := mload(add(add(buff, 0x20), offset)) } lt(tindex, byteLen) { tindex := add(tindex, 0x01) bindex := sub(bindex, 0x01) } { mstore8(add(tmpbytes, tindex), byte(bindex, bvalue)) } mstore(0x40, add(tmpbytes, byteLen)) v := mload(sub(tmpbytes, sub(0x20, byteLen))) } return (v, offset + 8); } /* @notice Read next 32 bytes as uint256 type starting from offset, there are limits considering the numerical limits in multi-chain * @param buff Source bytes array * @param offset The position from where we read the uint256 value * @return The read uint256 value and updated offset */ function NextUint255(bytes memory buff, uint256 offset) internal pure returns (uint256, uint256) { require(offset + 32 <= buff.length && offset < offset + 32, "NextUint255, offset exceeds maximum"); uint256 v; assembly { let tmpbytes := mload(0x40) let byteLen := 0x20 for { let tindex := 0x00 let bindex := sub(byteLen, 0x01) let bvalue := mload(add(add(buff, 0x20), offset)) } lt(tindex, byteLen) { tindex := add(tindex, 0x01) bindex := sub(bindex, 0x01) } { mstore8(add(tmpbytes, tindex), byte(bindex, bvalue)) } mstore(0x40, add(tmpbytes, byteLen)) v := mload(tmpbytes) } require(v <= 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, "Value exceeds the range"); return (v, offset + 32); } /* @notice Read next variable bytes starting from offset, the decoding rule coming from multi-chain * @param buff Source bytes array * @param offset The position from where we read the bytes value * @return The read variable bytes array value and updated offset */ function NextVarBytes(bytes memory buff, uint256 offset) internal pure returns (bytes memory, uint256) { uint256 len; (len, offset) = NextVarUint(buff, offset); require(offset + len <= buff.length && offset < offset + len, "NextVarBytes, offset exceeds maximum"); bytes memory tempBytes; assembly { switch iszero(len) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(len, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, len) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(buff, lengthmod), mul(0x20, iszero(lengthmod))), offset) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, len) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) mstore(0x40, add(tempBytes, 0x20)) } } return (tempBytes, offset + len); } /* @notice Read next 32 bytes starting from offset, * @param buff Source bytes array * @param offset The position from where we read the bytes value * @return The read bytes32 value and updated offset */ function NextHash(bytes memory buff, uint256 offset) internal pure returns (bytes32, uint256) { require(offset + 32 <= buff.length && offset < offset + 32, "NextHash, offset exceeds maximum"); bytes32 v; assembly { v := mload(add(buff, add(offset, 0x20))) } return (v, offset + 32); } /* @notice Read next 20 bytes starting from offset, * @param buff Source bytes array * @param offset The position from where we read the bytes value * @return The read bytes20 value and updated offset */ function NextAddress(bytes memory buff, uint256 offset) internal pure returns (address, uint256) { require(offset + 20 <= buff.length && offset < offset + 20, "NextAddress, offset exceeds maximum"); bytes20 v; assembly { v := mload(add(buff, add(offset, 0x20))) } return (address(v), offset + 20); } function NextVarUint(bytes memory buff, uint256 offset) internal pure returns (uint256, uint256) { uint8 v; (v, offset) = NextUint8(buff, offset); uint256 value; if (v == 0xFD) { // return NextUint16(buff, offset); (value, offset) = NextUint16(buff, offset); require(value >= 0xFD && value <= 0xFFFF, "NextUint16, value outside range"); return (value, offset); } else if (v == 0xFE) { // return NextUint32(buff, offset); (value, offset) = NextUint32(buff, offset); require(value > 0xFFFF && value <= 0xFFFFFFFF, "NextVarUint, value outside range"); return (value, offset); } else if (v == 0xFF) { // return NextUint64(buff, offset); (value, offset) = NextUint64(buff, offset); require(value > 0xFFFFFFFF, "NextVarUint, value outside range"); return (value, offset); } else { // return (uint8(v), offset); value = uint8(v); require(value < 0xFD, "NextVarUint, value outside range"); return (value, offset); } } }
// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"epochMinDuration","type":"uint256"}],"name":"EpochMinDurationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"epochMinRequestUpdateDuration","type":"uint256"}],"name":"EpochMinRequestUpdateDurationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"epochHash","type":"bytes32"},{"indexed":false,"internalType":"bytes32[]","name":"teamCollaterals","type":"bytes32[]"},{"indexed":false,"internalType":"uint256[]","name":"teamRatings","type":"uint256[]"},{"indexed":false,"internalType":"uint8","name":"ratingsDiff","type":"uint8"},{"indexed":false,"internalType":"uint32","name":"epochNum","type":"uint32"},{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"EpochRatingsApplied","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"currentEpochNum","type":"uint32"},{"indexed":false,"internalType":"uint64","name":"protocolVersion","type":"uint64"}],"name":"EpochUpdateRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"key","type":"bytes"},{"indexed":false,"internalType":"uint32","name":"epochNum","type":"uint32"},{"indexed":false,"internalType":"uint64","name":"protocolVersion","type":"uint64"}],"name":"EpochUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nodeRegistry","type":"address"}],"name":"NodeRegistrySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"nextVersion","type":"uint64"}],"name":"ProtocolVersionUpdateRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"string","name":"error","type":"string"}],"name":"RequestReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint64","name":"chainIdTo","type":"uint64"}],"name":"RequestSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum IBridgeV2.State","name":"state","type":"uint8"}],"name":"StateSet","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GATEKEEPER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VALIDATOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"x","type":"bytes32"}],"name":"castToAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"a","type":"address"}],"name":"castToBytes32","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"currentRequestIdChecker","outputs":[{"internalType":"contract RequestIdChecker","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochMinDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochMinRequestUpdateDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentEpoch","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPreviousEpoch","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRequestEpochUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextProtocolVersion","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nodeRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"previousRequestIdChecker","outputs":[{"internalType":"contract RequestIdChecker","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolVersion","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"blockHeader","type":"bytes"},{"internalType":"bytes","name":"merkleProof","type":"bytes"},{"internalType":"bytes","name":"votersPubKey","type":"bytes"},{"internalType":"bytes","name":"votersSignature","type":"bytes"},{"internalType":"uint256","name":"votersMask","type":"uint256"}],"internalType":"struct IBridgeV2.ReceiveParams[]","name":"params","type":"tuple[]"}],"name":"receiveV2","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requestEpochUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"version","type":"uint64"}],"name":"requestProtocolVersionUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resetEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"chainIdTo","type":"uint256"}],"internalType":"struct IBridgeV2.SendParams","name":"params","type":"tuple"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"sendV2","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochMinDuration_","type":"uint256"}],"name":"setEpochMinDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochMinRequestUpdateDuration_","type":"uint256"}],"name":"setEpochMinRequestUpdateDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nodeRegistry_","type":"address"}],"name":"setNodeRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"blockHeader","type":"bytes"},{"internalType":"bytes","name":"merkleProof","type":"bytes"},{"internalType":"bytes","name":"votersPubKey","type":"bytes"},{"internalType":"bytes","name":"votersSignature","type":"bytes"},{"internalType":"uint256","name":"votersMask","type":"uint256"}],"internalType":"struct IBridgeV2.ReceiveParams","name":"params","type":"tuple"}],"name":"setRatings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IBridgeV2.State","name":"state_","type":"uint8"}],"name":"setState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"state","outputs":[{"internalType":"enum IBridgeV2.State","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"blockHeader","type":"bytes"},{"internalType":"bytes","name":"merkleProof","type":"bytes"},{"internalType":"bytes","name":"votersPubKey","type":"bytes"},{"internalType":"bytes","name":"votersSignature","type":"bytes"},{"internalType":"uint256","name":"votersMask","type":"uint256"}],"internalType":"struct IBridgeV2.ReceiveParams","name":"params","type":"tuple"}],"name":"updateEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060016002556200002460003362000122565b604080518082019091526005815264322e322e3360d81b60208201526003906200004f90826200032a565b506040516200005e9062000278565b604051809103906000f0801580156200007b573d6000803e3d6000fd5b50600680546001600160a01b0319166001600160a01b0392909216919091179055604051620000aa9062000278565b604051809103906000f080158015620000c7573d6000803e3d6000fd5b50600780546001600160a01b0319166001600160a01b03929092169190911790556004805460ff19166001179055601880546001600160801b03191668010000000000000001179055611c20601a55610708601c55620003f6565b6200013982826200016560201b62001c551760201c565b60008281526001602090815260409091206200016091839062001cd962000206821b17901c565b505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1662000202576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001c13390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60006200021d836001600160a01b03841662000226565b90505b92915050565b60008181526001830160205260408120546200026f5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000220565b50600062000220565b61024b806200538c83390190565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620002b157607f821691505b602082108103620002d257634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200016057600081815260208120601f850160051c81016020861015620003015750805b601f850160051c820191505b8181101562000322578281556001016200030d565b505050505050565b81516001600160401b0381111562000346576200034662000286565b6200035e816200035784546200029c565b84620002d8565b602080601f8311600181146200039657600084156200037d5750858301515b600019600386901b1c1916600185901b17855562000322565b600085815260208120601f198616915b82811015620003c757888601518255948401946001909101908401620003a6565b5085821015620003e65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b614f8680620004066000396000f3fe608060405234801561001057600080fd5b506004361061023d5760003560e01c8063764ebf2a1161013b578063c5a37036116100b8578063d9b5c4a51161007c578063d9b5c4a514610531578063e1164b7214610544578063e586447f14610557578063f5b541a61461056a578063f60ca6411461057f57600080fd5b8063c5a37036146104be578063ca15c873146104d1578063d547741f146104e4578063d6fd3175146104f7578063d79de39e1461051e57600080fd5b8063a217fddf116100ff578063a217fddf1461045a578063b97dd9e214610462578063c19d93fb1461046a578063c29bf43514610484578063c49baebe1461049757600080fd5b8063764ebf2a146103f85780637ecebe001461040b5780639010d07c1461042b57806391d148541461043e5780639a80fc661461045157600080fd5b80632f2ff15d116101c9578063486a54f31161018d578063486a54f3146103a257806354fd4d50146103aa57806356de96db146103bf5780635f1a6f05146103d257806362099362146103e557600080fd5b80632f2ff15d146103475780632ff1a5291461035a57806331eab48a1461036d57806336568abe146103755780633e7e25c11461038857600080fd5b8063248a9ca311610210578063248a9ca3146102c157806326339a21146102e45780632ae9c600146102ed5780632ea94006146103185780632f1874401461032d57600080fd5b806301ffc9a714610242578063056768bf1461026a5780630e03e490146102815780631bc2359a146102aa575b600080fd5b61025561025036600461422f565b610588565b60405190151581526020015b60405180910390f35b6102726105b3565b604051610261939291906142a9565b61029261028f3660046142db565b90565b6040516001600160a01b039091168152602001610261565b6102b3601a5481565b604051908152602001610261565b6102b36102cf3660046142db565b60009081526020819052604090206001015490565b6102b3601b5481565b601854610300906001600160401b031681565b6040516001600160401b039091168152602001610261565b61032b6103263660046142db565b6105fa565b005b60185461030090600160401b90046001600160401b031681565b61032b61035536600461430b565b610642565b61032b610368366004614337565b61066c565b61032b610737565b61032b61038336600461430b565b6108b4565b6102b3610396366004614360565b6001600160a01b031690565b61032b610932565b6103b2610a64565b604051610261919061437b565b61032b6103cd36600461438e565b610af2565b61032b6103e03660046142db565b610b65565b600754610292906001600160a01b031681565b600654610292906001600160a01b031681565b6102b3610419366004614360565b60056020526000908152604090205481565b6102926104393660046143af565b610ba5565b61025561044c36600461430b565b610bc4565b6102b3601c5481565b6102b3600081565b610272610bed565b6004546104779060ff1681565b60405161026191906143e7565b61032b61049236600461440f565b610c34565b6102b37f21702c8af46127c7fa207f89d0b0a8441bb32959a0ac7df790e9ab1a25c9892681565b6102556104cc366004614449565b610f13565b6102b36104df3660046142db565b611643565b61032b6104f236600461430b565b61165a565b6102b37f3c63e605be3290ab6b04cfc46c6e1516e626d43236b034f09d7ede1d017beb0c81565b61032b61052c36600461440f565b61167f565b601d54610292906001600160a01b031681565b61032b610552366004614360565b6118ee565b6102556105653660046144bd565b61199d565b6102b3600080516020614f3183398151915281565b6102b360195481565b60006001600160e01b03198216635a05180f60e01b14806105ad57506105ad82611cee565b92915050565b606060008060106000016040516020016105cd9190614541565b60408051808303601f19018152919052601654909460ff8216945061010090910463ffffffff1692509050565b600061060581611d23565b601a8290556040518281527f8906f1615411c1be37bc832caf2d17b0903ad4624b9680d92fb9799b444f9aa2906020015b60405180910390a15050565b60008281526020819052604090206001015461065d81611d23565b6106678383611d2d565b505050565b600080516020614f3183398151915261068481611d23565b6018546001600160401b031661069b600184614575565b6001600160401b0316146106ca5760405162461bcd60e51b81526004016106c190614595565b60405180910390fd5b601880546fffffffffffffffff00000000000000001916600160401b6001600160401b038581168281029390931793849055604080519384529190930490921660208201527f6daa220d3e9550bfb5df36368059f0ad2708facf48ccc8248a632dc4ad81d13c9101610636565b600080516020614f3183398151915261074f81611d23565b6040805161012081019091526108209060088160a08101828160e084018260028282826020028201915b81548152602001906001019080831161077957505050918352505060408051808201918290526020909201919060028481019182845b8154815260200190600101908083116107af57505050919092525050508152604080518082018252600484015481526005840154602080830191909152830152600683015460ff811691830191909152610100900463ffffffff166060820152600790910154608090910152611d4f565b1561086c5761082d611d6a565b60165461084690610100900463ffffffff1660016145d6565b600e805463ffffffff929092166101000264ffffffff00199092169190911790556108a7565b600e5461088590610100900463ffffffff1660016145d6565b600e805463ffffffff929092166101000264ffffffff00199092169190911790555b6108b16000611f43565b50565b6001600160a01b03811633146109245760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084016106c1565b61092e828261203e565b5050565b601b5442116109925760405162461bcd60e51b815260206004820152602660248201527f476f764272696467653a206e6f7420656e6f7567682074696d6520616674657260448201526520726574727960d01b60648201526084016106c1565b601a546019546109a291906145f3565b42116109ff5760405162461bcd60e51b815260206004820152602660248201527f476f764272696467653a206e6f7420656e6f7567682074696d65206166746572604482015265040cae0dec6d60d31b60648201526084016106c1565b601c54610a0c90426145f3565b601b55600e546018546040805161010090930463ffffffff1683526001600160401b0390911660208301527ffcd60c668a304ac5a7450e369d6196673b3637ecf20947a69afa95ae9359b290910160405180910390a1565b60038054610a7190614606565b80601f0160208091040260200160405190810160405280929190818152602001828054610a9d90614606565b8015610aea5780601f10610abf57610100808354040283529160200191610aea565b820191906000526020600020905b815481529060010190602001808311610acd57829003601f168201915b505050505081565b600080516020614f31833981519152610b0a81611d23565b6004805483919060ff19166001836002811115610b2957610b296143d1565b02179055506004546040517fc635bb75c392e81c891d50372a48cfa81b6799ac6d594cb4c28a8c5e8bef6e9b916106369160ff909116906143e7565b6000610b7081611d23565b601c8290556040518281527f85b47f19cf7d13a9f8bfebfa580d1b080f93326645845e92716924630a0be77190602001610636565b6000828152600160205260408120610bbd9083612060565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60606000806008600001604051602001610c079190614541565b60408051808303601f19018152919052600e54909460ff8216945061010090910463ffffffff1692509050565b610c3f60088261206c565b6000610c9f610c516020840184614640565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610c9a9250610c95915086905080614640565b612165565b6121b2565b6020808201516000818152601e9092526040909120549192509060ff1615610d155760405162461bcd60e51b8152602060048201526024808201527f476f764272696467655632506f533a2072616974696e677320616c7265616479604482015263081cd95d60e21b60648201526084016106c1565b6000818152601e60209081526040808320805460ff1916600117905580516018808252610320820190925290929183908201610300803683370190505090506000826001600160401b03811115610d6e57610d6e614686565b604051908082528060200260200182016040528015610d97578160200160208202803683370190505b509050600160005b84811015610ea65760408051602081018390526bffffffffffffffffffffffff193360601b16918101919091524360548201526801156abf16a40f0000906074016040516020818303038152906040528051906020012060001c610e0391906146b2565b60001b848281518110610e1857610e186146c6565b602090810291909101810191909152604080519182018390526bffffffffffffffffffffffff193360601b1690820152436054820152600a906074016040516020818303038152906040528051906020012060001c610e7791906146b2565b838281518110610e8957610e896146c6565b602090810291909101015280610e9e816146dc565b915050610d9f565b50600e546018546040517fa5501772872d3fcfece437f2f86dec90ef4c286302154b737f6c2309e42b536092610f0292899288928892889261010090920463ffffffff1691600160401b9091046001600160401b0316906146f5565b60405180910390a150505050505050565b60007f21702c8af46127c7fa207f89d0b0a8441bb32959a0ac7df790e9ab1a25c98926610f3f81611d23565b610f476122eb565b600160045460ff166002811115610f6057610f606143d1565b03610fa65760405162461bcd60e51b81526020600482015260166024820152754272696467653a20737461746520696e61637469766560501b60448201526064016106c1565b60005b8381101561162d576000610fe9868684818110610fc857610fc86146c6565b9050602002810190610fda91906147a1565b610fe49080614640565b612342565b600f54909150810361111057604080516101208101918290526008805460e083019081526110c193839160a083019184918391839060029060096101008901808311610779575050509183525050604080518082019182905260028481018054835260209485019492939092600387019085018083116107af57505050919092525050508152604080518082018252600484015481526005840154602080830191909152830152600683015460ff811691830191909152610100900463ffffffff166060820152600790910154608090910152611d4f565b6110dd5760405162461bcd60e51b81526004016106c1906147c1565b61110b60088787858181106110f4576110f46146c6565b905060200281019061110691906147a1565b61206c565b611256565b601754810361121857604080516101208101918290526010805460e083019081526111e593839160a083019184918391839060029060116101008901808311610779575050509183525050604080518082019182905260028481018054835260209485019492939092600387019085018083116107af57505050919092525050508152604080518082018252600484015481526005840154602080830191909152830152600683015460ff811691830191909152610100900463ffffffff166060820152600790910154608090910152611d4f565b6112015760405162461bcd60e51b81526004016106c1906147c1565b61110b60108787858181106110f4576110f46146c6565b60405162461bcd60e51b8152602060048201526013602482015272084e4d2c8ceca7440eee4dedcce40cae0dec6d606b1b60448201526064016106c1565b60006112f587878581811061126d5761126d6146c6565b905060200281019061127f91906147a1565b61128d906020810190614640565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610c9a92508b91508a9050878181106112d9576112d96146c6565b90506020028101906112eb91906147a1565b610c959080614640565b905060008060008061130685612355565b935093509350935046816001600160401b03161461135f5760405162461bcd60e51b8152602060048201526016602482015275109c9a5919d94e881ddc9bdb99c818da185a5b881a5960521b60448201526064016106c1565b6001600160a01b0382163b6113c15760405162461bcd60e51b815260206004820152602260248201527f4272696467653a207265636569766572206973206e6f74206120636f6e74726160448201526118dd60f21b60648201526084016106c1565b600f54600090870361144357600654604051631ccf03c960e11b8152600481018790526001600160a01b039091169063399e0792906024016020604051808303816000875af1158015611418573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143c91906147f0565b90506114b5565b600754604051631ccf03c960e11b8152600481018790526001600160a01b039091169063399e0792906024016020604051808303816000875af115801561148e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b291906147f0565b90505b6060811561159357600080868060200190518101906114d49190614899565b909250905060006114ee6001600160a01b038816836123a4565b90508080602001905181019061150491906147f0565b6115475760405162461bcd60e51b8152602060048201526014602482015273109c9a5919d94e8818da1958dac819985a5b195960621b60448201526064016106c1565b604080518082019091526016815275109c9a5919d94e881c9958d95a5d994819985a5b195960521b602082015261158a906001600160a01b0389169085906123e8565b505050506115db565b60405162461bcd60e51b815260206004820152601f60248201527f4272696467653a207265717565737420696420616c7265616479207365656e0060448201526064016106c1565b7f4b5b2fd6aa26739a2dea52c41d52e1bfd74a3288c604a237c51bdfbdd3799006868260405161160c9291906148fc565b60405180910390a1505050505050505080611626906146dc565b9050610fa9565b506001915061163c6001600255565b5092915050565b60008181526001602052604081206105ad906123ff565b60008281526020819052604090206001015461167581611d23565b610667838361203e565b7f21702c8af46127c7fa207f89d0b0a8441bb32959a0ac7df790e9ab1a25c989266116a981611d23565b60006116ff6116bb6020850185614640565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610c9a9250610c95915087905080614640565b905060008060008061171085612409565b600e549397509195509350915063ffffffff80851691611738916101009091041660016145d6565b63ffffffff161461178b5760405162461bcd60e51b815260206004820152601a60248201527f4272696467653a2077726f6e672065706f6368206e756d62657200000000000060448201526064016106c1565b604080516101208101918290526008805460e0830190815261185793839160a083019184918391839060029060096101008901808311610779575050509183525050604080518082019182905260028481018054835260209485019492939092600387019085018083116107af57505050919092525050508152604080518082018252600484015481526005840154602080830191909152830152600683015460ff811691830191909152610100900463ffffffff166060820152600790910154608090910152611d4f565b1561186f5761186760088861206c565b61186f611d6a565b6000600261187d8980614640565b60405161188b929190614915565b602060405180830381855afa1580156118a8573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906118cb9190614925565b90506118db600884848785612454565b6118e485611f43565b5050505050505050565b60006118f981611d23565b6001600160a01b03821661194f5760405162461bcd60e51b815260206004820152601d60248201527f476f764272696467653a207a65726f206164647265737320676976656e00000060448201526064016106c1565b601d80546001600160a01b0319166001600160a01b0384169081179091556040519081527fef697ae2a61f63e7a8cb0d7e7a6c0a794c764a208b7d0360e47c241b14a0dbd990602001610636565b60007f3c63e605be3290ab6b04cfc46c6e1516e626d43236b034f09d7ede1d017beb0c6119c981611d23565b600060045460ff1660028111156119e2576119e26143d1565b14611a285760405162461bcd60e51b81526020600482015260166024820152754272696467653a20737461746520696e61637469766560501b60448201526064016106c1565b604080516101208101918290526010805460e08301908152611af493839160a083019184918391839060029060116101008901808311610779575050509183525050604080518082019182905260028481018054835260209485019492939092600387019085018083116107af57505050919092525050508152604080518082018252600484015481526005840154602080830191909152830152600683015460ff811691830191909152610100900463ffffffff166060820152600790910154608090910152611d4f565b80611bc65750604080516101208101918290526008805460e08301908152611bc693839160a083019184918391839060029060096101008901808311610779575050509183525050604080518082019182905260028481018054835260209485019492939092600387019085018083116107af57505050919092525050508152604080518082018252600484015481526005840154602080830191909152830152600683015460ff811691830191909152610100900463ffffffff166060820152600790910154608090910152611d4f565b611be25760405162461bcd60e51b81526004016106c1906147c1565b611bec848461255c565b7f5566d73d091d945ab32ea023cd1930c0d43aa43bef9aee4cb029775cfc94bdae8535611c1c6020880188614640565b611c2c60608a0160408b01614360565b8960600135604051611c4295949392919061493e565b60405180910390a1506001949350505050565b611c5f8282610bc4565b61092e576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055611c953390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000610bbd836001600160a01b0384166125ce565b60006001600160e01b03198216637965db0b60e01b14806105ad57506301ffc9a760e01b6001600160e01b03198316146105ad565b6108b1813361261d565b611d378282611c55565b60008281526001602052604090206106679082611cd9565b805151516000901515806105ad575050515160200151151590565b600860108181611d7c818360026140d5565b50611d8f600282810190848101906140d5565b505050600482810154908201556005808301549082015560068083018054918301805460ff19811660ff9094169384178255915463ffffffff61010091829004160264ffffffffff19909216909217179055600791820154910155611df2614110565b8051805182916008918290611e0a9082906002614160565b506020820151611e209060028084019190614160565b50505060208281015180516004808501919091559101516005830155604080840151600684018054606087015163ffffffff166101000264ffffffffff1990911660ff909316929092179190911790556080909301516007928301559054825163083197ef60e41b815292516001600160a01b03909116926383197ef0928181019260009290919082900301818387803b158015611ebd57600080fd5b505af1158015611ed1573d6000803e3d6000fd5b5050600654600780546001600160a01b0319166001600160a01b039092169190911790555050604051611f039061418e565b604051809103906000f080158015611f1f573d6000803e3d6000fd5b50600680546001600160a01b0319166001600160a01b039290921691909117905550565b6018546001600160401b0390811690821615611f7a576018805467ffffffffffffffff19166001600160401b038416179055611f9f565b60188054600160401b81046001600160401b031667ffffffffffffffff199091161790555b6018546001600160401b0380831691161015611fcd5760405162461bcd60e51b81526004016106c190614595565b426019556040517f7abd871edc50e0783b456da5e3441224a90207257b5a02f5b2410f905204e0c09061200590600890602001614541565b60408051808303601f1901815290829052600e546018546106369361010090920463ffffffff16916001600160401b0390911690614997565b6120488282612676565b600082815260016020526040902061066790826126db565b6000610bbd83836126f0565b60408051610120810190915261092e90838160a08101828160e084018260028282826020028201915b81548152602001906001019080831161209557505050918352505060408051808201918290526020909201919060028481019182845b8154815260200190600101908083116120cb57505050919092525050508152604080518082018252600484015481526005840154602080830191909152830152600683015460ff811691830191909152610100900463ffffffff1660608201526007909101546080909101526121418380614640565b61214e6040860186614640565b61215b6060880188614640565b886080013561271a565b6000610bbd6121786068604885876149cf565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506128eb92505050565b6060600060606121c28583612946565b9250905060006121d182612a54565b9050600060218488516121e491906149f9565b6121ee9190614a0c565b905060008060005b83811015612299576122088a88612ac6565b975091506122168a88612b81565b9750925060ff82166000036122365761222f8386612c0f565b9450612287565b8160ff1660010361224b5761222f8584612c0f565b60405162461bcd60e51b815260206004820152601160248201527013595c9adb194e881c1c9bdd9948195bd9607a1b60448201526064016106c1565b80612291816146dc565b9150506121f6565b508784146122de5760405162461bcd60e51b815260206004820152601260248201527113595c9adb194e881c1c9bdd99481c9bdbdd60721b60448201526064016106c1565b5092979650505050505050565b600280540361233c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106c1565b60028055565b6000610bbd6121786048602885876149cf565b6000606060008060006123688682612b81565b90955090506123778682612c8d565b90925090506123868682612d5e565b90935090506123958682612946565b50949694955091939092509050565b6060610bbd838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612df6565b60606123f78484600085612df6565b949350505050565b60006105ad825490565b6000806060818061241a8682612c8d565b90955090506124298682612ed1565b90945090506124388682612ac6565b90925090506124478682612946565b5094969395509092915050565b600061245f85612fa2565b9050600060405180604001604052806000815260200160008152509050600080836000015184602001518360405160200161249c93929190614a43565b60405160208183030381529060405290505b8660ff168210156124e5578160a08201526124d1836124cc83612fde565b6130a1565b9250816124dd816146dc565b9250506124ae565b835184908a906124f89082906002614160565b50602082015161250e9060028084019190614160565b5050835160048b01555050506020015160058701555060068501805463ffffffff9093166101000264ffffffffff1990931660ff909416939093179190911790915560079092019190915550565b6001600160a01b038216600090815260056020526040812080548392909190612584836146dc565b919050551461092e5760405162461bcd60e51b8152602060048201526016602482015275084e4d2c8ceca7440dcdedcc6ca40dad2e6dac2e8c6d60531b60448201526064016106c1565b6000818152600183016020526040812054612615575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105ad565b5060006105ad565b6126278282610bc4565b61092e576126348161313e565b61263f836020613150565b604051602001612650929190614a6b565b60408051601f198184030181529082905262461bcd60e51b82526106c19160040161437b565b6126808282610bc4565b1561092e576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610bbd836001600160a01b0384166132eb565b6000826000018281548110612707576127076146c6565b9060005260206000200154905092915050565b6003886040015160ff1660026127309190614ae0565b61273a9190614a0c565b612743826133de565b116127905760405162461bcd60e51b815260206004820152601e60248201527f426c6f636b3a206e6f7420656e6f756768207061727469636970616e7473000060448201526064016106c1565b876040015160ff1660ff14806127b05750876040015160ff166001901b81105b6127f55760405162461bcd60e51b8152602060048201526016602482015275426c6f636b3a206269746d61736b20746f6f2062696760501b60448201526064016106c1565b61289f8886868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8e018190048102820181019092528c815292508c91508b908190840183828082843760009201919091525050604080516020601f8b01819004810282018101909252898152925089915088908190840183828082843760009201919091525088925061340d915050565b6118e45760405162461bcd60e51b815260206004820152601860248201527f426c6f636b3a206d756c7469736967206d69736d61746368000000000000000060448201526064016106c1565b6000815160201461293e5760405162461bcd60e51b815260206004820152601760248201527f6279746573206c656e677468206973206e6f742033322e00000000000000000060448201526064016106c1565b506020015190565b60606000806129558585613654565b865190955090915061296782866145f3565b1115801561297d575061297a81856145f3565b84105b6129d55760405162461bcd60e51b8152602060048201526024808201527f4e65787456617242797465732c206f66667365742065786365656473206d6178604482015263696d756d60e01b60648201526084016106c1565b6060811580156129f057604051915060208201604052612a3a565b6040519150601f8316801560200281840101848101888315602002848c0101015b81831015612a29578051835260209283019201612a11565b5050848452601f01601f1916604052505b5080612a4683876145f3565b9350935050505b9250929050565b60006002600083604051602001612a6c929190614af7565b60408051601f1981840301815290829052612a8691614b26565b602060405180830381855afa158015612aa3573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105ad9190614925565b6000808351836001612ad891906145f3565b11158015612aef5750612aec8360016145f3565b83105b612b455760405162461bcd60e51b815260206004820152602160248201527f4e65787455696e74382c204f66667365742065786365656473206d6178696d756044820152606d60f81b60648201526084016106c1565b6000604051846020870101518060001a82535060018101604052601f81035191505080846001612b7591906145f3565b92509250509250929050565b6000808351836020612b9391906145f3565b11158015612baa5750612ba78360206145f3565b83105b612bf65760405162461bcd60e51b815260206004820181905260248201527f4e657874486173682c206f66667365742065786365656473206d6178696d756d60448201526064016106c1565b600060208401850151905080846020612b7591906145f3565b604051600160f81b6020820152602181018390526041810182905260009060029060610160408051601f1981840301815290829052612c4d91614b26565b602060405180830381855afa158015612c6a573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610bbd9190614925565b6000808351836008612c9f91906145f3565b11158015612cb65750612cb38360086145f3565b83105b612d0d5760405162461bcd60e51b815260206004820152602260248201527f4e65787455696e7436342c206f66667365742065786365656473206d6178696d604482015261756d60f01b60648201526084016106c1565b600060405160086000600182038760208a0101515b83831015612d425780821a83860153600183019250600182039150612d22565b505050016040819052601f190151905080612b758560086145f3565b6000808351836014612d7091906145f3565b11158015612d875750612d848360146145f3565b83105b612ddf5760405162461bcd60e51b815260206004820152602360248201527f4e657874416464726573732c206f66667365742065786365656473206d6178696044820152626d756d60e81b60648201526084016106c1565b83830160200151606081901c612b758560146145f3565b606082471015612e575760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016106c1565b600080866001600160a01b03168587604051612e739190614b26565b60006040518083038185875af1925050503d8060008114612eb0576040519150601f19603f3d011682016040523d82523d6000602084013e612eb5565b606091505b5091509150612ec6878383876137ab565b979650505050505050565b6000808351836004612ee391906145f3565b11158015612efa5750612ef78360046145f3565b83105b612f515760405162461bcd60e51b815260206004820152602260248201527f4e65787455696e7433322c206f66667365742065786365656473206d6178696d604482015261756d60f01b60648201526084016106c1565b600060405160046000600182038760208a0101515b83831015612f865780821a83860153600183019250600182039150612f66565b505050016040819052601f190151905080612b758560046145f3565b612faa61419b565b6020828101516040840151606085015160809095015184519290925283518301528282018051949094529251019190915290565b604080518082019091526000808252602082015260006002836040516130049190614b26565b602060405180830381855afa158015613021573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906130449190614925565b90506000613060600080516020614f11833981519152836146b2565b905060005b61306e82613824565b9050801561308f576040805180820190915291825260208201529392505050565b61309a6001836145f3565b9150613065565b60408051808201909152600080825260208201526130bd6141c0565b835181526020808501518183015283516040808401919091529084015160608301526000908360808460066107d05a03fa9050806131365760405162461bcd60e51b8152602060048201526016602482015275109b1cce88185919081c1bda5b9d1cc819985a5b195960521b60448201526064016106c1565b505092915050565b60606105ad6001600160a01b03831660145b6060600061315f836002614ae0565b61316a9060026145f3565b6001600160401b0381111561318157613181614686565b6040519080825280601f01601f1916602001820160405280156131ab576020820181803683370190505b509050600360fc1b816000815181106131c6576131c66146c6565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106131f5576131f56146c6565b60200101906001600160f81b031916908160001a9053506000613219846002614ae0565b6132249060016145f3565b90505b600181111561329c576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110613258576132586146c6565b1a60f81b82828151811061326e5761326e6146c6565b60200101906001600160f81b031916908160001a90535060049490941c9361329581614b38565b9050613227565b508315610bbd5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016106c1565b600081815260018301602052604081205480156133d457600061330f6001836149f9565b8554909150600090613323906001906149f9565b9050818114613388576000866000018281548110613343576133436146c6565b9060005260206000200154905080876000018481548110613366576133666146c6565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061339957613399614b4f565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105ad565b60009150506105ad565b60005b8115613408576133f26001836149f9565b9091169080613400816146dc565b9150506133e1565b919050565b60208086015186518051908301516040516000948593600193859361343493859101614a43565b60405160208183030381529060405290505b896040015160ff168310156134965781861660000361347d578260a082015261347a846124cc61347584612fde565b613860565b93505b60019190911b908261348e816146dc565b935050613446565b60408051600380825260808201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816134ae5750506040805160038082526080820190925291925060009190602082015b6134f861419b565b8152602001906001900390816134f0575050604080518082018252600080825260208083019182528d0151928d01519282529190915290915061353a90613860565b8260008151811061354d5761354d6146c6565b6020908102919091018101919091528c5180519082015160405161358d936135799392918f9101614b65565b604051602081830303815290604052612fde565b826001815181106135a0576135a06146c6565b602002602001018190525085826002815181106135bf576135bf6146c6565b60200260200101819052506135d26138ee565b816000815181106135e5576135e56146c6565b60200260200101819052506135f98b612fa2565b8160018151811061360c5761360c6146c6565b60200260200101819052508b600001518160028151811061362f5761362f6146c6565b602002602001018190525061364482826139ae565b9c9b505050505050505050505050565b60008060006136638585612ac6565b94509050600060ff821660fd036136f15761367e8686613d0b565b955061ffff16905060fd8110801590613699575061ffff8111155b6136e55760405162461bcd60e51b815260206004820152601f60248201527f4e65787455696e7431362c2076616c7565206f7574736964652072616e67650060448201526064016106c1565b9250839150612a4d9050565b8160ff1660fe03613741576137068686612ed1565b955063ffffffff16905061ffff81118015613725575063ffffffff8111155b6136e55760405162461bcd60e51b81526004016106c190614ba0565b8160ff1660ff03613786576137568686612c8d565b95506001600160401b0316905063ffffffff81116136e55760405162461bcd60e51b81526004016106c190614ba0565b5060ff811660fd81106136e55760405162461bcd60e51b81526004016106c190614ba0565b6060831561381a578251600003613813576001600160a01b0385163b6138135760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106c1565b50816123f7565b6123f78383613dc4565b60006105ad600080516020614f118339815191528061384585600383613dee565b6138509060036145f3565b61385a91906146b2565b90613e39565b604080518082019091526000808252602082015261387d8261401c565b1561389b575050604080518082019091526000808252602082015290565b604051806040016040528083600001518152602001600080516020614f1183398151915284602001516138ce91906146b2565b6138e690600080516020614f118339815191526149f9565b905292915050565b6138f661419b565b50604080516080810182527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c28183019081527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6060830152815281518083019092527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b82527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60208381019190915281019190915290565b60008151835114613a015760405162461bcd60e51b815260206004820152601960248201527f426c733a20706f696e7420636f756e74206d69736d617463680000000000000060448201526064016106c1565b82516000613a10826006614ae0565b90506000816001600160401b03811115613a2c57613a2c614686565b604051908082528060200260200182016040528015613a55578160200160208202803683370190505b50905060005b83811015613c9057868181518110613a7557613a756146c6565b60200260200101516000015182826006613a8f9190614ae0565b613a9a9060006145f3565b81518110613aaa57613aaa6146c6565b602002602001018181525050868181518110613ac857613ac86146c6565b60200260200101516020015182826006613ae29190614ae0565b613aed9060016145f3565b81518110613afd57613afd6146c6565b602002602001018181525050858181518110613b1b57613b1b6146c6565b6020908102919091010151515182613b34836006614ae0565b613b3f9060026145f3565b81518110613b4f57613b4f6146c6565b602002602001018181525050858181518110613b6d57613b6d6146c6565b60209081029190910181015151015182613b88836006614ae0565b613b939060036145f3565b81518110613ba357613ba36146c6565b602002602001018181525050858181518110613bc157613bc16146c6565b602002602001015160200151600060028110613bdf57613bdf6146c6565b602002015182613bf0836006614ae0565b613bfb9060046145f3565b81518110613c0b57613c0b6146c6565b602002602001018181525050858181518110613c2957613c296146c6565b602002602001015160200151600160028110613c4757613c476146c6565b602002015182613c58836006614ae0565b613c639060056145f3565b81518110613c7357613c736146c6565b602090810291909101015280613c88816146dc565b915050613a5b565b50613c996141de565b6000602082602086026020860160086107d05a03fa905080613cfd5760405162461bcd60e51b815260206004820152601d60248201527f426c733a2070616972696e67206f7065726174696f6e206661696c656400000060448201526064016106c1565b505115159695505050505050565b6000808351836002613d1d91906145f3565b11158015613d345750613d318360026145f3565b83105b613d8b5760405162461bcd60e51b815260206004820152602260248201527f4e65787455696e7431362c206f66667365742065786365656473206d6178696d604482015261756d60f01b60648201526084016106c1565b6000604051846020870101518060011a82538060001a60018301535060028101604052601e81035191505080846002612b7591906145f3565b815115613dd45781518083602001fd5b8060405162461bcd60e51b81526004016106c1919061437b565b60006040516020810160208152602080820152602060408201528560608201528460808201528360a082015260208260c0836005600019fa613e2f57600080fd5b5051949350505050565b6000613e458383614032565b600114613e54575060006105ad565b82600003613e64575060006105ad565b613e6f6004836146b2565b600303613e9e57613e97836004613e878560016145f3565b613e919190614a0c565b84613dee565b90506105ad565b6000613eab6001846149f9565b905060005b613ebb6002836146b2565b600003613ee157613ecd600283614a0c565b9150613eda8160016145f3565b9050613eb0565b60025b613eee8186614032565b60001914613f0857613f018160016145f3565b9050613ee4565b6000613f2b876002613f1b8760016145f3565b613f259190614a0c565b88613dee565b90506000613f3a888689613dee565b90506000613f4984878a613dee565b905084600080845b5060009050845b83821015613f885760018114613f8857613f748160028e613dee565b905081613f80816146dc565b925050613f58565b81600003613fa257869a50505050505050505050506105ad565b613fcd856001613fb285886149f9565b613fbc91906149f9565b613fc7906002614cb9565b8e613dee565b92508b613fda8480614ae0565b613fe491906146b2565b94508b613ff18489614ae0565b613ffb91906146b2565b96508b6140088688614ae0565b61401291906146b2565b9550819350613f51565b80516000901580156105ad575050602001511590565b6000806140568460026140466001876149f9565b6140509190614a0c565b85613dee565b90508015806140655750806001145b156140715790506105ad565b61407c6001846149f9565b810361408d576000199150506105ad565b60405162461bcd60e51b815260206004820152601d60248201527f4661696c656420746f2063616c63756c617465206c6567656e6472652e00000060448201526064016106c1565b8260028101928215614100579182015b828111156141005782548255916001019190600101906140e5565b5061410c9291506141fc565b5090565b6040518060a0016040528061412361419b565b8152602001614145604051806040016040528060008152602001600081525090565b81526000602082018190526040820181905260609091015290565b8260028101928215614100579160200282015b82811115614100578251825591602001919060010190614173565b61024b80614cc683390190565b60405180604001604052806141ae614211565b81526020016141bb614211565b905290565b60405180608001604052806004906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b5b8082111561410c57600081556001016141fd565b60405180604001604052806002906020820280368337509192915050565b60006020828403121561424157600080fd5b81356001600160e01b031981168114610bbd57600080fd5b60005b8381101561427457818101518382015260200161425c565b50506000910152565b60008151808452614295816020860160208601614259565b601f01601f19169290920160200192915050565b6060815260006142bc606083018661427d565b905060ff8416602083015263ffffffff83166040830152949350505050565b6000602082840312156142ed57600080fd5b5035919050565b80356001600160a01b038116811461340857600080fd5b6000806040838503121561431e57600080fd5b8235915061432e602084016142f4565b90509250929050565b60006020828403121561434957600080fd5b81356001600160401b0381168114610bbd57600080fd5b60006020828403121561437257600080fd5b610bbd826142f4565b602081526000610bbd602083018461427d565b6000602082840312156143a057600080fd5b813560038110610bbd57600080fd5b600080604083850312156143c257600080fd5b50508035926020909101359150565b634e487b7160e01b600052602160045260246000fd5b602081016003831061440957634e487b7160e01b600052602160045260246000fd5b91905290565b60006020828403121561442157600080fd5b81356001600160401b0381111561443757600080fd5b820160a08185031215610bbd57600080fd5b6000806020838503121561445c57600080fd5b82356001600160401b038082111561447357600080fd5b818501915085601f83011261448757600080fd5b81358181111561449657600080fd5b8660208260051b85010111156144ab57600080fd5b60209290920196919550909350505050565b6000806000606084860312156144d257600080fd5b83356001600160401b038111156144e857600080fd5b8401608081870312156144fa57600080fd5b9250614508602085016142f4565b9150604084013590509250925092565b8060005b600281101561453b57815484526020909301926001918201910161451c565b50505050565b6080810161454f8284614518565b6105ad6040830160028501614518565b634e487b7160e01b600052601160045260246000fd5b6001600160401b0382811682821603908082111561163c5761163c61455f565b60208082526021908201527f476f764272696467653a2077726f6e672070726f746f636f6c2076657273696f6040820152603760f91b606082015260800190565b63ffffffff81811683821601908082111561163c5761163c61455f565b808201808211156105ad576105ad61455f565b600181811c9082168061461a57607f821691505b60208210810361463a57634e487b7160e01b600052602260045260246000fd5b50919050565b6000808335601e1984360301811261465757600080fd5b8301803591506001600160401b0382111561467157600080fd5b602001915036819003821315612a4d57600080fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6000826146c1576146c161469c565b500690565b634e487b7160e01b600052603260045260246000fd5b6000600182016146ee576146ee61455f565b5060010190565b600060c08201888352602060c08185015281895180845260e086019150828b01935060005b818110156147365784518352938301939183019160010161471a565b50508481036040860152885180825290820192508189019060005b8181101561476d57825185529383019391830191600101614751565b5050505060ff9590951660608301525063ffffffff9290921660808301526001600160401b031660a0909101529392505050565b60008235609e198336030181126147b757600080fd5b9190910192915050565b602080825260159082015274109c9a5919d94e88195c1bd8da081b9bdd081cd95d605a1b604082015260600190565b60006020828403121561480257600080fd5b81518015158114610bbd57600080fd5b600082601f83011261482357600080fd5b81516001600160401b038082111561483d5761483d614686565b604051601f8301601f19908116603f0116810190828211818310171561486557614865614686565b8160405283815286602085880101111561487e57600080fd5b61488f846020830160208901614259565b9695505050505050565b600080604083850312156148ac57600080fd5b82516001600160401b03808211156148c357600080fd5b6148cf86838701614812565b935060208501519150808211156148e557600080fd5b506148f285828601614812565b9150509250929050565b8281526040602082015260006123f7604083018461427d565b8183823760009101908152919050565b60006020828403121561493757600080fd5b5051919050565b85815260806020820152836080820152838560a0830137600060a08583018101919091526001600160a01b039390931660408201526001600160401b03919091166060820152601f909201601f19169091010192915050565b6060815260006149aa606083018661427d565b905063ffffffff841660208301526001600160401b0383166040830152949350505050565b600080858511156149df57600080fd5b838611156149ec57600080fd5b5050820193919092039150565b818103818111156105ad576105ad61455f565b600082614a1b57614a1b61469c565b500490565b8060005b600281101561453b578151845260209384019390910190600101614a24565b614a4d8185614a20565b614a5a6040820184614a20565b608081019190915260a00192915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351614aa3816017850160208801614259565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351614ad4816028840160208801614259565b01602801949350505050565b80820281158282048414176105ad576105ad61455f565b60ff60f81b8360f81b16815260008251614b18816001850160208701614259565b919091016001019392505050565b600082516147b7818460208701614259565b600081614b4757614b4761455f565b506000190190565b634e487b7160e01b600052603160045260246000fd5b614b6f8185614a20565b614b7c6040820184614a20565b60008251614b91816080850160208701614259565b91909101608001949350505050565b6020808252818101527f4e65787456617255696e742c2076616c7565206f7574736964652072616e6765604082015260600190565b600181815b80851115614c10578160001904821115614bf657614bf661455f565b80851615614c0357918102915b93841c9390800290614bda565b509250929050565b600082614c27575060016105ad565b81614c34575060006105ad565b8160018114614c4a5760028114614c5457614c70565b60019150506105ad565b60ff841115614c6557614c6561455f565b50506001821b6105ad565b5060208310610133831016604e8410600b8410161715614c93575081810a6105ad565b614c9d8383614bd5565b8060001904821115614cb157614cb161455f565b029392505050565b6000610bbd8383614c1856fe608060405234801561001057600080fd5b50600180546001600160a01b03191633179055610219806100326000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063399e079214610051578063401a24911461007957806383197ef01461009c5780638da5cb5b146100a6575b600080fd5b61006461005f366004610181565b6100d1565b60405190151581526020015b60405180910390f35b610064610087366004610181565b60006020819052908152604090205460ff1681565b6100a4610149565b005b6001546100b9906001600160a01b031681565b6040516001600160a01b039091168152602001610070565b6001546000906001600160a01b031633146101075760405162461bcd60e51b81526004016100fe9061019a565b60405180910390fd5b60008281526020819052604081205460ff161515900361014157506000908152602081905260409020805460ff1916600190811790915590565b506000919050565b6001546001600160a01b031633146101735760405162461bcd60e51b81526004016100fe9061019a565b6001546001600160a01b0316ff5b60006020828403121561019357600080fd5b5035919050565b60208082526029908201527f526571756573744964436865636b65723a2063616c6c6572206973206e6f74206040820152683a34329037bbb732b960b91b60608201526080019056fea26469706673582212207f843daf6499596d0364145e8cd0674e0f1e96fcd3a60e9a9da78a5620f6a3b364736f6c6343000811003330644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4797667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b929a264697066735822122030b7ab678b94e851bfc7a3284b3a11ec3ea745a77834420007442f6422b9b15b64736f6c63430008110033608060405234801561001057600080fd5b50600180546001600160a01b03191633179055610219806100326000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063399e079214610051578063401a24911461007957806383197ef01461009c5780638da5cb5b146100a6575b600080fd5b61006461005f366004610181565b6100d1565b60405190151581526020015b60405180910390f35b610064610087366004610181565b60006020819052908152604090205460ff1681565b6100a4610149565b005b6001546100b9906001600160a01b031681565b6040516001600160a01b039091168152602001610070565b6001546000906001600160a01b031633146101075760405162461bcd60e51b81526004016100fe9061019a565b60405180910390fd5b60008281526020819052604081205460ff161515900361014157506000908152602081905260409020805460ff1916600190811790915590565b506000919050565b6001546001600160a01b031633146101735760405162461bcd60e51b81526004016100fe9061019a565b6001546001600160a01b0316ff5b60006020828403121561019357600080fd5b5035919050565b60208082526029908201527f526571756573744964436865636b65723a2063616c6c6572206973206e6f74206040820152683a34329037bbb732b960b91b60608201526080019056fea26469706673582212207f843daf6499596d0364145e8cd0674e0f1e96fcd3a60e9a9da78a5620f6a3b364736f6c63430008110033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061023d5760003560e01c8063764ebf2a1161013b578063c5a37036116100b8578063d9b5c4a51161007c578063d9b5c4a514610531578063e1164b7214610544578063e586447f14610557578063f5b541a61461056a578063f60ca6411461057f57600080fd5b8063c5a37036146104be578063ca15c873146104d1578063d547741f146104e4578063d6fd3175146104f7578063d79de39e1461051e57600080fd5b8063a217fddf116100ff578063a217fddf1461045a578063b97dd9e214610462578063c19d93fb1461046a578063c29bf43514610484578063c49baebe1461049757600080fd5b8063764ebf2a146103f85780637ecebe001461040b5780639010d07c1461042b57806391d148541461043e5780639a80fc661461045157600080fd5b80632f2ff15d116101c9578063486a54f31161018d578063486a54f3146103a257806354fd4d50146103aa57806356de96db146103bf5780635f1a6f05146103d257806362099362146103e557600080fd5b80632f2ff15d146103475780632ff1a5291461035a57806331eab48a1461036d57806336568abe146103755780633e7e25c11461038857600080fd5b8063248a9ca311610210578063248a9ca3146102c157806326339a21146102e45780632ae9c600146102ed5780632ea94006146103185780632f1874401461032d57600080fd5b806301ffc9a714610242578063056768bf1461026a5780630e03e490146102815780631bc2359a146102aa575b600080fd5b61025561025036600461422f565b610588565b60405190151581526020015b60405180910390f35b6102726105b3565b604051610261939291906142a9565b61029261028f3660046142db565b90565b6040516001600160a01b039091168152602001610261565b6102b3601a5481565b604051908152602001610261565b6102b36102cf3660046142db565b60009081526020819052604090206001015490565b6102b3601b5481565b601854610300906001600160401b031681565b6040516001600160401b039091168152602001610261565b61032b6103263660046142db565b6105fa565b005b60185461030090600160401b90046001600160401b031681565b61032b61035536600461430b565b610642565b61032b610368366004614337565b61066c565b61032b610737565b61032b61038336600461430b565b6108b4565b6102b3610396366004614360565b6001600160a01b031690565b61032b610932565b6103b2610a64565b604051610261919061437b565b61032b6103cd36600461438e565b610af2565b61032b6103e03660046142db565b610b65565b600754610292906001600160a01b031681565b600654610292906001600160a01b031681565b6102b3610419366004614360565b60056020526000908152604090205481565b6102926104393660046143af565b610ba5565b61025561044c36600461430b565b610bc4565b6102b3601c5481565b6102b3600081565b610272610bed565b6004546104779060ff1681565b60405161026191906143e7565b61032b61049236600461440f565b610c34565b6102b37f21702c8af46127c7fa207f89d0b0a8441bb32959a0ac7df790e9ab1a25c9892681565b6102556104cc366004614449565b610f13565b6102b36104df3660046142db565b611643565b61032b6104f236600461430b565b61165a565b6102b37f3c63e605be3290ab6b04cfc46c6e1516e626d43236b034f09d7ede1d017beb0c81565b61032b61052c36600461440f565b61167f565b601d54610292906001600160a01b031681565b61032b610552366004614360565b6118ee565b6102556105653660046144bd565b61199d565b6102b3600080516020614f3183398151915281565b6102b360195481565b60006001600160e01b03198216635a05180f60e01b14806105ad57506105ad82611cee565b92915050565b606060008060106000016040516020016105cd9190614541565b60408051808303601f19018152919052601654909460ff8216945061010090910463ffffffff1692509050565b600061060581611d23565b601a8290556040518281527f8906f1615411c1be37bc832caf2d17b0903ad4624b9680d92fb9799b444f9aa2906020015b60405180910390a15050565b60008281526020819052604090206001015461065d81611d23565b6106678383611d2d565b505050565b600080516020614f3183398151915261068481611d23565b6018546001600160401b031661069b600184614575565b6001600160401b0316146106ca5760405162461bcd60e51b81526004016106c190614595565b60405180910390fd5b601880546fffffffffffffffff00000000000000001916600160401b6001600160401b038581168281029390931793849055604080519384529190930490921660208201527f6daa220d3e9550bfb5df36368059f0ad2708facf48ccc8248a632dc4ad81d13c9101610636565b600080516020614f3183398151915261074f81611d23565b6040805161012081019091526108209060088160a08101828160e084018260028282826020028201915b81548152602001906001019080831161077957505050918352505060408051808201918290526020909201919060028481019182845b8154815260200190600101908083116107af57505050919092525050508152604080518082018252600484015481526005840154602080830191909152830152600683015460ff811691830191909152610100900463ffffffff166060820152600790910154608090910152611d4f565b1561086c5761082d611d6a565b60165461084690610100900463ffffffff1660016145d6565b600e805463ffffffff929092166101000264ffffffff00199092169190911790556108a7565b600e5461088590610100900463ffffffff1660016145d6565b600e805463ffffffff929092166101000264ffffffff00199092169190911790555b6108b16000611f43565b50565b6001600160a01b03811633146109245760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084016106c1565b61092e828261203e565b5050565b601b5442116109925760405162461bcd60e51b815260206004820152602660248201527f476f764272696467653a206e6f7420656e6f7567682074696d6520616674657260448201526520726574727960d01b60648201526084016106c1565b601a546019546109a291906145f3565b42116109ff5760405162461bcd60e51b815260206004820152602660248201527f476f764272696467653a206e6f7420656e6f7567682074696d65206166746572604482015265040cae0dec6d60d31b60648201526084016106c1565b601c54610a0c90426145f3565b601b55600e546018546040805161010090930463ffffffff1683526001600160401b0390911660208301527ffcd60c668a304ac5a7450e369d6196673b3637ecf20947a69afa95ae9359b290910160405180910390a1565b60038054610a7190614606565b80601f0160208091040260200160405190810160405280929190818152602001828054610a9d90614606565b8015610aea5780601f10610abf57610100808354040283529160200191610aea565b820191906000526020600020905b815481529060010190602001808311610acd57829003601f168201915b505050505081565b600080516020614f31833981519152610b0a81611d23565b6004805483919060ff19166001836002811115610b2957610b296143d1565b02179055506004546040517fc635bb75c392e81c891d50372a48cfa81b6799ac6d594cb4c28a8c5e8bef6e9b916106369160ff909116906143e7565b6000610b7081611d23565b601c8290556040518281527f85b47f19cf7d13a9f8bfebfa580d1b080f93326645845e92716924630a0be77190602001610636565b6000828152600160205260408120610bbd9083612060565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60606000806008600001604051602001610c079190614541565b60408051808303601f19018152919052600e54909460ff8216945061010090910463ffffffff1692509050565b610c3f60088261206c565b6000610c9f610c516020840184614640565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610c9a9250610c95915086905080614640565b612165565b6121b2565b6020808201516000818152601e9092526040909120549192509060ff1615610d155760405162461bcd60e51b8152602060048201526024808201527f476f764272696467655632506f533a2072616974696e677320616c7265616479604482015263081cd95d60e21b60648201526084016106c1565b6000818152601e60209081526040808320805460ff1916600117905580516018808252610320820190925290929183908201610300803683370190505090506000826001600160401b03811115610d6e57610d6e614686565b604051908082528060200260200182016040528015610d97578160200160208202803683370190505b509050600160005b84811015610ea65760408051602081018390526bffffffffffffffffffffffff193360601b16918101919091524360548201526801156abf16a40f0000906074016040516020818303038152906040528051906020012060001c610e0391906146b2565b60001b848281518110610e1857610e186146c6565b602090810291909101810191909152604080519182018390526bffffffffffffffffffffffff193360601b1690820152436054820152600a906074016040516020818303038152906040528051906020012060001c610e7791906146b2565b838281518110610e8957610e896146c6565b602090810291909101015280610e9e816146dc565b915050610d9f565b50600e546018546040517fa5501772872d3fcfece437f2f86dec90ef4c286302154b737f6c2309e42b536092610f0292899288928892889261010090920463ffffffff1691600160401b9091046001600160401b0316906146f5565b60405180910390a150505050505050565b60007f21702c8af46127c7fa207f89d0b0a8441bb32959a0ac7df790e9ab1a25c98926610f3f81611d23565b610f476122eb565b600160045460ff166002811115610f6057610f606143d1565b03610fa65760405162461bcd60e51b81526020600482015260166024820152754272696467653a20737461746520696e61637469766560501b60448201526064016106c1565b60005b8381101561162d576000610fe9868684818110610fc857610fc86146c6565b9050602002810190610fda91906147a1565b610fe49080614640565b612342565b600f54909150810361111057604080516101208101918290526008805460e083019081526110c193839160a083019184918391839060029060096101008901808311610779575050509183525050604080518082019182905260028481018054835260209485019492939092600387019085018083116107af57505050919092525050508152604080518082018252600484015481526005840154602080830191909152830152600683015460ff811691830191909152610100900463ffffffff166060820152600790910154608090910152611d4f565b6110dd5760405162461bcd60e51b81526004016106c1906147c1565b61110b60088787858181106110f4576110f46146c6565b905060200281019061110691906147a1565b61206c565b611256565b601754810361121857604080516101208101918290526010805460e083019081526111e593839160a083019184918391839060029060116101008901808311610779575050509183525050604080518082019182905260028481018054835260209485019492939092600387019085018083116107af57505050919092525050508152604080518082018252600484015481526005840154602080830191909152830152600683015460ff811691830191909152610100900463ffffffff166060820152600790910154608090910152611d4f565b6112015760405162461bcd60e51b81526004016106c1906147c1565b61110b60108787858181106110f4576110f46146c6565b60405162461bcd60e51b8152602060048201526013602482015272084e4d2c8ceca7440eee4dedcce40cae0dec6d606b1b60448201526064016106c1565b60006112f587878581811061126d5761126d6146c6565b905060200281019061127f91906147a1565b61128d906020810190614640565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610c9a92508b91508a9050878181106112d9576112d96146c6565b90506020028101906112eb91906147a1565b610c959080614640565b905060008060008061130685612355565b935093509350935046816001600160401b03161461135f5760405162461bcd60e51b8152602060048201526016602482015275109c9a5919d94e881ddc9bdb99c818da185a5b881a5960521b60448201526064016106c1565b6001600160a01b0382163b6113c15760405162461bcd60e51b815260206004820152602260248201527f4272696467653a207265636569766572206973206e6f74206120636f6e74726160448201526118dd60f21b60648201526084016106c1565b600f54600090870361144357600654604051631ccf03c960e11b8152600481018790526001600160a01b039091169063399e0792906024016020604051808303816000875af1158015611418573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143c91906147f0565b90506114b5565b600754604051631ccf03c960e11b8152600481018790526001600160a01b039091169063399e0792906024016020604051808303816000875af115801561148e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b291906147f0565b90505b6060811561159357600080868060200190518101906114d49190614899565b909250905060006114ee6001600160a01b038816836123a4565b90508080602001905181019061150491906147f0565b6115475760405162461bcd60e51b8152602060048201526014602482015273109c9a5919d94e8818da1958dac819985a5b195960621b60448201526064016106c1565b604080518082019091526016815275109c9a5919d94e881c9958d95a5d994819985a5b195960521b602082015261158a906001600160a01b0389169085906123e8565b505050506115db565b60405162461bcd60e51b815260206004820152601f60248201527f4272696467653a207265717565737420696420616c7265616479207365656e0060448201526064016106c1565b7f4b5b2fd6aa26739a2dea52c41d52e1bfd74a3288c604a237c51bdfbdd3799006868260405161160c9291906148fc565b60405180910390a1505050505050505080611626906146dc565b9050610fa9565b506001915061163c6001600255565b5092915050565b60008181526001602052604081206105ad906123ff565b60008281526020819052604090206001015461167581611d23565b610667838361203e565b7f21702c8af46127c7fa207f89d0b0a8441bb32959a0ac7df790e9ab1a25c989266116a981611d23565b60006116ff6116bb6020850185614640565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610c9a9250610c95915087905080614640565b905060008060008061171085612409565b600e549397509195509350915063ffffffff80851691611738916101009091041660016145d6565b63ffffffff161461178b5760405162461bcd60e51b815260206004820152601a60248201527f4272696467653a2077726f6e672065706f6368206e756d62657200000000000060448201526064016106c1565b604080516101208101918290526008805460e0830190815261185793839160a083019184918391839060029060096101008901808311610779575050509183525050604080518082019182905260028481018054835260209485019492939092600387019085018083116107af57505050919092525050508152604080518082018252600484015481526005840154602080830191909152830152600683015460ff811691830191909152610100900463ffffffff166060820152600790910154608090910152611d4f565b1561186f5761186760088861206c565b61186f611d6a565b6000600261187d8980614640565b60405161188b929190614915565b602060405180830381855afa1580156118a8573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906118cb9190614925565b90506118db600884848785612454565b6118e485611f43565b5050505050505050565b60006118f981611d23565b6001600160a01b03821661194f5760405162461bcd60e51b815260206004820152601d60248201527f476f764272696467653a207a65726f206164647265737320676976656e00000060448201526064016106c1565b601d80546001600160a01b0319166001600160a01b0384169081179091556040519081527fef697ae2a61f63e7a8cb0d7e7a6c0a794c764a208b7d0360e47c241b14a0dbd990602001610636565b60007f3c63e605be3290ab6b04cfc46c6e1516e626d43236b034f09d7ede1d017beb0c6119c981611d23565b600060045460ff1660028111156119e2576119e26143d1565b14611a285760405162461bcd60e51b81526020600482015260166024820152754272696467653a20737461746520696e61637469766560501b60448201526064016106c1565b604080516101208101918290526010805460e08301908152611af493839160a083019184918391839060029060116101008901808311610779575050509183525050604080518082019182905260028481018054835260209485019492939092600387019085018083116107af57505050919092525050508152604080518082018252600484015481526005840154602080830191909152830152600683015460ff811691830191909152610100900463ffffffff166060820152600790910154608090910152611d4f565b80611bc65750604080516101208101918290526008805460e08301908152611bc693839160a083019184918391839060029060096101008901808311610779575050509183525050604080518082019182905260028481018054835260209485019492939092600387019085018083116107af57505050919092525050508152604080518082018252600484015481526005840154602080830191909152830152600683015460ff811691830191909152610100900463ffffffff166060820152600790910154608090910152611d4f565b611be25760405162461bcd60e51b81526004016106c1906147c1565b611bec848461255c565b7f5566d73d091d945ab32ea023cd1930c0d43aa43bef9aee4cb029775cfc94bdae8535611c1c6020880188614640565b611c2c60608a0160408b01614360565b8960600135604051611c4295949392919061493e565b60405180910390a1506001949350505050565b611c5f8282610bc4565b61092e576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055611c953390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000610bbd836001600160a01b0384166125ce565b60006001600160e01b03198216637965db0b60e01b14806105ad57506301ffc9a760e01b6001600160e01b03198316146105ad565b6108b1813361261d565b611d378282611c55565b60008281526001602052604090206106679082611cd9565b805151516000901515806105ad575050515160200151151590565b600860108181611d7c818360026140d5565b50611d8f600282810190848101906140d5565b505050600482810154908201556005808301549082015560068083018054918301805460ff19811660ff9094169384178255915463ffffffff61010091829004160264ffffffffff19909216909217179055600791820154910155611df2614110565b8051805182916008918290611e0a9082906002614160565b506020820151611e209060028084019190614160565b50505060208281015180516004808501919091559101516005830155604080840151600684018054606087015163ffffffff166101000264ffffffffff1990911660ff909316929092179190911790556080909301516007928301559054825163083197ef60e41b815292516001600160a01b03909116926383197ef0928181019260009290919082900301818387803b158015611ebd57600080fd5b505af1158015611ed1573d6000803e3d6000fd5b5050600654600780546001600160a01b0319166001600160a01b039092169190911790555050604051611f039061418e565b604051809103906000f080158015611f1f573d6000803e3d6000fd5b50600680546001600160a01b0319166001600160a01b039290921691909117905550565b6018546001600160401b0390811690821615611f7a576018805467ffffffffffffffff19166001600160401b038416179055611f9f565b60188054600160401b81046001600160401b031667ffffffffffffffff199091161790555b6018546001600160401b0380831691161015611fcd5760405162461bcd60e51b81526004016106c190614595565b426019556040517f7abd871edc50e0783b456da5e3441224a90207257b5a02f5b2410f905204e0c09061200590600890602001614541565b60408051808303601f1901815290829052600e546018546106369361010090920463ffffffff16916001600160401b0390911690614997565b6120488282612676565b600082815260016020526040902061066790826126db565b6000610bbd83836126f0565b60408051610120810190915261092e90838160a08101828160e084018260028282826020028201915b81548152602001906001019080831161209557505050918352505060408051808201918290526020909201919060028481019182845b8154815260200190600101908083116120cb57505050919092525050508152604080518082018252600484015481526005840154602080830191909152830152600683015460ff811691830191909152610100900463ffffffff1660608201526007909101546080909101526121418380614640565b61214e6040860186614640565b61215b6060880188614640565b886080013561271a565b6000610bbd6121786068604885876149cf565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506128eb92505050565b6060600060606121c28583612946565b9250905060006121d182612a54565b9050600060218488516121e491906149f9565b6121ee9190614a0c565b905060008060005b83811015612299576122088a88612ac6565b975091506122168a88612b81565b9750925060ff82166000036122365761222f8386612c0f565b9450612287565b8160ff1660010361224b5761222f8584612c0f565b60405162461bcd60e51b815260206004820152601160248201527013595c9adb194e881c1c9bdd9948195bd9607a1b60448201526064016106c1565b80612291816146dc565b9150506121f6565b508784146122de5760405162461bcd60e51b815260206004820152601260248201527113595c9adb194e881c1c9bdd99481c9bdbdd60721b60448201526064016106c1565b5092979650505050505050565b600280540361233c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106c1565b60028055565b6000610bbd6121786048602885876149cf565b6000606060008060006123688682612b81565b90955090506123778682612c8d565b90925090506123868682612d5e565b90935090506123958682612946565b50949694955091939092509050565b6060610bbd838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612df6565b60606123f78484600085612df6565b949350505050565b60006105ad825490565b6000806060818061241a8682612c8d565b90955090506124298682612ed1565b90945090506124388682612ac6565b90925090506124478682612946565b5094969395509092915050565b600061245f85612fa2565b9050600060405180604001604052806000815260200160008152509050600080836000015184602001518360405160200161249c93929190614a43565b60405160208183030381529060405290505b8660ff168210156124e5578160a08201526124d1836124cc83612fde565b6130a1565b9250816124dd816146dc565b9250506124ae565b835184908a906124f89082906002614160565b50602082015161250e9060028084019190614160565b5050835160048b01555050506020015160058701555060068501805463ffffffff9093166101000264ffffffffff1990931660ff909416939093179190911790915560079092019190915550565b6001600160a01b038216600090815260056020526040812080548392909190612584836146dc565b919050551461092e5760405162461bcd60e51b8152602060048201526016602482015275084e4d2c8ceca7440dcdedcc6ca40dad2e6dac2e8c6d60531b60448201526064016106c1565b6000818152600183016020526040812054612615575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105ad565b5060006105ad565b6126278282610bc4565b61092e576126348161313e565b61263f836020613150565b604051602001612650929190614a6b565b60408051601f198184030181529082905262461bcd60e51b82526106c19160040161437b565b6126808282610bc4565b1561092e576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610bbd836001600160a01b0384166132eb565b6000826000018281548110612707576127076146c6565b9060005260206000200154905092915050565b6003886040015160ff1660026127309190614ae0565b61273a9190614a0c565b612743826133de565b116127905760405162461bcd60e51b815260206004820152601e60248201527f426c6f636b3a206e6f7420656e6f756768207061727469636970616e7473000060448201526064016106c1565b876040015160ff1660ff14806127b05750876040015160ff166001901b81105b6127f55760405162461bcd60e51b8152602060048201526016602482015275426c6f636b3a206269746d61736b20746f6f2062696760501b60448201526064016106c1565b61289f8886868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8e018190048102820181019092528c815292508c91508b908190840183828082843760009201919091525050604080516020601f8b01819004810282018101909252898152925089915088908190840183828082843760009201919091525088925061340d915050565b6118e45760405162461bcd60e51b815260206004820152601860248201527f426c6f636b3a206d756c7469736967206d69736d61746368000000000000000060448201526064016106c1565b6000815160201461293e5760405162461bcd60e51b815260206004820152601760248201527f6279746573206c656e677468206973206e6f742033322e00000000000000000060448201526064016106c1565b506020015190565b60606000806129558585613654565b865190955090915061296782866145f3565b1115801561297d575061297a81856145f3565b84105b6129d55760405162461bcd60e51b8152602060048201526024808201527f4e65787456617242797465732c206f66667365742065786365656473206d6178604482015263696d756d60e01b60648201526084016106c1565b6060811580156129f057604051915060208201604052612a3a565b6040519150601f8316801560200281840101848101888315602002848c0101015b81831015612a29578051835260209283019201612a11565b5050848452601f01601f1916604052505b5080612a4683876145f3565b9350935050505b9250929050565b60006002600083604051602001612a6c929190614af7565b60408051601f1981840301815290829052612a8691614b26565b602060405180830381855afa158015612aa3573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105ad9190614925565b6000808351836001612ad891906145f3565b11158015612aef5750612aec8360016145f3565b83105b612b455760405162461bcd60e51b815260206004820152602160248201527f4e65787455696e74382c204f66667365742065786365656473206d6178696d756044820152606d60f81b60648201526084016106c1565b6000604051846020870101518060001a82535060018101604052601f81035191505080846001612b7591906145f3565b92509250509250929050565b6000808351836020612b9391906145f3565b11158015612baa5750612ba78360206145f3565b83105b612bf65760405162461bcd60e51b815260206004820181905260248201527f4e657874486173682c206f66667365742065786365656473206d6178696d756d60448201526064016106c1565b600060208401850151905080846020612b7591906145f3565b604051600160f81b6020820152602181018390526041810182905260009060029060610160408051601f1981840301815290829052612c4d91614b26565b602060405180830381855afa158015612c6a573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610bbd9190614925565b6000808351836008612c9f91906145f3565b11158015612cb65750612cb38360086145f3565b83105b612d0d5760405162461bcd60e51b815260206004820152602260248201527f4e65787455696e7436342c206f66667365742065786365656473206d6178696d604482015261756d60f01b60648201526084016106c1565b600060405160086000600182038760208a0101515b83831015612d425780821a83860153600183019250600182039150612d22565b505050016040819052601f190151905080612b758560086145f3565b6000808351836014612d7091906145f3565b11158015612d875750612d848360146145f3565b83105b612ddf5760405162461bcd60e51b815260206004820152602360248201527f4e657874416464726573732c206f66667365742065786365656473206d6178696044820152626d756d60e81b60648201526084016106c1565b83830160200151606081901c612b758560146145f3565b606082471015612e575760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016106c1565b600080866001600160a01b03168587604051612e739190614b26565b60006040518083038185875af1925050503d8060008114612eb0576040519150601f19603f3d011682016040523d82523d6000602084013e612eb5565b606091505b5091509150612ec6878383876137ab565b979650505050505050565b6000808351836004612ee391906145f3565b11158015612efa5750612ef78360046145f3565b83105b612f515760405162461bcd60e51b815260206004820152602260248201527f4e65787455696e7433322c206f66667365742065786365656473206d6178696d604482015261756d60f01b60648201526084016106c1565b600060405160046000600182038760208a0101515b83831015612f865780821a83860153600183019250600182039150612f66565b505050016040819052601f190151905080612b758560046145f3565b612faa61419b565b6020828101516040840151606085015160809095015184519290925283518301528282018051949094529251019190915290565b604080518082019091526000808252602082015260006002836040516130049190614b26565b602060405180830381855afa158015613021573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906130449190614925565b90506000613060600080516020614f11833981519152836146b2565b905060005b61306e82613824565b9050801561308f576040805180820190915291825260208201529392505050565b61309a6001836145f3565b9150613065565b60408051808201909152600080825260208201526130bd6141c0565b835181526020808501518183015283516040808401919091529084015160608301526000908360808460066107d05a03fa9050806131365760405162461bcd60e51b8152602060048201526016602482015275109b1cce88185919081c1bda5b9d1cc819985a5b195960521b60448201526064016106c1565b505092915050565b60606105ad6001600160a01b03831660145b6060600061315f836002614ae0565b61316a9060026145f3565b6001600160401b0381111561318157613181614686565b6040519080825280601f01601f1916602001820160405280156131ab576020820181803683370190505b509050600360fc1b816000815181106131c6576131c66146c6565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106131f5576131f56146c6565b60200101906001600160f81b031916908160001a9053506000613219846002614ae0565b6132249060016145f3565b90505b600181111561329c576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110613258576132586146c6565b1a60f81b82828151811061326e5761326e6146c6565b60200101906001600160f81b031916908160001a90535060049490941c9361329581614b38565b9050613227565b508315610bbd5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016106c1565b600081815260018301602052604081205480156133d457600061330f6001836149f9565b8554909150600090613323906001906149f9565b9050818114613388576000866000018281548110613343576133436146c6565b9060005260206000200154905080876000018481548110613366576133666146c6565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061339957613399614b4f565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105ad565b60009150506105ad565b60005b8115613408576133f26001836149f9565b9091169080613400816146dc565b9150506133e1565b919050565b60208086015186518051908301516040516000948593600193859361343493859101614a43565b60405160208183030381529060405290505b896040015160ff168310156134965781861660000361347d578260a082015261347a846124cc61347584612fde565b613860565b93505b60019190911b908261348e816146dc565b935050613446565b60408051600380825260808201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816134ae5750506040805160038082526080820190925291925060009190602082015b6134f861419b565b8152602001906001900390816134f0575050604080518082018252600080825260208083019182528d0151928d01519282529190915290915061353a90613860565b8260008151811061354d5761354d6146c6565b6020908102919091018101919091528c5180519082015160405161358d936135799392918f9101614b65565b604051602081830303815290604052612fde565b826001815181106135a0576135a06146c6565b602002602001018190525085826002815181106135bf576135bf6146c6565b60200260200101819052506135d26138ee565b816000815181106135e5576135e56146c6565b60200260200101819052506135f98b612fa2565b8160018151811061360c5761360c6146c6565b60200260200101819052508b600001518160028151811061362f5761362f6146c6565b602002602001018190525061364482826139ae565b9c9b505050505050505050505050565b60008060006136638585612ac6565b94509050600060ff821660fd036136f15761367e8686613d0b565b955061ffff16905060fd8110801590613699575061ffff8111155b6136e55760405162461bcd60e51b815260206004820152601f60248201527f4e65787455696e7431362c2076616c7565206f7574736964652072616e67650060448201526064016106c1565b9250839150612a4d9050565b8160ff1660fe03613741576137068686612ed1565b955063ffffffff16905061ffff81118015613725575063ffffffff8111155b6136e55760405162461bcd60e51b81526004016106c190614ba0565b8160ff1660ff03613786576137568686612c8d565b95506001600160401b0316905063ffffffff81116136e55760405162461bcd60e51b81526004016106c190614ba0565b5060ff811660fd81106136e55760405162461bcd60e51b81526004016106c190614ba0565b6060831561381a578251600003613813576001600160a01b0385163b6138135760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106c1565b50816123f7565b6123f78383613dc4565b60006105ad600080516020614f118339815191528061384585600383613dee565b6138509060036145f3565b61385a91906146b2565b90613e39565b604080518082019091526000808252602082015261387d8261401c565b1561389b575050604080518082019091526000808252602082015290565b604051806040016040528083600001518152602001600080516020614f1183398151915284602001516138ce91906146b2565b6138e690600080516020614f118339815191526149f9565b905292915050565b6138f661419b565b50604080516080810182527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c28183019081527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6060830152815281518083019092527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b82527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60208381019190915281019190915290565b60008151835114613a015760405162461bcd60e51b815260206004820152601960248201527f426c733a20706f696e7420636f756e74206d69736d617463680000000000000060448201526064016106c1565b82516000613a10826006614ae0565b90506000816001600160401b03811115613a2c57613a2c614686565b604051908082528060200260200182016040528015613a55578160200160208202803683370190505b50905060005b83811015613c9057868181518110613a7557613a756146c6565b60200260200101516000015182826006613a8f9190614ae0565b613a9a9060006145f3565b81518110613aaa57613aaa6146c6565b602002602001018181525050868181518110613ac857613ac86146c6565b60200260200101516020015182826006613ae29190614ae0565b613aed9060016145f3565b81518110613afd57613afd6146c6565b602002602001018181525050858181518110613b1b57613b1b6146c6565b6020908102919091010151515182613b34836006614ae0565b613b3f9060026145f3565b81518110613b4f57613b4f6146c6565b602002602001018181525050858181518110613b6d57613b6d6146c6565b60209081029190910181015151015182613b88836006614ae0565b613b939060036145f3565b81518110613ba357613ba36146c6565b602002602001018181525050858181518110613bc157613bc16146c6565b602002602001015160200151600060028110613bdf57613bdf6146c6565b602002015182613bf0836006614ae0565b613bfb9060046145f3565b81518110613c0b57613c0b6146c6565b602002602001018181525050858181518110613c2957613c296146c6565b602002602001015160200151600160028110613c4757613c476146c6565b602002015182613c58836006614ae0565b613c639060056145f3565b81518110613c7357613c736146c6565b602090810291909101015280613c88816146dc565b915050613a5b565b50613c996141de565b6000602082602086026020860160086107d05a03fa905080613cfd5760405162461bcd60e51b815260206004820152601d60248201527f426c733a2070616972696e67206f7065726174696f6e206661696c656400000060448201526064016106c1565b505115159695505050505050565b6000808351836002613d1d91906145f3565b11158015613d345750613d318360026145f3565b83105b613d8b5760405162461bcd60e51b815260206004820152602260248201527f4e65787455696e7431362c206f66667365742065786365656473206d6178696d604482015261756d60f01b60648201526084016106c1565b6000604051846020870101518060011a82538060001a60018301535060028101604052601e81035191505080846002612b7591906145f3565b815115613dd45781518083602001fd5b8060405162461bcd60e51b81526004016106c1919061437b565b60006040516020810160208152602080820152602060408201528560608201528460808201528360a082015260208260c0836005600019fa613e2f57600080fd5b5051949350505050565b6000613e458383614032565b600114613e54575060006105ad565b82600003613e64575060006105ad565b613e6f6004836146b2565b600303613e9e57613e97836004613e878560016145f3565b613e919190614a0c565b84613dee565b90506105ad565b6000613eab6001846149f9565b905060005b613ebb6002836146b2565b600003613ee157613ecd600283614a0c565b9150613eda8160016145f3565b9050613eb0565b60025b613eee8186614032565b60001914613f0857613f018160016145f3565b9050613ee4565b6000613f2b876002613f1b8760016145f3565b613f259190614a0c565b88613dee565b90506000613f3a888689613dee565b90506000613f4984878a613dee565b905084600080845b5060009050845b83821015613f885760018114613f8857613f748160028e613dee565b905081613f80816146dc565b925050613f58565b81600003613fa257869a50505050505050505050506105ad565b613fcd856001613fb285886149f9565b613fbc91906149f9565b613fc7906002614cb9565b8e613dee565b92508b613fda8480614ae0565b613fe491906146b2565b94508b613ff18489614ae0565b613ffb91906146b2565b96508b6140088688614ae0565b61401291906146b2565b9550819350613f51565b80516000901580156105ad575050602001511590565b6000806140568460026140466001876149f9565b6140509190614a0c565b85613dee565b90508015806140655750806001145b156140715790506105ad565b61407c6001846149f9565b810361408d576000199150506105ad565b60405162461bcd60e51b815260206004820152601d60248201527f4661696c656420746f2063616c63756c617465206c6567656e6472652e00000060448201526064016106c1565b8260028101928215614100579182015b828111156141005782548255916001019190600101906140e5565b5061410c9291506141fc565b5090565b6040518060a0016040528061412361419b565b8152602001614145604051806040016040528060008152602001600081525090565b81526000602082018190526040820181905260609091015290565b8260028101928215614100579160200282015b82811115614100578251825591602001919060010190614173565b61024b80614cc683390190565b60405180604001604052806141ae614211565b81526020016141bb614211565b905290565b60405180608001604052806004906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b5b8082111561410c57600081556001016141fd565b60405180604001604052806002906020820280368337509192915050565b60006020828403121561424157600080fd5b81356001600160e01b031981168114610bbd57600080fd5b60005b8381101561427457818101518382015260200161425c565b50506000910152565b60008151808452614295816020860160208601614259565b601f01601f19169290920160200192915050565b6060815260006142bc606083018661427d565b905060ff8416602083015263ffffffff83166040830152949350505050565b6000602082840312156142ed57600080fd5b5035919050565b80356001600160a01b038116811461340857600080fd5b6000806040838503121561431e57600080fd5b8235915061432e602084016142f4565b90509250929050565b60006020828403121561434957600080fd5b81356001600160401b0381168114610bbd57600080fd5b60006020828403121561437257600080fd5b610bbd826142f4565b602081526000610bbd602083018461427d565b6000602082840312156143a057600080fd5b813560038110610bbd57600080fd5b600080604083850312156143c257600080fd5b50508035926020909101359150565b634e487b7160e01b600052602160045260246000fd5b602081016003831061440957634e487b7160e01b600052602160045260246000fd5b91905290565b60006020828403121561442157600080fd5b81356001600160401b0381111561443757600080fd5b820160a08185031215610bbd57600080fd5b6000806020838503121561445c57600080fd5b82356001600160401b038082111561447357600080fd5b818501915085601f83011261448757600080fd5b81358181111561449657600080fd5b8660208260051b85010111156144ab57600080fd5b60209290920196919550909350505050565b6000806000606084860312156144d257600080fd5b83356001600160401b038111156144e857600080fd5b8401608081870312156144fa57600080fd5b9250614508602085016142f4565b9150604084013590509250925092565b8060005b600281101561453b57815484526020909301926001918201910161451c565b50505050565b6080810161454f8284614518565b6105ad6040830160028501614518565b634e487b7160e01b600052601160045260246000fd5b6001600160401b0382811682821603908082111561163c5761163c61455f565b60208082526021908201527f476f764272696467653a2077726f6e672070726f746f636f6c2076657273696f6040820152603760f91b606082015260800190565b63ffffffff81811683821601908082111561163c5761163c61455f565b808201808211156105ad576105ad61455f565b600181811c9082168061461a57607f821691505b60208210810361463a57634e487b7160e01b600052602260045260246000fd5b50919050565b6000808335601e1984360301811261465757600080fd5b8301803591506001600160401b0382111561467157600080fd5b602001915036819003821315612a4d57600080fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6000826146c1576146c161469c565b500690565b634e487b7160e01b600052603260045260246000fd5b6000600182016146ee576146ee61455f565b5060010190565b600060c08201888352602060c08185015281895180845260e086019150828b01935060005b818110156147365784518352938301939183019160010161471a565b50508481036040860152885180825290820192508189019060005b8181101561476d57825185529383019391830191600101614751565b5050505060ff9590951660608301525063ffffffff9290921660808301526001600160401b031660a0909101529392505050565b60008235609e198336030181126147b757600080fd5b9190910192915050565b602080825260159082015274109c9a5919d94e88195c1bd8da081b9bdd081cd95d605a1b604082015260600190565b60006020828403121561480257600080fd5b81518015158114610bbd57600080fd5b600082601f83011261482357600080fd5b81516001600160401b038082111561483d5761483d614686565b604051601f8301601f19908116603f0116810190828211818310171561486557614865614686565b8160405283815286602085880101111561487e57600080fd5b61488f846020830160208901614259565b9695505050505050565b600080604083850312156148ac57600080fd5b82516001600160401b03808211156148c357600080fd5b6148cf86838701614812565b935060208501519150808211156148e557600080fd5b506148f285828601614812565b9150509250929050565b8281526040602082015260006123f7604083018461427d565b8183823760009101908152919050565b60006020828403121561493757600080fd5b5051919050565b85815260806020820152836080820152838560a0830137600060a08583018101919091526001600160a01b039390931660408201526001600160401b03919091166060820152601f909201601f19169091010192915050565b6060815260006149aa606083018661427d565b905063ffffffff841660208301526001600160401b0383166040830152949350505050565b600080858511156149df57600080fd5b838611156149ec57600080fd5b5050820193919092039150565b818103818111156105ad576105ad61455f565b600082614a1b57614a1b61469c565b500490565b8060005b600281101561453b578151845260209384019390910190600101614a24565b614a4d8185614a20565b614a5a6040820184614a20565b608081019190915260a00192915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351614aa3816017850160208801614259565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351614ad4816028840160208801614259565b01602801949350505050565b80820281158282048414176105ad576105ad61455f565b60ff60f81b8360f81b16815260008251614b18816001850160208701614259565b919091016001019392505050565b600082516147b7818460208701614259565b600081614b4757614b4761455f565b506000190190565b634e487b7160e01b600052603160045260246000fd5b614b6f8185614a20565b614b7c6040820184614a20565b60008251614b91816080850160208701614259565b91909101608001949350505050565b6020808252818101527f4e65787456617255696e742c2076616c7565206f7574736964652072616e6765604082015260600190565b600181815b80851115614c10578160001904821115614bf657614bf661455f565b80851615614c0357918102915b93841c9390800290614bda565b509250929050565b600082614c27575060016105ad565b81614c34575060006105ad565b8160018114614c4a5760028114614c5457614c70565b60019150506105ad565b60ff841115614c6557614c6561455f565b50506001821b6105ad565b5060208310610133831016604e8410600b8410161715614c93575081810a6105ad565b614c9d8383614bd5565b8060001904821115614cb157614cb161455f565b029392505050565b6000610bbd8383614c1856fe608060405234801561001057600080fd5b50600180546001600160a01b03191633179055610219806100326000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063399e079214610051578063401a24911461007957806383197ef01461009c5780638da5cb5b146100a6575b600080fd5b61006461005f366004610181565b6100d1565b60405190151581526020015b60405180910390f35b610064610087366004610181565b60006020819052908152604090205460ff1681565b6100a4610149565b005b6001546100b9906001600160a01b031681565b6040516001600160a01b039091168152602001610070565b6001546000906001600160a01b031633146101075760405162461bcd60e51b81526004016100fe9061019a565b60405180910390fd5b60008281526020819052604081205460ff161515900361014157506000908152602081905260409020805460ff1916600190811790915590565b506000919050565b6001546001600160a01b031633146101735760405162461bcd60e51b81526004016100fe9061019a565b6001546001600160a01b0316ff5b60006020828403121561019357600080fd5b5035919050565b60208082526029908201527f526571756573744964436865636b65723a2063616c6c6572206973206e6f74206040820152683a34329037bbb732b960b91b60608201526080019056fea26469706673582212207f843daf6499596d0364145e8cd0674e0f1e96fcd3a60e9a9da78a5620f6a3b364736f6c6343000811003330644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4797667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b929a264697066735822122030b7ab678b94e851bfc7a3284b3a11ec3ea745a77834420007442f6422b9b15b64736f6c63430008110033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.