Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
FusedMinterUpgradable
Compiler Version
v0.8.23+commit.f704f362
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2025-02-12
*/
// SPDX-License-Identifier: MIT
pragma solidity =0.8.23 >=0.8.13 ^0.8.0 ^0.8.1 ^0.8.2 ^0.8.8;
// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
/**
* @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);
}
// lib/openzeppelin-contracts/contracts/utils/math/Math.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// 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.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 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 + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
// lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
/**
* @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);
}
}
}
// lib/openzeppelin-contracts-upgradeable/contracts/access/IAccessControlUpgradeable.sol
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControlUpgradeable {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}
// lib/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC1967Upgradeable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*
* _Available since v4.8.3._
*/
interface IERC1967Upgradeable {
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
}
// lib/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC5267Upgradeable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol)
interface IERC5267Upgradeable {
/**
* @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
);
}
// lib/openzeppelin-contracts-upgradeable/contracts/interfaces/draft-IERC1822Upgradeable.sol
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822ProxiableUpgradeable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}
// lib/openzeppelin-contracts-upgradeable/contracts/proxy/beacon/IBeaconUpgradeable.sol
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeaconUpgradeable {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}
// lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
// lib/openzeppelin-contracts-upgradeable/contracts/utils/StorageSlotUpgradeable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlotUpgradeable {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}
// lib/openzeppelin-contracts-upgradeable/contracts/utils/introspection/IERC165Upgradeable.sol
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
/**
* @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 IERC165Upgradeable {
/**
* @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);
}
// lib/openzeppelin-contracts-upgradeable/contracts/utils/math/MathUpgradeable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library MathUpgradeable {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// 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.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 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 + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
// lib/openzeppelin-contracts-upgradeable/contracts/utils/math/SignedMathUpgradeable.sol
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMathUpgradeable {
/**
* @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);
}
}
}
// src/fair/IMaterials.sol
interface IMaterials {
// Custom error definitions
error NotOwner();
error IncorrectProof();
error NoTokenIdsSpecified();
error NoRecipients();
error InvalidStageTime();
error InvalidFusedMinter();
error ArraysLengthMismatch();
error NotFusedMinter();
event NewSecondaryRoyalties(address secondaryRoyaltyReceiver, uint96 newRoyaltyValue);
/**
* @dev Store all sale stage parameters
*/
struct SaleStage {
uint256 startTime;
bytes32 merkleRoot;
}
/**
* @dev Sets the new secondary royalty receiver and royalty percentage fee.
*
* Requirements:
* - `msg.sender` must be the contract owner.
*
* @param newSecondaryRoyaltyReceiver the address of the new secondary royalty receiver.
* @param newRoyaltyValue the new royalty value.
*/
function changeSecondaryRoyaltyReceiver(
address newSecondaryRoyaltyReceiver,
uint96 newRoyaltyValue
) external;
/**
* @dev Retrieve the URI for a given token ID.
*
* @param id the token ID.
* @return the URI of the given token ID.
*/
function uri(uint256 id) external view returns (string memory);
/**
* @dev Set the Sale Stage for a given sale ID
*
* Requirements:
* - `msg.sender` must be the contract owner.
*
* @param id the sale ID.
* @param stage the sale stage data for the ID
*/
function setSaleStage(uint256 id, SaleStage memory stage) external;
/**
* @dev Set the URI for a given token ID.
*
* Requirements:
* - `msg.sender` must be the contract owner.
*
* @param id the token ID.
* @param newURI the new URI for the given token ID.
*/
function setUri(uint256 id, string memory newURI) external;
/**
* @dev Pauses minting.
*
* Requirements:
* - `msg.sender` must be the contract owner.
*/
function pause() external;
/**
* @dev Unpauses minting.
*
* Requirements:
* - `msg.sender` must be the contract owner.
*/
function unpause() external;
/**
* @dev Burn a set of hounds to redeem a material.
*
* @param tokenIds the IDs of the tokens to burn.
* @param saleId the ID of the sale.
* @param _merkleProof the Merkle proof for the address and the ID of the sale.
*/
function burn2Redeem(uint256[] memory tokenIds, uint256 saleId, bytes32[] calldata _merkleProof) external;
/**
* @dev Airdrop the 5th material to a set of VIPs.
*
* Requirements:
* - `msg.sender` must be the contract owner.
*
* @param VIPs the addresses of the VIPs.
* @param amount the amount to airdrop to each VIP.
*/
function VIPAirdrop(address[] memory VIPs, uint256 amount) external;
/**
* @dev Verify if a given interface is supported.
*
* @param interfaceId the ID of the interface.
* @return true if the interface is supported, false otherwise.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
/**
* @dev Burn a set of materials.
*
* @param amountsPerType the amounts of the materials to burn.
* @param owner the owner of the materials.
*/
function burnMaterials(uint256[] memory amountsPerType, address owner) external;
}
// src/fair/interfaces/IFairxyzMintStagesRegistry.sol
// @author: Fair.xyz dev
struct Stage {
uint40 startTime;
uint40 endTime;
uint40 mintsPerWallet;
uint40 phaseLimit;
uint96 price;
bool signatureReleased;
}
struct FairxyzParameters {
address fairxyzSigner;
address fairxyzWithdrawAddress;
uint256 fairxyzFee;
}
interface IFairxyzMintStagesRegistry {
error NoActiveStage();
error NoStages();
error NoStagesSpecified();
error PhaseLimitsOverlap();
error SkippedStages();
error StageDoesNotExist();
error StageHasEnded();
error StageHasAlreadyStarted();
error StageLimitAboveMax();
error StageLimitBelowMin();
error StageTimesOverlap();
error TooManyUpcomingStages();
error Unauthorized();
/// @dev Emitted when a range of stages for a schedule are updated.
event ScheduleStagesUpdated(
address indexed registrant,
uint256 indexed scheduleId,
uint256 startIndex,
Stage[] stages
);
/// @dev Emitted when a range of stages for a schedule are cancelled.
event ScheduleStagesCancelled(
address indexed registrant,
uint256 indexed scheduleId,
uint256 startIndex
);
/**
* @dev Cancels all stages from the specified index onwards.
*
* Requirements:
* - `fromIndex` must be less than the total number of stages
*
* @param registrant the address of the registrant the schedule is managed by
* @param scheduleId the id of the schedule to cancel the stages for
* @param fromIndex the index from which to cancel stages
*/
function cancelStages(
address registrant,
uint256 scheduleId,
uint256 fromIndex
) external;
/**
* @dev Sets the parameters relevant to platform minting on Fair.xyz
*
* Requirements:
* - `msg.sender` must be the contract owner
*
* @param parameters a struct of parameters for Fair.xyz-related platform minting
*/
function setFairParameters(FairxyzParameters memory parameters) external;
/**
* @dev Sets a new series of stages, overwriting any existing stages and cancelling any stages after the last new stage.
*
* @param registrant the address of the registrant the schedule is managed by
* @param scheduleId the id of the schedule to update the stages for
* @param firstStageIndex the index from which to update stages
* @param stages array of new stages to add to / overwrite existing stages
* @param minPhaseLimit the minimum phaseLimit for the new stages e.g. current supply of the token the schedule is for
* @param maxPhaseLimit the maximum phaseLimit for the new stages e.g. maximum supply of the token the schedule is for
*/
function setStages(
address registrant,
uint256 scheduleId,
uint256 firstStageIndex,
Stage[] calldata stages,
uint256 minPhaseLimit,
uint256 maxPhaseLimit
) external;
/**
* @dev Finds the active stage for a schedule based on the current time being between the start and end times.
* @dev Reverts if no active stage is found.
*
* @param scheduleId The id of the schedule to find the active stage for
*
* @return fairxyzParameters the parameters around the Fair.xyz signature, withdrawal address and fees
* @return index The index of the active stage
* @return stage The active stage data
*/
function viewActiveStage(
address registrant,
uint256 scheduleId
) external view returns (FairxyzParameters memory fairxyzParameters, uint256 index, Stage memory stage);
/**
* @dev Finds the final stage for a schedule.
* @dev Does not revert. Instead, it returns an empty Stage if no stages exist for the schedule.
*
* @param scheduleId The id of the schedule to find the final stage for
*
* @return index The index of the final stage
* @return stage The final stage data
*/
function viewFinalStage(
address registrant,
uint256 scheduleId
) external view returns (uint256 index, Stage memory stage);
/**
* @dev Finds the index of the current/upcoming stage which has not yet ended.
* @dev A stage may not exist at the returned index if all existing stages have ended.
*
* @param scheduleId The id of the schedule to find the latest stage index for
*
* @return index
*/
function viewLatestStageIndex(
address registrant,
uint256 scheduleId
) external view returns (uint256 index);
/**
* @dev Returns the stage data for the specified schedule id and stage index.
* @dev Reverts if a stage does not exist or has been deleted at the index.
*
* @param scheduleId The id of the schedule to get the stage from
* @param stageIndex The index of the stage to get
*
* @return stage
*/
function viewStage(
address registrant,
uint256 scheduleId,
uint256 stageIndex
) external view returns (Stage memory stage);
}
// src/interfaces/IDelegateRegistry.sol
/**
* @title IDelegateRegistry
* @custom:version 2.0
* @custom:author foobar (0xfoobar)
* @notice A standalone immutable registry storing delegated permissions from one address to another
*/
interface IDelegateRegistry {
/// @notice Delegation type, NONE is used when a delegation does not exist or is revoked
enum DelegationType {
NONE,
ALL,
CONTRACT,
ERC721,
ERC20,
ERC1155
}
/// @notice Struct for returning delegations
struct Delegation {
DelegationType type_;
address to;
address from;
bytes32 rights;
address contract_;
uint256 tokenId;
uint256 amount;
}
/// @notice Emitted when an address delegates or revokes rights for their entire wallet
event DelegateAll(address indexed from, address indexed to, bytes32 rights, bool enable);
/// @notice Emitted when an address delegates or revokes rights for a contract address
event DelegateContract(
address indexed from,
address indexed to,
address indexed contract_,
bytes32 rights,
bool enable
);
/// @notice Emitted when an address delegates or revokes rights for an ERC721 tokenId
event DelegateERC721(
address indexed from,
address indexed to,
address indexed contract_,
uint256 tokenId,
bytes32 rights,
bool enable
);
/// @notice Emitted when an address delegates or revokes rights for an amount of ERC20 tokens
event DelegateERC20(
address indexed from,
address indexed to,
address indexed contract_,
bytes32 rights,
uint256 amount
);
/// @notice Emitted when an address delegates or revokes rights for an amount of an ERC1155 tokenId
event DelegateERC1155(
address indexed from,
address indexed to,
address indexed contract_,
uint256 tokenId,
bytes32 rights,
uint256 amount
);
/// @notice Thrown if multicall calldata is malformed
error MulticallFailed();
/**
* ----------- WRITE -----------
*/
/**
* @notice Call multiple functions in the current contract and return the data from all of them if they all succeed
* @param data The encoded function data for each of the calls to make to this contract
* @return results The results from each of the calls passed in via data
*/
function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for all contracts
* @param to The address to act as delegate
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param enable Whether to enable or disable this delegation, true delegates and false revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateAll(address to, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for a specific contract
* @param to The address to act as delegate
* @param contract_ The contract whose rights are being delegated
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param enable Whether to enable or disable this delegation, true delegates and false revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateContract(
address to,
address contract_,
bytes32 rights,
bool enable
) external payable returns (bytes32 delegationHash);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for a specific ERC721 token
* @param to The address to act as delegate
* @param contract_ The contract whose rights are being delegated
* @param tokenId The token id to delegate
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param enable Whether to enable or disable this delegation, true delegates and false revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateERC721(
address to,
address contract_,
uint256 tokenId,
bytes32 rights,
bool enable
) external payable returns (bytes32 delegationHash);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC20 tokens
* @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound)
* @param to The address to act as delegate
* @param contract_ The address for the fungible token contract
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param amount The amount to delegate, > 0 delegates and 0 revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateERC20(
address to,
address contract_,
bytes32 rights,
uint256 amount
) external payable returns (bytes32 delegationHash);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC1155 tokens
* @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound)
* @param to The address to act as delegate
* @param contract_ The address of the contract that holds the token
* @param tokenId The token id to delegate
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param amount The amount of that token id to delegate, > 0 delegates and 0 revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateERC1155(
address to,
address contract_,
uint256 tokenId,
bytes32 rights,
uint256 amount
) external payable returns (bytes32 delegationHash);
/**
* ----------- CHECKS -----------
*/
/**
* @notice Check if `to` is a delegate of `from` for the entire wallet
* @param to The potential delegate address
* @param from The potential address who delegated rights
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return valid Whether delegate is granted to act on the from's behalf
*/
function checkDelegateForAll(address to, address from, bytes32 rights) external view returns (bool);
/**
* @notice Check if `to` is a delegate of `from` for the specified `contract_` or the entire wallet
* @param to The delegated address to check
* @param contract_ The specific contract address being checked
* @param from The cold wallet who issued the delegation
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return valid Whether delegate is granted to act on from's behalf for entire wallet or that specific contract
*/
function checkDelegateForContract(
address to,
address from,
address contract_,
bytes32 rights
) external view returns (bool);
/**
* @notice Check if `to` is a delegate of `from` for the specific `contract` and `tokenId`, the entire `contract_`, or the entire wallet
* @param to The delegated address to check
* @param contract_ The specific contract address being checked
* @param tokenId The token id for the token to delegating
* @param from The wallet that issued the delegation
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return valid Whether delegate is granted to act on from's behalf for entire wallet, that contract, or that specific tokenId
*/
function checkDelegateForERC721(
address to,
address from,
address contract_,
uint256 tokenId,
bytes32 rights
) external view returns (bool);
/**
* @notice Returns the amount of ERC20 tokens the delegate is granted rights to act on the behalf of
* @param to The delegated address to check
* @param contract_ The address of the token contract
* @param from The cold wallet who issued the delegation
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return balance The delegated balance, which will be 0 if the delegation does not exist
*/
function checkDelegateForERC20(
address to,
address from,
address contract_,
bytes32 rights
) external view returns (uint256);
/**
* @notice Returns the amount of a ERC1155 tokens the delegate is granted rights to act on the behalf of
* @param to The delegated address to check
* @param contract_ The address of the token contract
* @param tokenId The token id to check the delegated amount of
* @param from The cold wallet who issued the delegation
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return balance The delegated balance, which will be 0 if the delegation does not exist
*/
function checkDelegateForERC1155(
address to,
address from,
address contract_,
uint256 tokenId,
bytes32 rights
) external view returns (uint256);
/**
* ----------- ENUMERATIONS -----------
*/
/**
* @notice Returns all enabled delegations a given delegate has received
* @param to The address to retrieve delegations for
* @return delegations Array of Delegation structs
*/
function getIncomingDelegations(address to) external view returns (Delegation[] memory delegations);
/**
* @notice Returns all enabled delegations an address has given out
* @param from The address to retrieve delegations for
* @return delegations Array of Delegation structs
*/
function getOutgoingDelegations(address from) external view returns (Delegation[] memory delegations);
/**
* @notice Returns all hashes associated with enabled delegations an address has received
* @param to The address to retrieve incoming delegation hashes for
* @return delegationHashes Array of delegation hashes
*/
function getIncomingDelegationHashes(address to) external view returns (bytes32[] memory delegationHashes);
/**
* @notice Returns all hashes associated with enabled delegations an address has given out
* @param from The address to retrieve outgoing delegation hashes for
* @return delegationHashes Array of delegation hashes
*/
function getOutgoingDelegationHashes(address from) external view returns (bytes32[] memory delegationHashes);
/**
* @notice Returns the delegations for a given array of delegation hashes
* @param delegationHashes is an array of hashes that correspond to delegations
* @return delegations Array of Delegation structs, return empty structs for nonexistent or revoked delegations
*/
function getDelegationsFromHashes(
bytes32[] calldata delegationHashes
) external view returns (Delegation[] memory delegations);
/**
* ----------- STORAGE ACCESS -----------
*/
/**
* @notice Allows external contracts to read arbitrary storage slots
*/
function readSlot(bytes32 location) external view returns (bytes32);
/**
* @notice Allows external contracts to read an arbitrary array of storage slots
*/
function readSlots(bytes32[] calldata locations) external view returns (bytes32[] memory);
}
// src/interfaces/IFusedMinter.sol
// @author: Novel Labs dev
bytes32 constant PAUSER_ROLE = keccak256('PAUSER_ROLE');
bytes32 constant ADMIN_ROLE = keccak256('ADMIN_ROLE');
uint256 constant WALLET_TYPE_WARMXYZ = 1;
uint256 constant WALLET_TYPE_DELEGATEXYZ = 2;
struct TokenParams {
uint256 tokenId;
uint256 collectionId;
uint256 walletType;
}
struct AllocationParams {
TokenParams[] tokenParams;
bytes signature;
address signer;
}
bytes32 constant ALLOCATION_TYPEHASH = keccak256(
'AllocationMessage(address minter,address signer)'
);
struct RecipeParam {
uint256 amount;
uint256[] materials;
}
struct MintParams {
address receiver;
RecipeParam[] recipeParams;
AllocationParams[] allocationParams;
}
interface IFusedMinter {
event CollectionAddressSet(address oldCollectionAddress, address newCollectionAddress);
event TokenUsed(address collectionAddress, uint256 tokenId);
function usedTokens(address collectionAddress, uint256 tokenId) external view returns (bool);
function mint(MintParams memory params) external;
function preSaleMint(uint256[] calldata tokensPerEdition, address receiver) external;
function setCollectionAddress(address collectionAddress_) external;
function getDigest(address minterAddress, address signer) external view returns (bytes32);
}
// src/interfaces/IWarmRegistry.sol
// @author: Novel Labs dev
interface IWarmRegistry {
function getColdWallets(address warmWallet) external view returns (address[] memory);
}
// lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
// lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
/**
* @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 Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 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 functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_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 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_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() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @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 {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}
// src/fair/interfaces/IFairxyzEditions.sol
// @author: Fair.xyz dev
/**
* @param maxMintsPerWallet the maximum number of tokens that can be minted per wallet/account
* @param maxSupply the maximum supply for the edition including paid mints and airdrops
* @param burnable_ the burnable state of the edition
* @param signatureReleased whether the signature is required to mint tokens for the edition
* @param soulbound whether the edition tokens are soulbound
*/
struct Edition {
uint40 maxMintsPerWallet;
uint40 maxSupply;
bool burnable;
bool signatureReleased;
bool soulbound;
}
/**
* @param externalId the external ID of the edition used to identify it off-chain
* @param edition the edition struct
* @param uri the URI for the edition/token metadata
* @param mintStages the mint stages for the edition
*/
struct EditionCreateParams {
uint256 externalId;
Edition edition;
string uri;
Stage[] mintStages;
}
struct EditionMinter {
uint40 mintedCount;
uint40 lastUsedNonce;
}
struct EditionMintingHandler {
uint256 allowedQuantity;
uint256 editionMintedTotal;
}
interface IFairxyzEditions {
error EditionAlreadyMinted();
error EditionDoesNotExist();
error EditionSignatureAlreadyReleased();
error EditionSupplyCanOnlyBeReduced();
error EditionSupplyLessThanMintedCount();
error EditionSupplyLessThanScheduledStagesPhaseLimit();
error EditionSupplyTooLarge();
error IncorrectEthValue();
error InvalidMintQuantity();
error InvalidNumberOfRecipients();
error InvalidSignatureNonce();
error InvalidSignature();
error InvalidURI();
error NotApprovedOrOwner();
error NotBurnable();
error NotEnoughSupplyRemaining();
error NotTransferable();
error RecipientAllowanceUsed();
error RecipientEditionAllowanceUsed();
error RecipientStageAllowanceUsed();
error SenderIsNotExtension();
error SignatureAlreadyUsed();
error SignatureExpired();
error StageSoldOut();
error TokenDoesNotExist();
error ZeroAddress();
/// @dev Emitted when the metadata of a range of tokens is changed.
event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
/// @dev Emitted when the default royalty details are changed.
event DefaultRoyalty(address receiver, uint96 royaltyFraction);
/// @dev Emitted when edition tokens are airdropped.
event EditionAirdrop(
uint256 indexed editionId,
uint256 indexed stageIndex,
address[] recipients,
uint256 quantity,
uint256 editionMintedCount
);
/// @dev Emitted when the burnable state of an edition is changed.
event EditionBurnable(uint256 indexed editionId, bool burnable);
/// @dev Emitted when a new edition is added.
event EditionCreated(
uint256 indexed editionId,
uint256 externalId,
Edition edition
);
/// @dev Emitted when an edition is deleted and can no longer be minted.
event EditionDeleted(uint256 indexed editionId);
/// @dev Emitted when the maximum mints per wallet for an edition is changed.
event EditionMaxMintsPerWallet(
uint256 indexed editionId,
uint256 maxMintsPerWallet
);
/// @dev Emitted when the maximum supply for an edition is changed.
event EditionMaxSupply(uint256 indexed editionId, uint256 maxSupply);
/// @dev Emitted when the royalty details for an edition are changed.
event EditionRoyalty(
uint256 indexed editionId,
address receiver,
uint96 royaltyFraction
);
/// @dev Emitted when a signature is no longer required to mint tokens for a specific edition.
event EditionSignatureReleased(uint256 indexed editionId);
// /// @dev Emitted when the soulbound state of an edition is changed.
// event EditionSoulbound(uint256 indexed editionId, bool soulbound);
/// @dev Emitted when edition tokens are minted during a mint stage.
event EditionStageMint(
uint256 indexed editionId,
uint256 indexed stageIndex,
address indexed recipient,
uint256 quantity,
uint256 editionMintedCount
);
/// @dev Emitted when the metadata URI for an edition is changed.
event EditionURI(uint256 indexed editionId, string uri);
/// @dev Emitted when the token URI extension for an edition is changed
event EditionURIExtension(uint256 editionId, address uriExtension);
/// @dev Emitted when the metadata of a token is changed.
event MetadataUpdate(uint256 _tokenId);
/// @dev Emitted when the mint extension is changed.
event MintingExtension(address mintingExtension);
/// @dev Emitted when the primary sale receiver address is changed.
event PrimarySaleReceiver(address primarySaleReceiver_);
/// @dev Emitted when the royalty extension is updated
event RoyaltyExtension(address royaltyExtension);
/**
* @dev Mints the same quantity of tokens from an edition to multiple recipients.
*
* @param editionId the ID of the edition to mint
* @param quantity the number of tokens to mint to each recipient
* @param recipients addresses to mint to
*/
function airdropEdition(
uint256 editionId,
uint256 quantity,
address[] memory recipients
) external;
/**
* @dev Adds new editions at the next token ID/range (depending on standard implemented)
*
* @param editions the editions to add
*/
function createEditions(EditionCreateParams[] calldata editions) external;
/**
* @dev Delete an edition i.e. make it no longer editable or mintable.
*
* @param editionId the ID of the edition to delete
*/
function deleteEdition(uint256 editionId) external;
/**
* @dev Returns the current total supply of tokens for an edition, taking both mints and burns into account.
*
* @param editionId the ID of the edition
*
* @return totalSupply the number of tokens in circulation
*/
function editionTotalSupply(
uint256 editionId
) external view returns (uint256 totalSupply);
/**
* @dev Returns the edition with ID `editionId`.
* @dev Should revert if the edition does not exist.
*
* @param editionId the ID of the edition
*
* @return edition
*/
function getEdition(
uint256 editionId
) external view returns (Edition memory);
/**
* @dev Grants the `DEFAULT_ADMIN_ROLE` role to an address.
* @dev Intended to be used only by the contract owner. Other admin management is done via AccessControl contract functions.
*
* @param admin the address to grant the default admin role to
*/
function grantDefaultAdmin(address admin) external;
/**
* @dev Mint a quantity of tokens for an edition to a single recipient.
* @dev Can be called by any account with a valid signature and the correct value.
*
* @param editionId the ID of the edition
* @param recipient the address to transfer the minted tokens to
* @param quantity the quantity of tokens to mint
* @param signatureNonce a value that is recorded for signature expiry and reuse prevention, typically a recent block number
* @param signatureMaxMints the maximum number of mints specific to the recipient and validated in the signature
* @param signature a signature containing the other function params for authorizing the execution
*/
function mintEdition(
uint256 editionId,
address recipient,
uint256 quantity,
uint40 signatureNonce,
uint256 signatureMaxMints,
bytes memory signature
) external payable returns (EditionMintingHandler memory handler);
/**
* @dev Turns off signature validation for calls to `mintEdition` for a specific edition i.e. allows signature-less minting.
*
* @param editionId the ID of the edition
*/
function releaseEditionSignature(uint256 editionId) external;
/**
* @dev Set the default royalty receiver and fraction for the collection.
*
* @param receiver the address to receive royalties
* @param royaltyFraction the fraction of the sale price to pay as royalties (out of 10000)
*/
function setDefaultRoyalty(
address receiver,
uint96 royaltyFraction
) external;
/**
* @dev Updates the maximum number of tokens each wallet can mint for an edition.
*
* @param editionId the ID of the edition to update
* @param maxMintsPerWallet the new maximum number of mints
*/
function setEditionMaxMintsPerWallet(
uint256 editionId,
uint40 maxMintsPerWallet
) external;
/**
* @dev Updates the maximum supply available for an edition.
*
* @param editionId the ID of the edition to update
* @param maxSupply the new maximum supply of tokens for the edition
*/
function setEditionMaxSupply(uint256 editionId, uint40 maxSupply) external;
/**
* @notice Set Edition Royalty
* @dev updates the edition royalty receiver and fraction, which overrides the collection default
*
* @param editionId the ID of the edition to update
* @param receiver the address that should receive royalty payments
* @param royaltyFraction the portion of the defined denominator that the receiver should be sent from a secondary sale
*/
function setEditionRoyalty(
uint256 editionId,
address receiver,
uint96 royaltyFraction
) external;
/**
* @notice Update Edition Mint Stages
* @dev Add and update a range of mint stages for an edition.
*
* @param editionId the ID of the edition
* @param firstStageIndex the index of the first stage being det
* @param newStages the new stage data to set
*/
function setEditionStages(
uint256 editionId,
uint256 firstStageIndex,
Stage[] calldata newStages
) external;
/**
* @notice Set Edition Metadata URI
* @dev updates the edition metadata URI
*
* @param editionId the ID of the edition to update
* @param uri the URI of the metadata for the edition
*/
function setEditionURI(uint256 editionId, string calldata uri) external;
/**
* @notice Set Edition URI Extension
* @dev Updates the URI extension address for an edition.
*
* @param editionId the edition ID for which the extension is to be set
* @param uriExtension the new URI extension address for the edition ID
*/
function setEditionURIExtension(
uint256 editionId,
address uriExtension
) external;
/**
* @dev Set the address of an extension contract that can mint tokens.
*
* @param newMintingExtension the new Minting extension address for the edition ID
*/
function setMintingExtension(address newMintingExtension) external;
/**
* @dev Updates the address that the contract balance is withdrawn to.
*
* @param primarySaleReceiver_ the address that should receive funds when withdraw is called
*/
function setPrimarySaleReceiver(address primarySaleReceiver_) external;
/**
* @dev Updates the royalties extension address for the contract.
*
* @param newRoyaltyExtension the contract address of the new royalty extension
*/
function setRoyaltyExtension(address newRoyaltyExtension) external;
/**
* @dev returns the current total supply of tokens for the collection, taking both mints and burns into account.
*
* @return supply the number of tokens in circulation
*/
function totalSupply() external view returns (uint256 supply);
/**
* @dev Sends the contract balance to the primary sale receiver address stored in the contract.
*/
function withdraw() external;
}
// lib/openzeppelin-contracts/contracts/utils/Strings.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(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) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}
// lib/openzeppelin-contracts-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
/**
* @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;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @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) {
return _status == _ENTERED;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
// lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
/**
* @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;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
// lib/openzeppelin-contracts-upgradeable/contracts/utils/StringsUpgradeable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
/**
* @dev String operations.
*/
library StringsUpgradeable {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = MathUpgradeable.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMathUpgradeable.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, MathUpgradeable.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}
// lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)
/**
* @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,
InvalidSignatureV // Deprecated in v4.8
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode 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 {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]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
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);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode 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 {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
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]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
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.
*
* _Available since v4.2._
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
// 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);
}
// 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);
}
return (signer, RecoverError.NoError);
}
/**
* @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) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32")
mstore(0x1c, hash)
message := keccak256(0x00, 0x3c)
}
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, "\x19\x01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
data := keccak256(ptr, 0x42)
}
}
/**
* @dev Returns an Ethereum Signed Data with intended validator, created from a
* `validator` and `data` according to the version 0 of EIP-191.
*
* See {recover}.
*/
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x00", validator, data));
}
}
// lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
/**
* @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);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
function __Pausable_init() internal onlyInitializing {
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal onlyInitializing {
_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) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
// lib/openzeppelin-contracts-upgradeable/contracts/utils/cryptography/ECDSAUpgradeable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)
/**
* @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 ECDSAUpgradeable {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV // Deprecated in v4.8
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode 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 {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]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
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);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode 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 {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
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]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
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.
*
* _Available since v4.2._
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
// 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);
}
// 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);
}
return (signer, RecoverError.NoError);
}
/**
* @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) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32")
mstore(0x1c, hash)
message := keccak256(0x00, 0x3c)
}
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", StringsUpgradeable.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, "\x19\x01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
data := keccak256(ptr, 0x42)
}
}
/**
* @dev Returns an Ethereum Signed Data with intended validator, created from a
* `validator` and `data` according to the version 0 of EIP-191.
*
* See {recover}.
*/
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x00", validator, data));
}
}
// lib/openzeppelin-contracts-upgradeable/contracts/utils/introspection/ERC165Upgradeable.sol
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {
function __ERC165_init() internal onlyInitializing {
}
function __ERC165_init_unchained() internal onlyInitializing {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165Upgradeable).interfaceId;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
// lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*/
abstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {
function __ERC1967Upgrade_init() internal onlyInitializing {
}
function __ERC1967Upgrade_init_unchained() internal onlyInitializing {
}
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
AddressUpgradeable.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
}
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
// lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
function __UUPSUpgradeable_init() internal onlyInitializing {
}
function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
}
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
_;
}
/**
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
return _IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeTo(address newImplementation) public virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
// lib/openzeppelin-contracts-upgradeable/contracts/utils/cryptography/EIP712Upgradeable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol)
/**
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
*
* The encoding specified in the EIP is very generic, and such a generic 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 their contracts 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.
*
* _Available since v3.4._
*
* @custom:storage-size 52
*/
abstract contract EIP712Upgradeable is Initializable, IERC5267Upgradeable {
bytes32 private constant _TYPE_HASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
/// @custom:oz-renamed-from _HASHED_NAME
bytes32 private _hashedName;
/// @custom:oz-renamed-from _HASHED_VERSION
bytes32 private _hashedVersion;
string private _name;
string private _version;
/**
* @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 {
_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 ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash);
}
/**
* @dev See {EIP-5267}.
*
* _Available since v4.9._
*/
function eip712Domain()
public
view
virtual
override
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
)
{
// 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 virtual view returns (string memory) {
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 virtual view returns (string memory) {
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) {
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) {
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("");
}
}
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[48] private __gap;
}
// lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```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, IAccessControlUpgradeable, ERC165Upgradeable {
function __AccessControl_init() internal onlyInitializing {
}
function __AccessControl_init_unchained() internal onlyInitializing {
}
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
StringsUpgradeable.toHexString(account),
" is missing role ",
StringsUpgradeable.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
// src/FusedMinterUpgradable.sol
// @author: Novel Labs dev
/// @title FusedMinterUpgradable
/// @notice A contract for minting fused NFTs using various material combinations with upgradeability support
/// @dev Implements UUPS upgradeable pattern with access control, reentrancy protection, and EIP712 for signatures
/// Delegation is supported for checking associated token ownership
contract FusedMinterUpgradable is
UUPSUpgradeable,
PausableUpgradeable,
AccessControlUpgradeable,
ReentrancyGuardUpgradeable,
EIP712Upgradeable,
IFusedMinter
{
/*//////////////////////////////////////////////////////////////
CONSTANTS AND IMMUTABLES
//////////////////////////////////////////////////////////////*/
/// @notice Collection ID constant for OATH collection
uint256 public constant OATH_COLLECTION_ID = 1;
/// @notice Collection ID constant for MAYC collection
uint256 public constant MAYC_COLLECTION_ID = 2;
/// @notice Collection ID constant for BAYC collection
uint256 public constant BAYC_COLLECTION_ID = 3;
/// @notice Edition ID constant for Reaper type
uint256 public constant REAPER_EDITION_ID = 1;
/// @notice Edition ID constant for Ironbound type
uint256 public constant IRONBOUND_EDITION_ID = 2;
/// @notice Edition ID constant for Juggernaut type
uint256 public constant JUGGERNAUT_EDITION_ID = 3;
/// @notice Edition ID constant for Berserker type
uint256 public constant BERSERKER_EDITION_ID = 4;
/// @notice Edition ID constant for Awakened type
uint256 public constant AWAKENED_EDITION_ID = 5;
/// @notice The address of the OATH NFT collection
address public immutable OATH_COLLECTION_ADDRESS;
/// @notice The address of the MAYC NFT collection
address public immutable MAYC_COLLECTION_ADDRESS;
/// @notice The address of the BAYC NFT collection
address public immutable BAYC_COLLECTION_ADDRESS;
/// @notice The address of the materials contract
address public immutable materialsAddress;
/// @notice Interface for the warm wallet registry
IWarmRegistry public immutable warmRegistry;
/// @notice Interface for the delegate registry
IDelegateRegistry public immutable delegateRegistry;
/*//////////////////////////////////////////////////////////////
STORAGE
//////////////////////////////////////////////////////////////*/
/// @notice Mapping to track which tokens have been used for minting
mapping(address collectionAddress => mapping(uint256 tokenId => bool)) public usedTokens;
/// @notice The address of the target NFT collection for minting
address public collectionAddress;
/*//////////////////////////////////////////////////////////////
GAP
//////////////////////////////////////////////////////////////*/
/// @notice Gap for future upgrades
uint256[48] private __gap;
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
error FusedMinterUpgradable__constructor__InvalidCollectionAddress();
error FusedMinterUpgradable__mint__InvalidReceiverAddress();
error FusedMinterUpgradable__mint__InvalidMintParams();
error FusedMinterUpgradable__getCollectionAddress__InvalidCollectionId();
error FusedMinterUpgradable__validateAllocation__ArraysLengthMismatch();
error FusedMinterUpgradable__validateAllocation__InvalidSignature();
error FusedMinterUpgradable__validateTokenOwner__InvalidTokenOwner();
error FusedMinterUpgradable__getCollectionAllocation__InvalidCollectionId();
error FusedMinterUpgradable__mint__InvalidCollectionAddress();
error FusedMinterUpgradable__mint__AllocationExceeded();
error FusedMinterUpgradable__mint__InvalidMaterialId();
error FusedMinterUpgradable__preSaleMint__InvalidCollectionAddress();
error FusedMinterUpgradable__preSaleMint__InvalidReceiverAddress();
error FusedMinterUpgradable__preSaleMint__InvalidMintParams();
error FusedMinterUpgradable__validateAllocation__TokenAlreadyUsed();
error FusedMinterUpgradable__setCollectionAddress__InvalidCollectionAddress();
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
/// @notice Initializes the contract with required addresses
/// @param materialsAddress_ The address of the materials contract
/// @param oathCollectionAddress_ The address of the OATH collection
/// @param maycCollectionAddress_ The address of the MAYC collection
/// @param baycCollectionAddress_ The address of the BAYC collection
/// @param warmRegistry_ The address of the warm wallet registry
/// @param delegateRegistry_ The address of the delegate registry
constructor(
address materialsAddress_,
address oathCollectionAddress_,
address maycCollectionAddress_,
address baycCollectionAddress_,
address warmRegistry_,
address delegateRegistry_
) {
if (
oathCollectionAddress_ == address(0) ||
maycCollectionAddress_ == address(0) ||
baycCollectionAddress_ == address(0) ||
materialsAddress_ == address(0)
) {
revert FusedMinterUpgradable__constructor__InvalidCollectionAddress();
}
OATH_COLLECTION_ADDRESS = oathCollectionAddress_;
MAYC_COLLECTION_ADDRESS = maycCollectionAddress_;
BAYC_COLLECTION_ADDRESS = baycCollectionAddress_;
materialsAddress = materialsAddress_;
warmRegistry = IWarmRegistry(warmRegistry_);
delegateRegistry = IDelegateRegistry(delegateRegistry_);
_disableInitializers();
}
/*//////////////////////////////////////////////////////////////
INITIALIZATION
//////////////////////////////////////////////////////////////*/
/// @notice Initializes the contract with default admin roles and paused state
function initialize() public initializer {
__EIP712_init("FusedMinter", "1");
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(ADMIN_ROLE, msg.sender);
_grantRole(PAUSER_ROLE, msg.sender);
_pause();
}
/// @notice Authorizes an upgrade to a new implementation
/// @param newImplementation Address of the new implementation contract
function _authorizeUpgrade(address newImplementation) internal override onlyRole(ADMIN_ROLE) {}
/*//////////////////////////////////////////////////////////////
ALLOCATION VALIDATION
//////////////////////////////////////////////////////////////*/
/// @dev Validates allocation parameters and returns total allocation
/// @param allocationParams Array of allocation parameters to validate
/// @return Total allocation amount
function _validateAllocation(AllocationParams[] calldata allocationParams) internal returns (uint256) {
uint256 allocationParamsLength = allocationParams.length;
if (allocationParamsLength == 0) {
return 0;
}
uint256 totalAllocation = 0;
for (uint256 i = 0; i < allocationParamsLength; i++) {
AllocationParams calldata params = allocationParams[i];
uint256 tokenParamsLength = params.tokenParams.length;
for (uint256 j = 0; j < tokenParamsLength; j++) {
TokenParams calldata tokenParam = params.tokenParams[j];
// Get collection address for the given collectionId
address tokenCollectionAddress = _getCollectionAddress(tokenParam.collectionId);
// Check if any tokens have been used
if (usedTokens[tokenCollectionAddress][tokenParam.tokenId]) {
revert FusedMinterUpgradable__validateAllocation__TokenAlreadyUsed();
}
}
// Validate the signer of the allocation
_validateSigner(params.signer, params.signature);
// Validate token ownership and mark as used
for (uint256 j = 0; j < tokenParamsLength; j++) {
TokenParams calldata tokenParam = params.tokenParams[j];
address tokenCollectionAddress = _getCollectionAddress(tokenParam.collectionId);
_validateTokenOwner(params.signer, tokenParam.walletType, IERC721(tokenCollectionAddress), tokenParam.tokenId);
usedTokens[tokenCollectionAddress][tokenParam.tokenId] = true;
totalAllocation += _getCollectionAllocation(tokenParam.collectionId, tokenParam.tokenId);
emit TokenUsed(tokenCollectionAddress, tokenParam.tokenId);
}
}
return totalAllocation;
}
/// @dev Validates the signer of the allocation
/// @param signer The address of the signer
/// @param signature The signature of the signer
function _validateSigner(address signer, bytes calldata signature) internal view {
// if the signer is the same as the sender, we don't need to validate the signature
if (signer == msg.sender) {
return;
}
// Get the digest for the allocation message
bytes32 digest = getDigest(msg.sender, signer);
address recoveredSigner = ECDSA.recover(digest, signature);
// Verify the signer matches the provided signer
if (recoveredSigner != signer) {
revert FusedMinterUpgradable__validateAllocation__InvalidSignature();
}
}
/// @dev Validates token ownership based on wallet type
/// @param signer The address of the signer
/// @param walletType The type of wallet
/// @param collection The ERC721 collection contract
/// @param tokenId The ID of the token
function _validateTokenOwner(address signer, uint256 walletType, IERC721 collection, uint256 tokenId) internal view {
address owner = collection.ownerOf(tokenId);
if (walletType == WALLET_TYPE_WARMXYZ) {
address[] memory coldWallets = warmRegistry.getColdWallets(signer);
for (uint256 i = 0; i < coldWallets.length; i++) {
if (coldWallets[i] == owner) {
return;
}
}
revert FusedMinterUpgradable__validateTokenOwner__InvalidTokenOwner();
} else if (walletType == WALLET_TYPE_DELEGATEXYZ) {
// Check if the signer has delegation rights for this specific token
bool hasValidDelegation = delegateRegistry.checkDelegateForERC721(
signer,
owner,
address(collection),
tokenId,
bytes32(0) // Pass zero to check for full delegation rights
);
if (!hasValidDelegation) {
revert FusedMinterUpgradable__validateTokenOwner__InvalidTokenOwner();
}
} else {
if (owner != signer) {
revert FusedMinterUpgradable__validateTokenOwner__InvalidTokenOwner();
}
}
}
/*//////////////////////////////////////////////////////////////
COLLECTION MANAGEMENT
//////////////////////////////////////////////////////////////*/
/// @dev Returns the collection address for a given collection ID
/// @param collectionId The ID of the collection
/// @return The address of the collection contract
function _getCollectionAddress(uint256 collectionId) internal view returns (address) {
if (collectionId == OATH_COLLECTION_ID) {
return OATH_COLLECTION_ADDRESS;
} else if (collectionId == MAYC_COLLECTION_ID) {
return MAYC_COLLECTION_ADDRESS;
} else if (collectionId == BAYC_COLLECTION_ID) {
return BAYC_COLLECTION_ADDRESS;
} else {
revert FusedMinterUpgradable__getCollectionAddress__InvalidCollectionId();
}
}
/// @dev Returns the allocation amount for a given collection and token ID
/// @param collectionId The ID of the collection
/// @param tokenId The ID of the token
/// @return The allocation amount
function _getCollectionAllocation(uint256 collectionId, uint256 tokenId) internal pure returns (uint256) {
if (collectionId < OATH_COLLECTION_ID || collectionId > BAYC_COLLECTION_ID) {
revert FusedMinterUpgradable__getCollectionAllocation__InvalidCollectionId();
}
if (collectionId == OATH_COLLECTION_ID) {
// we can assume that the tokenId is in a valid range otherwise the ownership check would fail
uint256 firstDigit = tokenId / 1e9;
return firstDigit == 2 ? 2 : 1;
}
return 1;
}
/*//////////////////////////////////////////////////////////////
MINTING LOGIC
//////////////////////////////////////////////////////////////*/
/// @dev Determines the fused type based on the materials used
/// @param materials Array of material IDs used in the recipe
/// @return The edition ID of the resulting fused type
function _getFusedType(uint256[] memory materials) internal pure returns (uint256) {
/// Material types:
/// 1. Hound Organs
/// 2. Bottled Soul
/// 3. Dark Serum
/// 4. Hacked DNA
/// 5. Canopic Jar
/// Recipes for each fused type:
/// 1. Reaper : Bottled Soul (2) + Dark Serum (3)
/// 2. Ironbound : Dark Serum (3) + Hacked DNA (4)
/// 3. Juggernaut : Hound Organs (1) + Hacked DNA (4)
/// 4. Berserker : Bottled Soul (2) + Hound Organs (1)
/// 5. Awakened : Any valid recipe + Canopic Jar
uint256 length = materials.length;
if (length < 2 || length > 3) {
revert FusedMinterUpgradable__mint__InvalidMintParams();
}
if (length == 3) {
// Find Canopic Jar and get the other two materials for the base recipe
uint256 mat1;
uint256 mat2;
bool foundCanopic = false;
for (uint256 i = 0; i < 3; i++) {
if (materials[i] == 5) {
// Canopic Jar
foundCanopic = true;
} else {
if (mat1 == 0) {
mat1 = materials[i];
} else {
mat2 = materials[i];
}
}
}
if (!foundCanopic) {
revert FusedMinterUpgradable__mint__InvalidMintParams();
}
// Sort the two non-Canopic materials
if (mat1 > mat2) {
(mat1, mat2) = (mat2, mat1);
}
// Create a unique key for the material combination
uint256 recipeKey = (mat1 << 3) | mat2;
// Check if it's a valid base recipe
if (
recipeKey == ((2 << 3) | 3) || // Bottled Soul (2) + Dark Serum (3)
recipeKey == ((1 << 3) | 4) || // Hound Organs (1) + Hacked DNA (4)
recipeKey == ((3 << 3) | 4) || // Dark Serum (3) + Hacked DNA (4)
recipeKey == ((1 << 3) | 2)
) {
// Bottled Soul (2) + Hound Organs (1)
return AWAKENED_EDITION_ID;
}
} else {
// Regular two-material recipe
uint256 mat1 = materials[0] < materials[1] ? materials[0] : materials[1];
uint256 mat2 = materials[0] < materials[1] ? materials[1] : materials[0];
// Create a unique key for the material combination
uint256 recipeKey = (mat1 << 3) | mat2;
if (recipeKey == ((2 << 3) | 3)) {
// Bottled Soul (2) + Dark Serum (3)
return REAPER_EDITION_ID;
} else if (recipeKey == ((3 << 3) | 4)) {
// Dark Serum (3) + Hacked DNA (4)
return IRONBOUND_EDITION_ID;
} else if (recipeKey == ((1 << 3) | 4)) {
// Hound Organs (1) + Hacked DNA (4)
return JUGGERNAUT_EDITION_ID;
} else if (recipeKey == ((1 << 3) | 2)) {
// Bottled Soul (2) + Hound Organs (1)
return BERSERKER_EDITION_ID;
}
}
revert FusedMinterUpgradable__mint__InvalidMintParams();
}
/// @notice Mints new fused NFTs based on the provided parameters
/// @param params The minting parameters including recipe and allocation details
function mint(MintParams calldata params) external override nonReentrant whenNotPaused {
if (collectionAddress == address(0)) {
revert FusedMinterUpgradable__mint__InvalidCollectionAddress();
}
// Validate input parameters
if (params.receiver == address(0)) {
revert FusedMinterUpgradable__mint__InvalidReceiverAddress();
}
if (params.recipeParams.length == 0) {
revert FusedMinterUpgradable__mint__InvalidMintParams();
}
// Get the Fair721Editions contract
IFairxyzEditions collection = IFairxyzEditions(collectionAddress);
uint256 computeAllocation = _validateAllocation(params.allocationParams);
// 5 types of materials offset by 1
uint256[] memory usedMaterials = new uint256[](6);
uint256[] memory mintedEditions = new uint256[](6);
uint256 mintedEditionsCount = 0;
// Iterate through recipeParams array
uint256 recipeParamsLength = params.recipeParams.length;
for (uint256 i = 0; i < recipeParamsLength; i++) {
RecipeParam memory recipeParam = params.recipeParams[i];
uint256 amount = recipeParam.amount;
for (uint256 materialIndex = 0; materialIndex < recipeParam.materials.length; materialIndex++) {
uint256 materialId = recipeParam.materials[materialIndex];
if (materialId > 5 || materialId == 0) {
revert FusedMinterUpgradable__mint__InvalidMaterialId();
}
usedMaterials[materialId] += amount;
}
uint256 typeId = _getFusedType(recipeParam.materials);
mintedEditions[typeId] += amount;
mintedEditionsCount += amount;
}
// validate allocation
if (mintedEditionsCount > computeAllocation) {
revert FusedMinterUpgradable__mint__AllocationExceeded();
}
// Burn materials
IMaterials materials = IMaterials(materialsAddress);
materials.burnMaterials(usedMaterials, msg.sender);
// Mint editions
for (uint256 i = REAPER_EDITION_ID; i <= AWAKENED_EDITION_ID; i++) {
if (mintedEditions[i] > 0) {
collection.mintEdition(i, params.receiver, mintedEditions[i], 0, 0, '');
}
}
}
/// @notice Mints new fused NFTs based on the provided parameters
/// @param tokensPerEdition Array of tokens per edition
/// @param receiver The address of the receiver
function preSaleMint(
uint256[] calldata tokensPerEdition,
address receiver
) external override nonReentrant whenNotPaused onlyRole(ADMIN_ROLE) {
if (collectionAddress == address(0)) {
revert FusedMinterUpgradable__preSaleMint__InvalidCollectionAddress();
}
if (receiver == address(0)) {
revert FusedMinterUpgradable__preSaleMint__InvalidReceiverAddress();
}
IFairxyzEditions collection = IFairxyzEditions(collectionAddress);
if (tokensPerEdition.length != 6) {
revert FusedMinterUpgradable__preSaleMint__InvalidMintParams();
}
for (uint256 editionIdx = REAPER_EDITION_ID; editionIdx <= AWAKENED_EDITION_ID; editionIdx++) {
if (tokensPerEdition[editionIdx] > 0) {
collection.mintEdition(editionIdx, receiver, tokensPerEdition[editionIdx], 0, 0, '');
}
}
}
/*//////////////////////////////////////////////////////////////
ADMIN FUNCTIONS
//////////////////////////////////////////////////////////////*/
/// @notice Pauses the contract
function pause() external onlyRole(ADMIN_ROLE) {
_pause();
}
/// @notice Unpauses the contract
function unpause() external onlyRole(ADMIN_ROLE) {
_unpause();
}
/// @notice Sets the collection address for the contract
/// @param collectionAddress_ The address of the collection contract
function setCollectionAddress(address collectionAddress_) external onlyRole(ADMIN_ROLE) {
if (collectionAddress_ == address(0)) {
revert FusedMinterUpgradable__setCollectionAddress__InvalidCollectionAddress();
}
collectionAddress = collectionAddress_;
emit CollectionAddressSet(collectionAddress, collectionAddress_);
}
/// @notice Helper function to get the digest for the allocation message
/// @param minterAddress The address of the minter
/// @param signerAddress The address of the signer
/// @return The digest
function getDigest(
address minterAddress,
address signerAddress
) public view override returns (bytes32) {
return _hashTypedDataV4(keccak256(abi.encode(ALLOCATION_TYPEHASH, minterAddress, signerAddress)));
}
function resetUsedTokens(uint256 collectionId, uint256[] calldata tokenIds) external onlyRole(ADMIN_ROLE) {
address collectionAddress_ = _getCollectionAddress(collectionId);
for (uint256 i = 0; i < tokenIds.length; i++) {
usedTokens[collectionAddress_][tokenIds[i]] = false;
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"materialsAddress_","type":"address"},{"internalType":"address","name":"oathCollectionAddress_","type":"address"},{"internalType":"address","name":"maycCollectionAddress_","type":"address"},{"internalType":"address","name":"baycCollectionAddress_","type":"address"},{"internalType":"address","name":"warmRegistry_","type":"address"},{"internalType":"address","name":"delegateRegistry_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FusedMinterUpgradable__constructor__InvalidCollectionAddress","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__getCollectionAddress__InvalidCollectionId","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__getCollectionAllocation__InvalidCollectionId","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__mint__AllocationExceeded","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__mint__InvalidCollectionAddress","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__mint__InvalidMaterialId","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__mint__InvalidMintParams","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__mint__InvalidReceiverAddress","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__preSaleMint__InvalidCollectionAddress","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__preSaleMint__InvalidMintParams","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__preSaleMint__InvalidReceiverAddress","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__setCollectionAddress__InvalidCollectionAddress","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__validateAllocation__ArraysLengthMismatch","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__validateAllocation__InvalidSignature","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__validateAllocation__TokenAlreadyUsed","type":"error"},{"inputs":[],"name":"FusedMinterUpgradable__validateTokenOwner__InvalidTokenOwner","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldCollectionAddress","type":"address"},{"indexed":false,"internalType":"address","name":"newCollectionAddress","type":"address"}],"name":"CollectionAddressSet","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"collectionAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"TokenUsed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"AWAKENED_EDITION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BAYC_COLLECTION_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BAYC_COLLECTION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BERSERKER_EDITION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"IRONBOUND_EDITION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"JUGGERNAUT_EDITION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAYC_COLLECTION_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAYC_COLLECTION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OATH_COLLECTION_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OATH_COLLECTION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REAPER_EDITION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collectionAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delegateRegistry","outputs":[{"internalType":"contract IDelegateRegistry","name":"","type":"address"}],"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":"address","name":"minterAddress","type":"address"},{"internalType":"address","name":"signerAddress","type":"address"}],"name":"getDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"materialsAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"receiver","type":"address"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256[]","name":"materials","type":"uint256[]"}],"internalType":"struct RecipeParam[]","name":"recipeParams","type":"tuple[]"},{"components":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"collectionId","type":"uint256"},{"internalType":"uint256","name":"walletType","type":"uint256"}],"internalType":"struct TokenParams[]","name":"tokenParams","type":"tuple[]"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct AllocationParams[]","name":"allocationParams","type":"tuple[]"}],"internalType":"struct MintParams","name":"params","type":"tuple"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"tokensPerEdition","type":"uint256[]"},{"internalType":"address","name":"receiver","type":"address"}],"name":"preSaleMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"collectionId","type":"uint256"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"resetUsedTokens","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":"collectionAddress_","type":"address"}],"name":"setCollectionAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"collectionAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"usedTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"warmRegistry","outputs":[{"internalType":"contract IWarmRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6101606040523060805234801562000015575f80fd5b50604051620036d1380380620036d18339810160408190526200003891620001b9565b6001600160a01b03851615806200005657506001600160a01b038416155b806200006957506001600160a01b038316155b806200007c57506001600160a01b038616155b156200009b576040516312f2570960e11b815260040160405180910390fd5b6001600160a01b0380861660a05284811660c05283811660e0528681166101005282811661012052811661014052620000d3620000df565b50505050505062000236565b5f54610100900460ff16156200014b5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116146200019b575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b0381168114620001b4575f80fd5b919050565b5f805f805f8060c08789031215620001cf575f80fd5b620001da876200019d565b9550620001ea602088016200019d565b9450620001fa604088016200019d565b93506200020a606088016200019d565b92506200021a608088016200019d565b91506200022a60a088016200019d565b90509295509295509295565b60805160a05160c05160e051610100516101205161014051613403620002ce5f395f818161023601526120f001525f81816102d90152611fca01525f818161030c015261111501525f818161059501526115df01525f81816105e701526115b001525f818161052f015261158101525f81816107140152818161075401528181610889015281816108c9015261094001526134035ff3fe6080604052600436106101cb575f3560e01c80637dcbe0bb116100f5578063a8f10e131161008e578063a8f10e131461051e578063cb11169714610551578063cbe4c56314610203578063d547741f14610565578063ddb39a4014610551578063e644004d14610584578063ede2d72c146105b7578063f0befc51146105d6578063f21c15d114610609575f80fd5b80637dcbe0bb146102935780638129fc1c146104255780638456cb591461043957806384b0196e1461044d57806391d1485414610474578063951e78ee14610493578063a217fddf146104cd578063a45fcd07146104e0578063a6904aa5146104ff575f80fd5b80633659cfe6116101675780633659cfe61461034d578063378dce4e1461036c5780633c1e50b11461038b5780633f4ba83a1461039f5780634f1ef286146103b357806352d1902d146103c65780635c975abb146103da5780636aa00371146103f1578063791fe82814610411575f80fd5b806301ffc9a7146101cf5780630a7ff4a61461020357806313bfffac14610225578063248a9ca3146102655780632c950c4e146102935780632f2ff15d146102a757806331c65737146102c857806332f3c629146102fb57806336568abe1461032e575b5f80fd5b3480156101da575f80fd5b506101ee6101e93660046128af565b610628565b60405190151581526020015b60405180910390f35b34801561020e575f80fd5b50610217600281565b6040519081526020016101fa565b348015610230575f80fd5b506102587f000000000000000000000000000000000000000000000000000000000000000081565b6040516101fa91906128d6565b348015610270575f80fd5b5061021761027f3660046128ea565b5f90815260fb602052604090206001015490565b34801561029e575f80fd5b50610217600181565b3480156102b2575f80fd5b506102c66102c1366004612915565b61065e565b005b3480156102d3575f80fd5b506102587f000000000000000000000000000000000000000000000000000000000000000081565b348015610306575f80fd5b506102587f000000000000000000000000000000000000000000000000000000000000000081565b348015610339575f80fd5b506102c6610348366004612915565b610687565b348015610358575f80fd5b506102c6610367366004612943565b61070a565b348015610377575f80fd5b506102c661038636600461299e565b6107d1565b348015610396575f80fd5b50610217600581565b3480156103aa575f80fd5b506102c6610860565b6102c66103c1366004612a51565b61087f565b3480156103d1575f80fd5b50610217610934565b3480156103e5575f80fd5b5060975460ff166101ee565b3480156103fc575f80fd5b5061019454610258906001600160a01b031681565b34801561041c575f80fd5b50610217600481565b348015610430575f80fd5b506102c66109e0565b348015610444575f80fd5b506102c6610b7b565b348015610458575f80fd5b50610461610b9a565b6040516101fa9796959493929190612b79565b34801561047f575f80fd5b506101ee61048e366004612915565b610c35565b34801561049e575f80fd5b506101ee6104ad366004612be8565b61019360209081525f928352604080842090915290825290205460ff1681565b3480156104d8575f80fd5b506102175f81565b3480156104eb575f80fd5b506102c66104fa366004612c12565b610c5f565b34801561050a575f80fd5b506102c6610519366004612943565b610ddd565b348015610529575f80fd5b506102587f000000000000000000000000000000000000000000000000000000000000000081565b34801561055c575f80fd5b50610217600381565b348015610570575f80fd5b506102c661057f366004612915565b610e78565b34801561058f575f80fd5b506102587f000000000000000000000000000000000000000000000000000000000000000081565b3480156105c2575f80fd5b506102c66105d1366004612c64565b610e9c565b3480156105e1575f80fd5b506102587f000000000000000000000000000000000000000000000000000000000000000081565b348015610614575f80fd5b50610217610623366004612c9a565b61126f565b5f6001600160e01b03198216637965db0b60e01b148061065857506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f82815260fb6020526040902060010154610678816112e4565b61068283836112ee565b505050565b6001600160a01b03811633146106fc5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6107068282611373565b5050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036107525760405162461bcd60e51b81526004016106f390612cc6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166107846113d9565b6001600160a01b0316146107aa5760405162461bcd60e51b81526004016106f390612d12565b6107b3816113f4565b604080515f808252602082019092526107ce9183919061140b565b50565b5f805160206133ae8339815191526107e8816112e4565b5f6107f285611575565b90505f5b83811015610858576001600160a01b0382165f908152610193602052604081208187878581811061082957610829612d5e565b602090810292909201358352508101919091526040015f20805460ff19169115159190911790556001016107f6565b505050505050565b5f805160206133ae833981519152610877816112e4565b6107ce61161c565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036108c75760405162461bcd60e51b81526004016106f390612cc6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166108f96113d9565b6001600160a01b03161461091f5760405162461bcd60e51b81526004016106f390612d12565b610928826113f4565b6107068282600161140b565b5f306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146109ce5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b60648201526084016106f3565b505f8051602061336783398151915290565b5f54610100900460ff16158080156109fe57505f54600160ff909116105b80610a175750303b158015610a1757505f5460ff166001145b610a7a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016106f3565b5f805460ff191660011790558015610a9b575f805461ff0019166101001790555b610ae16040518060400160405280600b81526020016a233ab9b2b226b4b73a32b960a91b815250604051806040016040528060018152602001603160f81b815250611668565b610aeb5f336112ee565b610b025f805160206133ae833981519152336112ee565b610b2c7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a336112ee565b610b34611698565b80156107ce575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b5f805160206133ae833981519152610b92816112e4565b6107ce611698565b5f6060805f805f606061015f545f801b148015610bb8575061016054155b610bfc5760405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b60448201526064016106f3565b610c046116d5565b610c0c611766565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b5f91825260fb602090815260408084206001600160a01b0393909316845291905290205460ff1690565b610c67611776565b610c6f6117d1565b5f805160206133ae833981519152610c86816112e4565b610194546001600160a01b0316610cb05760405163bd28e40960e01b815260040160405180910390fd5b6001600160a01b038216610cd75760405163c31160ab60e01b815260040160405180910390fd5b610194546001600160a01b031660068414610d055760405163153c810b60e21b815260040160405180910390fd5b60015b60058111610dcf575f868683818110610d2357610d23612d5e565b905060200201351115610dbd57816001600160a01b0316630c267ed68286898986818110610d5357610d53612d5e565b905060200201355f806040518663ffffffff1660e01b8152600401610d7c959493929190612d72565b60408051808303815f875af1158015610d97573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dbb9190612db3565b505b80610dc781612df7565b915050610d08565b505050610682600161012d55565b5f805160206133ae833981519152610df4816112e4565b6001600160a01b038216610e1b57604051630146038560e11b815260040160405180910390fd5b61019480546001600160a01b0319166001600160a01b0384169081179091556040805182815260208101929092527faadbacde6d52adfcaa45e064cfc34885b286e20ad9e665e48d10dea5ae54b4cc910160405180910390a15050565b5f82815260fb6020526040902060010154610e92816112e4565b6106828383611373565b610ea4611776565b610eac6117d1565b610194546001600160a01b0316610ed65760405163413ec12d60e01b815260040160405180910390fd5b5f610ee46020830183612943565b6001600160a01b031603610f0b5760405163c39bd29560e01b815260040160405180910390fd5b610f186020820182612e0f565b90505f03610f3957604051633be06f8160e11b815260040160405180910390fd5b610194546001600160a01b03165f610f5c610f576040850185612e0f565b611819565b60408051600680825260e082019092529192505f91906020820160c080368337505060408051600680825260e082019092529293505f9291506020820160c0803683370190505090505f80610fb46020880188612e0f565b905090505f5b818110156110e4575f610fd060208a018a612e0f565b83818110610fe057610fe0612d5e565b9050602002810190610ff29190612e54565b610ffb90612e94565b80519091505f5b82602001515181101561108e575f8360200151828151811061102657611026612d5e565b60200260200101519050600581118061103d575080155b1561105b57604051630de93ed960e41b815260040160405180910390fd5b8289828151811061106e5761106e612d5e565b602002602001018181516110829190612f39565b90525050600101611002565b505f61109d8360200151611a28565b9050818782815181106110b2576110b2612d5e565b602002602001018181516110c69190612f39565b9052506110d38287612f39565b95505060019092019150610fba9050565b508482111561110657604051632070190d60e11b815260040160405180910390fd5b60405163178fdb9160e31b81527f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b0382169063bc7edc88906111569088903390600401612f4c565b5f604051808303815f87803b15801561116d575f80fd5b505af115801561117f573d5f803e3d5ffd5b506001925050505b6005811161125c575f8582815181106111a2576111a2612d5e565b6020026020010151111561124a576001600160a01b038816630c267ed6826111cd60208d018d612943565b8885815181106111df576111df612d5e565b60200260200101515f806040518663ffffffff1660e01b8152600401611209959493929190612d72565b60408051808303815f875af1158015611224573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112489190612db3565b505b8061125481612df7565b915050611187565b50505050505050506107ce600161012d55565b5f6112dd7f98fe0d162b663453ff7f454bbd833fa89a020b434fd66b63c3d9919fb71ac7b384846040516020016112c2939291909283526001600160a01b03918216602084015216604082015260600190565b60405160208183030381529060405280519060200120611cbd565b9392505050565b6107ce8133611ce9565b6112f88282610c35565b610706575f82815260fb602090815260408083206001600160a01b03851684529091529020805460ff1916600117905561132f3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b61137d8282610c35565b15610706575f82815260fb602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b5f80516020613367833981519152546001600160a01b031690565b5f805160206133ae833981519152610706816112e4565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561143e5761068283611d42565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611498575060408051601f3d908101601f1916820190925261149591810190612f75565b60015b6114fb5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016106f3565b5f8051602061336783398151915281146115695760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016106f3565b50610682838383611ddd565b5f600182036115a557507f0000000000000000000000000000000000000000000000000000000000000000919050565b600282036115d457507f0000000000000000000000000000000000000000000000000000000000000000919050565b6003820361160357507f0000000000000000000000000000000000000000000000000000000000000000919050565b604051630cb782df60e01b815260040160405180910390fd5b611624611e07565b6097805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405161165e91906128d6565b60405180910390a1565b5f54610100900460ff1661168e5760405162461bcd60e51b81526004016106f390612f8c565b6107068282611e50565b6116a06117d1565b6097805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586116513390565b606061016180546116e590612fd7565b80601f016020809104026020016040519081016040528092919081815260200182805461171190612fd7565b801561175c5780601f106117335761010080835404028352916020019161175c565b820191905f5260205f20905b81548152906001019060200180831161173f57829003601f168201915b5050505050905090565b606061016280546116e590612fd7565b600261012d54036117c95760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106f3565b600261012d55565b60975460ff16156118175760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016106f3565b565b5f8180820361182b575f915050610658565b5f805b82811015611a1f573686868381811061184957611849612d5e565b905060200281019061185b919061300f565b90505f6118688280613023565b905090505f5b818110156118fa57366118818480613023565b8381811061189157611891612d5e565b90506060020190505f6118a78260200135611575565b6001600160a01b0381165f908152610193602090815260408083208635845290915290205490915060ff16156118f05760405163195d2cad60e01b815260040160405180910390fd5b505060010161186e565b5061192061190e6060840160408501612943565b61191b6020850185613067565b611ea1565b5f5b81811015611a1457366119358480613023565b8381811061194557611945612d5e565b90506060020190505f61195b8260200135611575565b905061197d6119706060870160408801612943565b6040840135838535611f3e565b6001600160a01b0381165f9081526101936020908152604080832085358085529083529220805460ff191660011790556119bb9190840135906121b3565b6119c59088612f39565b604080516001600160a01b0384168152843560208201529198507f8a598ee0f736ea6ad6f489c030c0e073ec11994f86e132f30227d647f2f3b58f910160405180910390a15050600101611922565b50505060010161182e565b50949350505050565b80515f906002811080611a3b5750600381115b15611a5957604051633be06f8160e11b815260040160405180910390fd5b80600303611b58575f805f805b6003811015611ae657868181518110611a8157611a81612d5e565b6020026020010151600503611a995760019150611ade565b835f03611ac157868181518110611ab257611ab2612d5e565b60200260200101519350611ade565b868181518110611ad357611ad3612d5e565b602002602001015192505b600101611a66565b5080611b0557604051633be06f8160e11b815260040160405180910390fd5b81831115611b11579091905b600383901b82176013811480611b27575080600c145b80611b32575080601c145b80611b3d575080600a145b15611b4f575060059695505050505050565b50505050611ca4565b5f83600181518110611b6c57611b6c612d5e565b6020026020010151845f81518110611b8657611b86612d5e565b602002602001015110611bb35783600181518110611ba657611ba6612d5e565b6020026020010151611bce565b835f81518110611bc557611bc5612d5e565b60200260200101515b90505f84600181518110611be457611be4612d5e565b6020026020010151855f81518110611bfe57611bfe612d5e565b602002602001015110611c2a57845f81518110611c1d57611c1d612d5e565b6020026020010151611c46565b84600181518110611c3d57611c3d612d5e565b60200260200101515b9050600382901b81176013819003611c645750600195945050505050565b80601c03611c785750600295945050505050565b80600c03611c8c5750600395945050505050565b80600a03611ca05750600495945050505050565b5050505b604051633be06f8160e11b815260040160405180910390fd5b5f610658611cc9612220565b8360405161190160f01b8152600281019290925260228201526042902090565b611cf38282610c35565b61070657611d008161222e565b611d0b836020612240565b604051602001611d1c9291906130a9565b60408051601f198184030181529082905262461bcd60e51b82526106f391600401613117565b6001600160a01b0381163b611daf5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016106f3565b5f8051602061336783398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b611de6836123d5565b5f82511180611df25750805b1561068257611e018383612414565b50505050565b60975460ff166118175760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016106f3565b5f54610100900460ff16611e765760405162461bcd60e51b81526004016106f390612f8c565b610161611e83838261316d565b50610162611e91828261316d565b50505f61015f8190556101605550565b336001600160a01b03841603611eb657505050565b5f611ec1338561126f565b90505f611f038285858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061243992505050565b9050846001600160a01b0316816001600160a01b031614611f3757604051631f57cb8960e11b815260040160405180910390fd5b5050505050565b6040516331a9108f60e11b8152600481018290525f906001600160a01b03841690636352211e90602401602060405180830381865afa158015611f83573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fa79190613228565b9050600184036120a95760405163a3ba430160e01b81525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a3ba430190611fff9089906004016128d6565b5f60405180830381865afa158015612019573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526120409190810190613243565b90505f5b815181101561208f57826001600160a01b031682828151811061206957612069612d5e565b60200260200101516001600160a01b03160361208757505050611e01565b600101612044565b5060405163f4ce9d5960e01b815260040160405180910390fd5b6002840361218157604051632e7cda1d60e21b81526001600160a01b03868116600483015282811660248301528481166044830152606482018490525f60848301819052917f00000000000000000000000000000000000000000000000000000000000000009091169063b9f368749060a401602060405180830381865afa158015612137573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061215b91906132d7565b90508061217b5760405163f4ce9d5960e01b815260040160405180910390fd5b50611f37565b846001600160a01b0316816001600160a01b031614611f375760405163f4ce9d5960e01b815260040160405180910390fd5b5f60018310806121c35750600383115b156121e15760405163136d190960e01b815260040160405180910390fd5b60018303612217575f6121f8633b9aca00846132f6565b90508060021461220957600161220c565b60025b60ff16915050610658565b50600192915050565b5f61222961245b565b905090565b60606106586001600160a01b03831660145b60605f61224e836002613315565b612259906002612f39565b6001600160401b03811115612270576122706129e5565b6040519080825280601f01601f19166020018201604052801561229a576020820181803683370190505b509050600360fc1b815f815181106122b4576122b4612d5e565b60200101906001600160f81b03191690815f1a905350600f60fb1b816001815181106122e2576122e2612d5e565b60200101906001600160f81b03191690815f1a9053505f612304846002613315565b61230f906001612f39565b90505b6001811115612386576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061234357612343612d5e565b1a60f81b82828151811061235957612359612d5e565b60200101906001600160f81b03191690815f1a90535060049490941c9361237f8161332c565b9050612312565b5083156112dd5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016106f3565b6123de81611d42565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606112dd8383604051806060016040528060278152602001613387602791396124ce565b5f805f6124468585612542565b9150915061245381612584565b509392505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6124856126c8565b61248d612721565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b60605f80856001600160a01b0316856040516124ea9190613341565b5f60405180830381855af49150503d805f8114612522576040519150601f19603f3d011682016040523d82523d5f602084013e612527565b606091505b509150915061253886838387612752565b9695505050505050565b5f808251604103612576576020830151604084015160608501515f1a61256a878285856127d2565b9450945050505061257d565b505f905060025b9250929050565b5f81600481111561259757612597613352565b0361259f5750565b60018160048111156125b3576125b3613352565b036125fb5760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b60448201526064016106f3565b600281600481111561260f5761260f613352565b0361265c5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016106f3565b600381600481111561267057612670613352565b036107ce5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016106f3565b5f806126d26116d5565b8051909150156126e9578051602090910120919050565b61015f5480156126f95792915050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709250505090565b5f8061272b611766565b805190915015612742578051602090910120919050565b6101605480156126f95792915050565b606083156127c05782515f036127b9576001600160a01b0385163b6127b95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106f3565b50816127ca565b6127ca8383612885565b949350505050565b5f806fa2a8918ca85bafe22016d0b997e4df60600160ff1b038311156127fd57505f9050600361287c565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561284e573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116612876575f6001925092505061287c565b91505f90505b94509492505050565b8151156128955781518083602001fd5b8060405162461bcd60e51b81526004016106f39190613117565b5f602082840312156128bf575f80fd5b81356001600160e01b0319811681146112dd575f80fd5b6001600160a01b0391909116815260200190565b5f602082840312156128fa575f80fd5b5035919050565b6001600160a01b03811681146107ce575f80fd5b5f8060408385031215612926575f80fd5b82359150602083013561293881612901565b809150509250929050565b5f60208284031215612953575f80fd5b81356112dd81612901565b5f8083601f84011261296e575f80fd5b5081356001600160401b03811115612984575f80fd5b6020830191508360208260051b850101111561257d575f80fd5b5f805f604084860312156129b0575f80fd5b8335925060208401356001600160401b038111156129cc575f80fd5b6129d88682870161295e565b9497909650939450505050565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715612a1b57612a1b6129e5565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612a4957612a496129e5565b604052919050565b5f8060408385031215612a62575f80fd5b8235612a6d81612901565b91506020838101356001600160401b0380821115612a89575f80fd5b818601915086601f830112612a9c575f80fd5b813581811115612aae57612aae6129e5565b612ac0601f8201601f19168501612a21565b91508082528784828501011115612ad5575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f5b83811015612b0c578181015183820152602001612af4565b50505f910152565b5f8151808452612b2b816020860160208601612af2565b601f01601f19169290920160200192915050565b5f815180845260208085019450602084015f5b83811015612b6e57815187529582019590820190600101612b52565b509495945050505050565b60ff60f81b8816815260e060208201525f612b9760e0830189612b14565b8281036040840152612ba98189612b14565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501529050612bda8185612b3f565b9a9950505050505050505050565b5f8060408385031215612bf9575f80fd5b8235612c0481612901565b946020939093013593505050565b5f805f60408486031215612c24575f80fd5b83356001600160401b03811115612c39575f80fd5b612c458682870161295e565b9094509250506020840135612c5981612901565b809150509250925092565b5f60208284031215612c74575f80fd5b81356001600160401b03811115612c89575f80fd5b8201606081850312156112dd575f80fd5b5f8060408385031215612cab575f80fd5b8235612cb681612901565b9150602083013561293881612901565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b5f52603260045260245ffd5b9485526001600160a01b03939093166020850152604084019190915264ffffffffff166060830152608082015260c060a082018190525f9082015260e00190565b5f60408284031215612dc3575f80fd5b612dcb6129f9565b82518152602083015160208201528091505092915050565b634e487b7160e01b5f52601160045260245ffd5b5f60018201612e0857612e08612de3565b5060010190565b5f808335601e19843603018112612e24575f80fd5b8301803591506001600160401b03821115612e3d575f80fd5b6020019150600581901b360382131561257d575f80fd5b5f8235603e19833603018112612e68575f80fd5b9190910192915050565b5f6001600160401b03821115612e8a57612e8a6129e5565b5060051b60200190565b5f60408236031215612ea4575f80fd5b612eac6129f9565b823581526020808401356001600160401b03811115612ec9575f80fd5b840136601f820112612ed9575f80fd5b8035612eec612ee782612e72565b612a21565b81815260059190911b82018301908381019036831115612f0a575f80fd5b928401925b82841015612f2857833582529284019290840190612f0f565b938501939093525091949350505050565b8082018082111561065857610658612de3565b604081525f612f5e6040830185612b3f565b905060018060a01b03831660208301529392505050565b5f60208284031215612f85575f80fd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600181811c90821680612feb57607f821691505b60208210810361300957634e487b7160e01b5f52602260045260245ffd5b50919050565b5f8235605e19833603018112612e68575f80fd5b5f808335601e19843603018112613038575f80fd5b8301803591506001600160401b03821115613051575f80fd5b602001915060608102360382131561257d575f80fd5b5f808335601e1984360301811261307c575f80fd5b8301803591506001600160401b03821115613095575f80fd5b60200191503681900382131561257d575f80fd5b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b81525f83516130da816017850160208801612af2565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161310b816028840160208801612af2565b01602801949350505050565b602081525f6112dd6020830184612b14565b601f82111561068257805f5260205f20601f840160051c8101602085101561314e5750805b601f840160051c820191505b81811015611f37575f815560010161315a565b81516001600160401b03811115613186576131866129e5565b61319a816131948454612fd7565b84613129565b602080601f8311600181146131cd575f84156131b65750858301515b5f19600386901b1c1916600185901b178555610858565b5f85815260208120601f198616915b828110156131fb578886015182559484019460019091019084016131dc565b508582101561321857878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f60208284031215613238575f80fd5b81516112dd81612901565b5f6020808385031215613254575f80fd5b82516001600160401b03811115613269575f80fd5b8301601f81018513613279575f80fd5b8051613287612ee782612e72565b81815260059190911b820183019083810190878311156132a5575f80fd5b928401925b828410156132cc5783516132bd81612901565b825292840192908401906132aa565b979650505050505050565b5f602082840312156132e7575f80fd5b815180151581146112dd575f80fd5b5f8261331057634e487b7160e01b5f52601260045260245ffd5b500490565b808202811582820484141761065857610658612de3565b5f8161333a5761333a612de3565b505f190190565b5f8251612e68818460208701612af2565b634e487b7160e01b5f52602160045260245ffdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775a26469706673582212204e81f989b9d1018c671159ed7dd591ec6caf7f3be5fc3b4bbbc8925df1c33d5d64736f6c63430008170033000000000000000000000000684ea83d4577e4ab131cb6d7971cace0f4925785000000000000000000000000dbc63ded1f67b8192a86431da3e7b570755c5d2100000000000000000000000060e4d786628fea6478f785a6d7e704777c86a7c6000000000000000000000000bc4ca0eda7647a8ab7c2061c2e118a18a936f13d000000000000000000000000c3aa9bc72bd623168860a1e5c6a4530d3d80456c00000000000000000000000000000000000000447e69651d841bd8d104bed493
Deployed Bytecode
0x6080604052600436106101cb575f3560e01c80637dcbe0bb116100f5578063a8f10e131161008e578063a8f10e131461051e578063cb11169714610551578063cbe4c56314610203578063d547741f14610565578063ddb39a4014610551578063e644004d14610584578063ede2d72c146105b7578063f0befc51146105d6578063f21c15d114610609575f80fd5b80637dcbe0bb146102935780638129fc1c146104255780638456cb591461043957806384b0196e1461044d57806391d1485414610474578063951e78ee14610493578063a217fddf146104cd578063a45fcd07146104e0578063a6904aa5146104ff575f80fd5b80633659cfe6116101675780633659cfe61461034d578063378dce4e1461036c5780633c1e50b11461038b5780633f4ba83a1461039f5780634f1ef286146103b357806352d1902d146103c65780635c975abb146103da5780636aa00371146103f1578063791fe82814610411575f80fd5b806301ffc9a7146101cf5780630a7ff4a61461020357806313bfffac14610225578063248a9ca3146102655780632c950c4e146102935780632f2ff15d146102a757806331c65737146102c857806332f3c629146102fb57806336568abe1461032e575b5f80fd5b3480156101da575f80fd5b506101ee6101e93660046128af565b610628565b60405190151581526020015b60405180910390f35b34801561020e575f80fd5b50610217600281565b6040519081526020016101fa565b348015610230575f80fd5b506102587f00000000000000000000000000000000000000447e69651d841bd8d104bed49381565b6040516101fa91906128d6565b348015610270575f80fd5b5061021761027f3660046128ea565b5f90815260fb602052604090206001015490565b34801561029e575f80fd5b50610217600181565b3480156102b2575f80fd5b506102c66102c1366004612915565b61065e565b005b3480156102d3575f80fd5b506102587f000000000000000000000000c3aa9bc72bd623168860a1e5c6a4530d3d80456c81565b348015610306575f80fd5b506102587f000000000000000000000000684ea83d4577e4ab131cb6d7971cace0f492578581565b348015610339575f80fd5b506102c6610348366004612915565b610687565b348015610358575f80fd5b506102c6610367366004612943565b61070a565b348015610377575f80fd5b506102c661038636600461299e565b6107d1565b348015610396575f80fd5b50610217600581565b3480156103aa575f80fd5b506102c6610860565b6102c66103c1366004612a51565b61087f565b3480156103d1575f80fd5b50610217610934565b3480156103e5575f80fd5b5060975460ff166101ee565b3480156103fc575f80fd5b5061019454610258906001600160a01b031681565b34801561041c575f80fd5b50610217600481565b348015610430575f80fd5b506102c66109e0565b348015610444575f80fd5b506102c6610b7b565b348015610458575f80fd5b50610461610b9a565b6040516101fa9796959493929190612b79565b34801561047f575f80fd5b506101ee61048e366004612915565b610c35565b34801561049e575f80fd5b506101ee6104ad366004612be8565b61019360209081525f928352604080842090915290825290205460ff1681565b3480156104d8575f80fd5b506102175f81565b3480156104eb575f80fd5b506102c66104fa366004612c12565b610c5f565b34801561050a575f80fd5b506102c6610519366004612943565b610ddd565b348015610529575f80fd5b506102587f000000000000000000000000dbc63ded1f67b8192a86431da3e7b570755c5d2181565b34801561055c575f80fd5b50610217600381565b348015610570575f80fd5b506102c661057f366004612915565b610e78565b34801561058f575f80fd5b506102587f000000000000000000000000bc4ca0eda7647a8ab7c2061c2e118a18a936f13d81565b3480156105c2575f80fd5b506102c66105d1366004612c64565b610e9c565b3480156105e1575f80fd5b506102587f00000000000000000000000060e4d786628fea6478f785a6d7e704777c86a7c681565b348015610614575f80fd5b50610217610623366004612c9a565b61126f565b5f6001600160e01b03198216637965db0b60e01b148061065857506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f82815260fb6020526040902060010154610678816112e4565b61068283836112ee565b505050565b6001600160a01b03811633146106fc5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6107068282611373565b5050565b6001600160a01b037f000000000000000000000000b6d4e782729f0bf633e1a9ae9fb9ee51c20529f51630036107525760405162461bcd60e51b81526004016106f390612cc6565b7f000000000000000000000000b6d4e782729f0bf633e1a9ae9fb9ee51c20529f56001600160a01b03166107846113d9565b6001600160a01b0316146107aa5760405162461bcd60e51b81526004016106f390612d12565b6107b3816113f4565b604080515f808252602082019092526107ce9183919061140b565b50565b5f805160206133ae8339815191526107e8816112e4565b5f6107f285611575565b90505f5b83811015610858576001600160a01b0382165f908152610193602052604081208187878581811061082957610829612d5e565b602090810292909201358352508101919091526040015f20805460ff19169115159190911790556001016107f6565b505050505050565b5f805160206133ae833981519152610877816112e4565b6107ce61161c565b6001600160a01b037f000000000000000000000000b6d4e782729f0bf633e1a9ae9fb9ee51c20529f51630036108c75760405162461bcd60e51b81526004016106f390612cc6565b7f000000000000000000000000b6d4e782729f0bf633e1a9ae9fb9ee51c20529f56001600160a01b03166108f96113d9565b6001600160a01b03161461091f5760405162461bcd60e51b81526004016106f390612d12565b610928826113f4565b6107068282600161140b565b5f306001600160a01b037f000000000000000000000000b6d4e782729f0bf633e1a9ae9fb9ee51c20529f516146109ce5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b60648201526084016106f3565b505f8051602061336783398151915290565b5f54610100900460ff16158080156109fe57505f54600160ff909116105b80610a175750303b158015610a1757505f5460ff166001145b610a7a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016106f3565b5f805460ff191660011790558015610a9b575f805461ff0019166101001790555b610ae16040518060400160405280600b81526020016a233ab9b2b226b4b73a32b960a91b815250604051806040016040528060018152602001603160f81b815250611668565b610aeb5f336112ee565b610b025f805160206133ae833981519152336112ee565b610b2c7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a336112ee565b610b34611698565b80156107ce575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b5f805160206133ae833981519152610b92816112e4565b6107ce611698565b5f6060805f805f606061015f545f801b148015610bb8575061016054155b610bfc5760405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b60448201526064016106f3565b610c046116d5565b610c0c611766565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b5f91825260fb602090815260408084206001600160a01b0393909316845291905290205460ff1690565b610c67611776565b610c6f6117d1565b5f805160206133ae833981519152610c86816112e4565b610194546001600160a01b0316610cb05760405163bd28e40960e01b815260040160405180910390fd5b6001600160a01b038216610cd75760405163c31160ab60e01b815260040160405180910390fd5b610194546001600160a01b031660068414610d055760405163153c810b60e21b815260040160405180910390fd5b60015b60058111610dcf575f868683818110610d2357610d23612d5e565b905060200201351115610dbd57816001600160a01b0316630c267ed68286898986818110610d5357610d53612d5e565b905060200201355f806040518663ffffffff1660e01b8152600401610d7c959493929190612d72565b60408051808303815f875af1158015610d97573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dbb9190612db3565b505b80610dc781612df7565b915050610d08565b505050610682600161012d55565b5f805160206133ae833981519152610df4816112e4565b6001600160a01b038216610e1b57604051630146038560e11b815260040160405180910390fd5b61019480546001600160a01b0319166001600160a01b0384169081179091556040805182815260208101929092527faadbacde6d52adfcaa45e064cfc34885b286e20ad9e665e48d10dea5ae54b4cc910160405180910390a15050565b5f82815260fb6020526040902060010154610e92816112e4565b6106828383611373565b610ea4611776565b610eac6117d1565b610194546001600160a01b0316610ed65760405163413ec12d60e01b815260040160405180910390fd5b5f610ee46020830183612943565b6001600160a01b031603610f0b5760405163c39bd29560e01b815260040160405180910390fd5b610f186020820182612e0f565b90505f03610f3957604051633be06f8160e11b815260040160405180910390fd5b610194546001600160a01b03165f610f5c610f576040850185612e0f565b611819565b60408051600680825260e082019092529192505f91906020820160c080368337505060408051600680825260e082019092529293505f9291506020820160c0803683370190505090505f80610fb46020880188612e0f565b905090505f5b818110156110e4575f610fd060208a018a612e0f565b83818110610fe057610fe0612d5e565b9050602002810190610ff29190612e54565b610ffb90612e94565b80519091505f5b82602001515181101561108e575f8360200151828151811061102657611026612d5e565b60200260200101519050600581118061103d575080155b1561105b57604051630de93ed960e41b815260040160405180910390fd5b8289828151811061106e5761106e612d5e565b602002602001018181516110829190612f39565b90525050600101611002565b505f61109d8360200151611a28565b9050818782815181106110b2576110b2612d5e565b602002602001018181516110c69190612f39565b9052506110d38287612f39565b95505060019092019150610fba9050565b508482111561110657604051632070190d60e11b815260040160405180910390fd5b60405163178fdb9160e31b81527f000000000000000000000000684ea83d4577e4ab131cb6d7971cace0f4925785906001600160a01b0382169063bc7edc88906111569088903390600401612f4c565b5f604051808303815f87803b15801561116d575f80fd5b505af115801561117f573d5f803e3d5ffd5b506001925050505b6005811161125c575f8582815181106111a2576111a2612d5e565b6020026020010151111561124a576001600160a01b038816630c267ed6826111cd60208d018d612943565b8885815181106111df576111df612d5e565b60200260200101515f806040518663ffffffff1660e01b8152600401611209959493929190612d72565b60408051808303815f875af1158015611224573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112489190612db3565b505b8061125481612df7565b915050611187565b50505050505050506107ce600161012d55565b5f6112dd7f98fe0d162b663453ff7f454bbd833fa89a020b434fd66b63c3d9919fb71ac7b384846040516020016112c2939291909283526001600160a01b03918216602084015216604082015260600190565b60405160208183030381529060405280519060200120611cbd565b9392505050565b6107ce8133611ce9565b6112f88282610c35565b610706575f82815260fb602090815260408083206001600160a01b03851684529091529020805460ff1916600117905561132f3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b61137d8282610c35565b15610706575f82815260fb602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b5f80516020613367833981519152546001600160a01b031690565b5f805160206133ae833981519152610706816112e4565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561143e5761068283611d42565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611498575060408051601f3d908101601f1916820190925261149591810190612f75565b60015b6114fb5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016106f3565b5f8051602061336783398151915281146115695760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016106f3565b50610682838383611ddd565b5f600182036115a557507f000000000000000000000000dbc63ded1f67b8192a86431da3e7b570755c5d21919050565b600282036115d457507f00000000000000000000000060e4d786628fea6478f785a6d7e704777c86a7c6919050565b6003820361160357507f000000000000000000000000bc4ca0eda7647a8ab7c2061c2e118a18a936f13d919050565b604051630cb782df60e01b815260040160405180910390fd5b611624611e07565b6097805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405161165e91906128d6565b60405180910390a1565b5f54610100900460ff1661168e5760405162461bcd60e51b81526004016106f390612f8c565b6107068282611e50565b6116a06117d1565b6097805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586116513390565b606061016180546116e590612fd7565b80601f016020809104026020016040519081016040528092919081815260200182805461171190612fd7565b801561175c5780601f106117335761010080835404028352916020019161175c565b820191905f5260205f20905b81548152906001019060200180831161173f57829003601f168201915b5050505050905090565b606061016280546116e590612fd7565b600261012d54036117c95760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106f3565b600261012d55565b60975460ff16156118175760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016106f3565b565b5f8180820361182b575f915050610658565b5f805b82811015611a1f573686868381811061184957611849612d5e565b905060200281019061185b919061300f565b90505f6118688280613023565b905090505f5b818110156118fa57366118818480613023565b8381811061189157611891612d5e565b90506060020190505f6118a78260200135611575565b6001600160a01b0381165f908152610193602090815260408083208635845290915290205490915060ff16156118f05760405163195d2cad60e01b815260040160405180910390fd5b505060010161186e565b5061192061190e6060840160408501612943565b61191b6020850185613067565b611ea1565b5f5b81811015611a1457366119358480613023565b8381811061194557611945612d5e565b90506060020190505f61195b8260200135611575565b905061197d6119706060870160408801612943565b6040840135838535611f3e565b6001600160a01b0381165f9081526101936020908152604080832085358085529083529220805460ff191660011790556119bb9190840135906121b3565b6119c59088612f39565b604080516001600160a01b0384168152843560208201529198507f8a598ee0f736ea6ad6f489c030c0e073ec11994f86e132f30227d647f2f3b58f910160405180910390a15050600101611922565b50505060010161182e565b50949350505050565b80515f906002811080611a3b5750600381115b15611a5957604051633be06f8160e11b815260040160405180910390fd5b80600303611b58575f805f805b6003811015611ae657868181518110611a8157611a81612d5e565b6020026020010151600503611a995760019150611ade565b835f03611ac157868181518110611ab257611ab2612d5e565b60200260200101519350611ade565b868181518110611ad357611ad3612d5e565b602002602001015192505b600101611a66565b5080611b0557604051633be06f8160e11b815260040160405180910390fd5b81831115611b11579091905b600383901b82176013811480611b27575080600c145b80611b32575080601c145b80611b3d575080600a145b15611b4f575060059695505050505050565b50505050611ca4565b5f83600181518110611b6c57611b6c612d5e565b6020026020010151845f81518110611b8657611b86612d5e565b602002602001015110611bb35783600181518110611ba657611ba6612d5e565b6020026020010151611bce565b835f81518110611bc557611bc5612d5e565b60200260200101515b90505f84600181518110611be457611be4612d5e565b6020026020010151855f81518110611bfe57611bfe612d5e565b602002602001015110611c2a57845f81518110611c1d57611c1d612d5e565b6020026020010151611c46565b84600181518110611c3d57611c3d612d5e565b60200260200101515b9050600382901b81176013819003611c645750600195945050505050565b80601c03611c785750600295945050505050565b80600c03611c8c5750600395945050505050565b80600a03611ca05750600495945050505050565b5050505b604051633be06f8160e11b815260040160405180910390fd5b5f610658611cc9612220565b8360405161190160f01b8152600281019290925260228201526042902090565b611cf38282610c35565b61070657611d008161222e565b611d0b836020612240565b604051602001611d1c9291906130a9565b60408051601f198184030181529082905262461bcd60e51b82526106f391600401613117565b6001600160a01b0381163b611daf5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016106f3565b5f8051602061336783398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b611de6836123d5565b5f82511180611df25750805b1561068257611e018383612414565b50505050565b60975460ff166118175760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016106f3565b5f54610100900460ff16611e765760405162461bcd60e51b81526004016106f390612f8c565b610161611e83838261316d565b50610162611e91828261316d565b50505f61015f8190556101605550565b336001600160a01b03841603611eb657505050565b5f611ec1338561126f565b90505f611f038285858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061243992505050565b9050846001600160a01b0316816001600160a01b031614611f3757604051631f57cb8960e11b815260040160405180910390fd5b5050505050565b6040516331a9108f60e11b8152600481018290525f906001600160a01b03841690636352211e90602401602060405180830381865afa158015611f83573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fa79190613228565b9050600184036120a95760405163a3ba430160e01b81525f906001600160a01b037f000000000000000000000000c3aa9bc72bd623168860a1e5c6a4530d3d80456c169063a3ba430190611fff9089906004016128d6565b5f60405180830381865afa158015612019573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526120409190810190613243565b90505f5b815181101561208f57826001600160a01b031682828151811061206957612069612d5e565b60200260200101516001600160a01b03160361208757505050611e01565b600101612044565b5060405163f4ce9d5960e01b815260040160405180910390fd5b6002840361218157604051632e7cda1d60e21b81526001600160a01b03868116600483015282811660248301528481166044830152606482018490525f60848301819052917f00000000000000000000000000000000000000447e69651d841bd8d104bed4939091169063b9f368749060a401602060405180830381865afa158015612137573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061215b91906132d7565b90508061217b5760405163f4ce9d5960e01b815260040160405180910390fd5b50611f37565b846001600160a01b0316816001600160a01b031614611f375760405163f4ce9d5960e01b815260040160405180910390fd5b5f60018310806121c35750600383115b156121e15760405163136d190960e01b815260040160405180910390fd5b60018303612217575f6121f8633b9aca00846132f6565b90508060021461220957600161220c565b60025b60ff16915050610658565b50600192915050565b5f61222961245b565b905090565b60606106586001600160a01b03831660145b60605f61224e836002613315565b612259906002612f39565b6001600160401b03811115612270576122706129e5565b6040519080825280601f01601f19166020018201604052801561229a576020820181803683370190505b509050600360fc1b815f815181106122b4576122b4612d5e565b60200101906001600160f81b03191690815f1a905350600f60fb1b816001815181106122e2576122e2612d5e565b60200101906001600160f81b03191690815f1a9053505f612304846002613315565b61230f906001612f39565b90505b6001811115612386576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061234357612343612d5e565b1a60f81b82828151811061235957612359612d5e565b60200101906001600160f81b03191690815f1a90535060049490941c9361237f8161332c565b9050612312565b5083156112dd5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016106f3565b6123de81611d42565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606112dd8383604051806060016040528060278152602001613387602791396124ce565b5f805f6124468585612542565b9150915061245381612584565b509392505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6124856126c8565b61248d612721565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b60605f80856001600160a01b0316856040516124ea9190613341565b5f60405180830381855af49150503d805f8114612522576040519150601f19603f3d011682016040523d82523d5f602084013e612527565b606091505b509150915061253886838387612752565b9695505050505050565b5f808251604103612576576020830151604084015160608501515f1a61256a878285856127d2565b9450945050505061257d565b505f905060025b9250929050565b5f81600481111561259757612597613352565b0361259f5750565b60018160048111156125b3576125b3613352565b036125fb5760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b60448201526064016106f3565b600281600481111561260f5761260f613352565b0361265c5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016106f3565b600381600481111561267057612670613352565b036107ce5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016106f3565b5f806126d26116d5565b8051909150156126e9578051602090910120919050565b61015f5480156126f95792915050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709250505090565b5f8061272b611766565b805190915015612742578051602090910120919050565b6101605480156126f95792915050565b606083156127c05782515f036127b9576001600160a01b0385163b6127b95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106f3565b50816127ca565b6127ca8383612885565b949350505050565b5f806fa2a8918ca85bafe22016d0b997e4df60600160ff1b038311156127fd57505f9050600361287c565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561284e573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116612876575f6001925092505061287c565b91505f90505b94509492505050565b8151156128955781518083602001fd5b8060405162461bcd60e51b81526004016106f39190613117565b5f602082840312156128bf575f80fd5b81356001600160e01b0319811681146112dd575f80fd5b6001600160a01b0391909116815260200190565b5f602082840312156128fa575f80fd5b5035919050565b6001600160a01b03811681146107ce575f80fd5b5f8060408385031215612926575f80fd5b82359150602083013561293881612901565b809150509250929050565b5f60208284031215612953575f80fd5b81356112dd81612901565b5f8083601f84011261296e575f80fd5b5081356001600160401b03811115612984575f80fd5b6020830191508360208260051b850101111561257d575f80fd5b5f805f604084860312156129b0575f80fd5b8335925060208401356001600160401b038111156129cc575f80fd5b6129d88682870161295e565b9497909650939450505050565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715612a1b57612a1b6129e5565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612a4957612a496129e5565b604052919050565b5f8060408385031215612a62575f80fd5b8235612a6d81612901565b91506020838101356001600160401b0380821115612a89575f80fd5b818601915086601f830112612a9c575f80fd5b813581811115612aae57612aae6129e5565b612ac0601f8201601f19168501612a21565b91508082528784828501011115612ad5575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f5b83811015612b0c578181015183820152602001612af4565b50505f910152565b5f8151808452612b2b816020860160208601612af2565b601f01601f19169290920160200192915050565b5f815180845260208085019450602084015f5b83811015612b6e57815187529582019590820190600101612b52565b509495945050505050565b60ff60f81b8816815260e060208201525f612b9760e0830189612b14565b8281036040840152612ba98189612b14565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501529050612bda8185612b3f565b9a9950505050505050505050565b5f8060408385031215612bf9575f80fd5b8235612c0481612901565b946020939093013593505050565b5f805f60408486031215612c24575f80fd5b83356001600160401b03811115612c39575f80fd5b612c458682870161295e565b9094509250506020840135612c5981612901565b809150509250925092565b5f60208284031215612c74575f80fd5b81356001600160401b03811115612c89575f80fd5b8201606081850312156112dd575f80fd5b5f8060408385031215612cab575f80fd5b8235612cb681612901565b9150602083013561293881612901565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b5f52603260045260245ffd5b9485526001600160a01b03939093166020850152604084019190915264ffffffffff166060830152608082015260c060a082018190525f9082015260e00190565b5f60408284031215612dc3575f80fd5b612dcb6129f9565b82518152602083015160208201528091505092915050565b634e487b7160e01b5f52601160045260245ffd5b5f60018201612e0857612e08612de3565b5060010190565b5f808335601e19843603018112612e24575f80fd5b8301803591506001600160401b03821115612e3d575f80fd5b6020019150600581901b360382131561257d575f80fd5b5f8235603e19833603018112612e68575f80fd5b9190910192915050565b5f6001600160401b03821115612e8a57612e8a6129e5565b5060051b60200190565b5f60408236031215612ea4575f80fd5b612eac6129f9565b823581526020808401356001600160401b03811115612ec9575f80fd5b840136601f820112612ed9575f80fd5b8035612eec612ee782612e72565b612a21565b81815260059190911b82018301908381019036831115612f0a575f80fd5b928401925b82841015612f2857833582529284019290840190612f0f565b938501939093525091949350505050565b8082018082111561065857610658612de3565b604081525f612f5e6040830185612b3f565b905060018060a01b03831660208301529392505050565b5f60208284031215612f85575f80fd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600181811c90821680612feb57607f821691505b60208210810361300957634e487b7160e01b5f52602260045260245ffd5b50919050565b5f8235605e19833603018112612e68575f80fd5b5f808335601e19843603018112613038575f80fd5b8301803591506001600160401b03821115613051575f80fd5b602001915060608102360382131561257d575f80fd5b5f808335601e1984360301811261307c575f80fd5b8301803591506001600160401b03821115613095575f80fd5b60200191503681900382131561257d575f80fd5b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b81525f83516130da816017850160208801612af2565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161310b816028840160208801612af2565b01602801949350505050565b602081525f6112dd6020830184612b14565b601f82111561068257805f5260205f20601f840160051c8101602085101561314e5750805b601f840160051c820191505b81811015611f37575f815560010161315a565b81516001600160401b03811115613186576131866129e5565b61319a816131948454612fd7565b84613129565b602080601f8311600181146131cd575f84156131b65750858301515b5f19600386901b1c1916600185901b178555610858565b5f85815260208120601f198616915b828110156131fb578886015182559484019460019091019084016131dc565b508582101561321857878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f60208284031215613238575f80fd5b81516112dd81612901565b5f6020808385031215613254575f80fd5b82516001600160401b03811115613269575f80fd5b8301601f81018513613279575f80fd5b8051613287612ee782612e72565b81815260059190911b820183019083810190878311156132a5575f80fd5b928401925b828410156132cc5783516132bd81612901565b825292840192908401906132aa565b979650505050505050565b5f602082840312156132e7575f80fd5b815180151581146112dd575f80fd5b5f8261331057634e487b7160e01b5f52601260045260245ffd5b500490565b808202811582820484141761065857610658612de3565b5f8161333a5761333a612de3565b505f190190565b5f8251612e68818460208701612af2565b634e487b7160e01b5f52602160045260245ffdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775a26469706673582212204e81f989b9d1018c671159ed7dd591ec6caf7f3be5fc3b4bbbc8925df1c33d5d64736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000684ea83d4577e4ab131cb6d7971cace0f4925785000000000000000000000000dbc63ded1f67b8192a86431da3e7b570755c5d2100000000000000000000000060e4d786628fea6478f785a6d7e704777c86a7c6000000000000000000000000bc4ca0eda7647a8ab7c2061c2e118a18a936f13d000000000000000000000000c3aa9bc72bd623168860a1e5c6a4530d3d80456c00000000000000000000000000000000000000447e69651d841bd8d104bed493
-----Decoded View---------------
Arg [0] : materialsAddress_ (address): 0x684Ea83d4577e4ab131CB6D7971CaCE0F4925785
Arg [1] : oathCollectionAddress_ (address): 0xdBc63dEd1f67b8192a86431dA3e7B570755c5d21
Arg [2] : maycCollectionAddress_ (address): 0x60E4d786628Fea6478F785A6d7e704777c86a7c6
Arg [3] : baycCollectionAddress_ (address): 0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D
Arg [4] : warmRegistry_ (address): 0xC3AA9bc72Bd623168860a1e5c6a4530d3D80456c
Arg [5] : delegateRegistry_ (address): 0x00000000000000447e69651d841bD8D104Bed493
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000684ea83d4577e4ab131cb6d7971cace0f4925785
Arg [1] : 000000000000000000000000dbc63ded1f67b8192a86431da3e7b570755c5d21
Arg [2] : 00000000000000000000000060e4d786628fea6478f785a6d7e704777c86a7c6
Arg [3] : 000000000000000000000000bc4ca0eda7647a8ab7c2061c2e118a18a936f13d
Arg [4] : 000000000000000000000000c3aa9bc72bd623168860a1e5c6a4530d3d80456c
Arg [5] : 00000000000000000000000000000000000000447e69651d841bd8d104bed493
Deployed Bytecode Sourcemap
160968:22027:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;154572:215;;;;;;;;;;-1:-1:-1;154572:215:0;;;;;:::i;:::-;;:::i;:::-;;;470:14:1;;463:22;445:41;;433:2;418:18;154572:215:0;;;;;;;;161858:48;;;;;;;;;;;;161905:1;161858:48;;;;;643:25:1;;;631:2;616:18;161858:48:0;497:177:1;162847:51:0;;;;;;;;;;;;;;;;;;;;;;:::i;156428:131::-;;;;;;;;;;-1:-1:-1;156428:131:0;;;;;:::i;:::-;156502:7;156529:12;;;:6;:12;;;;;:22;;;;156428:131;161750:45;;;;;;;;;;;;161794:1;161750:45;;156869:147;;;;;;;;;;-1:-1:-1;156869:147:0;;;;;:::i;:::-;;:::i;:::-;;162744:43;;;;;;;;;;;;;;;162638:41;;;;;;;;;;;;;;;158013:218;;;;;;;;;;-1:-1:-1;158013:218:0;;;;;:::i;:::-;;:::i;141964:198::-;;;;;;;;;;-1:-1:-1;141964:198:0;;;;;:::i;:::-;;:::i;182669:323::-;;;;;;;;;;-1:-1:-1;182669:323:0;;;;;:::i;:::-;;:::i;162192:47::-;;;;;;;;;;;;162238:1;162192:47;;181593:78;;;;;;;;;;;;;:::i;142493:223::-;;;;;;:::i;:::-;;:::i;141570:133::-;;;;;;;;;;;;;:::i;119742:86::-;;;;;;;;;;-1:-1:-1;119813:7:0;;;;119742:86;;163329:32;;;;;;;;;;-1:-1:-1;163329:32:0;;;;-1:-1:-1;;;;;163329:32:0;;;162082:48;;;;;;;;;;;;162129:1;162082:48;;166882:256;;;;;;;;;;;;;:::i;181472:74::-;;;;;;;;;;;;;:::i;148019:889::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;154879:147::-;;;;;;;;;;-1:-1:-1;154879:147:0;;;;;:::i;:::-;;:::i;163162:88::-;;;;;;;;;;-1:-1:-1;163162:88:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;153973:49;;;;;;;;;;-1:-1:-1;153973:49:0;154018:4;153973:49;;180286:954;;;;;;;;;;-1:-1:-1;180286:954:0;;;;;:::i;:::-;;:::i;181815:375::-;;;;;;;;;;-1:-1:-1;181815:375:0;;;;;:::i;:::-;;:::i;162304:48::-;;;;;;;;;;;;;;;161970:49;;;;;;;;;;;;162018:1;161970:49;;157309:149;;;;;;;;;;-1:-1:-1;157309:149:0;;;;;:::i;:::-;;:::i;162526:48::-;;;;;;;;;;;;;;;177678:2415;;;;;;;;;;-1:-1:-1;177678:2415:0;;;;;:::i;:::-;;:::i;162415:48::-;;;;;;;;;;;;;;;182416:245;;;;;;;;;;-1:-1:-1;182416:245:0;;;;;:::i;:::-;;:::i;154572:215::-;154657:4;-1:-1:-1;;;;;;154681:58:0;;-1:-1:-1;;;154681:58:0;;:98;;-1:-1:-1;;;;;;;;;;131553:51:0;;;154743:36;154674:105;154572:215;-1:-1:-1;;154572:215:0:o;156869:147::-;156502:7;156529:12;;;:6;:12;;;;;:22;;;154464:16;154475:4;154464:10;:16::i;:::-;156983:25:::1;156994:4;157000:7;156983:10;:25::i;:::-;156869:147:::0;;;:::o;158013:218::-;-1:-1:-1;;;;;158109:23:0;;105238:10;158109:23;158101:83;;;;-1:-1:-1;;;158101:83:0;;8665:2:1;158101:83:0;;;8647:21:1;8704:2;8684:18;;;8677:30;8743:34;8723:18;;;8716:62;-1:-1:-1;;;8794:18:1;;;8787:45;8849:19;;158101:83:0;;;;;;;;;158197:26;158209:4;158215:7;158197:11;:26::i;:::-;158013:218;;:::o;141964:198::-;-1:-1:-1;;;;;140440:6:0;140423:23;140431:4;140423:23;140415:80;;;;-1:-1:-1;;;140415:80:0;;;;;;;:::i;:::-;140538:6;-1:-1:-1;;;;;140514:30:0;:20;:18;:20::i;:::-;-1:-1:-1;;;;;140514:30:0;;140506:87;;;;-1:-1:-1;;;140506:87:0;;;;;;;:::i;:::-;142046:36:::1;142064:17;142046;:36::i;:::-;142134:12;::::0;;142144:1:::1;142134:12:::0;;;::::1;::::0;::::1;::::0;;;142093:61:::1;::::0;142115:17;;142134:12;142093:21:::1;:61::i;:::-;141964:198:::0;:::o;182669:323::-;-1:-1:-1;;;;;;;;;;;154464:16:0;154475:4;154464:10;:16::i;:::-;182786:26:::1;182815:35;182837:12;182815:21;:35::i;:::-;182786:64;;182866:9;182861:124;182881:19:::0;;::::1;182861:124;;;-1:-1:-1::0;;;;;182922:30:0;::::1;182968:5;182922:30:::0;;;:10:::1;:30;::::0;;;;182968:5;182953:8;;182962:1;182953:11;;::::1;;;;;:::i;:::-;;::::0;;::::1;::::0;;;::::1;;182922:43:::0;;-1:-1:-1;182922:43:0;::::1;::::0;;;;;;-1:-1:-1;182922:43:0;:51;;-1:-1:-1;;182922:51:0::1;::::0;::::1;;::::0;;;::::1;::::0;;-1:-1:-1;182902:3:0::1;182861:124;;;;182775:217;182669:323:::0;;;;:::o;181593:78::-;-1:-1:-1;;;;;;;;;;;154464:16:0;154475:4;154464:10;:16::i;:::-;181653:10:::1;:8;:10::i;142493:223::-:0;-1:-1:-1;;;;;140440:6:0;140423:23;140431:4;140423:23;140415:80;;;;-1:-1:-1;;;140415:80:0;;;;;;;:::i;:::-;140538:6;-1:-1:-1;;;;;140514:30:0;:20;:18;:20::i;:::-;-1:-1:-1;;;;;140514:30:0;;140506:87;;;;-1:-1:-1;;;140506:87:0;;;;;;;:::i;:::-;142609:36:::1;142627:17;142609;:36::i;:::-;142656:52;142678:17;142697:4;142703;142656:21;:52::i;141570:133::-:0;141648:7;140876:4;-1:-1:-1;;;;;140885:6:0;140868:23;;140860:92;;;;-1:-1:-1;;;140860:92:0;;10039:2:1;140860:92:0;;;10021:21:1;10078:2;10058:18;;;10051:30;10117:34;10097:18;;;10090:62;-1:-1:-1;;;10168:18:1;;;10161:54;10232:19;;140860:92:0;9837:420:1;140860:92:0;-1:-1:-1;;;;;;;;;;;;141570:133:0;:::o;166882:256::-;82041:19;82064:13;;;;;;82063:14;;82111:34;;;;-1:-1:-1;82129:12:0;;82144:1;82129:12;;;;:16;82111:34;82110:108;;;-1:-1:-1;82190:4:0;23276:19;:23;;;82151:66;;-1:-1:-1;82200:12:0;;;;;:17;82151:66;82088:204;;;;-1:-1:-1;;;82088:204:0;;10464:2:1;82088:204:0;;;10446:21:1;10503:2;10483:18;;;10476:30;10542:34;10522:18;;;10515:62;-1:-1:-1;;;10593:18:1;;;10586:44;10647:19;;82088:204:0;10262:410:1;82088:204:0;82303:12;:16;;-1:-1:-1;;82303:16:0;82318:1;82303:16;;;82330:67;;;;82365:13;:20;;-1:-1:-1;;82365:20:0;;;;;82330:67;166934:33:::1;;;;;;;;;;;;;;-1:-1:-1::0;;;166934:33:0::1;;::::0;::::1;;;;;;;;;;;;;-1:-1:-1::0;;;166934:33:0::1;;::::0;:13:::1;:33::i;:::-;166978:42;154018:4;167009:10;166978;:42::i;:::-;167031:34;-1:-1:-1::0;;;;;;;;;;;167054:10:0::1;167031;:34::i;:::-;167076:35;72239:24;167100:10;167076;:35::i;:::-;167122:8;:6;:8::i;:::-;82423:14:::0;82419:102;;;82470:5;82454:21;;-1:-1:-1;;82454:21:0;;;82495:14;;-1:-1:-1;10829:36:1;;82495:14:0;;10817:2:1;10802:18;82495:14:0;;;;;;;82030:498;166882:256::o;181472:74::-;-1:-1:-1;;;;;;;;;;;154464:16:0;154475:4;154464:10;:16::i;:::-;181530:8:::1;:6;:8::i;148019:889::-:0;148140:13;148168:18;148201:21;148237:15;148267:25;148307:12;148334:27;148602:11;;148617:1;148602:16;;;:39;;;;-1:-1:-1;148622:14:0;;:19;148602:39;148594:73;;;;-1:-1:-1;;;148594:73:0;;11078:2:1;148594:73:0;;;11060:21:1;11117:2;11097:18;;;11090:30;-1:-1:-1;;;11136:18:1;;;11129:51;11197:18;;148594:73:0;10876:345:1;148594:73:0;148733:13;:11;:13::i;:::-;148761:16;:14;:16::i;:::-;148873;;;148856:1;148873:16;;;;;;;;;-1:-1:-1;;;148680:220:0;;;-1:-1:-1;148680:220:0;;-1:-1:-1;148792:13:0;;-1:-1:-1;148828:4:0;;-1:-1:-1;148856:1:0;-1:-1:-1;148873:16:0;-1:-1:-1;148680:220:0;-1:-1:-1;148019:889:0:o;154879:147::-;154965:4;154989:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;154989:29:0;;;;;;;;;;;;;;;154879:147::o;180286:954::-;103113:21;:19;:21::i;:::-;119347:19:::1;:17;:19::i;:::-;-1:-1:-1::0;;;;;;;;;;;154464:16:0::2;154475:4;154464:10;:16::i;:::-;180468:17:::3;::::0;-1:-1:-1;;;;;180468:17:0::3;180464:133;;180523:62;;-1:-1:-1::0;;;180523:62:0::3;;;;;;;;;;;180464:133;-1:-1:-1::0;;;;;180613:22:0;::::3;180609:122;;180659:60;;-1:-1:-1::0;;;180659:60:0::3;;;;;;;;;;;180609:122;180790:17;::::0;-1:-1:-1;;;;;180790:17:0::3;180852:1;180825:28:::0;::::3;180821:123;;180877:55;;-1:-1:-1::0;;;180877:55:0::3;;;;;;;;;;;180821:123;161794:1;180956:277;162238:1;181001:10;:33;180956:277;;181100:1;181069:16;;181086:10;181069:28;;;;;;;:::i;:::-;;;;;;;:32;181065:157;;;181122:10;-1:-1:-1::0;;;;;181122:22:0::3;;181145:10;181157:8;181167:16;;181184:10;181167:28;;;;;;;:::i;:::-;;;;;;;181197:1;181200::::0;181122:84:::3;;;;;;;;;;;;;;;;;;;:::i;:::-;;::::0;::::3;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;181065:157;181036:12:::0;::::3;::::0;::::3;:::i;:::-;;;;180956:277;;;;180453:787;119377:1:::2;103157:20:::0;102374:1;103677:7;:22;103494:213;181815:375;-1:-1:-1;;;;;;;;;;;154464:16:0;154475:4;154464:10;:16::i;:::-;-1:-1:-1;;;;;181918:32:0;::::1;181914:143;;181974:71;;-1:-1:-1::0;;;181974:71:0::1;;;;;;;;;;;181914:143;182067:17;:38:::0;;-1:-1:-1;;;;;;182067:38:0::1;-1:-1:-1::0;;;;;182067:38:0;::::1;::::0;;::::1;::::0;;;182123:59:::1;::::0;;12777:34:1;;;12842:2;12827:18;;12820:43;;;;182123:59:0::1;::::0;12712:18:1;182123:59:0::1;;;;;;;181815:375:::0;;:::o;157309:149::-;156502:7;156529:12;;;:6;:12;;;;;:22;;;154464:16;154475:4;154464:10;:16::i;:::-;157424:26:::1;157436:4;157442:7;157424:11;:26::i;177678:2415::-:0;103113:21;:19;:21::i;:::-;119347:19:::1;:17;:19::i;:::-;177780:17:::2;::::0;-1:-1:-1;;;;;177780:17:0::2;177776:126;;177835:55;;-1:-1:-1::0;;;177835:55:0::2;;;;;;;;;;;177776:126;177983:1;177956:15;;::::0;::::2;:6:::0;:15:::2;:::i;:::-;-1:-1:-1::0;;;;;177956:29:0::2;::::0;177952:122:::2;;178009:53;;-1:-1:-1::0;;;178009:53:0::2;;;;;;;;;;;177952:122;178088:19;;::::0;::::2;:6:::0;:19:::2;:::i;:::-;:26;;178118:1;178088:31:::0;178084:119:::2;;178143:48;;-1:-1:-1::0;;;178143:48:0::2;;;;;;;;;;;178084:119;178307:17;::::0;-1:-1:-1;;;;;178307:17:0::2;178260:27;178364:44;178384:23;;::::0;::::2;:6:::0;:23:::2;:::i;:::-;178364:19;:44::i;:::-;178499:16;::::0;;178513:1:::2;178499:16:::0;;;;;::::2;::::0;;;178336:72;;-1:-1:-1;178466:30:0::2;::::0;178499:16;::::2;::::0;::::2;::::0;;::::2;::::0;::::2;-1:-1:-1::0;;178560:16:0::2;::::0;;178574:1:::2;178560:16:::0;;;;;::::2;::::0;;;178466:49;;-1:-1:-1;178526:31:0::2;::::0;178560:16;-1:-1:-1;178560:16:0::2;::::0;::::2;::::0;;::::2;::::0;::::2;;::::0;-1:-1:-1;;178526:50:0;-1:-1:-1;178587:27:0::2;::::0;178707:19:::2;;::::0;::::2;:6:::0;:19:::2;:::i;:::-;:26;;178678:55;;178749:9;178744:754;178768:18;178764:1;:22;178744:754;;;178808:30;178841:19;;::::0;::::2;:6:::0;:19:::2;:::i;:::-;178861:1;178841:22;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;178808:55;;;:::i;:::-;178895:18:::0;;178808:55;;-1:-1:-1;178878:14:0::2;178930:396;178978:11;:21;;;:28;178962:13;:44;178930:396;;;179044:18;179065:11;:21;;;179087:13;179065:36;;;;;;;;:::i;:::-;;;;;;;179044:57;;179137:1;179124:10;:14;:33;;;-1:-1:-1::0;179142:15:0;;179124:33:::2;179120:137;;;179189:48;;-1:-1:-1::0;;;179189:48:0::2;;;;;;;;;;;179120:137;179304:6;179275:13;179289:10;179275:25;;;;;;;;:::i;:::-;;;;;;:35;;;;;;;:::i;:::-;::::0;;-1:-1:-1;;179008:15:0::2;;178930:396;;;;179342:14;179359:36;179373:11;:21;;;179359:13;:36::i;:::-;179342:53;;179436:6;179410:14;179425:6;179410:22;;;;;;;;:::i;:::-;;;;;;:32;;;;;;;:::i;:::-;::::0;;-1:-1:-1;179457:29:0::2;179480:6:::0;179457:29;::::2;:::i;:::-;::::0;-1:-1:-1;;178788:3:0::2;::::0;;::::2;::::0;-1:-1:-1;178744:754:0::2;::::0;-1:-1:-1;178744:754:0::2;;;179568:17;179546:19;:39;179542:128;;;179609:49;;-1:-1:-1::0;;;179609:49:0::2;;;;;;;;;;;179542:128;179771:50;::::0;-1:-1:-1;;;179771:50:0;;179743:16:::2;::::0;-1:-1:-1;;;;;179771:23:0;::::2;::::0;::::2;::::0;:50:::2;::::0;179795:13;;179810:10:::2;::::0;179771:50:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;161794:1:0::2;::::0;-1:-1:-1;;;179860:226:0::2;162238:1;179896;:24;179860:226;;179966:1;179946:14;179961:1;179946:17;;;;;;;;:::i;:::-;;;;;;;:21;179942:133;;;-1:-1:-1::0;;;;;179988:22:0;::::2;;180011:1:::0;180014:15:::2;;::::0;::::2;:6:::0;:15:::2;:::i;:::-;180031:14;180046:1;180031:17;;;;;;;;:::i;:::-;;;;;;;180050:1;180053::::0;179988:71:::2;;;;;;;;;;;;;;;;;;;:::i;:::-;;::::0;::::2;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;179942:133;179922:3:::0;::::2;::::0;::::2;:::i;:::-;;;;179860:226;;;;177765:2328;;;;;;;103157:20:::0;102374:1;103677:7;:22;103494:213;182416:245;182536:7;182563:90;72663:69;182622:13;182637;182590:61;;;;;;;;;16338:25:1;;;-1:-1:-1;;;;;16437:15:1;;;16432:2;16417:18;;16410:43;16489:15;16484:2;16469:18;;16462:43;16326:2;16311:18;;16136:375;182590:61:0;;;;;;;;;;;;;182580:72;;;;;;182563:16;:90::i;:::-;182556:97;182416:245;-1:-1:-1;;;182416:245:0:o;155330:105::-;155397:30;155408:4;105238:10;155397;:30::i;159610:238::-;159694:22;159702:4;159708:7;159694;:22::i;:::-;159689:152;;159733:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;159733:29:0;;;;;;;;;:36;;-1:-1:-1;;159733:36:0;159765:4;159733:36;;;159816:12;105238:10;;105158:98;159816:12;-1:-1:-1;;;;;159789:40:0;159807:7;-1:-1:-1;;;;;159789:40:0;159801:4;159789:40;;;;;;;;;;159610:238;;:::o;160028:239::-;160112:22;160120:4;160126:7;160112;:22::i;:::-;160108:152;;;160183:5;160151:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;160151:29:0;;;;;;;;;;:37;;-1:-1:-1;;160151:37:0;;;160208:40;105238:10;;160151:12;;160208:40;;160183:5;160208:40;160028:239;;:::o;133160:153::-;-1:-1:-1;;;;;;;;;;;133240:65:0;-1:-1:-1;;;;;133240:65:0;;133160:153::o;167286:95::-;-1:-1:-1;;;;;;;;;;;154464:16:0;154475:4;154464:10;:16::i;134562:958::-;132662:66;134982:59;;;134978:535;;;135058:37;135077:17;135058:18;:37::i;134978:535::-;135161:17;-1:-1:-1;;;;;135132:61:0;;:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;135132:63:0;;;;;;;;-1:-1:-1;;135132:63:0;;;;;;;;;;;;:::i;:::-;;;135128:306;;135362:56;;-1:-1:-1;;;135362:56:0;;16907:2:1;135362:56:0;;;16889:21:1;16946:2;16926:18;;;16919:30;16985:34;16965:18;;;16958:62;-1:-1:-1;;;17036:18:1;;;17029:44;17090:19;;135362:56:0;16705:410:1;135128:306:0;-1:-1:-1;;;;;;;;;;;135246:28:0;;135238:82;;;;-1:-1:-1;;;135238:82:0;;17322:2:1;135238:82:0;;;17304:21:1;17361:2;17341:18;;;17334:30;17400:34;17380:18;;;17373:62;-1:-1:-1;;;17451:18:1;;;17444:39;17500:19;;135238:82:0;17120:405:1;135238:82:0;135196:140;135448:53;135466:17;135485:4;135491:9;135448:17;:53::i;172449:512::-;172525:7;161461:1;172549:12;:34;172545:409;;-1:-1:-1;172607:23:0;;172449:512;-1:-1:-1;172449:512:0:o;172545:409::-;161574:1;172652:12;:34;172648:306;;-1:-1:-1;172710:23:0;;172449:512;-1:-1:-1;172449:512:0:o;172648:306::-;161687:1;172755:12;:34;172751:203;;-1:-1:-1;172813:23:0;;172449:512;-1:-1:-1;172449:512:0:o;172751:203::-;172876:66;;-1:-1:-1;;;172876:66:0;;;;;;;;;;;120597:120;119606:16;:14;:16::i;:::-;120656:7:::1;:15:::0;;-1:-1:-1;;120656:15:0::1;::::0;;120687:22:::1;105238:10:::0;120696:12:::1;120687:22;;;;;;:::i;:::-;;;;;;;;120597:120::o:0;146269:149::-;84184:13;;;;;;;84176:69;;;;-1:-1:-1;;;84176:69:0;;;;;;;:::i;:::-;146372:38:::1;146396:4;146402:7;146372:23;:38::i;120338:118::-:0;119347:19;:17;:19::i;:::-;120398:7:::1;:14:::0;;-1:-1:-1;;120398:14:0::1;120408:4;120398:14;::::0;;120428:20:::1;120435:12;105238:10:::0;;105158:98;149140:100;149194:13;149227:5;149220:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;149140:100;:::o;149475:106::-;149532:13;149565:8;149558:15;;;;;:::i;103193:293::-;102418:1;103327:7;;:19;103319:63;;;;-1:-1:-1;;;103319:63:0;;18529:2:1;103319:63:0;;;18511:21:1;18568:2;18548:18;;;18541:30;18607:33;18587:18;;;18580:61;18658:18;;103319:63:0;18327:355:1;103319:63:0;102418:1;103460:7;:18;103193:293::o;119901:108::-;119813:7;;;;119971:9;119963:38;;;;-1:-1:-1;;;119963:38:0;;18889:2:1;119963:38:0;;;18871:21:1;18928:2;18908:18;;;18901:30;-1:-1:-1;;;18947:18:1;;;18940:46;19003:18;;119963:38:0;18687:340:1;119963:38:0;119901:108::o;167770:1932::-;167863:7;167916:16;167954:27;;;167950:68;;168005:1;167998:8;;;;;167950:68;168028:23;168073:9;168068:1592;168092:22;168088:1;:26;168068:1592;;;168136:32;168171:16;;168188:1;168171:19;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;168136:54;-1:-1:-1;168207:25:0;168235:18;168136:54;;168235:18;:::i;:::-;:25;;168207:53;;168280:9;168275:552;168299:17;168295:1;:21;168275:552;;;168342:31;168376:18;:6;;:18;:::i;:::-;168395:1;168376:21;;;;;;;:::i;:::-;;;;;;168342:55;;168486:30;168519:46;168541:10;:23;;;168519:21;:46::i;:::-;-1:-1:-1;;;;;168645:34:0;;;;;;:10;:34;;;;;;;;168680:18;;168645:54;;;;;;;;168486:79;;-1:-1:-1;168645:54:0;;168641:171;;;168731:61;;-1:-1:-1;;;168731:61:0;;;;;;;;;;;168641:171;-1:-1:-1;;168318:3:0;;168275:552;;;-1:-1:-1;168897:48:0;168913:13;;;;;;;;:::i;:::-;168928:16;;;;:6;:16;:::i;:::-;168897:15;:48::i;:::-;169025:9;169020:629;169044:17;169040:1;:21;169020:629;;;169087:31;169121:18;:6;;:18;:::i;:::-;169140:1;169121:21;;;;;;;:::i;:::-;;;;;;169087:55;;169161:30;169194:46;169216:10;:23;;;169194:21;:46::i;:::-;169161:79;-1:-1:-1;169259:110:0;169279:13;;;;;;;;:::i;:::-;169294:21;;;;169325:22;169350:18;;169259:19;:110::i;:::-;-1:-1:-1;;;;;169388:34:0;;;;;;:10;:34;;;;;;;;169423:18;;169388:54;;;;;;;;:61;;-1:-1:-1;;169388:61:0;169445:4;169388:61;;;169487:69;;169512:23;;;;;169487:24;:69::i;:::-;169468:88;;;;:::i;:::-;169580:53;;;-1:-1:-1;;;;;20672:32:1;;20654:51;;169614:18:0;;20736:2:1;20721:18;;20714:34;169468:88:0;;-1:-1:-1;169580:53:0;;20627:18:1;169580:53:0;;;;;;;-1:-1:-1;;169063:3:0;;169020:629;;;-1:-1:-1;;;168116:3:0;;168068:1592;;;-1:-1:-1;169679:15:0;167770:1932;-1:-1:-1;;;;167770:1932:0:o;174161:3352::-;174791:16;;174235:7;;174831:1;174822:10;;;:24;;;174845:1;174836:6;:10;174822:24;174818:112;;;174870:48;;-1:-1:-1;;;174870:48:0;;;;;;;;;;;174818:112;174946:6;174956:1;174946:11;174942:2496;;175059:12;175086;175113:17;175160:9;175155:396;175179:1;175175;:5;175155:396;;;175210:9;175220:1;175210:12;;;;;;;;:::i;:::-;;;;;;;175226:1;175210:17;175206:330;;175303:4;175288:19;;175206:330;;;175360:4;175368:1;175360:9;175356:161;;175405:9;175415:1;175405:12;;;;;;;;:::i;:::-;;;;;;;175398:19;;175356:161;;;175481:9;175491:1;175481:12;;;;;;;;:::i;:::-;;;;;;;175474:19;;175356:161;175182:3;;175155:396;;;;175572:12;175567:109;;175612:48;;-1:-1:-1;;;175612:48:0;;;;;;;;;;;175567:109;175754:4;175747;:11;175743:79;;;175795:4;;175801;175743:79;175932:1;175924:9;;;175923:18;;176044:12;176030:27;;;:112;;;176115:9;176129:12;176115:27;176030:112;:197;;;;176200:9;176214:12;176200:27;176030:197;:280;;;;176283:9;176297:12;176283:27;176030:280;176008:435;;;-1:-1:-1;162238:1:0;;174161:3352;-1:-1:-1;;;;;;174161:3352:0:o;176008:435::-;174959:1495;;;;174942:2496;;;176519:12;176549:9;176559:1;176549:12;;;;;;;;:::i;:::-;;;;;;;176534:9;176544:1;176534:12;;;;;;;;:::i;:::-;;;;;;;:27;:57;;176579:9;176589:1;176579:12;;;;;;;;:::i;:::-;;;;;;;176534:57;;;176564:9;176574:1;176564:12;;;;;;;;:::i;:::-;;;;;;;176534:57;176519:72;;176606:12;176636:9;176646:1;176636:12;;;;;;;;:::i;:::-;;;;;;;176621:9;176631:1;176621:12;;;;;;;;:::i;:::-;;;;;;;:27;:57;;176666:9;176676:1;176666:12;;;;;;;;:::i;:::-;;;;;;;176621:57;;;176651:9;176661:1;176651:12;;;;;;;;:::i;:::-;;;;;;;176621:57;176606:72;-1:-1:-1;176789:1:0;176781:9;;;176780:18;;176833:12;176819:27;;;176815:612;;-1:-1:-1;161794:1:0;;174161:3352;-1:-1:-1;;;;;174161:3352:0:o;176815:612::-;176971:9;176985:12;176971:27;176967:460;;-1:-1:-1;161905:1:0;;174161:3352;-1:-1:-1;;;;;174161:3352:0:o;176967:460::-;177124:9;177138:12;177124:27;177120:307;;-1:-1:-1;162018:1:0;;174161:3352;-1:-1:-1;;;;;174161:3352:0:o;177120:307::-;177280:9;177294:12;177280:27;177276:151;;-1:-1:-1;162129:1:0;;174161:3352;-1:-1:-1;;;;;174161:3352:0:o;177276:151::-;176460:978;;;174942:2496;177457:48;;-1:-1:-1;;;177457:48:0;;;;;;;;;;;147746:178;147823:7;147850:66;147883:20;:18;:20::i;:::-;147905:10;129786:4;129780:11;-1:-1:-1;;;129805:23:0;;129858:4;129849:14;;129842:39;;;;129911:4;129902:14;;129895:34;129966:4;129951:20;;;129583:406;155725:514;155814:22;155822:4;155828:7;155814;:22::i;:::-;155809:423;;156002:39;156033:7;156002:30;:39::i;:::-;156114:49;156153:4;156160:2;156114:30;:49::i;:::-;155907:279;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;155907:279:0;;;;;;;;;;-1:-1:-1;;;155853:367:0;;;;;;;:::i;133409:284::-;-1:-1:-1;;;;;23276:19:0;;;133483:106;;;;-1:-1:-1;;;133483:106:0;;22003:2:1;133483:106:0;;;21985:21:1;22042:2;22022:18;;;22015:30;22081:34;22061:18;;;22054:62;-1:-1:-1;;;22132:18:1;;;22125:43;22185:19;;133483:106:0;21801:409:1;133483:106:0;-1:-1:-1;;;;;;;;;;;133600:85:0;;-1:-1:-1;;;;;;133600:85:0;-1:-1:-1;;;;;133600:85:0;;;;;;;;;;133409:284::o;134102:281::-;134211:29;134222:17;134211:10;:29::i;:::-;134269:1;134255:4;:11;:15;:28;;;;134274:9;134255:28;134251:125;;;134300:64;134340:17;134359:4;134300:39;:64::i;:::-;;134102:281;;;:::o;120086:108::-;119813:7;;;;120145:41;;;;-1:-1:-1;;;120145:41:0;;22417:2:1;120145:41:0;;;22399:21:1;22456:2;22436:18;;;22429:30;-1:-1:-1;;;22475:18:1;;;22468:50;22535:18;;120145:41:0;22215:344:1;146426:274:0;84184:13;;;;;;;84176:69;;;;-1:-1:-1;;;84176:69:0;;;;;;;:::i;:::-;146539:5:::1;:12;146547:4:::0;146539:5;:12:::1;:::i;:::-;-1:-1:-1::0;146562:8:0::1;:18;146573:7:::0;146562:8;:18:::1;:::i;:::-;-1:-1:-1::0;;146662:1:0::1;146648:11;:15:::0;;;146674:14:::1;:18:::0;-1:-1:-1;146426:274:0:o;169866:629::-;170065:10;-1:-1:-1;;;;;170055:20:0;;;170051:59;;169866:629;;;:::o;170051:59::-;170176:14;170193:29;170203:10;170215:6;170193:9;:29::i;:::-;170176:46;;170233:23;170259:32;170273:6;170281:9;;170259:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;170259:13:0;;-1:-1:-1;;;170259:32:0:i;:::-;170233:58;;170385:6;-1:-1:-1;;;;;170366:25:0;:15;-1:-1:-1;;;;;170366:25:0;;170362:126;;170415:61;;-1:-1:-1;;;170415:61:0;;;;;;;;;;;170362:126;169947:548;;169866:629;;;:::o;170761:1310::-;170904:27;;-1:-1:-1;;;170904:27:0;;;;;643:25:1;;;170888:13:0;;-1:-1:-1;;;;;170904:18:0;;;;;616::1;;170904:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;170888:43;;72363:1;170946:10;:33;170942:1122;;171027:35;;-1:-1:-1;;;171027:35:0;;170996:28;;-1:-1:-1;;;;;171027:12:0;:27;;;;:35;;171055:6;;171027:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;171027:35:0;;;;;;;;;;;;:::i;:::-;170996:66;;171082:9;171077:161;171101:11;:18;171097:1;:22;171077:161;;;171167:5;-1:-1:-1;;;;;171149:23:0;:11;171161:1;171149:14;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;171149:23:0;;171145:78;;171197:7;;;;;171145:78;171121:3;;171077:161;;;;171259:62;;-1:-1:-1;;;171259:62:0;;;;;;;;;;;170942:1122;72410:1;171343:10;:37;171339:725;;171505:245;;-1:-1:-1;;;171505:245:0;;-1:-1:-1;;;;;26266:15:1;;;171505:245:0;;;26248:34:1;26318:15;;;26298:18;;;26291:43;26370:15;;;26350:18;;;26343:43;26402:18;;;26395:34;;;171479:23:0;26445:19:1;;;26438:35;;;171479:23:0;171505:16;:39;;;;;;26182:19:1;;171505:245:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;171479:271;;171772:18;171767:129;;171818:62;;-1:-1:-1;;;171818:62:0;;;;;;;;;;;171767:129;171382:525;171339:725;;;171941:6;-1:-1:-1;;;;;171932:15:0;:5;-1:-1:-1;;;;;171932:15:0;;171928:125;;171975:62;;-1:-1:-1;;;171975:62:0;;;;;;;;;;;173186:587;173282:7;161461:1;173306:12;:33;:70;;;;161687:1;173343:12;:33;173306:70;173302:179;;;173400:69;;-1:-1:-1;;;173400:69:0;;;;;;;;;;;173302:179;161461:1;173497:12;:34;173493:254;;173656:18;173677:13;173687:3;173677:7;:13;:::i;:::-;173656:34;;173712:10;173726:1;173712:15;:23;;173734:1;173712:23;;;173730:1;173712:23;173705:30;;;;;;;173493:254;-1:-1:-1;173764:1:0;173186:587;;;;:::o;146791:111::-;146844:7;146871:23;:21;:23::i;:::-;146864:30;;146791:111;:::o;108157:151::-;108215:13;108248:52;-1:-1:-1;;;;;108260:22:0;;105999:2;107553:447;107628:13;107654:19;107686:10;107690:6;107686:1;:10;:::i;:::-;:14;;107699:1;107686:14;:::i;:::-;-1:-1:-1;;;;;107676:25:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;107676:25:0;;107654:47;;-1:-1:-1;;;107712:6:0;107719:1;107712:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;107712:15:0;;;;;;;;;-1:-1:-1;;;107738:6:0;107745:1;107738:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;107738:15:0;;;;;;;;-1:-1:-1;107769:9:0;107781:10;107785:6;107781:1;:10;:::i;:::-;:14;;107794:1;107781:14;:::i;:::-;107769:26;;107764:131;107801:1;107797;:5;107764:131;;;-1:-1:-1;;;107845:5:0;107853:3;107845:11;107836:21;;;;;;;:::i;:::-;;;;107824:6;107831:1;107824:9;;;;;;;;:::i;:::-;;;;:33;-1:-1:-1;;;;;107824:33:0;;;;;;;;-1:-1:-1;107882:1:0;107872:11;;;;;107804:3;;;:::i;:::-;;;107764:131;;;-1:-1:-1;107913:10:0;;107905:55;;;;-1:-1:-1;;;107905:55:0;;27504:2:1;107905:55:0;;;27486:21:1;;;27523:18;;;27516:30;27582:34;27562:18;;;27555:62;27634:18;;107905:55:0;27302:356:1;133806:155:0;133873:37;133892:17;133873:18;:37::i;:::-;133926:27;;-1:-1:-1;;;;;133926:27:0;;;;;;;;133806:155;:::o;28373:200::-;28456:12;28488:77;28509:6;28517:4;28488:77;;;;;;;;;;;;;;;;;:20;:77::i;112275:231::-;112353:7;112374:17;112393:18;112415:27;112426:4;112432:9;112415:10;:27::i;:::-;112373:69;;;;112453:18;112465:5;112453:11;:18::i;:::-;-1:-1:-1;112489:9:0;112275:231;-1:-1:-1;;;112275:231:0:o;146910:194::-;146965:7;145362:95;147025:17;:15;:17::i;:::-;147044:20;:18;:20::i;:::-;147002:93;;;;;;27922:25:1;;;;27963:18;;27956:34;;;;28006:18;;;27999:34;147066:13:0;28049:18:1;;;28042:34;147089:4:0;28092:19:1;;;28085:61;27894:19;;147002:93:0;;;;;;;;;;;;146992:104;;;;;;146985:111;;146910:194;:::o;28767:332::-;28912:12;28938;28952:23;28979:6;-1:-1:-1;;;;;28979:19:0;28999:4;28979:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28937:67;;;;29022:69;29049:6;29057:7;29066:10;29078:12;29022:26;:69::i;:::-;29015:76;28767:332;-1:-1:-1;;;;;;28767:332:0:o;110726:747::-;110807:7;110816:12;110845:9;:16;110865:2;110845:22;110841:625;;111189:4;111174:20;;111168:27;111239:4;111224:20;;111218:27;111297:4;111282:20;;111276:27;110884:9;111268:36;111340:25;111351:4;111268:36;111168:27;111218;111340:10;:25::i;:::-;111333:32;;;;;;;;;110841:625;-1:-1:-1;111414:1:0;;-1:-1:-1;111418:35:0;110841:625;110726:747;;;;;:::o;109119:521::-;109197:20;109188:5;:29;;;;;;;;:::i;:::-;;109184:449;;109119:521;:::o;109184:449::-;109295:29;109286:5;:38;;;;;;;;:::i;:::-;;109282:351;;109341:34;;-1:-1:-1;;;109341:34:0;;28783:2:1;109341:34:0;;;28765:21:1;28822:2;28802:18;;;28795:30;-1:-1:-1;;;28841:18:1;;;28834:54;28905:18;;109341:34:0;28581:348:1;109282:351:0;109406:35;109397:5;:44;;;;;;;;:::i;:::-;;109393:240;;109458:41;;-1:-1:-1;;;109458:41:0;;29136:2:1;109458:41:0;;;29118:21:1;29175:2;29155:18;;;29148:30;29214:33;29194:18;;;29187:61;29265:18;;109458:41:0;28934:355:1;109393:240:0;109530:30;109521:5;:39;;;;;;;;:::i;:::-;;109517:116;;109577:44;;-1:-1:-1;;;109577:44:0;;29496:2:1;109577:44:0;;;29478:21:1;29535:2;29515:18;;;29508:30;29574:34;29554:18;;;29547:62;-1:-1:-1;;;29625:18:1;;;29618:32;29667:19;;109577:44:0;29294:398:1;149803:644:0;149853:7;149873:18;149894:13;:11;:13::i;:::-;149922:18;;149873:34;;-1:-1:-1;149922:22:0;149918:522;;149968:22;;;;;;;;149803:644;-1:-1:-1;149803:644:0:o;149918:522::-;150269:11;;150299:15;;150295:134;;150342:10;149803:644;-1:-1:-1;;149803:644:0:o;150295:134::-;150400:13;150393:20;;;;149803:644;:::o;150675:680::-;150728:7;150748:21;150772:16;:14;:16::i;:::-;150803:21;;150748:40;;-1:-1:-1;150803:25:0;150799:549;;150852:25;;;;;;;;150675:680;-1:-1:-1;150675:680:0:o;150799:549::-;151168:14;;151201:18;;151197:140;;151247:13;150675:680;-1:-1:-1;;150675:680:0:o;29395:644::-;29580:12;29609:7;29605:427;;;29637:10;:17;29658:1;29637:22;29633:290;;-1:-1:-1;;;;;23276:19:0;;;29847:60;;;;-1:-1:-1;;;29847:60:0;;29899:2:1;29847:60:0;;;29881:21:1;29938:2;29918:18;;;29911:30;29977:31;29957:18;;;29950:59;30026:18;;29847:60:0;29697:353:1;29847:60:0;-1:-1:-1;29944:10:0;29937:17;;29605:427;29987:33;29995:10;30007:12;29987:7;:33::i;:::-;29395:644;;;;;;:::o;113659:1477::-;113747:7;;-1:-1:-1;;;;;114668:79:0;;114664:163;;;-1:-1:-1;114780:1:0;;-1:-1:-1;114784:30:0;114764:51;;114664:163;114941:24;;;114924:14;114941:24;;;;;;;;;30282:25:1;;;30355:4;30343:17;;30323:18;;;30316:45;;;;30377:18;;;30370:34;;;30420:18;;;30413:34;;;114941:24:0;;30254:19:1;;114941:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;114941:24:0;;-1:-1:-1;;114941:24:0;;;-1:-1:-1;;;;;;;114980:20:0;;114976:103;;115033:1;115037:29;115017:50;;;;;;;114976:103;115099:6;-1:-1:-1;115107:20:0;;-1:-1:-1;113659:1477:0;;;;;;;;:::o;30581:552::-;30742:17;;:21;30738:388;;30974:10;30968:17;31031:15;31018:10;31014:2;31010:19;31003:44;30738:388;31101:12;31094:20;;-1:-1:-1;;;31094:20:0;;;;;;;;:::i;14:286:1:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:1;;209:43;;199:71;;266:1;263;256:12;679:229;-1:-1:-1;;;;;869:32:1;;;;851:51;;839:2;824:18;;679:229::o;913:180::-;972:6;1025:2;1013:9;1004:7;1000:23;996:32;993:52;;;1041:1;1038;1031:12;993:52;-1:-1:-1;1064:23:1;;913:180;-1:-1:-1;913:180:1:o;1280:131::-;-1:-1:-1;;;;;1355:31:1;;1345:42;;1335:70;;1401:1;1398;1391:12;1416:315;1484:6;1492;1545:2;1533:9;1524:7;1520:23;1516:32;1513:52;;;1561:1;1558;1551:12;1513:52;1597:9;1584:23;1574:33;;1657:2;1646:9;1642:18;1629:32;1670:31;1695:5;1670:31;:::i;:::-;1720:5;1710:15;;;1416:315;;;;;:::o;2174:247::-;2233:6;2286:2;2274:9;2265:7;2261:23;2257:32;2254:52;;;2302:1;2299;2292:12;2254:52;2341:9;2328:23;2360:31;2385:5;2360:31;:::i;2426:367::-;2489:8;2499:6;2553:3;2546:4;2538:6;2534:17;2530:27;2520:55;;2571:1;2568;2561:12;2520:55;-1:-1:-1;2594:20:1;;-1:-1:-1;;;;;2626:30:1;;2623:50;;;2669:1;2666;2659:12;2623:50;2706:4;2698:6;2694:17;2682:29;;2766:3;2759:4;2749:6;2746:1;2742:14;2734:6;2730:27;2726:38;2723:47;2720:67;;;2783:1;2780;2773:12;2798:505;2893:6;2901;2909;2962:2;2950:9;2941:7;2937:23;2933:32;2930:52;;;2978:1;2975;2968:12;2930:52;3014:9;3001:23;2991:33;;3075:2;3064:9;3060:18;3047:32;-1:-1:-1;;;;;3094:6:1;3091:30;3088:50;;;3134:1;3131;3124:12;3088:50;3173:70;3235:7;3226:6;3215:9;3211:22;3173:70;:::i;:::-;2798:505;;3262:8;;-1:-1:-1;3147:96:1;;-1:-1:-1;;;;2798:505:1:o;3308:127::-;3369:10;3364:3;3360:20;3357:1;3350:31;3400:4;3397:1;3390:15;3424:4;3421:1;3414:15;3440:251;3512:2;3506:9;;;3542:15;;-1:-1:-1;;;;;3572:34:1;;3608:22;;;3569:62;3566:88;;;3634:18;;:::i;:::-;3670:2;3663:22;3440:251;:::o;3696:275::-;3767:2;3761:9;3832:2;3813:13;;-1:-1:-1;;3809:27:1;3797:40;;-1:-1:-1;;;;;3852:34:1;;3888:22;;;3849:62;3846:88;;;3914:18;;:::i;:::-;3950:2;3943:22;3696:275;;-1:-1:-1;3696:275:1:o;3976:898::-;4053:6;4061;4114:2;4102:9;4093:7;4089:23;4085:32;4082:52;;;4130:1;4127;4120:12;4082:52;4169:9;4156:23;4188:31;4213:5;4188:31;:::i;:::-;4238:5;-1:-1:-1;4262:2:1;4300:18;;;4287:32;-1:-1:-1;;;;;4368:14:1;;;4365:34;;;4395:1;4392;4385:12;4365:34;4433:6;4422:9;4418:22;4408:32;;4478:7;4471:4;4467:2;4463:13;4459:27;4449:55;;4500:1;4497;4490:12;4449:55;4536:2;4523:16;4558:2;4554;4551:10;4548:36;;;4564:18;;:::i;:::-;4606:53;4649:2;4630:13;;-1:-1:-1;;4626:27:1;4622:36;;4606:53;:::i;:::-;4593:66;;4682:2;4675:5;4668:17;4722:7;4717:2;4712;4708;4704:11;4700:20;4697:33;4694:53;;;4743:1;4740;4733:12;4694:53;4798:2;4793;4789;4785:11;4780:2;4773:5;4769:14;4756:45;4842:1;4837:2;4832;4825:5;4821:14;4817:23;4810:34;;4863:5;4853:15;;;;;3976:898;;;;;:::o;4879:250::-;4964:1;4974:113;4988:6;4985:1;4982:13;4974:113;;;5064:11;;;5058:18;5045:11;;;5038:39;5010:2;5003:10;4974:113;;;-1:-1:-1;;5121:1:1;5103:16;;5096:27;4879:250::o;5134:271::-;5176:3;5214:5;5208:12;5241:6;5236:3;5229:19;5257:76;5326:6;5319:4;5314:3;5310:14;5303:4;5296:5;5292:16;5257:76;:::i;:::-;5387:2;5366:15;-1:-1:-1;;5362:29:1;5353:39;;;;5394:4;5349:50;;5134:271;-1:-1:-1;;5134:271:1:o;5410:439::-;5463:3;5501:5;5495:12;5528:6;5523:3;5516:19;5554:4;5583;5578:3;5574:14;5567:21;;5622:4;5615:5;5611:16;5645:1;5655:169;5669:6;5666:1;5663:13;5655:169;;;5730:13;;5718:26;;5764:12;;;;5799:15;;;;5691:1;5684:9;5655:169;;;-1:-1:-1;5840:3:1;;5410:439;-1:-1:-1;;;;;5410:439:1:o;5854:920::-;6260:3;6255;6251:13;6243:6;6239:26;6228:9;6221:45;6302:3;6297:2;6286:9;6282:18;6275:31;6202:4;6329:46;6370:3;6359:9;6355:19;6347:6;6329:46;:::i;:::-;6423:9;6415:6;6411:22;6406:2;6395:9;6391:18;6384:50;6457:33;6483:6;6475;6457:33;:::i;:::-;6521:2;6506:18;;6499:34;;;-1:-1:-1;;;;;6570:32:1;;6564:3;6549:19;;6542:61;6590:3;6619:19;;6612:35;;;6684:22;;;6678:3;6663:19;;6656:51;6443:47;-1:-1:-1;6724:44:1;6443:47;6753:6;6724:44;:::i;:::-;6716:52;5854:920;-1:-1:-1;;;;;;;;;;5854:920:1:o;6779:315::-;6847:6;6855;6908:2;6896:9;6887:7;6883:23;6879:32;6876:52;;;6924:1;6921;6914:12;6876:52;6963:9;6950:23;6982:31;7007:5;6982:31;:::i;:::-;7032:5;7084:2;7069:18;;;;7056:32;;-1:-1:-1;;;6779:315:1:o;7099:572::-;7194:6;7202;7210;7263:2;7251:9;7242:7;7238:23;7234:32;7231:52;;;7279:1;7276;7269:12;7231:52;7319:9;7306:23;-1:-1:-1;;;;;7344:6:1;7341:30;7338:50;;;7384:1;7381;7374:12;7338:50;7423:70;7485:7;7476:6;7465:9;7461:22;7423:70;:::i;:::-;7512:8;;-1:-1:-1;7397:96:1;-1:-1:-1;;7597:2:1;7582:18;;7569:32;7610:31;7569:32;7610:31;:::i;:::-;7660:5;7650:15;;;7099:572;;;;;:::o;7676:389::-;7765:6;7818:2;7806:9;7797:7;7793:23;7789:32;7786:52;;;7834:1;7831;7824:12;7786:52;7874:9;7861:23;-1:-1:-1;;;;;7899:6:1;7896:30;7893:50;;;7939:1;7936;7929:12;7893:50;7962:22;;8018:2;8000:16;;;7996:25;7993:45;;;8034:1;8031;8024:12;8070:388;8138:6;8146;8199:2;8187:9;8178:7;8174:23;8170:32;8167:52;;;8215:1;8212;8205:12;8167:52;8254:9;8241:23;8273:31;8298:5;8273:31;:::i;:::-;8323:5;-1:-1:-1;8380:2:1;8365:18;;8352:32;8393:33;8352:32;8393:33;:::i;8879:408::-;9081:2;9063:21;;;9120:2;9100:18;;;9093:30;9159:34;9154:2;9139:18;;9132:62;-1:-1:-1;;;9225:2:1;9210:18;;9203:42;9277:3;9262:19;;8879:408::o;9292:::-;9494:2;9476:21;;;9533:2;9513:18;;;9506:30;9572:34;9567:2;9552:18;;9545:62;-1:-1:-1;;;9638:2:1;9623:18;;9616:42;9690:3;9675:19;;9292:408::o;9705:127::-;9766:10;9761:3;9757:20;9754:1;9747:31;9797:4;9794:1;9787:15;9821:4;9818:1;9811:15;11226:703;11564:25;;;-1:-1:-1;;;;;11625:32:1;;;;11620:2;11605:18;;11598:60;11689:2;11674:18;;11667:34;;;;11749:12;11737:25;11732:2;11717:18;;11710:53;11794:3;11779:19;;11772:35;11844:3;11645;11823:19;;11816:32;;;-1:-1:-1;11864:19:1;;;11857:30;11919:3;11904:19;;11226:703::o;11934:354::-;12043:6;12096:2;12084:9;12075:7;12071:23;12067:32;12064:52;;;12112:1;12109;12102:12;12064:52;12138:22;;:::i;:::-;12189:9;12183:16;12176:5;12169:31;12253:2;12242:9;12238:18;12232:25;12227:2;12220:5;12216:14;12209:49;12277:5;12267:15;;;11934:354;;;;:::o;12293:127::-;12354:10;12349:3;12345:20;12342:1;12335:31;12385:4;12382:1;12375:15;12409:4;12406:1;12399:15;12425:135;12464:3;12485:17;;;12482:43;;12505:18;;:::i;:::-;-1:-1:-1;12552:1:1;12541:13;;12425:135::o;12874:576::-;12998:4;13004:6;13064:11;13051:25;13158:2;13154:7;13143:8;13127:14;13123:29;13119:43;13099:18;13095:68;13085:96;;13177:1;13174;13167:12;13085:96;13204:33;;13256:20;;;-1:-1:-1;;;;;;13288:30:1;;13285:50;;;13331:1;13328;13321:12;13285:50;13364:4;13352:17;;-1:-1:-1;13415:1:1;13411:14;;;13395;13391:35;13381:46;;13378:66;;;13440:1;13437;13430:12;14041:328;14138:4;14196:11;14183:25;14290:2;14286:7;14275:8;14259:14;14255:29;14251:43;14231:18;14227:68;14217:96;;14309:1;14306;14299:12;14217:96;14330:33;;;;;14041:328;-1:-1:-1;;14041:328:1:o;14374:183::-;14434:4;-1:-1:-1;;;;;14459:6:1;14456:30;14453:56;;;14489:18;;:::i;:::-;-1:-1:-1;14534:1:1;14530:14;14546:4;14526:25;;14374:183::o;14562:1076::-;14672:9;14731:4;14723:5;14707:14;14703:26;14699:37;14696:57;;;14749:1;14746;14739:12;14696:57;14777:22;;:::i;:::-;14837:5;14824:19;14815:7;14808:36;14863:2;14912;14905:5;14901:14;14888:28;-1:-1:-1;;;;;14931:6:1;14928:30;14925:50;;;14971:1;14968;14961:12;14925:50;14994:18;;15050:14;15043:4;15035:13;;15031:34;15021:62;;15079:1;15076;15069:12;15021:62;15115:2;15102:16;15138:60;15154:43;15194:2;15154:43;:::i;:::-;15138:60;:::i;:::-;15232:15;;;15314:1;15310:10;;;;15302:19;;15298:28;;;15263:12;;;;15349:14;15338:26;;15335:46;;;15377:1;15374;15367:12;15335:46;15401:11;;;;15421:142;15437:6;15432:3;15429:15;15421:142;;;15503:17;;15491:30;;15454:12;;;;15541;;;;15421:142;;;15579:16;;;15572:31;;;;-1:-1:-1;15583:7:1;;14562:1076;-1:-1:-1;;;;14562:1076:1:o;15643:125::-;15708:9;;;15729:10;;;15726:36;;;15742:18;;:::i;15773:358::-;15980:2;15969:9;15962:21;15943:4;16000:56;16052:2;16041:9;16037:18;16029:6;16000:56;:::i;:::-;15992:64;;16121:1;16117;16112:3;16108:11;16104:19;16096:6;16092:32;16087:2;16076:9;16072:18;16065:60;15773:358;;;;;:::o;16516:184::-;16586:6;16639:2;16627:9;16618:7;16614:23;16610:32;16607:52;;;16655:1;16652;16645:12;16607:52;-1:-1:-1;16678:16:1;;16516:184;-1:-1:-1;16516:184:1:o;17530:407::-;17732:2;17714:21;;;17771:2;17751:18;;;17744:30;17810:34;17805:2;17790:18;;17783:62;-1:-1:-1;;;17876:2:1;17861:18;;17854:41;17927:3;17912:19;;17530:407::o;17942:380::-;18021:1;18017:12;;;;18064;;;18085:61;;18139:4;18131:6;18127:17;18117:27;;18085:61;18192:2;18184:6;18181:14;18161:18;18158:38;18155:161;;18238:10;18233:3;18229:20;18226:1;18219:31;18273:4;18270:1;18263:15;18301:4;18298:1;18291:15;18155:161;;17942:380;;;:::o;19032:333::-;19134:4;19192:11;19179:25;19286:2;19282:7;19271:8;19255:14;19251:29;19247:43;19227:18;19223:68;19213:96;;19305:1;19302;19295:12;19370:579;19494:4;19500:6;19560:11;19547:25;19654:2;19650:7;19639:8;19623:14;19619:29;19615:43;19595:18;19591:68;19581:96;;19673:1;19670;19663:12;19581:96;19700:33;;19752:20;;;-1:-1:-1;;;;;;19784:30:1;;19781:50;;;19827:1;19824;19817:12;19781:50;19860:4;19848:17;;-1:-1:-1;19919:4:1;19907:17;;19891:14;19887:38;19877:49;;19874:69;;;19939:1;19936;19929:12;19954:521;20031:4;20037:6;20097:11;20084:25;20191:2;20187:7;20176:8;20160:14;20156:29;20152:43;20132:18;20128:68;20118:96;;20210:1;20207;20200:12;20118:96;20237:33;;20289:20;;;-1:-1:-1;;;;;;20321:30:1;;20318:50;;;20364:1;20361;20354:12;20318:50;20397:4;20385:17;;-1:-1:-1;20428:14:1;20424:27;;;20414:38;;20411:58;;;20465:1;20462;20455:12;20759:812;-1:-1:-1;;;21165:3:1;21158:38;21140:3;21225:6;21219:13;21241:75;21309:6;21304:2;21299:3;21295:12;21288:4;21280:6;21276:17;21241:75;:::i;:::-;-1:-1:-1;;;21375:2:1;21335:16;;;21367:11;;;21360:40;21425:13;;21447:76;21425:13;21509:2;21501:11;;21494:4;21482:17;;21447:76;:::i;:::-;21543:17;21562:2;21539:26;;20759:812;-1:-1:-1;;;;20759:812:1:o;21576:220::-;21725:2;21714:9;21707:21;21688:4;21745:45;21786:2;21775:9;21771:18;21763:6;21745:45;:::i;22690:518::-;22792:2;22787:3;22784:11;22781:421;;;22828:5;22825:1;22818:16;22872:4;22869:1;22859:18;22942:2;22930:10;22926:19;22923:1;22919:27;22913:4;22909:38;22978:4;22966:10;22963:20;22960:47;;;-1:-1:-1;23001:4:1;22960:47;23056:2;23051:3;23047:12;23044:1;23040:20;23034:4;23030:31;23020:41;;23111:81;23129:2;23122:5;23119:13;23111:81;;;23188:1;23174:16;;23155:1;23144:13;23111:81;;23384:1345;23510:3;23504:10;-1:-1:-1;;;;;23529:6:1;23526:30;23523:56;;;23559:18;;:::i;:::-;23588:97;23678:6;23638:38;23670:4;23664:11;23638:38;:::i;:::-;23632:4;23588:97;:::i;:::-;23740:4;;23797:2;23786:14;;23814:1;23809:663;;;;24516:1;24533:6;24530:89;;;-1:-1:-1;24585:19:1;;;24579:26;24530:89;-1:-1:-1;;23341:1:1;23337:11;;;23333:24;23329:29;23319:40;23365:1;23361:11;;;23316:57;24632:81;;23779:944;;23809:663;22637:1;22630:14;;;22674:4;22661:18;;-1:-1:-1;;23845:20:1;;;23963:236;23977:7;23974:1;23971:14;23963:236;;;24066:19;;;24060:26;24045:42;;24158:27;;;;24126:1;24114:14;;;;23993:19;;23963:236;;;23967:3;24227:6;24218:7;24215:19;24212:201;;;24288:19;;;24282:26;-1:-1:-1;;24371:1:1;24367:14;;;24383:3;24363:24;24359:37;24355:42;24340:58;24325:74;;24212:201;-1:-1:-1;;;;;24459:1:1;24443:14;;;24439:22;24426:36;;-1:-1:-1;23384:1345:1:o;24734:251::-;24804:6;24857:2;24845:9;24836:7;24832:23;24828:32;24825:52;;;24873:1;24870;24863:12;24825:52;24905:9;24899:16;24924:31;24949:5;24924:31;:::i;24990:956::-;25085:6;25116:2;25159;25147:9;25138:7;25134:23;25130:32;25127:52;;;25175:1;25172;25165:12;25127:52;25208:9;25202:16;-1:-1:-1;;;;;25233:6:1;25230:30;25227:50;;;25273:1;25270;25263:12;25227:50;25296:22;;25349:4;25341:13;;25337:27;-1:-1:-1;25327:55:1;;25378:1;25375;25368:12;25327:55;25407:2;25401:9;25430:60;25446:43;25486:2;25446:43;:::i;25430:60::-;25524:15;;;25606:1;25602:10;;;;25594:19;;25590:28;;;25555:12;;;;25630:19;;;25627:39;;;25662:1;25659;25652:12;25627:39;25686:11;;;;25706:210;25722:6;25717:3;25714:15;25706:210;;;25795:3;25789:10;25812:31;25837:5;25812:31;:::i;:::-;25856:18;;25739:12;;;;25894;;;;25706:210;;;25935:5;24990:956;-1:-1:-1;;;;;;;24990:956:1:o;26484:277::-;26551:6;26604:2;26592:9;26583:7;26579:23;26575:32;26572:52;;;26620:1;26617;26610:12;26572:52;26652:9;26646:16;26705:5;26698:13;26691:21;26684:5;26681:32;26671:60;;26727:1;26724;26717:12;26766:217;26806:1;26832;26822:132;;26876:10;26871:3;26867:20;26864:1;26857:31;26911:4;26908:1;26901:15;26939:4;26936:1;26929:15;26822:132;-1:-1:-1;26968:9:1;;26766:217::o;26988:168::-;27061:9;;;27092;;27109:15;;;27103:22;;27089:37;27079:71;;27130:18;;:::i;27161:136::-;27200:3;27228:5;27218:39;;27237:18;;:::i;:::-;-1:-1:-1;;;27273:18:1;;27161:136::o;28157:287::-;28286:3;28324:6;28318:13;28340:66;28399:6;28394:3;28387:4;28379:6;28375:17;28340:66;:::i;28449:127::-;28510:10;28505:3;28501:20;28498:1;28491:31;28541:4;28538:1;28531:15;28565:4;28562:1;28555:15
Swarm Source
ipfs://4e81f989b9d1018c671159ed7dd591ec6caf7f3be5fc3b4bbbc8925df1c33d5d
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.