Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 424358655 | 32 hrs ago | 0.00111867 ETH | ||||
| 424358655 | 32 hrs ago | 0.00111867 ETH | ||||
| 424275574 | 37 hrs ago | 0.00161552 ETH | ||||
| 424275574 | 37 hrs ago | 0.00161552 ETH | ||||
| 424171889 | 45 hrs ago | 0.00118507 ETH | ||||
| 424171889 | 45 hrs ago | 0.00118507 ETH | ||||
| 424171884 | 45 hrs ago | 0.00118527 ETH | ||||
| 424171884 | 45 hrs ago | 0.00118527 ETH | ||||
| 424116320 | 2 days ago | 0.00167672 ETH | ||||
| 424116320 | 2 days ago | 0.00167672 ETH | ||||
| 423968212 | 2 days ago | 0.00109308 ETH | ||||
| 423968212 | 2 days ago | 0.00109308 ETH | ||||
| 423293155 | 4 days ago | 0.00151688 ETH | ||||
| 423293155 | 4 days ago | 0.00151688 ETH | ||||
| 418770320 | 17 days ago | 1 ETH | ||||
| 417804849 | 20 days ago | 0.00031838 ETH | ||||
| 417804849 | 20 days ago | 0.00031838 ETH | ||||
| 417461598 | 21 days ago | 0.00071037 ETH | ||||
| 417461598 | 21 days ago | 0.00071037 ETH | ||||
| 415740984 | 26 days ago | 0.00053718 ETH | ||||
| 415740984 | 26 days ago | 0.00053718 ETH | ||||
| 415740798 | 26 days ago | 0.0006017 ETH | ||||
| 415740798 | 26 days ago | 0.0006017 ETH | ||||
| 415649654 | 26 days ago | 0.00035365 ETH | ||||
| 415649654 | 26 days ago | 0.00035365 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
CablesRFQ
Compiler Version
v0.8.20+commit.a1b79de6
Contract Source Code (Solidity)
/** *Submitted for verification at Arbiscan.io on 2024-09-30 */ // Sources flattened with hardhat v2.22.4 https://hardhat.org // SPDX-License-Identifier: Apache-2.0 AND BUSL-1.1 AND MIT // File @openzeppelin/contracts/access/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @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. */ 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 `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; } // File @openzeppelin/contracts/access/extensions/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol) pragma solidity ^0.8.20; /** * @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); } // File @openzeppelin/contracts/utils/math/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @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 towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (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 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 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. uint256 twos = denominator & (0 - denominator); 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 (unsignedRoundsUp(rounding) && 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 * towards zero. * * 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 + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * 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 + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * 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 + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * 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 256, 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 + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } } // File @openzeppelin/contracts/utils/math/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } } // File @openzeppelin/contracts/utils/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @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), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @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) { uint256 localValue = value; 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] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } 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); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } } // File @openzeppelin/contracts/utils/cryptography/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } } // File contracts/interfaces/IERC1271.sol // Original license: SPDX_License_Identifier: BUSL-1.1 pragma solidity 0.8.20; /** * @title Interface of ERC1271 */ // The code in this file is part of Cables project. // Please see the LICENSE.txt file for licensing info. // Copyright 2023 Cables. interface IERC1271 { function isValidSignature(bytes32 _hash, bytes memory _signature) external view returns (bytes4 magicValue); } // File contracts/interfaces/IErrors.sol // Original license: SPDX_License_Identifier: BUSL-1.1 pragma solidity 0.8.20; /** * @title Interface of Errors */ // The code in this file is part of Cables project. // Please see the LICENSE.txt file for licensing info. // Copyright 2023 Cables. interface IErrors { /** * @dev swapSigner should not be zero. */ error swapSignerCannotBeZero(); /** * @dev swrapped native token address should not be zero. */ error wethAddressCannotBeZero(); /** * @dev argument address should not be zero. */ error addressCannotBeZero(); /** * @dev transfer should succeed */ error transferFailed(); /** * @dev batch arrays should have same length */ error batchArraysMismatch(); /** * @dev msg.value should be greater enough */ error invalidMsgValue(); /** * @dev there should be always at least one admin */ error atLeastOneAdminNeeded(); /** * @dev amount should be greater than zero */ error zeroAmount(); /** * @dev should be a valid nonce */ error invalidNonce(); /** * @dev order expired due to override */ error expiredByOverride(); /** * @dev order expired due to timestamp */ error expired(); /** * @dev order should be signed with valid signature */ error invalidSignature(); } // File contracts/interfaces/IWETH9.sol // Original license: SPDX_License_Identifier: Apache-2.0 pragma solidity 0.8.20; interface IWETH9 { function deposit() external payable; function withdraw(uint256 _amount) external; } // File @openzeppelin/contracts/utils/structs/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @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. * * ```solidity * 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 is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @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._positions[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 cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 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 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[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._positions[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; } } // File contracts/openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } } // File contracts/openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } } // File @openzeppelin/contracts/utils/introspection/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File contracts/openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; /** * @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); * } * ``` */ abstract contract ERC165Upgradeable is Initializable, IERC165 { function __ERC165_init() internal onlyInitializing { } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } } // File contracts/openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; /** * @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: * * ```solidity * 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}: * * ```solidity * 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. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControl, ERC165Upgradeable { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /// @custom:storage-location erc7201:openzeppelin.storage.AccessControl struct AccessControlStorage { mapping(bytes32 role => RoleData) _roles; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessControl")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant AccessControlStorageLocation = 0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800; function _getAccessControlStorage() private pure returns (AccessControlStorage storage $) { assembly { $.slot := AccessControlStorageLocation } } /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } function __AccessControl_init() internal onlyInitializing { } function __AccessControl_init_unchained() internal onlyInitializing { } /** * @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 returns (bool) { AccessControlStorage storage $ = _getAccessControlStorage(); return $._roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @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 returns (bytes32) { AccessControlStorage storage $ = _getAccessControlStorage(); 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 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 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 `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { AccessControlStorage storage $ = _getAccessControlStorage(); bytes32 previousAdminRole = getRoleAdmin(role); $._roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { AccessControlStorage storage $ = _getAccessControlStorage(); if (!hasRole(role, account)) { $._roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { AccessControlStorage storage $ = _getAccessControlStorage(); if (hasRole(role, account)) { $._roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } } // File contracts/openzeppelin/contracts-upgradeable/access/extensions/AccessControlEnumerableUpgradeable.sol // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol) pragma solidity ^0.8.20; /** * @dev Extension of {AccessControl} that allows enumerating the members of each role. */ abstract contract AccessControlEnumerableUpgradeable is Initializable, IAccessControlEnumerable, AccessControlUpgradeable { using EnumerableSet for EnumerableSet.AddressSet; /// @custom:storage-location erc7201:openzeppelin.storage.AccessControlEnumerable struct AccessControlEnumerableStorage { mapping(bytes32 role => EnumerableSet.AddressSet) _roleMembers; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessControlEnumerable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant AccessControlEnumerableStorageLocation = 0xc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e82371705932000; function _getAccessControlEnumerableStorage() private pure returns (AccessControlEnumerableStorage storage $) { assembly { $.slot := AccessControlEnumerableStorageLocation } } function __AccessControlEnumerable_init() internal onlyInitializing { } function __AccessControlEnumerable_init_unchained() internal onlyInitializing { } /** * @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 returns (address) { AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage(); 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 returns (uint256) { AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage(); return $._roleMembers[role].length(); } /** * @dev Overload {AccessControl-_grantRole} to track enumerable memberships */ function _grantRole(bytes32 role, address account) internal virtual override returns (bool) { AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage(); bool granted = super._grantRole(role, account); if (granted) { $._roleMembers[role].add(account); } return granted; } /** * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships */ function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) { AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage(); bool revoked = super._revokeRole(role, account); if (revoked) { $._roleMembers[role].remove(account); } return revoked; } } // File @openzeppelin/contracts/interfaces/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.20; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); } // File contracts/openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.20; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. */ abstract contract EIP712Upgradeable is Initializable, IERC5267 { bytes32 private constant TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); /// @custom:storage-location erc7201:openzeppelin.storage.EIP712 struct EIP712Storage { /// @custom:oz-renamed-from _HASHED_NAME bytes32 _hashedName; /// @custom:oz-renamed-from _HASHED_VERSION bytes32 _hashedVersion; string _name; string _version; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.EIP712")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant EIP712StorageLocation = 0xa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100; function _getEIP712Storage() private pure returns (EIP712Storage storage $) { assembly { $.slot := EIP712StorageLocation } } /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ function __EIP712_init(string memory name, string memory version) internal onlyInitializing { __EIP712_init_unchained(name, version); } function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing { EIP712Storage storage $ = _getEIP712Storage(); $._name = name; $._version = version; // Reset prior values in storage if upgrading $._hashedName = 0; $._hashedVersion = 0; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { return _buildDomainSeparator(); } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash(), block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {IERC-5267}. */ function eip712Domain() public view virtual returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { EIP712Storage storage $ = _getEIP712Storage(); // If the hashed name and version in storage are non-zero, the contract hasn't been properly initialized // and the EIP712 domain is not reliable, as it will be missing name and version. require($._hashedName == 0 && $._hashedVersion == 0, "EIP712: Uninitialized"); return ( hex"0f", // 01111 _EIP712Name(), _EIP712Version(), block.chainid, address(this), bytes32(0), new uint256[](0) ); } /** * @dev The name parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712Name() internal view virtual returns (string memory) { EIP712Storage storage $ = _getEIP712Storage(); return $._name; } /** * @dev The version parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712Version() internal view virtual returns (string memory) { EIP712Storage storage $ = _getEIP712Storage(); return $._version; } /** * @dev The hash of the name parameter for the EIP712 domain. * * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Name` instead. */ function _EIP712NameHash() internal view returns (bytes32) { EIP712Storage storage $ = _getEIP712Storage(); string memory name = _EIP712Name(); if (bytes(name).length > 0) { return keccak256(bytes(name)); } else { // If the name is empty, the contract may have been upgraded without initializing the new storage. // We return the name hash in storage if non-zero, otherwise we assume the name is empty by design. bytes32 hashedName = $._hashedName; if (hashedName != 0) { return hashedName; } else { return keccak256(""); } } } /** * @dev The hash of the version parameter for the EIP712 domain. * * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Version` instead. */ function _EIP712VersionHash() internal view returns (bytes32) { EIP712Storage storage $ = _getEIP712Storage(); string memory version = _EIP712Version(); if (bytes(version).length > 0) { return keccak256(bytes(version)); } else { // If the version is empty, the contract may have been upgraded without initializing the new storage. // We return the version hash in storage if non-zero, otherwise we assume the version is empty by design. bytes32 hashedVersion = $._hashedVersion; if (hashedVersion != 0) { return hashedVersion; } else { return keccak256(""); } } } } // File contracts/openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) pragma solidity ^0.8.20; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Pausable struct PausableStorage { bool _paused; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Pausable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300; function _getPausableStorage() private pure returns (PausableStorage storage $) { assembly { $.slot := PausableStorageLocation } } /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); /** * @dev The operation failed because the contract is paused. */ error EnforcedPause(); /** * @dev The operation failed because the contract is not paused. */ error ExpectedPause(); /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { PausableStorage storage $ = _getPausableStorage(); $._paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { PausableStorage storage $ = _getPausableStorage(); return $._paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { if (paused()) { revert EnforcedPause(); } } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { if (!paused()) { revert ExpectedPause(); } } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { PausableStorage storage $ = _getPausableStorage(); $._paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { PausableStorage storage $ = _getPausableStorage(); $._paused = false; emit Unpaused(_msgSender()); } } // File contracts/openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @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 ReentrancyGuardUpgradeable is Initializable { // 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; /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard struct ReentrancyGuardStorage { uint256 _status; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) { assembly { $.slot := ReentrancyGuardStorageLocation } } /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); $._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 { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // On the first call to nonReentrant, _status will be NOT_ENTERED if ($._status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail $._status = ENTERED; } function _nonReentrantAfter() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) $._status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); return $._status == ENTERED; } } // File contracts/openzeppelin/contracts/token/ERC20/IERC20.sol // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); } // File contracts/openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // File contracts/openzeppelin/contracts/utils/Address.sol // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) 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 FailedInnerCall(); } } } // File contracts/openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } } // File contracts/openzeppelin/contracts/utils/cryptography/ECDSA.sol // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } } // File contracts/CablesRFQ.sol // Original license: SPDX_License_Identifier: BUSL-1.1 pragma solidity 0.8.20; /** * @title Cables Finance RFQ Contract * @notice This contract uses prices from Cables Finance to facilitate token swaps * on EVM-compatible chains. Users must request a quote via our RFQ API. * Using this quote, users can execute a swap on the current chain using simpleSwap() or partialSwap(). * @dev After getting a firm quote from our off-chain RFQ API, call the simpleSwap() function with * the quote. This will execute a swap, exchanging the taker asset (asset you provide) with * the maker asset (asset we provide). */ contract CablesRFQ is AccessControlEnumerableUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable, EIP712Upgradeable, IERC1271, IErrors { using ECDSA for bytes32; using SafeERC20 for IERC20; // version bytes32 public constant VERSION = bytes32("1.0.1"); // rebalancer admin role bytes32 public constant REBALANCER_ADMIN_ROLE = keccak256("REBALANCER_ADMIN_ROLE"); // typehash for same chain swaps bytes32 private constant ORDER_TYPEHASH = keccak256( "Order(uint256 nonceAndMeta,uint128 expiry,address makerAsset,address takerAsset,address maker,address taker,uint256 makerAmount,uint256 takerAmount)" ); // firm order data structure sent to user for regular swap from RFQ API struct Order { uint256 nonceAndMeta; uint128 expiry; address makerAsset; address takerAsset; address maker; address taker; uint256 makerAmount; uint256 takerAmount; } struct SwapData { uint256 nonceAndMeta; // originating user address taker; // destination user address destTrader; uint256 destChainId; address srcAsset; address destAsset; uint256 srcAmount; uint256 destAmount; } // address used to sign and verify swap orders address public swapSigner; // address of the native wrapped token address public wethAddress; // uses a bitmap to keep track of nonces used in executed swaps mapping(uint256 => uint256) public completedSwaps; // uses a bitmap to keep track of nonces of swaps that have been set to expire prior to execution mapping(uint256 => uint256) public expiredSwaps; // storage gap for upgradeability uint256[44] __gap; event SwapSignerUpdated(address newSwapSigner); event RoleUpdated(string indexed name, string actionName, bytes32 updatedRole, address updatedAddress); event AddressSet(string indexed name, string actionName, address newAddress); event SwapExecuted( uint256 indexed nonceAndMeta, address taker, address destTrader, uint256 destChainId, address srcAsset, address destAsset, uint256 srcAmount, uint256 destAmount ); event RebalancerWithdraw(address asset, uint256 amount); event SwapExpired(uint256 nonceAndMeta, uint256 timestamp); /** * @notice Initializer function for Upgradeable RFQ * @param _swapSigner Address of swap signer (rebalancer is also defaulted to swap signer) * @param _wethAddress Address of the wrapped native token */ function initialize(address _swapSigner, address _wethAddress) external initializer { if (_swapSigner == address(0)) { revert swapSignerCannotBeZero(); } if (_wethAddress == address(0)) { revert wethAddressCannotBeZero(); } __AccessControlEnumerable_init(); __Pausable_init(); __ReentrancyGuard_init(); __EIP712_init("Cables", "1"); _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(REBALANCER_ADMIN_ROLE, _swapSigner); swapSigner = _swapSigner; wethAddress = _wethAddress; } /** * @notice Used to rebalance native token on RFQ contract and store it in wrapped form. * @dev There is no limitaion on the address of the sender apart from WETH contract. * Native token from other sources is deposited to WETH contract. * Native token coming from the WETH contract is used for the exchange flow. */ receive() external payable { if (msg.sender != wethAddress) { IWETH9(wethAddress).deposit{ value: msg.value }(); } } /** * @notice Swaps two assets for another smart contract or EOA, based off a predetermined swap price. * @dev This function can only be called after generating a firm quote from the RFQ API. * All parameters are generated from the RFQ API. Prices are determined based off of the * orderbook from Cables Finance. * @param _order Trade parameters for swap generated from /quote * @param _signature Signature of trade parameters generated from /quote **/ function simpleSwap(Order calldata _order, bytes calldata _signature) external payable nonReentrant whenNotPaused { address destTrader = _verifyOrder(_order, _signature); _executeOrder(_order, _order.makerAmount, _order.takerAmount, destTrader); } /** * @notice Swaps two assets for another smart contract or EOA, based off a predetermined swap price. * @dev This function can only be called after generating a firm quote from the RFQ API. * All parameters are generated from the RFQ API. Prices are determined based off of the * orderbook from the Cables Finance. This function will partially fill at the quoted price. * @param _order Trade parameters for swap generated from /quote * @param _signature Signature of trade parameters generated from /quote * @param _takerAmount Actual amount of takerAsset utilized in swap **/ function partialSwap( Order calldata _order, bytes calldata _signature, uint256 _takerAmount ) external payable nonReentrant whenNotPaused { address destTrader = _verifyOrder(_order, _signature); uint256 makerAmount = _order.makerAmount; if (_takerAmount < _order.takerAmount) { makerAmount = (makerAmount * _takerAmount) / _order.takerAmount; } _executeOrder(_order, makerAmount, _takerAmount, destTrader); } /** * @notice Updates the expiry of a order. The new expiry * is the deadline a trader has to execute the swap. * @dev Only rebalancer can call this function. * @param _nonceAndMeta Nonce of order **/ function updateSwapExpiry(uint256 _nonceAndMeta) external onlyRole(REBALANCER_ADMIN_ROLE) { expiredSwaps[_nonceAndMeta >> 8] |= 1 << (_nonceAndMeta & 0xff); emit SwapExpired(_nonceAndMeta, block.timestamp); } /** * @notice Updates the signer address * @dev Only DEFAULT_ADMIN can call this function. * @param _swapSigner Address of new swap signer **/ function setSwapSigner(address _swapSigner) external onlyRole(DEFAULT_ADMIN_ROLE) { if (_swapSigner == address(0)) { revert swapSignerCannotBeZero(); } swapSigner = _swapSigner; emit SwapSignerUpdated(_swapSigner); } /** * @notice Pause contract * @dev Only callable by admin */ function pause() external onlyRole(DEFAULT_ADMIN_ROLE) { _pause(); } /** * @notice Unpause contract * @dev Only callable by admin */ function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) { _unpause(); } /** * @notice Allows rebalancer to withdraw an asset from the smart contract * @dev Only callable by admin * @param _asset Address of the asset to be withdrawn * @param _amount Amount of asset to be withdrawn */ function claimBalance(address _asset, uint256 _amount) external nonReentrant onlyRole(REBALANCER_ADMIN_ROLE) { if (_asset == address(0)) { IWETH9(wethAddress).withdraw(_amount); (bool success, ) = payable(msg.sender).call{value: _amount}(""); if (!success) { revert transferFailed(); } } else { IERC20(_asset).safeTransfer(msg.sender, _amount); } emit RebalancerWithdraw(_asset, _amount); } /** * @notice Allows rebalancer to withdraw multiple assets from the smart contract * @dev Only callable by admin * @param _assets Array of addresses of the assets to be withdrawn * @param _amounts Array of amounts of assets to be withdrawn */ function batchClaimBalance( address[] calldata _assets, uint256[] calldata _amounts ) external nonReentrant onlyRole(REBALANCER_ADMIN_ROLE) { if (_assets.length != _amounts.length) { revert batchArraysMismatch(); } uint256 i; while (i < _assets.length) { if (_assets[i] == address(0)) { IWETH9(wethAddress).withdraw(_amounts[i]); (bool success, ) = payable(msg.sender).call{value: _amounts[i]}(""); if (!success) { revert transferFailed(); } } else { IERC20(_assets[i]).safeTransfer(msg.sender, _amounts[i]); } emit RebalancerWithdraw(_assets[i], _amounts[i]); unchecked { ++i; } } } /** * @notice Adds Rebalancer Admin role to the address * @param _address Address to add role to */ function addRebalancer(address _address) external virtual onlyRole(DEFAULT_ADMIN_ROLE) { if (_address == address(0)) { revert addressCannotBeZero(); } emit RoleUpdated("RFQ", "ADD-ROLE", REBALANCER_ADMIN_ROLE, _address); grantRole(REBALANCER_ADMIN_ROLE, _address); } /** * @notice Removes Rebalancer Admin role from the address * @param _address Address to remove role from */ function removeRebalancer(address _address) external virtual onlyRole(DEFAULT_ADMIN_ROLE) { if (getRoleMemberCount(REBALANCER_ADMIN_ROLE) < 2) { revert atLeastOneAdminNeeded(); } emit RoleUpdated("RFQ", "REMOVE-ROLE", REBALANCER_ADMIN_ROLE, _address); revokeRole(REBALANCER_ADMIN_ROLE, _address); } /** * @notice Adds Default Admin role to the address * @param _address Address to add role to */ function addAdmin(address _address) external virtual onlyRole(DEFAULT_ADMIN_ROLE) { if (_address == address(0)) { revert addressCannotBeZero(); } emit RoleUpdated("RFQ", "ADD-ROLE", DEFAULT_ADMIN_ROLE, _address); grantRole(DEFAULT_ADMIN_ROLE, _address); } /** * @notice Removes Default Admin role from the address * @param _address Address to remove role from */ function removeAdmin(address _address) external virtual onlyRole(DEFAULT_ADMIN_ROLE) { if (getRoleMemberCount(DEFAULT_ADMIN_ROLE) < 2) { revert atLeastOneAdminNeeded(); } emit RoleUpdated("RFQ", "REMOVE-ROLE", DEFAULT_ADMIN_ROLE, _address); revokeRole(DEFAULT_ADMIN_ROLE, _address); } /** * @notice Checks if address has Rebalancer Admin role * @param _address Address to check * @return bool True if address has Rebalancer Admin role */ function isRebalancer(address _address) external view returns (bool) { return hasRole(REBALANCER_ADMIN_ROLE, _address); } /** * @notice Checks if address has Default Admin role * @param _address Address to check * @return bool True if address has Default Admin role */ function isAdmin(address _address) external view returns (bool) { return hasRole(DEFAULT_ADMIN_ROLE, _address); } /** * @notice Verifies Signature in accordance with the ERC1271 standard * @param _hash Hash of order data * @param _signature Signature of trade parameters generated from /quote * @return bytes4 The Magic Value based on the ERC1271 standard. 0x1626ba7e represents * a valid signature, while 0x00000000 represents an invalid signature. **/ function isValidSignature(bytes32 _hash, bytes calldata _signature) public view override returns (bytes4) { (address signer, , ) = ECDSA.tryRecover(_hash, _signature); if (signer == swapSigner) { return 0x1626ba7e; } else { return 0x00000000; } } /** * @notice Verifies that an order is valid and has not been executed already * @param _order Trade parameters for swap generated from /quote * @param _signature Signature of trade parameters generated from /quote * @return address The address where the funds will be transferred **/ function _verifyOrder(Order calldata _order, bytes calldata _signature) private returns (address) { address destTrader = address(uint160(_order.nonceAndMeta >> 96)); if (destTrader == address(0)) { revert addressCannotBeZero(); } if (_order.takerAmount == 0) { revert zeroAmount(); } bytes32 hashedStruct = keccak256( abi.encode( ORDER_TYPEHASH, _order.nonceAndMeta, _order.expiry, _order.makerAsset, _order.takerAsset, _order.maker, _order.taker, _order.makerAmount, _order.takerAmount ) ); _verifySwapInternal( _order.nonceAndMeta, _order.expiry, hashedStruct, _signature ); return destTrader; } /** * @notice Handles the exchange of assets based on swap type and * if the assets are ERC-20's or native tokens. * @param _order Trade parameters for swap generated from /quote * @param _makerAmount The proper makerAmount for the trade * @param _takerAmount The proper takerAmount for the trade * @param _destTrader The address to transfer funds to **/ function _executeOrder( Order calldata _order, uint256 _makerAmount, uint256 _takerAmount, address _destTrader ) private { SwapData memory swapData = SwapData({ nonceAndMeta: _order.nonceAndMeta, taker: _order.taker, destTrader: _destTrader, destChainId: block.chainid, srcAsset: _order.takerAsset, destAsset: _order.makerAsset, srcAmount: _takerAmount, destAmount: _makerAmount }); _executeSwapInternal(swapData); } /** * @notice Verifies that a swap has a valid signature, nonce, and expiry * @param _nonceAndMeta Nonce of swap * @param _expiry Expiry of swap * @param _hashedStruct Hashed swap struct (required for signature verification) * @param _signature Signature of swap * */ function _verifySwapInternal( uint256 _nonceAndMeta, uint256 _expiry, bytes32 _hashedStruct, bytes calldata _signature ) private { uint256 bucket = _nonceAndMeta >> 8; uint256 mask = 1 << (_nonceAndMeta & 0xff); uint256 bitmap = completedSwaps[bucket]; if (bitmap & mask != 0) { revert invalidNonce(); } if (expiredSwaps[bucket] & mask != 0) { revert expiredByOverride(); } if (block.timestamp > _expiry) { revert expired(); } if (isValidSignature(_hashTypedDataV4(_hashedStruct), _signature) != 0x1626ba7e) { revert invalidSignature(); } completedSwaps[bucket] = bitmap | mask; } /** * @notice Pulls funds for a swap from the _swapData.taker * @param _swapData Struct containing all information for executing a swap */ function _takeFunds(SwapData memory _swapData) private { if (_swapData.srcAsset == address(0)) { if (msg.value < _swapData.srcAmount) { revert invalidMsgValue(); } IWETH9(wethAddress).deposit{ value: msg.value }(); } else { IERC20(_swapData.srcAsset).safeTransferFrom(_swapData.taker, address(this), _swapData.srcAmount); } } /** * @notice Release funds for a swap to the destTrader * @param _swapData Struct containing all information for executing a swap */ function _releaseFunds(SwapData memory _swapData) private { if (_swapData.destAsset == address(0)) { IWETH9(wethAddress).withdraw(_swapData.destAmount); (bool success, ) = payable(_swapData.destTrader).call{value: _swapData.destAmount}(""); if (!success) { revert transferFailed(); } } else { IERC20(_swapData.destAsset).safeTransfer(_swapData.destTrader, _swapData.destAmount); } } /** * @notice Refunds remaining native token to the msg.sender * @param _swapData Struct containing all information for executing a swap */ function _refundNative(SwapData memory _swapData) private { if (_swapData.srcAsset == address(0) && msg.value > _swapData.srcAmount) { IWETH9(wethAddress).withdraw(msg.value - _swapData.srcAmount); (bool success, ) = payable(msg.sender).call{value: msg.value - _swapData.srcAmount}(""); if (!success) { revert transferFailed(); } } } /** * @notice Executes a swap by taking funds from the msg.sender and funds * are released to the destTrader. Emits SwapExecuted event upon completion. * @param _swapData Struct containing all information for executing a swap */ function _executeSwapInternal(SwapData memory _swapData) private { _takeFunds(_swapData); _releaseFunds(_swapData); _refundNative(_swapData); emit SwapExecuted( _swapData.nonceAndMeta, _swapData.taker, _swapData.destTrader, _swapData.destChainId, _swapData.srcAsset, _swapData.destAsset, _swapData.srcAmount, _swapData.destAmount ); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"addressCannotBeZero","type":"error"},{"inputs":[],"name":"atLeastOneAdminNeeded","type":"error"},{"inputs":[],"name":"batchArraysMismatch","type":"error"},{"inputs":[],"name":"expired","type":"error"},{"inputs":[],"name":"expiredByOverride","type":"error"},{"inputs":[],"name":"invalidMsgValue","type":"error"},{"inputs":[],"name":"invalidNonce","type":"error"},{"inputs":[],"name":"invalidSignature","type":"error"},{"inputs":[],"name":"swapSignerCannotBeZero","type":"error"},{"inputs":[],"name":"transferFailed","type":"error"},{"inputs":[],"name":"wethAddressCannotBeZero","type":"error"},{"inputs":[],"name":"zeroAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"actionName","type":"string"},{"indexed":false,"internalType":"address","name":"newAddress","type":"address"}],"name":"AddressSet","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RebalancerWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"actionName","type":"string"},{"indexed":false,"internalType":"bytes32","name":"updatedRole","type":"bytes32"},{"indexed":false,"internalType":"address","name":"updatedAddress","type":"address"}],"name":"RoleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nonceAndMeta","type":"uint256"},{"indexed":false,"internalType":"address","name":"taker","type":"address"},{"indexed":false,"internalType":"address","name":"destTrader","type":"address"},{"indexed":false,"internalType":"uint256","name":"destChainId","type":"uint256"},{"indexed":false,"internalType":"address","name":"srcAsset","type":"address"},{"indexed":false,"internalType":"address","name":"destAsset","type":"address"},{"indexed":false,"internalType":"uint256","name":"srcAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"}],"name":"SwapExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nonceAndMeta","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"SwapExpired","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newSwapSigner","type":"address"}],"name":"SwapSignerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REBALANCER_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"addRebalancer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_assets","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"batchClaimBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"claimBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"completedSwaps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"expiredSwaps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_swapSigner","type":"address"},{"internalType":"address","name":"_wethAddress","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isRebalancer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nonceAndMeta","type":"uint256"},{"internalType":"uint128","name":"expiry","type":"uint128"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"taker","type":"address"},{"internalType":"uint256","name":"makerAmount","type":"uint256"},{"internalType":"uint256","name":"takerAmount","type":"uint256"}],"internalType":"struct CablesRFQ.Order","name":"_order","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"uint256","name":"_takerAmount","type":"uint256"}],"name":"partialSwap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"removeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"removeRebalancer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_swapSigner","type":"address"}],"name":"setSwapSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nonceAndMeta","type":"uint256"},{"internalType":"uint128","name":"expiry","type":"uint128"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"taker","type":"address"},{"internalType":"uint256","name":"makerAmount","type":"uint256"},{"internalType":"uint256","name":"takerAmount","type":"uint256"}],"internalType":"struct CablesRFQ.Order","name":"_order","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"simpleSwap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nonceAndMeta","type":"uint256"}],"name":"updateSwapExpiry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wethAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060405234801561000f575f80fd5b506133178061001d5f395ff3fe6080604052600436106101f7575f3560e01c80636c75d6f511610117578063944bda00116100ac578063ca15c8731161007c578063d547741f11610062578063d547741f146106e5578063ed7df71a14610704578063ffa1ad741461072f575f80fd5b8063ca15c8731461069b578063d4c2c752146106ba575f80fd5b8063944bda0014610637578063a217fddf1461064a578063aa8b38d91461065d578063c1ad7e201461067c575f80fd5b80638456cb59116100e75780638456cb591461057a57806384b0196e1461058e5780639010d07c146105b557806391d14854146105d4575f80fd5b80636c75d6f51461050b578063704802751461051e57806380ca29f41461053d578063822a65721461055c575f80fd5b80633111133c1161018d578063467c9eff1161015d578063467c9eff14610460578063485cc9551461047f5780634f0e0ef31461049e5780635c975abb146104d5575f80fd5b80633111133c146103db57806336568abe1461040e5780633f4ba83a1461042d57806343bc4b9a14610441575f80fd5b80631785f53c116101c85780631785f53c14610323578063248a9ca31461034257806324d7806c1461039d5780632f2ff15d146103bc575f80fd5b80629310ba1461027957806301ffc9a7146102985780630c979919146102cc5780631626ba7e146102eb575f80fd5b36610275576001546001600160a01b031633146102735760015f9054906101000a90046001600160a01b03166001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004015f604051808303818588803b15801561025b575f80fd5b505af115801561026d573d5f803e3d5ffd5b50505050505b005b5f80fd5b348015610284575f80fd5b50610273610293366004612cc4565b610762565b3480156102a3575f80fd5b506102b76102b2366004612cdb565b6107f1565b60405190151581526020015b60405180910390f35b3480156102d7575f80fd5b506102736102e6366004612d1d565b610834565b3480156102f6575f80fd5b5061030a610305366004612d7b565b610927565b6040516001600160e01b031990911681526020016102c3565b34801561032e575f80fd5b5061027361033d366004612d1d565b6109b7565b34801561034d575f80fd5b5061038f61035c366004612cc4565b5f9081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b6040519081526020016102c3565b3480156103a8575f80fd5b506102b76103b7366004612d1d565b610a6c565b3480156103c7575f80fd5b506102736103d6366004612dc3565b610aab565b3480156103e6575f80fd5b5061038f7ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab981565b348015610419575f80fd5b50610273610428366004612dc3565b610af4565b348015610438575f80fd5b50610273610b45565b34801561044c575f80fd5b5061027361045b366004612d1d565b610b5a565b34801561046b575f80fd5b506102b761047a366004612d1d565b610c6f565b34801561048a575f80fd5b50610273610499366004612ded565b610cae565b3480156104a9575f80fd5b506001546104bd906001600160a01b031681565b6040516001600160a01b0390911681526020016102c3565b3480156104e0575f80fd5b507fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff166102b7565b610273610519366004612e2c565b610f46565b348015610529575f80fd5b50610273610538366004612d1d565b610fa2565b348015610548575f80fd5b50610273610557366004612d1d565b611051565b348015610567575f80fd5b505f546104bd906001600160a01b031681565b348015610585575f80fd5b506102736110dc565b348015610599575f80fd5b506105a26110ee565b6040516102c39796959493929190612eb2565b3480156105c0575f80fd5b506104bd6105cf366004612f62565b6111ed565b3480156105df575f80fd5b506102b76105ee366004612dc3565b5f9182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408084206001600160a01b0393909316845291905290205460ff1690565b610273610645366004612f82565b61122d565b348015610655575f80fd5b5061038f5f81565b348015610668575f80fd5b50610273610677366004612fdc565b6112af565b348015610687575f80fd5b50610273610696366004613045565b611434565b3480156106a6575f80fd5b5061038f6106b5366004612cc4565b6116c1565b3480156106c5575f80fd5b5061038f6106d4366004612cc4565b60036020525f908152604090205481565b3480156106f0575f80fd5b506102736106ff366004612dc3565b6116f8565b34801561070f575f80fd5b5061038f61071e366004612cc4565b60026020525f908152604090205481565b34801561073a575f80fd5b5061038f7f312e302e3100000000000000000000000000000000000000000000000000000081565b7ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab961078c8161173b565b600882901c5f90815260036020526040908190208054600160ff86161b179055517f4e26543a3310528c7ccde0f2a250a579a7eb3192762bd6ae53d14c811f8b1209906107e59084904290918252602082015260400190565b60405180910390a15050565b5f6001600160e01b031982167f5a05180f00000000000000000000000000000000000000000000000000000000148061082e575061082e82611745565b92915050565b5f61083e8161173b565b6001600160a01b0382166108655760405163bb6bc9ad60e01b815260040160405180910390fd5b604080516252465160e81b815281519081900360030181206060808352600890830152674144442d524f4c4560c01b60808301527ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab960208301526001600160a01b0385168284015291517fbafee6bdc2193912cf2754d0840b53e34485a4341b4071fb7da8d091ffef67bf9181900360a00190a26109237ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab983610aab565b5050565b5f806109688585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506117ab92505050565b50505f549091506001600160a01b03908116908216036109ab57507f1626ba7e0000000000000000000000000000000000000000000000000000000090506109b0565b505f90505b9392505050565b5f6109c18161173b565b60026109cc5f6116c1565b10156109eb57604051635acf42fb60e01b815260040160405180910390fd5b604080516252465160e81b815281519081900360030181206060808352600b908301526a52454d4f56452d524f4c4560a81b60808301525f60208301526001600160a01b0385168284015291517fbafee6bdc2193912cf2754d0840b53e34485a4341b4071fb7da8d091ffef67bf9181900360a00190a26109235f836116f8565b6001600160a01b0381165f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604081205460ff1661082e565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040902060010154610ae48161173b565b610aee83836117f4565b50505050565b6001600160a01b0381163314610b36576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b408282611849565b505050565b5f610b4f8161173b565b610b57611895565b50565b5f610b648161173b565b6002610b8f7ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab96116c1565b1015610bae57604051635acf42fb60e01b815260040160405180910390fd5b604080516252465160e81b815281519081900360030181206060808352600b908301526a52454d4f56452d524f4c4560a81b60808301527ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab960208301526001600160a01b0385168284015291517fbafee6bdc2193912cf2754d0840b53e34485a4341b4071fb7da8d091ffef67bf9181900360a00190a26109237ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab9836116f8565b6001600160a01b0381165f9081527fe9680e5511d61ade835a081870812c17eb80397105a095e0ffec5f4921adf8d7602052604081205460ff1661082e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610cf85750825b90505f8267ffffffffffffffff166001148015610d145750303b155b905081158015610d22575080155b15610d59576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d8d57845468ff00000000000000001916680100000000000000001785555b6001600160a01b038716610db45760405163393e83a160e11b815260040160405180910390fd5b6001600160a01b038616610df4576040517f05f8e07700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfc611907565b610e04611911565b610e0c611921565b610e806040518060400160405280600681526020017f4361626c657300000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250611931565b610e8a5f336117f4565b50610eb57ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab9886117f4565b505f80546001600160a01b03808a1673ffffffffffffffffffffffffffffffffffffffff199283161790925560018054928916929091169190911790558315610f3d57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b610f4e611943565b610f566119a6565b5f610f62848484611a02565b9050610f78848560c001358660e0013584611b93565b50610b4060017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b5f610fac8161173b565b6001600160a01b038216610fd35760405163bb6bc9ad60e01b815260040160405180910390fd5b604080516252465160e81b815281519081900360030181206060808352600890830152674144442d524f4c4560c01b60808301525f60208301526001600160a01b0385168284015291517fbafee6bdc2193912cf2754d0840b53e34485a4341b4071fb7da8d091ffef67bf9181900360a00190a26109235f83610aab565b5f61105b8161173b565b6001600160a01b0382166110825760405163393e83a160e11b815260040160405180910390fd5b5f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091556040519081527fe6243347c190ae7a28aef8cfd36bcecf9459bbe5d32fb1ee1bf7358dac0b4b40906020016107e5565b5f6110e68161173b565b610b57611c5d565b5f60608082808083817fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100805490915015801561112c57506001810154155b611197576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4549503731323a20556e696e697469616c697a6564000000000000000000000060448201526064015b60405180910390fd5b61119f611cb8565b6111a7611d8b565b604080515f808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009c939b5091995046985030975095509350915050565b5f8281527fc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e823717059320006020819052604082206112259084611ddc565b949350505050565b611235611943565b61123d6119a6565b5f611249858585611a02565b905060c085013560e08601358310156112785760e086013561126b84836130d4565b61127591906130eb565b90505b61128486828585611b93565b5050610aee60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b6112b7611943565b7ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab96112e18161173b565b6001600160a01b0383166113b457600154604051632e1a7d4d60e01b8152600481018490526001600160a01b0390911690632e1a7d4d906024015f604051808303815f87803b158015611332575f80fd5b505af1158015611344573d5f803e3d5ffd5b50506040515f925033915084908381818185875af1925050503d805f8114611387576040519150601f19603f3d011682016040523d82523d5f602084013e61138c565b606091505b50509050806113ae57604051637232c81f60e11b815260040160405180910390fd5b506113c8565b6113c86001600160a01b0384163384611de7565b604080516001600160a01b0385168152602081018490527fa3e40bab7c3da0937e283e65aacdd378a146806f8ac5b873ce32c1f13f45376d910160405180910390a15061092360017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b61143c611943565b7ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab96114668161173b565b83821461149f576040517fe4990ff700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b84811015611284575f8686838181106114bc576114bc61310a565b90506020020160208101906114d19190612d1d565b6001600160a01b0316036115e2576001546001600160a01b0316632e1a7d4d8585848181106115025761150261310a565b905060200201356040518263ffffffff1660e01b815260040161152791815260200190565b5f604051808303815f87803b15801561153e575f80fd5b505af1158015611550573d5f803e3d5ffd5b505050505f336001600160a01b03168585848181106115715761157161310a565b905060200201356040515f6040518083038185875af1925050503d805f81146115b5576040519150601f19603f3d011682016040523d82523d5f602084013e6115ba565b606091505b50509050806115dc57604051637232c81f60e11b815260040160405180910390fd5b50611636565b611636338585848181106115f8576115f861310a565b905060200201358888858181106116115761161161310a565b90506020020160208101906116269190612d1d565b6001600160a01b03169190611de7565b7fa3e40bab7c3da0937e283e65aacdd378a146806f8ac5b873ce32c1f13f45376d8686838181106116695761166961310a565b905060200201602081019061167e9190612d1d565b8585848181106116905761169061310a565b604080516001600160a01b0390951685526020918202939093013590840152500160405180910390a16001016114a1565b5f8181527fc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e823717059320006020819052604082206109b090611e5b565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260409020600101546117318161173b565b610aee8383611849565b610b578133611e64565b5f6001600160e01b031982167f7965db0b00000000000000000000000000000000000000000000000000000000148061082e57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b031983161461082e565b5f805f83516041036117e2576020840151604085015160608601515f1a6117d488828585611ef0565b9550955095505050506117ed565b505081515f91506002905b9250925092565b5f7fc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e82371705932000816118218585611fb8565b90508015611225575f8581526020839052604090206118409085612084565b50949350505050565b5f7fc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e82371705932000816118768585612098565b90508015611225575f858152602083905260409020611840908561213c565b61189d612150565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300805460ff191681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a150565b61190f6121ab565b565b6119196121ab565b61190f612212565b6119296121ab565b61190f612245565b6119396121ab565b610923828261224d565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f008054600119016119a0576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60029055565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff161561190f576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f833560601c80611a265760405163bb6bc9ad60e01b815260040160405180910390fd5b8460e001355f03611a63576040517f7685565700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f95afddf5e4bb9f692716b7fdff640e6b8a0d2869597405c6e9d35857ed19a1508635611a976040890160208a0161311e565b611aa760608a0160408b01612d1d565b611ab760808b0160608c01612d1d565b611ac760a08c0160808d01612d1d565b611ad760c08d0160a08e01612d1d565b6040805160208101989098528701959095526fffffffffffffffffffffffffffffffff90931660608601526001600160a01b039182166080860152811660a085015290811660c084810191909152911660e0838101919091529088013561010083015287013561012082015261014001604051602081830303815290604052805190602001209050611840865f0135876020016020810190611b79919061311e565b6fffffffffffffffffffffffffffffffff168388886122bf565b604080516101008101909152843581525f9060208101611bb960c0880160a08901612d1d565b6001600160a01b03168152602001836001600160a01b03168152602001468152602001866060016020810190611bef9190612d1d565b6001600160a01b03168152602001611c0d6060880160408901612d1d565b6001600160a01b03168152602001848152602001858152509050611c308161241f565b5050505050565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b611c656119a6565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300805460ff191660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258336118e9565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10280546060917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10091611d099061314d565b80601f0160208091040260200160405190810160405280929190818152602001828054611d359061314d565b8015611d805780601f10611d5757610100808354040283529160200191611d80565b820191905f5260205f20905b815481529060010190602001808311611d6357829003601f168201915b505050505091505090565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10380546060917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10091611d099061314d565b5f6109b083836124de565b6040516001600160a01b03838116602483015260448201839052610b4091859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612504565b5f61082e825490565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408083206001600160a01b038516845290915290205460ff16610923576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024810183905260440161118e565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115611f2957505f91506003905082611fae565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015611f7a573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116611fa557505f925060019150829050611fae565b92505f91508190505b9450945094915050565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff1661207b575f848152602082815260408083206001600160a01b03871684529091529020805460ff191660011790556120313390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600191505061082e565b5f91505061082e565b5f6109b0836001600160a01b03841661257e565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff161561207b575f848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4600191505061082e565b5f6109b0836001600160a01b0384166125ca565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1661190f576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661190f576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61221a6121ab565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300805460ff19169055565b611c376121ab565b6122556121ab565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1026122a184826131c4565b50600381016122b083826131c4565b505f8082556001909101555050565b600885901c5f81815260026020526040902054600160ff88161b9080821615612314576040517fd3b9dd1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8381526003602052604090205482161561235b576040517fdc44eb9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86421115612395576040517f4c2067c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123a86123a1876126a4565b8686610927565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916631626ba7e60e01b14612406576040517fd1cc120200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f92835260026020526040909220911790555050505050565b612428816126eb565b612431816127ce565b61243a816128e6565b805f01517f68eb6d948c037c94e470f9a5b288dd93debbcd9342635408e66cb0211686f7f782602001518360400151846060015185608001518660a001518760c001518860e001516040516124d397969594939291906001600160a01b039788168152958716602087015260408601949094529185166060850152909316608083015260a082019290925260c081019190915260e00190565b60405180910390a250565b5f825f0182815481106124f3576124f361310a565b905f5260205f200154905092915050565b5f6125186001600160a01b038416836129c4565b905080515f1415801561253c57508080602001905181019061253a9190613280565b155b15610b40576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260240161118e565b5f8181526001830160205260408120546125c357508154600181810184555f84815260208082209093018490558454848252828601909352604090209190915561082e565b505f61082e565b5f818152600183016020526040812054801561207b575f6125ec60018361329f565b85549091505f906125ff9060019061329f565b905080821461265e575f865f01828154811061261d5761261d61310a565b905f5260205f200154905080875f01848154811061263d5761263d61310a565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061266f5761266f6132b2565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f90556001935050505061082e565b5f61082e6126b06129d1565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b60808101516001600160a01b03166127a2578060c0015134101561273b576040517fd9127f0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015f9054906101000a90046001600160a01b03166001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004015f604051808303818588803b158015612788575f80fd5b505af115801561279a573d5f803e3d5ffd5b505050505050565b610b578160200151308360c0015184608001516001600160a01b03166129df909392919063ffffffff16565b60a08101516001600160a01b03166128bc5760015460e0820151604051632e1a7d4d60e01b81526001600160a01b0390921691632e1a7d4d916128179160040190815260200190565b5f604051808303815f87803b15801561282e575f80fd5b505af1158015612840573d5f803e3d5ffd5b505050505f81604001516001600160a01b03168260e001516040515f6040518083038185875af1925050503d805f8114612895576040519150601f19603f3d011682016040523d82523d5f602084013e61289a565b606091505b505090508061092357604051637232c81f60e11b815260040160405180910390fd5b610b5781604001518260e001518360a001516001600160a01b0316611de79092919063ffffffff16565b60808101516001600160a01b031615801561290457508060c0015134115b15610b575760015460c08201516001600160a01b0390911690632e1a7d4d9061292d903461329f565b6040518263ffffffff1660e01b815260040161294b91815260200190565b5f604051808303815f87803b158015612962575f80fd5b505af1158015612974573d5f803e3d5ffd5b50505060c08201515f9150339061298b903461329f565b6040515f81818185875af1925050503d805f8114612895576040519150601f19603f3d011682016040523d82523d5f602084013e61289a565b60606109b083835f612a18565b5f6129da612aca565b905090565b6040516001600160a01b038481166024830152838116604483015260648201839052610aee9186918216906323b872dd90608401611e14565b606081471015612a56576040517fcd78605900000000000000000000000000000000000000000000000000000000815230600482015260240161118e565b5f80856001600160a01b03168486604051612a7191906132c6565b5f6040518083038185875af1925050503d805f8114612aab576040519150601f19603f3d011682016040523d82523d5f602084013e612ab0565b606091505b5091509150612ac0868383612b3d565b9695505050505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f612af4612bb2565b612afc612c2d565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b606082612b5257612b4d82612c82565b6109b0565b8151158015612b6957506001600160a01b0384163b155b15612bab576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260240161118e565b50806109b0565b5f7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10081612bdd611cb8565b805190915015612bf557805160209091012092915050565b81548015612c04579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b5f7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10081612c58611d8b565b805190915015612c7057805160209091012092915050565b60018201548015612c04579392505050565b805115612c925780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60208284031215612cd4575f80fd5b5035919050565b5f60208284031215612ceb575f80fd5b81356001600160e01b0319811681146109b0575f80fd5b80356001600160a01b0381168114612d18575f80fd5b919050565b5f60208284031215612d2d575f80fd5b6109b082612d02565b5f8083601f840112612d46575f80fd5b50813567ffffffffffffffff811115612d5d575f80fd5b602083019150836020828501011115612d74575f80fd5b9250929050565b5f805f60408486031215612d8d575f80fd5b83359250602084013567ffffffffffffffff811115612daa575f80fd5b612db686828701612d36565b9497909650939450505050565b5f8060408385031215612dd4575f80fd5b82359150612de460208401612d02565b90509250929050565b5f8060408385031215612dfe575f80fd5b612e0783612d02565b9150612de460208401612d02565b5f6101008284031215612e26575f80fd5b50919050565b5f805f6101208486031215612e3f575f80fd5b612e498585612e15565b925061010084013567ffffffffffffffff811115612daa575f80fd5b5f5b83811015612e7f578181015183820152602001612e67565b50505f910152565b5f8151808452612e9e816020860160208601612e65565b601f01601f19169290920160200192915050565b7fff00000000000000000000000000000000000000000000000000000000000000881681525f602060e081840152612eed60e084018a612e87565b8381036040850152612eff818a612e87565b606085018990526001600160a01b038816608086015260a0850187905284810360c086015285518082528387019250908301905f5b81811015612f5057835183529284019291840191600101612f34565b50909c9b505050505050505050505050565b5f8060408385031215612f73575f80fd5b50508035926020909101359150565b5f805f806101408587031215612f96575f80fd5b612fa08686612e15565b935061010085013567ffffffffffffffff811115612fbc575f80fd5b612fc887828801612d36565b959890975094956101200135949350505050565b5f8060408385031215612fed575f80fd5b612ff683612d02565b946020939093013593505050565b5f8083601f840112613014575f80fd5b50813567ffffffffffffffff81111561302b575f80fd5b6020830191508360208260051b8501011115612d74575f80fd5b5f805f8060408587031215613058575f80fd5b843567ffffffffffffffff8082111561306f575f80fd5b61307b88838901613004565b90965094506020870135915080821115613093575f80fd5b506130a087828801613004565b95989497509550505050565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761082e5761082e6130c0565b5f8261310557634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffd5b5f6020828403121561312e575f80fd5b81356fffffffffffffffffffffffffffffffff811681146109b0575f80fd5b600181811c9082168061316157607f821691505b602082108103612e2657634e487b7160e01b5f52602260045260245ffd5b601f821115610b40575f81815260208120601f850160051c810160208610156131a55750805b601f850160051c820191505b8181101561279a578281556001016131b1565b815167ffffffffffffffff8111156131de576131de6130ac565b6131f2816131ec845461314d565b8461317f565b602080601f831160018114613225575f841561320e5750858301515b5f19600386901b1c1916600185901b17855561279a565b5f85815260208120601f198616915b8281101561325357888601518255948401946001909101908401613234565b508582101561327057878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f60208284031215613290575f80fd5b815180151581146109b0575f80fd5b8181038181111561082e5761082e6130c0565b634e487b7160e01b5f52603160045260245ffd5b5f82516132d7818460208701612e65565b919091019291505056fea2646970667358221220dca18d1a0013ecb6ec7dcd8a6f542c58718dc35bff54f7db9f7f59a50e54bb5564736f6c63430008140033
Deployed Bytecode
0x6080604052600436106101f7575f3560e01c80636c75d6f511610117578063944bda00116100ac578063ca15c8731161007c578063d547741f11610062578063d547741f146106e5578063ed7df71a14610704578063ffa1ad741461072f575f80fd5b8063ca15c8731461069b578063d4c2c752146106ba575f80fd5b8063944bda0014610637578063a217fddf1461064a578063aa8b38d91461065d578063c1ad7e201461067c575f80fd5b80638456cb59116100e75780638456cb591461057a57806384b0196e1461058e5780639010d07c146105b557806391d14854146105d4575f80fd5b80636c75d6f51461050b578063704802751461051e57806380ca29f41461053d578063822a65721461055c575f80fd5b80633111133c1161018d578063467c9eff1161015d578063467c9eff14610460578063485cc9551461047f5780634f0e0ef31461049e5780635c975abb146104d5575f80fd5b80633111133c146103db57806336568abe1461040e5780633f4ba83a1461042d57806343bc4b9a14610441575f80fd5b80631785f53c116101c85780631785f53c14610323578063248a9ca31461034257806324d7806c1461039d5780632f2ff15d146103bc575f80fd5b80629310ba1461027957806301ffc9a7146102985780630c979919146102cc5780631626ba7e146102eb575f80fd5b36610275576001546001600160a01b031633146102735760015f9054906101000a90046001600160a01b03166001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004015f604051808303818588803b15801561025b575f80fd5b505af115801561026d573d5f803e3d5ffd5b50505050505b005b5f80fd5b348015610284575f80fd5b50610273610293366004612cc4565b610762565b3480156102a3575f80fd5b506102b76102b2366004612cdb565b6107f1565b60405190151581526020015b60405180910390f35b3480156102d7575f80fd5b506102736102e6366004612d1d565b610834565b3480156102f6575f80fd5b5061030a610305366004612d7b565b610927565b6040516001600160e01b031990911681526020016102c3565b34801561032e575f80fd5b5061027361033d366004612d1d565b6109b7565b34801561034d575f80fd5b5061038f61035c366004612cc4565b5f9081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b6040519081526020016102c3565b3480156103a8575f80fd5b506102b76103b7366004612d1d565b610a6c565b3480156103c7575f80fd5b506102736103d6366004612dc3565b610aab565b3480156103e6575f80fd5b5061038f7ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab981565b348015610419575f80fd5b50610273610428366004612dc3565b610af4565b348015610438575f80fd5b50610273610b45565b34801561044c575f80fd5b5061027361045b366004612d1d565b610b5a565b34801561046b575f80fd5b506102b761047a366004612d1d565b610c6f565b34801561048a575f80fd5b50610273610499366004612ded565b610cae565b3480156104a9575f80fd5b506001546104bd906001600160a01b031681565b6040516001600160a01b0390911681526020016102c3565b3480156104e0575f80fd5b507fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff166102b7565b610273610519366004612e2c565b610f46565b348015610529575f80fd5b50610273610538366004612d1d565b610fa2565b348015610548575f80fd5b50610273610557366004612d1d565b611051565b348015610567575f80fd5b505f546104bd906001600160a01b031681565b348015610585575f80fd5b506102736110dc565b348015610599575f80fd5b506105a26110ee565b6040516102c39796959493929190612eb2565b3480156105c0575f80fd5b506104bd6105cf366004612f62565b6111ed565b3480156105df575f80fd5b506102b76105ee366004612dc3565b5f9182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408084206001600160a01b0393909316845291905290205460ff1690565b610273610645366004612f82565b61122d565b348015610655575f80fd5b5061038f5f81565b348015610668575f80fd5b50610273610677366004612fdc565b6112af565b348015610687575f80fd5b50610273610696366004613045565b611434565b3480156106a6575f80fd5b5061038f6106b5366004612cc4565b6116c1565b3480156106c5575f80fd5b5061038f6106d4366004612cc4565b60036020525f908152604090205481565b3480156106f0575f80fd5b506102736106ff366004612dc3565b6116f8565b34801561070f575f80fd5b5061038f61071e366004612cc4565b60026020525f908152604090205481565b34801561073a575f80fd5b5061038f7f312e302e3100000000000000000000000000000000000000000000000000000081565b7ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab961078c8161173b565b600882901c5f90815260036020526040908190208054600160ff86161b179055517f4e26543a3310528c7ccde0f2a250a579a7eb3192762bd6ae53d14c811f8b1209906107e59084904290918252602082015260400190565b60405180910390a15050565b5f6001600160e01b031982167f5a05180f00000000000000000000000000000000000000000000000000000000148061082e575061082e82611745565b92915050565b5f61083e8161173b565b6001600160a01b0382166108655760405163bb6bc9ad60e01b815260040160405180910390fd5b604080516252465160e81b815281519081900360030181206060808352600890830152674144442d524f4c4560c01b60808301527ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab960208301526001600160a01b0385168284015291517fbafee6bdc2193912cf2754d0840b53e34485a4341b4071fb7da8d091ffef67bf9181900360a00190a26109237ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab983610aab565b5050565b5f806109688585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506117ab92505050565b50505f549091506001600160a01b03908116908216036109ab57507f1626ba7e0000000000000000000000000000000000000000000000000000000090506109b0565b505f90505b9392505050565b5f6109c18161173b565b60026109cc5f6116c1565b10156109eb57604051635acf42fb60e01b815260040160405180910390fd5b604080516252465160e81b815281519081900360030181206060808352600b908301526a52454d4f56452d524f4c4560a81b60808301525f60208301526001600160a01b0385168284015291517fbafee6bdc2193912cf2754d0840b53e34485a4341b4071fb7da8d091ffef67bf9181900360a00190a26109235f836116f8565b6001600160a01b0381165f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604081205460ff1661082e565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040902060010154610ae48161173b565b610aee83836117f4565b50505050565b6001600160a01b0381163314610b36576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b408282611849565b505050565b5f610b4f8161173b565b610b57611895565b50565b5f610b648161173b565b6002610b8f7ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab96116c1565b1015610bae57604051635acf42fb60e01b815260040160405180910390fd5b604080516252465160e81b815281519081900360030181206060808352600b908301526a52454d4f56452d524f4c4560a81b60808301527ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab960208301526001600160a01b0385168284015291517fbafee6bdc2193912cf2754d0840b53e34485a4341b4071fb7da8d091ffef67bf9181900360a00190a26109237ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab9836116f8565b6001600160a01b0381165f9081527fe9680e5511d61ade835a081870812c17eb80397105a095e0ffec5f4921adf8d7602052604081205460ff1661082e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610cf85750825b90505f8267ffffffffffffffff166001148015610d145750303b155b905081158015610d22575080155b15610d59576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d8d57845468ff00000000000000001916680100000000000000001785555b6001600160a01b038716610db45760405163393e83a160e11b815260040160405180910390fd5b6001600160a01b038616610df4576040517f05f8e07700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfc611907565b610e04611911565b610e0c611921565b610e806040518060400160405280600681526020017f4361626c657300000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250611931565b610e8a5f336117f4565b50610eb57ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab9886117f4565b505f80546001600160a01b03808a1673ffffffffffffffffffffffffffffffffffffffff199283161790925560018054928916929091169190911790558315610f3d57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b610f4e611943565b610f566119a6565b5f610f62848484611a02565b9050610f78848560c001358660e0013584611b93565b50610b4060017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b5f610fac8161173b565b6001600160a01b038216610fd35760405163bb6bc9ad60e01b815260040160405180910390fd5b604080516252465160e81b815281519081900360030181206060808352600890830152674144442d524f4c4560c01b60808301525f60208301526001600160a01b0385168284015291517fbafee6bdc2193912cf2754d0840b53e34485a4341b4071fb7da8d091ffef67bf9181900360a00190a26109235f83610aab565b5f61105b8161173b565b6001600160a01b0382166110825760405163393e83a160e11b815260040160405180910390fd5b5f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091556040519081527fe6243347c190ae7a28aef8cfd36bcecf9459bbe5d32fb1ee1bf7358dac0b4b40906020016107e5565b5f6110e68161173b565b610b57611c5d565b5f60608082808083817fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100805490915015801561112c57506001810154155b611197576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4549503731323a20556e696e697469616c697a6564000000000000000000000060448201526064015b60405180910390fd5b61119f611cb8565b6111a7611d8b565b604080515f808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009c939b5091995046985030975095509350915050565b5f8281527fc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e823717059320006020819052604082206112259084611ddc565b949350505050565b611235611943565b61123d6119a6565b5f611249858585611a02565b905060c085013560e08601358310156112785760e086013561126b84836130d4565b61127591906130eb565b90505b61128486828585611b93565b5050610aee60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b6112b7611943565b7ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab96112e18161173b565b6001600160a01b0383166113b457600154604051632e1a7d4d60e01b8152600481018490526001600160a01b0390911690632e1a7d4d906024015f604051808303815f87803b158015611332575f80fd5b505af1158015611344573d5f803e3d5ffd5b50506040515f925033915084908381818185875af1925050503d805f8114611387576040519150601f19603f3d011682016040523d82523d5f602084013e61138c565b606091505b50509050806113ae57604051637232c81f60e11b815260040160405180910390fd5b506113c8565b6113c86001600160a01b0384163384611de7565b604080516001600160a01b0385168152602081018490527fa3e40bab7c3da0937e283e65aacdd378a146806f8ac5b873ce32c1f13f45376d910160405180910390a15061092360017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b61143c611943565b7ff48fc9fa479390222c2fd5227bb7e4f7c4a85d969b82dfa11eb0954487273ab96114668161173b565b83821461149f576040517fe4990ff700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b84811015611284575f8686838181106114bc576114bc61310a565b90506020020160208101906114d19190612d1d565b6001600160a01b0316036115e2576001546001600160a01b0316632e1a7d4d8585848181106115025761150261310a565b905060200201356040518263ffffffff1660e01b815260040161152791815260200190565b5f604051808303815f87803b15801561153e575f80fd5b505af1158015611550573d5f803e3d5ffd5b505050505f336001600160a01b03168585848181106115715761157161310a565b905060200201356040515f6040518083038185875af1925050503d805f81146115b5576040519150601f19603f3d011682016040523d82523d5f602084013e6115ba565b606091505b50509050806115dc57604051637232c81f60e11b815260040160405180910390fd5b50611636565b611636338585848181106115f8576115f861310a565b905060200201358888858181106116115761161161310a565b90506020020160208101906116269190612d1d565b6001600160a01b03169190611de7565b7fa3e40bab7c3da0937e283e65aacdd378a146806f8ac5b873ce32c1f13f45376d8686838181106116695761166961310a565b905060200201602081019061167e9190612d1d565b8585848181106116905761169061310a565b604080516001600160a01b0390951685526020918202939093013590840152500160405180910390a16001016114a1565b5f8181527fc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e823717059320006020819052604082206109b090611e5b565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260409020600101546117318161173b565b610aee8383611849565b610b578133611e64565b5f6001600160e01b031982167f7965db0b00000000000000000000000000000000000000000000000000000000148061082e57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b031983161461082e565b5f805f83516041036117e2576020840151604085015160608601515f1a6117d488828585611ef0565b9550955095505050506117ed565b505081515f91506002905b9250925092565b5f7fc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e82371705932000816118218585611fb8565b90508015611225575f8581526020839052604090206118409085612084565b50949350505050565b5f7fc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e82371705932000816118768585612098565b90508015611225575f858152602083905260409020611840908561213c565b61189d612150565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300805460ff191681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a150565b61190f6121ab565b565b6119196121ab565b61190f612212565b6119296121ab565b61190f612245565b6119396121ab565b610923828261224d565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f008054600119016119a0576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60029055565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff161561190f576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f833560601c80611a265760405163bb6bc9ad60e01b815260040160405180910390fd5b8460e001355f03611a63576040517f7685565700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f95afddf5e4bb9f692716b7fdff640e6b8a0d2869597405c6e9d35857ed19a1508635611a976040890160208a0161311e565b611aa760608a0160408b01612d1d565b611ab760808b0160608c01612d1d565b611ac760a08c0160808d01612d1d565b611ad760c08d0160a08e01612d1d565b6040805160208101989098528701959095526fffffffffffffffffffffffffffffffff90931660608601526001600160a01b039182166080860152811660a085015290811660c084810191909152911660e0838101919091529088013561010083015287013561012082015261014001604051602081830303815290604052805190602001209050611840865f0135876020016020810190611b79919061311e565b6fffffffffffffffffffffffffffffffff168388886122bf565b604080516101008101909152843581525f9060208101611bb960c0880160a08901612d1d565b6001600160a01b03168152602001836001600160a01b03168152602001468152602001866060016020810190611bef9190612d1d565b6001600160a01b03168152602001611c0d6060880160408901612d1d565b6001600160a01b03168152602001848152602001858152509050611c308161241f565b5050505050565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b611c656119a6565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300805460ff191660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258336118e9565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10280546060917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10091611d099061314d565b80601f0160208091040260200160405190810160405280929190818152602001828054611d359061314d565b8015611d805780601f10611d5757610100808354040283529160200191611d80565b820191905f5260205f20905b815481529060010190602001808311611d6357829003601f168201915b505050505091505090565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10380546060917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10091611d099061314d565b5f6109b083836124de565b6040516001600160a01b03838116602483015260448201839052610b4091859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612504565b5f61082e825490565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408083206001600160a01b038516845290915290205460ff16610923576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024810183905260440161118e565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115611f2957505f91506003905082611fae565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015611f7a573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116611fa557505f925060019150829050611fae565b92505f91508190505b9450945094915050565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff1661207b575f848152602082815260408083206001600160a01b03871684529091529020805460ff191660011790556120313390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600191505061082e565b5f91505061082e565b5f6109b0836001600160a01b03841661257e565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff161561207b575f848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4600191505061082e565b5f6109b0836001600160a01b0384166125ca565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1661190f576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661190f576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61221a6121ab565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300805460ff19169055565b611c376121ab565b6122556121ab565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1026122a184826131c4565b50600381016122b083826131c4565b505f8082556001909101555050565b600885901c5f81815260026020526040902054600160ff88161b9080821615612314576040517fd3b9dd1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8381526003602052604090205482161561235b576040517fdc44eb9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86421115612395576040517f4c2067c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123a86123a1876126a4565b8686610927565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916631626ba7e60e01b14612406576040517fd1cc120200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f92835260026020526040909220911790555050505050565b612428816126eb565b612431816127ce565b61243a816128e6565b805f01517f68eb6d948c037c94e470f9a5b288dd93debbcd9342635408e66cb0211686f7f782602001518360400151846060015185608001518660a001518760c001518860e001516040516124d397969594939291906001600160a01b039788168152958716602087015260408601949094529185166060850152909316608083015260a082019290925260c081019190915260e00190565b60405180910390a250565b5f825f0182815481106124f3576124f361310a565b905f5260205f200154905092915050565b5f6125186001600160a01b038416836129c4565b905080515f1415801561253c57508080602001905181019061253a9190613280565b155b15610b40576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260240161118e565b5f8181526001830160205260408120546125c357508154600181810184555f84815260208082209093018490558454848252828601909352604090209190915561082e565b505f61082e565b5f818152600183016020526040812054801561207b575f6125ec60018361329f565b85549091505f906125ff9060019061329f565b905080821461265e575f865f01828154811061261d5761261d61310a565b905f5260205f200154905080875f01848154811061263d5761263d61310a565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061266f5761266f6132b2565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f90556001935050505061082e565b5f61082e6126b06129d1565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b60808101516001600160a01b03166127a2578060c0015134101561273b576040517fd9127f0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015f9054906101000a90046001600160a01b03166001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004015f604051808303818588803b158015612788575f80fd5b505af115801561279a573d5f803e3d5ffd5b505050505050565b610b578160200151308360c0015184608001516001600160a01b03166129df909392919063ffffffff16565b60a08101516001600160a01b03166128bc5760015460e0820151604051632e1a7d4d60e01b81526001600160a01b0390921691632e1a7d4d916128179160040190815260200190565b5f604051808303815f87803b15801561282e575f80fd5b505af1158015612840573d5f803e3d5ffd5b505050505f81604001516001600160a01b03168260e001516040515f6040518083038185875af1925050503d805f8114612895576040519150601f19603f3d011682016040523d82523d5f602084013e61289a565b606091505b505090508061092357604051637232c81f60e11b815260040160405180910390fd5b610b5781604001518260e001518360a001516001600160a01b0316611de79092919063ffffffff16565b60808101516001600160a01b031615801561290457508060c0015134115b15610b575760015460c08201516001600160a01b0390911690632e1a7d4d9061292d903461329f565b6040518263ffffffff1660e01b815260040161294b91815260200190565b5f604051808303815f87803b158015612962575f80fd5b505af1158015612974573d5f803e3d5ffd5b50505060c08201515f9150339061298b903461329f565b6040515f81818185875af1925050503d805f8114612895576040519150601f19603f3d011682016040523d82523d5f602084013e61289a565b60606109b083835f612a18565b5f6129da612aca565b905090565b6040516001600160a01b038481166024830152838116604483015260648201839052610aee9186918216906323b872dd90608401611e14565b606081471015612a56576040517fcd78605900000000000000000000000000000000000000000000000000000000815230600482015260240161118e565b5f80856001600160a01b03168486604051612a7191906132c6565b5f6040518083038185875af1925050503d805f8114612aab576040519150601f19603f3d011682016040523d82523d5f602084013e612ab0565b606091505b5091509150612ac0868383612b3d565b9695505050505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f612af4612bb2565b612afc612c2d565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b606082612b5257612b4d82612c82565b6109b0565b8151158015612b6957506001600160a01b0384163b155b15612bab576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b038516600482015260240161118e565b50806109b0565b5f7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10081612bdd611cb8565b805190915015612bf557805160209091012092915050565b81548015612c04579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b5f7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10081612c58611d8b565b805190915015612c7057805160209091012092915050565b60018201548015612c04579392505050565b805115612c925780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60208284031215612cd4575f80fd5b5035919050565b5f60208284031215612ceb575f80fd5b81356001600160e01b0319811681146109b0575f80fd5b80356001600160a01b0381168114612d18575f80fd5b919050565b5f60208284031215612d2d575f80fd5b6109b082612d02565b5f8083601f840112612d46575f80fd5b50813567ffffffffffffffff811115612d5d575f80fd5b602083019150836020828501011115612d74575f80fd5b9250929050565b5f805f60408486031215612d8d575f80fd5b83359250602084013567ffffffffffffffff811115612daa575f80fd5b612db686828701612d36565b9497909650939450505050565b5f8060408385031215612dd4575f80fd5b82359150612de460208401612d02565b90509250929050565b5f8060408385031215612dfe575f80fd5b612e0783612d02565b9150612de460208401612d02565b5f6101008284031215612e26575f80fd5b50919050565b5f805f6101208486031215612e3f575f80fd5b612e498585612e15565b925061010084013567ffffffffffffffff811115612daa575f80fd5b5f5b83811015612e7f578181015183820152602001612e67565b50505f910152565b5f8151808452612e9e816020860160208601612e65565b601f01601f19169290920160200192915050565b7fff00000000000000000000000000000000000000000000000000000000000000881681525f602060e081840152612eed60e084018a612e87565b8381036040850152612eff818a612e87565b606085018990526001600160a01b038816608086015260a0850187905284810360c086015285518082528387019250908301905f5b81811015612f5057835183529284019291840191600101612f34565b50909c9b505050505050505050505050565b5f8060408385031215612f73575f80fd5b50508035926020909101359150565b5f805f806101408587031215612f96575f80fd5b612fa08686612e15565b935061010085013567ffffffffffffffff811115612fbc575f80fd5b612fc887828801612d36565b959890975094956101200135949350505050565b5f8060408385031215612fed575f80fd5b612ff683612d02565b946020939093013593505050565b5f8083601f840112613014575f80fd5b50813567ffffffffffffffff81111561302b575f80fd5b6020830191508360208260051b8501011115612d74575f80fd5b5f805f8060408587031215613058575f80fd5b843567ffffffffffffffff8082111561306f575f80fd5b61307b88838901613004565b90965094506020870135915080821115613093575f80fd5b506130a087828801613004565b95989497509550505050565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761082e5761082e6130c0565b5f8261310557634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffd5b5f6020828403121561312e575f80fd5b81356fffffffffffffffffffffffffffffffff811681146109b0575f80fd5b600181811c9082168061316157607f821691505b602082108103612e2657634e487b7160e01b5f52602260045260245ffd5b601f821115610b40575f81815260208120601f850160051c810160208610156131a55750805b601f850160051c820191505b8181101561279a578281556001016131b1565b815167ffffffffffffffff8111156131de576131de6130ac565b6131f2816131ec845461314d565b8461317f565b602080601f831160018114613225575f841561320e5750858301515b5f19600386901b1c1916600185901b17855561279a565b5f85815260208120601f198616915b8281101561325357888601518255948401946001909101908401613234565b508582101561327057878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f60208284031215613290575f80fd5b815180151581146109b0575f80fd5b8181038181111561082e5761082e6130c0565b634e487b7160e01b5f52603160045260245ffd5b5f82516132d7818460208701612e65565b919091019291505056fea2646970667358221220dca18d1a0013ecb6ec7dcd8a6f542c58718dc35bff54f7db9f7f59a50e54bb5564736f6c63430008140033
Deployed Bytecode Sourcemap
115750:18331:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119550:11;;-1:-1:-1;;;;;119550:11:0;119536:10;:25;119532:107;;119585:11;;;;;;;;;-1:-1:-1;;;;;119585:11:0;-1:-1:-1;;;;;119578:27:0;;119614:9;119578:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119532:107;115750:18331;;;;;121820:231;;;;;;;;;;-1:-1:-1;121820:231:0;;;;;:::i;:::-;;:::i;67270:214::-;;;;;;;;;;-1:-1:-1;67270:214:0;;;;;:::i;:::-;;:::i;:::-;;;701:14:1;;694:22;676:41;;664:2;649:18;67270:214:0;;;;;;;;124957:320;;;;;;;;;;-1:-1:-1;124957:320:0;;;;;:::i;:::-;;:::i;127738:315::-;;;;;;;;;;-1:-1:-1;127738:315:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;;2116:79:1;;;2098:98;;2086:2;2071:18;127738:315:0;1954:248:1;126357:338:0;;;;;;;;;;-1:-1:-1;126357:338:0;;;;;:::i;:::-;;:::i;62111:194::-;;;;;;;;;;-1:-1:-1;62111:194:0;;;;;:::i;:::-;62176:7;62273:14;;;60215:28;62273:14;;;;;:24;;;;62111:194;;;;2538:25:1;;;2526:2;2511:18;62111:194:0;2392:177:1;127220:127:0;;;;;;;;;;-1:-1:-1;127220:127:0;;;;;:::i;:::-;;:::i;62615:138::-;;;;;;;;;;-1:-1:-1;62615:138:0;;;;;:::i;:::-;;:::i;116102:82::-;;;;;;;;;;;;116150:34;116102:82;;63752:251;;;;;;;;;;-1:-1:-1;63752:251:0;;;;;:::i;:::-;;:::i;122781:86::-;;;;;;;;;;;;;:::i;125422:352::-;;;;;;;;;;-1:-1:-1;125422:352:0;;;;;:::i;:::-;;:::i;126893:135::-;;;;;;;;;;-1:-1:-1;126893:135:0;;;;;:::i;:::-;;:::i;118508:623::-;;;;;;;;;;-1:-1:-1;118508:623:0;;;;;:::i;:::-;;:::i;117248:26::-;;;;;;;;;;-1:-1:-1;117248:26:0;;;;-1:-1:-1;;;;;117248:26:0;;;;;;-1:-1:-1;;;;;3262:55:1;;;3244:74;;3232:2;3217:18;117248:26:0;3098:226:1;82046:148:0;;;;;;;;;;-1:-1:-1;80561:23:0;82177:9;;;82046:148;;120154:272;;;;;;:::i;:::-;;:::i;125906:309::-;;;;;;;;;;-1:-1:-1;125906:309:0;;;;;:::i;:::-;;:::i;122231:270::-;;;;;;;;;;-1:-1:-1;122231:270:0;;;;;:::i;:::-;;:::i;117170:25::-;;;;;;;;;;-1:-1:-1;117170:25:0;;;;-1:-1:-1;;;;;117170:25:0;;;122599:82;;;;;;;;;;;;;:::i;75674:931::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;68083:236::-;;;;;;;;;;-1:-1:-1;68083:236:0;;;;;:::i;:::-;;:::i;61055:210::-;;;;;;;;;;-1:-1:-1;61055:210:0;;;;;:::i;:::-;61132:4;61226:14;;;60215:28;61226:14;;;;;;;;-1:-1:-1;;;;;61226:31:0;;;;;;;;;;;;;;;61055:210;121066:508;;;;;;:::i;:::-;;:::i;59599:49::-;;;;;;;;;;-1:-1:-1;59599:49:0;59644:4;59599:49;;123133:527;;;;;;;;;;-1:-1:-1;123133:527:0;;;;;:::i;:::-;;:::i;123958:864::-;;;;;;;;;;-1:-1:-1;123958:864:0;;;;;:::i;:::-;;:::i;68493:225::-;;;;;;;;;;-1:-1:-1;68493:225:0;;;;;:::i;:::-;;:::i;117511:47::-;;;;;;;;;;-1:-1:-1;117511:47:0;;;;;:::i;:::-;;;;;;;;;;;;;;63046:140;;;;;;;;;;-1:-1:-1;63046:140:0;;;;;:::i;:::-;;:::i;117352:49::-;;;;;;;;;;-1:-1:-1;117352:49:0;;;;;:::i;:::-;;;;;;;;;;;;;;116013:50;;;;;;;;;;;;116047:16;116013:50;;121820:231;116150:34;60495:16;60506:4;60495:10;:16::i;:::-;121951:1:::1;121934:18:::0;;::::1;121921:32;::::0;;;:12:::1;:32;::::0;;;;;;:63;;121957:1:::1;121979:4;121963:20:::0;::::1;121957:27;121921:63;::::0;;122000:43;::::1;::::0;::::1;::::0;121963:13;;122027:15:::1;::::0;8522:25:1;;;8578:2;8563:18;;8556:34;8510:2;8495:18;;8348:248;122000:43:0::1;;;;;;;;121820:231:::0;;:::o;67270:214::-;67355:4;-1:-1:-1;;;;;;67379:57:0;;67394:42;67379:57;;:97;;;67440:36;67464:11;67440:23;:36::i;:::-;67372:104;67270:214;-1:-1:-1;;67270:214:0:o;124957:320::-;59644:4;60495:16;59644:4;60495:10;:16::i;:::-;-1:-1:-1;;;;;125059:22:0;::::1;125055:83;;125105:21;;-1:-1:-1::0;;;125105:21:0::1;;;;;;;;;;;125055:83;125153:63;::::0;;-1:-1:-1;;;8803:18:1;;125153:63:0;;;;;;8846:1:1;125153:63:0;;;9117:2:1;9099:21;;;9156:1;9136:18;;;9129:29;-1:-1:-1;;;9189:3:1;9174:19;;9167:39;116150:34:0::1;9273:4:1::0;9258:20;;9251:36;-1:-1:-1;;;;;9323:55:1;;9303:18;;;9296:83;125153:63:0;;::::1;::::0;;;;9238:3:1;125153:63:0;;::::1;125227:42;116150:34;125260:8;125227:9;:42::i;:::-;124957:320:::0;;:::o;127738:315::-;127836:6;127856:14;127878:35;127895:5;127902:10;;127878:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;127878:16:0;;-1:-1:-1;;;127878:35:0:i;:::-;-1:-1:-1;;127940:10:0;;127855:58;;-1:-1:-1;;;;;;127940:10:0;;;127930:20;;;;127926:120;;-1:-1:-1;127967:17:0;;-1:-1:-1;127967:17:0;;127926:120;-1:-1:-1;128024:10:0;;-1:-1:-1;127738:315:0;;;;;;:::o;126357:338::-;59644:4;60495:16;59644:4;60495:10;:16::i;:::-;126498:1:::1;126457:38;59644:4;126457:18;:38::i;:::-;:42;126453:105;;;126523:23;;-1:-1:-1::0;;;126523:23:0::1;;;;;;;;;;;126453:105;126573:63;::::0;;-1:-1:-1;;;8803:18:1;;126573:63:0;;;;;;8846:1:1;126573:63:0;;;9648:2:1;9630:21;;;9687:2;9667:18;;;9660:30;-1:-1:-1;;;9721:3:1;9706:19;;9699:42;-1:-1:-1;9808:4:1;9793:20;;9786:36;-1:-1:-1;;;;;9858:55:1;;9838:18;;;9831:83;126573:63:0;;::::1;::::0;;;;9773:3:1;126573:63:0;;::::1;126647:40;59644:4;126678:8:::0;126647:10:::1;:40::i;127220:127::-:0;-1:-1:-1;;;;;61226:31:0;;127278:4;61226:31;;;:14;;:31;:14;:31;;;;;127302:37;61055:210;62615:138;62176:7;62273:14;;;60215:28;62273:14;;;;;:24;;;60495:16;60506:4;60495:10;:16::i;:::-;62720:25:::1;62731:4;62737:7;62720:10;:25::i;:::-;;62615:138:::0;;;:::o;63752:251::-;-1:-1:-1;;;;;63846:34:0;;54992:10;63846:34;63842:104;;63904:30;;;;;;;;;;;;;;63842:104;63958:37;63970:4;63976:18;63958:11;:37::i;:::-;;63752:251;;:::o;122781:86::-;59644:4;60495:16;59644:4;60495:10;:16::i;:::-;122849:10:::1;:8;:10::i;:::-;122781:86:::0;:::o;125422:352::-;59644:4;60495:16;59644:4;60495:10;:16::i;:::-;125571:1:::1;125527:41;116150:34;125527:18;:41::i;:::-;:45;125523:108;;;125596:23;;-1:-1:-1::0;;;125596:23:0::1;;;;;;;;;;;125523:108;125646:66;::::0;;-1:-1:-1;;;8803:18:1;;125646:66:0;;;;;;8846:1:1;125646:66:0;;;9648:2:1;9630:21;;;9687:2;9667:18;;;9660:30;-1:-1:-1;;;9721:3:1;9706:19;;9699:42;116150:34:0::1;9808:4:1::0;9793:20;;9786:36;-1:-1:-1;;;;;9858:55:1;;9838:18;;;9831:83;125646:66:0;;::::1;::::0;;;;9773:3:1;125646:66:0;;::::1;125723:43;116150:34;125757:8;125723:10;:43::i;126893:135::-:0;-1:-1:-1;;;;;61226:31:0;;126956:4;61226:31;;;:14;;:31;:14;:31;;;;;126980:40;61055:210;118508:623;53917:21;49233:15;;;;;;;49232:16;;49280:14;;49086:30;49665:16;;:34;;;;;49685:14;49665:34;49645:54;;49710:17;49730:11;:16;;49745:1;49730:16;:50;;;;-1:-1:-1;49758:4:0;49750:25;:30;49730:50;49710:70;;49798:12;49797:13;:30;;;;;49815:12;49814:13;49797:30;49793:93;;;49851:23;;;;;;;;;;;;;;49793:93;49896:18;;-1:-1:-1;;49896:18:0;49913:1;49896:18;;;49925:69;;;;49960:22;;-1:-1:-1;;49960:22:0;;;;;49925:69;-1:-1:-1;;;;;118607:25:0;::::1;118603:89;;118656:24;;-1:-1:-1::0;;;118656:24:0::1;;;;;;;;;;;118603:89;-1:-1:-1::0;;;;;118706:26:0;::::1;118702:91;;118756:25;;;;;;;;;;;;;;118702:91;118803:32;:30;:32::i;:::-;118846:17;:15;:17::i;:::-;118874:24;:22;:24::i;:::-;118909:28;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;::::0;:13:::1;:28::i;:::-;118950:42;59644:4;118981:10;118950;:42::i;:::-;;119003:46;116150:34;119037:11;119003:10;:46::i;:::-;-1:-1:-1::0;119062:10:0::1;:24:::0;;-1:-1:-1;;;;;119062:24:0;;::::1;-1:-1:-1::0;;119062:24:0;;::::1;;::::0;;;;119097:26;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;50016:104;;;;50051:23;;-1:-1:-1;;50051:23:0;;;50094:14;;-1:-1:-1;10078:50:1;;50094:14:0;;10066:2:1;10051:18;50094:14:0;;;;;;;50016:104;49018:1109;;;;;118508:623;;:::o;120154:272::-;86632:21;:19;:21::i;:::-;81651:19:::1;:17;:19::i;:::-;120279:18:::2;120300:32;120313:6;120321:10;;120300:12;:32::i;:::-;120279:53;;120345:73;120359:6;120367;:18;;;120387:6;:18;;;120407:10;120345:13;:73::i;:::-;120268:158;86676:20:::0;85147:1;85743:30;87370:23;87113:288;125906:309;59644:4;60495:16;59644:4;60495:10;:16::i;:::-;-1:-1:-1;;;;;126003:22:0;::::1;125999:83;;126049:21;;-1:-1:-1::0;;;126049:21:0::1;;;;;;;;;;;125999:83;126097:60;::::0;;-1:-1:-1;;;8803:18:1;;126097:60:0;;;;;;8846:1:1;126097:60:0;;;9117:2:1;9099:21;;;9156:1;9136:18;;;9129:29;-1:-1:-1;;;9189:3:1;9174:19;;9167:39;-1:-1:-1;9273:4:1;9258:20;;9251:36;-1:-1:-1;;;;;9323:55:1;;9303:18;;;9296:83;126097:60:0;;::::1;::::0;;;;9238:3:1;126097:60:0;;::::1;126168:39;59644:4;126198:8:::0;126168:9:::1;:39::i;122231:270::-:0;59644:4;60495:16;59644:4;60495:10;:16::i;:::-;-1:-1:-1;;;;;122328:25:0;::::1;122324:89;;122377:24;;-1:-1:-1::0;;;122377:24:0::1;;;;;;;;;;;122324:89;122423:10;:24:::0;;-1:-1:-1;;122423:24:0::1;-1:-1:-1::0;;;;;122423:24:0;::::1;::::0;;::::1;::::0;;;122463:30:::1;::::0;3244:74:1;;;122463:30:0::1;::::0;3232:2:1;3217:18;122463:30:0::1;3098:226:1::0;122599:82:0;59644:4;60495:16;59644:4;60495:10;:16::i;:::-;122665:8:::1;:6;:8::i;75674:931::-:0;75777:13;75805:18;;75777:13;;;75805:18;75777:13;73277:21;76295:13;;76026:45;;-1:-1:-1;76295:18:0;:43;;;;-1:-1:-1;76317:16:0;;;;:21;76295:43;76287:77;;;;;;;10341:2:1;76287:77:0;;;10323:21:1;10380:2;10360:18;;;10353:30;10419:23;10399:18;;;10392:51;10460:18;;76287:77:0;;;;;;;;;76430:13;:11;:13::i;:::-;76458:16;:14;:16::i;:::-;76570;;;76553:1;76570:16;;;;;;;;;76377:220;;;;-1:-1:-1;76377:220:0;;-1:-1:-1;76489:13:0;;-1:-1:-1;76525:4:0;;-1:-1:-1;76553:1:0;-1:-1:-1;76570:16:0;-1:-1:-1;76377:220:0;-1:-1:-1;;75674:931:0:o;68083:236::-;68164:7;68281:20;;;66966:38;68281:20;;;;;;;:30;;68305:5;68281:23;:30::i;:::-;68274:37;68083:236;-1:-1:-1;;;;68083:236:0:o;121066:508::-;86632:21;:19;:21::i;:::-;81651:19:::1;:17;:19::i;:::-;121248:18:::2;121269:32;121282:6;121290:10;;121269:12;:32::i;:::-;121248:53:::0;-1:-1:-1;121336:18:0::2;::::0;::::2;;121384;::::0;::::2;;121369:33:::0;::::2;121365:129;;;121464:18;::::0;::::2;;121434:26;121448:12:::0;121434:11;:26:::2;:::i;:::-;121433:49;;;;:::i;:::-;121419:63;;121365:129;121506:60;121520:6;121528:11;121541:12;121555:10;121506:13;:60::i;:::-;121237:337;;86676:20:::0;85147:1;85743:30;87370:23;87113:288;123133:527;86632:21;:19;:21::i;:::-;116150:34:::1;60495:16;60506:4;60495:10;:16::i;:::-;-1:-1:-1::0;;;;;123257:20:0;::::2;123253:349;;123301:11;::::0;123294:37:::2;::::0;-1:-1:-1;;;123294:37:0;;::::2;::::0;::::2;2538:25:1::0;;;-1:-1:-1;;;;;123301:11:0;;::::2;::::0;123294:28:::2;::::0;2511:18:1;;123294:37:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;123365:44:0::2;::::0;123347:12:::2;::::0;-1:-1:-1;123373:10:0::2;::::0;-1:-1:-1;123397:7:0;;123347:12;123365:44;123347:12;123365:44;123397:7;123373:10;123365:44:::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;123346:63;;;123429:7;123424:72;;123464:16;;-1:-1:-1::0;;;123464:16:0::2;;;;;;;;;;;123424:72;123279:242;123253:349;;;123542:48;-1:-1:-1::0;;;;;123542:27:0;::::2;123570:10;123582:7:::0;123542:27:::2;:48::i;:::-;123617:35;::::0;;-1:-1:-1;;;;;11721:55:1;;11703:74;;11808:2;11793:18;;11786:34;;;123617:35:0::2;::::0;11676:18:1;123617:35:0::2;;;;;;;86664:1:::1;86676:20:::0;85147:1;85743:30;87370:23;87113:288;123958:864;86632:21;:19;:21::i;:::-;116150:34:::1;60495:16;60506:4;60495:10;:16::i;:::-;124136:33:::0;;::::2;124132:94;;124193:21;;;;;;;;;;;;;;124132:94;124236:9;124258:557;124265:18:::0;;::::2;124258:557;;;124326:1;124304:7:::0;;124312:1;124304:10;;::::2;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;124304:24:0::2;::::0;124300:379:::2;;124356:11;::::0;-1:-1:-1;;;;;124356:11:0::2;124349:28;124378:8:::0;;124387:1;124378:11;;::::2;;;;;:::i;:::-;;;;;;;124349:41;;;;;;;;;;;;;2538:25:1::0;;2526:2;2511:18;;2392:177;124349:41:0::2;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;124410:12;124436:10;-1:-1:-1::0;;;;;124428:24:0::2;124460:8;;124469:1;124460:11;;;;;;;:::i;:::-;;;;;;;124428:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;124409:67;;;124500:7;124495:72;;124535:16;;-1:-1:-1::0;;;124535:16:0::2;;;;;;;;;;;124495:72;124330:252;124300:379;;;124607:56;124639:10;124651:8;;124660:1;124651:11;;;;;;;:::i;:::-;;;;;;;124614:7;;124622:1;124614:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;124607:31:0::2;::::0;:56;:31:::2;:56::i;:::-;124698:43;124717:7;;124725:1;124717:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;124729:8;;124738:1;124729:11;;;;;;;:::i;:::-;124698:43;::::0;;-1:-1:-1;;;;;11721:55:1;;;11703:74;;124729:11:0::2;::::0;;::::2;::::0;;;::::2;;11793:18:1::0;;;11786:34;-1:-1:-1;11676:18:1;124698:43:0::2;;;;;;;124785:3;;124258:557;;68493:225:::0;68564:7;68681:20;;;66966:38;68681:20;;;;;;;:29;;:27;:29::i;63046:140::-;62176:7;62273:14;;;60215:28;62273:14;;;;;:24;;;60495:16;60506:4;60495:10;:16::i;:::-;63152:26:::1;63164:4;63170:7;63152:11;:26::i;61480:105::-:0;61547:30;61558:4;54992:10;61547;:30::i;60759:204::-;60844:4;-1:-1:-1;;;;;;60868:47:0;;60883:32;60868:47;;:87;;-1:-1:-1;57369:25:0;-1:-1:-1;;;;;;57354:40:0;;;60919:36;57254:148;109339:783;109420:7;109429:12;109443:7;109467:9;:16;109487:2;109467:22;109463:652;;109811:4;109796:20;;109790:27;109861:4;109846:20;;109840:27;109919:4;109904:20;;109898:27;109506:9;109890:36;109962:25;109973:4;109890:36;109790:27;109840;109962:10;:25::i;:::-;109955:32;;;;;;;;;;;109463:652;-1:-1:-1;;110085:16:0;;110036:1;;-1:-1:-1;110040:35:0;;109463:652;109339:783;;;;;:::o;68825:355::-;68911:4;66966:38;68911:4;69033:31;69050:4;69056:7;69033:16;:31::i;:::-;69018:46;;69079:7;69075:73;;;69103:14;:20;;;;;;;;;;:33;;69128:7;69103:24;:33::i;:::-;;69165:7;68825:355;-1:-1:-1;;;;68825:355:0:o;69288:360::-;69375:4;66966:38;69375:4;69497:32;69515:4;69521:7;69497:17;:32::i;:::-;69482:47;;69544:7;69540:76;;;69568:14;:20;;;;;;;;;;:36;;69596:7;69568:27;:36::i;83071:182::-;81910:16;:14;:16::i;:::-;80561:23;83190:17;;-1:-1:-1;;83190:17:0::1;::::0;;83223:22:::1;54992:10:::0;83232:12:::1;83223:22;::::0;-1:-1:-1;;;;;3262:55:1;;;3244:74;;3232:2;3217:18;83223:22:0::1;;;;;;;83119:134;83071:182::o:0;67030:76::-;51924:20;:18;:20::i;:::-;67030:76::o;81154:99::-;51924:20;:18;:20::i;:::-;81218:27:::1;:25;:27::i;85904:113::-:0;51924:20;:18;:20::i;:::-;85975:34:::1;:32;:34::i;73900:149::-:0;51924:20;:18;:20::i;:::-;74003:38:::1;74027:4;74033:7;74003:23;:38::i;86712:393::-:0;85743:30;86915:9;;-1:-1:-1;;86915:20:0;86911:90;;86959:30;;;;;;;;;;;;;;86911:90;85190:1;87078:19;;86712:393::o;82267:132::-;80561:23;82177:9;;;82329:63;;;82365:15;;;;;;;;;;;;;;128382:953;128471:7;128528:19;;128551:2;128528:25;;128568:85;;128620:21;;-1:-1:-1;;;128620:21:0;;;;;;;;;;;128568:85;128667:6;:18;;;128689:1;128667:23;128663:75;;128714:12;;;;;;;;;;;;;;128663:75;128750:20;116280:185;128859:19;;128897:13;;;;;;;;:::i;:::-;128929:17;;;;;;;;:::i;:::-;128965;;;;;;;;:::i;:::-;129001:12;;;;;;;;:::i;:::-;129032;;;;;;;;:::i;:::-;128797:336;;;;;;12697:25:1;;;;12738:18;;12731:34;;;;12813;12801:47;;;12781:18;;;12774:75;-1:-1:-1;;;;;12946:15:1;;;12926:18;;;12919:43;12999:15;;12978:19;;;12971:44;13052:15;;;129063:18:0;13031:19:1;;;13024:44;;;;13105:15;;129100:18:0;13084:19:1;;;13077:44;;;;129063:18:0;;;;13137:19:1;;;13130:35;129100:18:0;;;13181:19:1;;;13174:35;12669:19;;128797:336:0;;;;;;;;;;;;128773:371;;;;;;128750:394;;129155:144;129189:6;:19;;;129223:6;:13;;;;;;;;;;:::i;:::-;129155:144;;129251:12;129278:10;;129155:19;:144::i;129745:593::-;129945:344;;;;;;;;;129983:19;;129945:344;;129918:24;;129945:344;;;130024:12;;;;;;;;:::i;:::-;-1:-1:-1;;;;;129945:344:0;;;;;130063:11;-1:-1:-1;;;;;129945:344:0;;;;;130102:13;129945:344;;;;130140:6;:17;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;129945:344:0;;;;;130183:17;;;;;;;;:::i;:::-;-1:-1:-1;;;;;129945:344:0;;;;;130226:12;129945:344;;;;130265:12;129945:344;;;129918:371;;130300:30;130321:8;130300:20;:30::i;:::-;129907:431;129745:593;;;;:::o;87113:288::-;85147:1;85743:30;87370:23;87113:288::o;82750:180::-;81651:19;:17;:19::i;:::-;80561:23;82870:16;;-1:-1:-1;;82870:16:0::1;82882:4;82870:16;::::0;;82902:20:::1;54992:10:::0;82909:12:::1;54912:98:::0;76837:158;76980:7;76973:14;;76891:13;;73277:21;;76973:14;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76837:158;:::o;77230:164::-;77376:10;77369:17;;77287:13;;73277:21;;77369:17;;;:::i;41220:158::-;41294:7;41345:22;41349:3;41361:5;41345:3;:22::i;102510:162::-;102620:43;;-1:-1:-1;;;;;11721:55:1;;;102620:43:0;;;11703:74:1;11793:18;;;11786:34;;;102593:71:0;;102613:5;;102635:14;;;;;11676:18:1;;102620:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102593:19;:71::i;40749:117::-;40812:7;40839:19;40847:3;36049:18;;35966:109;61721:201;61132:4;61226:14;;;60215:28;61226:14;;;;;;;;-1:-1:-1;;;;;61226:31:0;;;;;;;;;;;;61805:110;;61856:47;;;;;-1:-1:-1;;;;;11721:55:1;;61856:47:0;;;11703:74:1;11793:18;;;11786:34;;;11676:18;;61856:47:0;11529:297:1;112416:1556:0;112547:7;;;113490:66;113477:79;;113473:166;;;-1:-1:-1;113589:1:0;;-1:-1:-1;113593:30:0;;-1:-1:-1;113625:1:0;113573:54;;113473:166;113753:24;;;113736:14;113753:24;;;;;;;;;14191:25:1;;;14264:4;14252:17;;14232:18;;;14225:45;;;;14286:18;;;14279:34;;;14329:18;;;14322:34;;;113753:24:0;;14163:19:1;;113753:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;113753:24:0;;-1:-1:-1;;113753:24:0;;;-1:-1:-1;;;;;;;113792:20:0;;113788:115;;-1:-1:-1;113845:1:0;;-1:-1:-1;113849:29:0;;-1:-1:-1;113845:1:0;;-1:-1:-1;113829:62:0;;113788:115;113923:6;-1:-1:-1;113931:20:0;;-1:-1:-1;113931:20:0;;-1:-1:-1;112416:1556:0;;;;;;;;;:::o;64701:396::-;64778:4;61226:14;;;60215:28;61226:14;;;;;;;;-1:-1:-1;;;;;61226:31:0;;;;;;;;;;;;64865:225;;64909:8;:14;;;;;;;;;;;-1:-1:-1;;;;;64909:31:0;;;;;;;;;:38;;-1:-1:-1;;64909:38:0;64943:4;64909:38;;;64994:12;54992:10;;54912:98;64994:12;-1:-1:-1;;;;;64967:40:0;64985:7;-1:-1:-1;;;;;64967:40:0;64979:4;64967:40;;;;;;;;;;65029:4;65022:11;;;;;64865:225;65073:5;65066:12;;;;;39924:152;39994:4;40018:50;40023:3;-1:-1:-1;;;;;40043:23:0;;40018:4;:50::i;65341:397::-;65419:4;61226:14;;;60215:28;61226:14;;;;;;;;-1:-1:-1;;;;;61226:31:0;;;;;;;;;;;;65506:225;;;65583:5;65549:14;;;;;;;;;;;-1:-1:-1;;;;;65549:31:0;;;;;;;;;;:39;;-1:-1:-1;;65549:39:0;;;65608:40;54992:10;;65549:14;;65608:40;;65583:5;65608:40;65670:4;65663:11;;;;;40252:158;40325:4;40349:53;40357:3;-1:-1:-1;;;;;40377:23:0;;40349:7;:53::i;82476:130::-;80561:23;82177:9;;;82535:64;;82572:15;;;;;;;;;;;;;;52084:145;53917:21;53598:40;;;;;;52147:75;;52193:17;;;;;;;;;;;;;;81261:159;51924:20;:18;:20::i;:::-;80561:23;81395:17;;-1:-1:-1;;81395:17:0::1;::::0;;81261:159::o;86025:186::-;51924:20;:18;:20::i;74057:338::-;51924:20;:18;:20::i;:::-;73277:21;74226:7;:14:::1;74236:4:::0;74226:7;:14:::1;:::i;:::-;-1:-1:-1::0;74251:10:0::1;::::0;::::1;:20;74264:7:::0;74251:10;:20:::1;:::i;:::-;-1:-1:-1::0;74355:1:0::1;74339:17:::0;;;74367:16:::1;::::0;;::::1;:20:::0;-1:-1:-1;;74057:338:0:o;130661:800::-;130876:1;130859:18;;;130842:14;130958:22;;;:14;:22;;;;;;130903:1;130925:4;130909:20;;130903:27;;130997:13;;;:18;130993:72;;131039:14;;;;;;;;;;;;;;130993:72;131079:20;;;;:12;:20;;;;;;:27;;:32;131075:91;;131135:19;;;;;;;;;;;;;;131075:91;131198:7;131180:15;:25;131176:74;;;131229:9;;;;;;;;;;;;;;131176:74;131274:61;131291:31;131308:13;131291:16;:31::i;:::-;131324:10;;131274:16;:61::i;:::-;:75;;;131339:10;131274:75;;;131270:133;;131373:18;;;;;;;;;;;;;;131270:133;131415:22;;;;:14;:22;;;;;;131440:13;;131415:38;;-1:-1:-1;;;;;130661:800:0:o;133580:496::-;133656:21;133667:9;133656:10;:21::i;:::-;133694:24;133708:9;133694:13;:24::i;:::-;133729;133743:9;133729:13;:24::i;:::-;133798:9;:22;;;133771:297;133835:9;:15;;;133865:9;:20;;;133900:9;:21;;;133936:9;:18;;;133969:9;:19;;;134003:9;:19;;;134037:9;:20;;;133771:297;;;;;;;;;;;-1:-1:-1;;;;;16965:15:1;;;16947:34;;17017:15;;;17012:2;16997:18;;16990:43;17064:2;17049:18;;17042:34;;;;17112:15;;;17107:2;17092:18;;17085:43;17165:15;;;17159:3;17144:19;;17137:44;17212:3;17197:19;;17190:35;;;;17256:3;17241:19;;17234:35;;;;16873:3;16858:19;;16571:704;133771:297:0;;;;;;;;133580:496;:::o;36429:120::-;36496:7;36523:3;:11;;36535:5;36523:18;;;;;;;;:::i;:::-;;;;;;;;;36516:25;;36429:120;;;;:::o;105321:638::-;105745:23;105771:33;-1:-1:-1;;;;;105771:27:0;;105799:4;105771:27;:33::i;:::-;105745:59;;105819:10;:17;105840:1;105819:22;;:57;;;;;105857:10;105846:30;;;;;;;;;;;;:::i;:::-;105845:31;105819:57;105815:137;;;105900:40;;;;;-1:-1:-1;;;;;3262:55:1;;105900:40:0;;;3244:74:1;3217:18;;105900:40:0;3098:226:1;33671:416:0;33734:4;35846:21;;;:14;;;:21;;;;;;33751:329;;-1:-1:-1;33794:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;33979:18;;33955:21;;;:14;;;:21;;;;;;:42;;;;34012:11;;33751:329;-1:-1:-1;34063:5:0;34056:12;;34263:1400;34329:4;34460:21;;;:14;;;:21;;;;;;34498:13;;34494:1162;;34871:18;34892:12;34903:1;34892:8;:12;:::i;:::-;34939:18;;34871:33;;-1:-1:-1;34919:17:0;;34939:22;;34960:1;;34939:22;:::i;:::-;34919:42;;34996:9;34982:10;:23;34978:385;;35026:17;35046:3;:11;;35058:9;35046:22;;;;;;;;:::i;:::-;;;;;;;;;35026:42;;35196:9;35170:3;:11;;35182:10;35170:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;35311:25;;;:14;;;:25;;;;;:36;;;34978:385;35444:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;35550:3;:14;;:21;35565:5;35550:21;;;;;;;;;;;35543:28;;;35595:4;35588:11;;;;;;;75440:178;75517:7;75544:66;75577:20;:18;:20::i;:::-;75599:10;28827:4;28821:11;28858:10;28846:23;;28899:4;28890:14;;28883:39;;;;28952:4;28943:14;;28936:34;29009:4;28994:20;;;28622:410;131631:426;131701:18;;;;-1:-1:-1;;;;;131701:32:0;131697:353;;131766:9;:19;;;131754:9;:31;131750:96;;;131813:17;;;;;;;;;;;;;;131750:96;131867:11;;;;;;;;;-1:-1:-1;;;;;131867:11:0;-1:-1:-1;;;;;131860:27:0;;131896:9;131860:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;122781:86;:::o;131697:353::-;131942:96;131986:9;:15;;;132011:4;132018:9;:19;;;131949:9;:18;;;-1:-1:-1;;;;;131942:43:0;;;:96;;;;;;:::i;132222:496::-;132295:19;;;;-1:-1:-1;;;;;132295:33:0;132291:420;;132352:11;;132374:20;;;;132345:50;;-1:-1:-1;;;132345:50:0;;-1:-1:-1;;;;;132352:11:0;;;;132345:28;;:50;;;;2538:25:1;;;2526:2;2511:18;;2392:177;132345:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132411:12;132437:9;:20;;;-1:-1:-1;;;;;132429:34:0;132471:9;:20;;;132429:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132410:86;;;132516:7;132511:72;;132551:16;;-1:-1:-1;;;132551:16:0;;;;;;;;;;;132291:420;132615:84;132656:9;:20;;;132678:9;:20;;;132622:9;:19;;;-1:-1:-1;;;;;132615:40:0;;;:84;;;;;:::i;132889:425::-;132962:18;;;;-1:-1:-1;;;;;132962:32:0;;:67;;;;;133010:9;:19;;;132998:9;:31;132962:67;132958:349;;;133053:11;;133087:19;;;;-1:-1:-1;;;;;133053:11:0;;;;133046:28;;133075:31;;:9;:31;:::i;:::-;133046:61;;;;;;;;;;;;;2538:25:1;;2526:2;2511:18;;2392:177;133046:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;133185:19:0;;;;133123:12;;-1:-1:-1;133149:10:0;;133173:31;;:9;:31;:::i;:::-;133141:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97579:153;97654:12;97686:38;97708:6;97716:4;97722:1;97686:21;:38::i;74486:111::-;74539:7;74566:23;:21;:23::i;:::-;74559:30;;74486:111;:::o;102917:190::-;103045:53;;-1:-1:-1;;;;;18165:15:1;;;103045:53:0;;;18147:34:1;18217:15;;;18197:18;;;18190:43;18249:18;;;18242:34;;;103018:81:0;;103038:5;;103060:18;;;;;18059::1;;103045:53:0;17884:398:1;98067::0;98166:12;98219:5;98195:21;:29;98191:110;;;98248:41;;;;;98283:4;98248:41;;;3244:74:1;3217:18;;98248:41:0;3098:226:1;98191:110:0;98312:12;98326:23;98353:6;-1:-1:-1;;;;;98353:11:0;98372:5;98379:4;98353:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98311:73;;;;98402:55;98429:6;98437:7;98446:10;98402:26;:55::i;:::-;98395:62;98067:398;-1:-1:-1;;;;;;98067:398:0:o;74605:193::-;74660:7;72493:95;74719:17;:15;:17::i;:::-;74738:20;:18;:20::i;:::-;74697:92;;;;;;18838:25:1;;;;18879:18;;18872:34;;;;18922:18;;;18915:34;74760:13:0;18965:18:1;;;18958:34;74783:4:0;19008:19:1;;;19001:84;18810:19;;74697:92:0;;;;;;;;;;;;74687:103;;;;;;74680:110;;74605:193;:::o;99543:597::-;99691:12;99721:7;99716:417;;99745:19;99753:10;99745:7;:19::i;:::-;99716:417;;;99973:17;;:22;:49;;;;-1:-1:-1;;;;;;99999:18:0;;;:23;99973:49;99969:121;;;100050:24;;;;;-1:-1:-1;;;;;3262:55:1;;100050:24:0;;;3244:74:1;3217:18;;100050:24:0;3098:226:1;99969:121:0;-1:-1:-1;100111:10:0;100104:17;;77616:702;77666:7;73277:21;77666:7;77763:13;:11;:13::i;:::-;77791:18;;77742:34;;-1:-1:-1;77791:22:0;77787:524;;77837:22;;;;;;;;77616:702;-1:-1:-1;;77616:702:0:o;77787:524::-;78138:13;;78170:15;;78166:134;;78213:10;77616:702;-1:-1:-1;;;77616:702:0:o;78166:134::-;78271:13;78264:20;;;;;77616:702;:::o;78546:738::-;78599:7;73277:21;78599:7;78699:16;:14;:16::i;:::-;78730:21;;78675:40;;-1:-1:-1;78730:25:0;78726:551;;78779:25;;;;;;;;78546:738;-1:-1:-1;;78546:738:0:o;78726:551::-;79095:16;;;;79130:18;;79126:140;;79176:13;78546:738;-1:-1:-1;;;78546:738:0:o;100693:528::-;100826:17;;:21;100822:392;;101058:10;101052:17;101115:15;101102:10;101098:2;101094:19;101087:44;100822:392;101185:17;;;;;;;;;;;;;;14:180:1;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:1;;14:180;-1:-1:-1;14:180:1:o;199:332::-;257:6;310:2;298:9;289:7;285:23;281:32;278:52;;;326:1;323;316:12;278:52;365:9;352:23;-1:-1:-1;;;;;;408:5:1;404:78;397:5;394:89;384:117;;497:1;494;487:12;728:196;796:20;;-1:-1:-1;;;;;845:54:1;;835:65;;825:93;;914:1;911;904:12;825:93;728:196;;;:::o;929:186::-;988:6;1041:2;1029:9;1020:7;1016:23;1012:32;1009:52;;;1057:1;1054;1047:12;1009:52;1080:29;1099:9;1080:29;:::i;1120:347::-;1171:8;1181:6;1235:3;1228:4;1220:6;1216:17;1212:27;1202:55;;1253:1;1250;1243:12;1202:55;-1:-1:-1;1276:20:1;;1319:18;1308:30;;1305:50;;;1351:1;1348;1341:12;1305:50;1388:4;1380:6;1376:17;1364:29;;1440:3;1433:4;1424:6;1416;1412:19;1408:30;1405:39;1402:59;;;1457:1;1454;1447:12;1402:59;1120:347;;;;;:::o;1472:477::-;1551:6;1559;1567;1620:2;1608:9;1599:7;1595:23;1591:32;1588:52;;;1636:1;1633;1626:12;1588:52;1672:9;1659:23;1649:33;;1733:2;1722:9;1718:18;1705:32;1760:18;1752:6;1749:30;1746:50;;;1792:1;1789;1782:12;1746:50;1831:58;1881:7;1872:6;1861:9;1857:22;1831:58;:::i;:::-;1472:477;;1908:8;;-1:-1:-1;1805:84:1;;-1:-1:-1;;;;1472:477:1:o;2574:254::-;2642:6;2650;2703:2;2691:9;2682:7;2678:23;2674:32;2671:52;;;2719:1;2716;2709:12;2671:52;2755:9;2742:23;2732:33;;2784:38;2818:2;2807:9;2803:18;2784:38;:::i;:::-;2774:48;;2574:254;;;;;:::o;2833:260::-;2901:6;2909;2962:2;2950:9;2941:7;2937:23;2933:32;2930:52;;;2978:1;2975;2968:12;2930:52;3001:29;3020:9;3001:29;:::i;:::-;2991:39;;3049:38;3083:2;3072:9;3068:18;3049:38;:::i;3329:154::-;3387:5;3432:3;3423:6;3418:3;3414:16;3410:26;3407:46;;;3449:1;3446;3439:12;3407:46;-1:-1:-1;3471:6:1;3329:154;-1:-1:-1;3329:154:1:o;3488:533::-;3592:6;3600;3608;3661:3;3649:9;3640:7;3636:23;3632:33;3629:53;;;3678:1;3675;3668:12;3629:53;3701:52;3745:7;3734:9;3701:52;:::i;:::-;3691:62;;3804:3;3793:9;3789:19;3776:33;3832:18;3824:6;3821:30;3818:50;;;3864:1;3861;3854:12;4026:250;4111:1;4121:113;4135:6;4132:1;4129:13;4121:113;;;4211:11;;;4205:18;4192:11;;;4185:39;4157:2;4150:10;4121:113;;;-1:-1:-1;;4268:1:1;4250:16;;4243:27;4026:250::o;4281:271::-;4323:3;4361:5;4355:12;4388:6;4383:3;4376:19;4404:76;4473:6;4466:4;4461:3;4457:14;4450:4;4443:5;4439:16;4404:76;:::i;:::-;4534:2;4513:15;-1:-1:-1;;4509:29:1;4500:39;;;;4541:4;4496:50;;4281:271;-1:-1:-1;;4281:271:1:o;4557:1335::-;4954:66;4946:6;4942:79;4931:9;4924:98;4905:4;5041:2;5079:3;5074:2;5063:9;5059:18;5052:31;5106:46;5147:3;5136:9;5132:19;5124:6;5106:46;:::i;:::-;5200:9;5192:6;5188:22;5183:2;5172:9;5168:18;5161:50;5234:33;5260:6;5252;5234:33;:::i;:::-;5298:2;5283:18;;5276:34;;;-1:-1:-1;;;;;5347:55:1;;5341:3;5326:19;;5319:84;5434:3;5419:19;;5412:35;;;5484:22;;;5478:3;5463:19;;5456:51;5556:13;;5578:22;;;5654:15;;;;-1:-1:-1;5616:15:1;;;;-1:-1:-1;5697:169:1;5711:6;5708:1;5705:13;5697:169;;;5772:13;;5760:26;;5841:15;;;;5806:12;;;;5733:1;5726:9;5697:169;;;-1:-1:-1;5883:3:1;;4557:1335;-1:-1:-1;;;;;;;;;;;;4557:1335:1:o;5897:248::-;5965:6;5973;6026:2;6014:9;6005:7;6001:23;5997:32;5994:52;;;6042:1;6039;6032:12;5994:52;-1:-1:-1;;6065:23:1;;;6135:2;6120:18;;;6107:32;;-1:-1:-1;5897:248:1:o;6150:602::-;6263:6;6271;6279;6287;6340:3;6328:9;6319:7;6315:23;6311:33;6308:53;;;6357:1;6354;6347:12;6308:53;6380:52;6424:7;6413:9;6380:52;:::i;:::-;6370:62;;6483:3;6472:9;6468:19;6455:33;6511:18;6503:6;6500:30;6497:50;;;6543:1;6540;6533:12;6497:50;6582:58;6632:7;6623:6;6612:9;6608:22;6582:58;:::i;:::-;6150:602;;6659:8;;-1:-1:-1;6556:84:1;;6741:3;6726:19;6713:33;;6150:602;-1:-1:-1;;;;6150:602:1:o;6757:254::-;6825:6;6833;6886:2;6874:9;6865:7;6861:23;6857:32;6854:52;;;6902:1;6899;6892:12;6854:52;6925:29;6944:9;6925:29;:::i;:::-;6915:39;7001:2;6986:18;;;;6973:32;;-1:-1:-1;;;6757:254:1:o;7016:367::-;7079:8;7089:6;7143:3;7136:4;7128:6;7124:17;7120:27;7110:55;;7161:1;7158;7151:12;7110:55;-1:-1:-1;7184:20:1;;7227:18;7216:30;;7213:50;;;7259:1;7256;7249:12;7213:50;7296:4;7288:6;7284:17;7272:29;;7356:3;7349:4;7339:6;7336:1;7332:14;7324:6;7320:27;7316:38;7313:47;7310:67;;;7373:1;7370;7363:12;7388:773;7510:6;7518;7526;7534;7587:2;7575:9;7566:7;7562:23;7558:32;7555:52;;;7603:1;7600;7593:12;7555:52;7643:9;7630:23;7672:18;7713:2;7705:6;7702:14;7699:34;;;7729:1;7726;7719:12;7699:34;7768:70;7830:7;7821:6;7810:9;7806:22;7768:70;:::i;:::-;7857:8;;-1:-1:-1;7742:96:1;-1:-1:-1;7945:2:1;7930:18;;7917:32;;-1:-1:-1;7961:16:1;;;7958:36;;;7990:1;7987;7980:12;7958:36;;8029:72;8093:7;8082:8;8071:9;8067:24;8029:72;:::i;:::-;7388:773;;;;-1:-1:-1;8120:8:1;-1:-1:-1;;;;7388:773:1:o;10489:184::-;-1:-1:-1;;;10538:1:1;10531:88;10638:4;10635:1;10628:15;10662:4;10659:1;10652:15;10678:184;-1:-1:-1;;;10727:1:1;10720:88;10827:4;10824:1;10817:15;10851:4;10848:1;10841:15;10867:168;10940:9;;;10971;;10988:15;;;10982:22;;10968:37;10958:71;;11009:18;;:::i;11040:274::-;11080:1;11106;11096:189;;-1:-1:-1;;;11138:1:1;11131:88;11242:4;11239:1;11232:15;11270:4;11267:1;11260:15;11096:189;-1:-1:-1;11299:9:1;;11040:274::o;11831:184::-;-1:-1:-1;;;11880:1:1;11873:88;11980:4;11977:1;11970:15;12004:4;12001:1;11994:15;12020:301;12079:6;12132:2;12120:9;12111:7;12107:23;12103:32;12100:52;;;12148:1;12145;12138:12;12100:52;12187:9;12174:23;12237:34;12230:5;12226:46;12219:5;12216:57;12206:85;;12287:1;12284;12277:12;13220:437;13299:1;13295:12;;;;13342;;;13363:61;;13417:4;13409:6;13405:17;13395:27;;13363:61;13470:2;13462:6;13459:14;13439:18;13436:38;13433:218;;-1:-1:-1;;;13504:1:1;13497:88;13608:4;13605:1;13598:15;13636:4;13633:1;13626:15;14493:545;14595:2;14590:3;14587:11;14584:448;;;14631:1;14656:5;14652:2;14645:17;14701:4;14697:2;14687:19;14771:2;14759:10;14755:19;14752:1;14748:27;14742:4;14738:38;14807:4;14795:10;14792:20;14789:47;;;-1:-1:-1;14830:4:1;14789:47;14885:2;14880:3;14876:12;14873:1;14869:20;14863:4;14859:31;14849:41;;14940:82;14958:2;14951:5;14948:13;14940:82;;;15003:17;;;14984:1;14973:13;14940:82;;15214:1352;15340:3;15334:10;15367:18;15359:6;15356:30;15353:56;;;15389:18;;:::i;:::-;15418:97;15508:6;15468:38;15500:4;15494:11;15468:38;:::i;:::-;15462:4;15418:97;:::i;:::-;15570:4;;15634:2;15623:14;;15651:1;15646:663;;;;16353:1;16370:6;16367:89;;;-1:-1:-1;16422:19:1;;;16416:26;16367:89;-1:-1:-1;;15171:1:1;15167:11;;;15163:24;15159:29;15149:40;15195:1;15191:11;;;15146:57;16469:81;;15616:944;;15646:663;14440:1;14433:14;;;14477:4;14464:18;;-1:-1:-1;;15682:20:1;;;15800:236;15814:7;15811:1;15808:14;15800:236;;;15903:19;;;15897:26;15882:42;;15995:27;;;;15963:1;15951:14;;;;15830:19;;15800:236;;;15804:3;16064:6;16055:7;16052:19;16049:201;;;16125:19;;;16119:26;-1:-1:-1;;16208:1:1;16204:14;;;16220:3;16200:24;16196:37;16192:42;16177:58;16162:74;;16049:201;-1:-1:-1;;;;;16296:1:1;16280:14;;;16276:22;16263:36;;-1:-1:-1;15214:1352:1:o;17280:277::-;17347:6;17400:2;17388:9;17379:7;17375:23;17371:32;17368:52;;;17416:1;17413;17406:12;17368:52;17448:9;17442:16;17501:5;17494:13;17487:21;17480:5;17477:32;17467:60;;17523:1;17520;17513:12;17562:128;17629:9;;;17650:11;;;17647:37;;;17664:18;;:::i;17695:184::-;-1:-1:-1;;;17744:1:1;17737:88;17844:4;17841:1;17834:15;17868:4;17865:1;17858:15;18287:287;18416:3;18454:6;18448:13;18470:66;18529:6;18524:3;18517:4;18509:6;18505:17;18470:66;:::i;:::-;18552:16;;;;;18287:287;-1:-1:-1;;18287:287:1:o
Swarm Source
ipfs://dca18d1a0013ecb6ec7dcd8a6f542c58718dc35bff54f7db9f7f59a50e54bb55
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$441,099.19
Net Worth in ETH
149.155364
Token Allocations
BTC.B
44.30%
USDC.E
18.69%
USDC
16.96%
Others
20.06%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| AVAX | 44.30% | $89,262 | 2.1889 | $195,384.94 | |
| AVAX | 15.74% | $0.999697 | 69,437.9027 | $69,416.85 | |
| AVAX | 9.58% | $0.999697 | 42,252.2996 | $42,239.49 | |
| AVAX | 8.97% | $0.998506 | 39,637.1956 | $39,577.96 | |
| AVAX | 3.20% | $2,960.01 | 4.7701 | $14,119.68 | |
| AVAX | 0.05% | $12.03 | 16.7913 | $201.96 | |
| ARB | 7.38% | $0.999702 | 32,558.6684 | $32,548.97 | |
| ARB | 3.45% | $2,959.49 | 5.141 | $15,214.67 | |
| ARB | 3.15% | $0.998391 | 13,897.1357 | $13,874.78 | |
| ARB | 2.96% | $0.999702 | 13,040.5371 | $13,036.65 | |
| ARB | 1.24% | $0.00 | 2,000,000 | $0.00 | |
| ARB | <0.01% | $0.175601 | 12.609 | $2.21 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.