Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 72 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Set Approval For... | 24640770 | 39 hrs ago | IN | 0 ETH | 0.00009595 | ||||
| Transfer From | 24637791 | 2 days ago | IN | 0 ETH | 0.0001613 | ||||
| Set Approval For... | 24634568 | 2 days ago | IN | 0 ETH | 0.00011086 | ||||
| Set Approval For... | 24622095 | 4 days ago | IN | 0 ETH | 0.00001668 | ||||
| Set Base URI | 24621875 | 4 days ago | IN | 0 ETH | 0.00009612 | ||||
| Secondary Reserv... | 24621633 | 4 days ago | IN | 0 ETH | 0.00017044 | ||||
| Secondary Reserv... | 24621633 | 4 days ago | IN | 0 ETH | 0.00017044 | ||||
| Secondary Reserv... | 24621631 | 4 days ago | IN | 0 ETH | 0.00016979 | ||||
| Secondary Reserv... | 24621631 | 4 days ago | IN | 0 ETH | 0.00016979 | ||||
| Secondary Reserv... | 24621631 | 4 days ago | IN | 0 ETH | 0.00016979 | ||||
| Secondary Reserv... | 24621631 | 4 days ago | IN | 0 ETH | 0.00016979 | ||||
| Secondary Reserv... | 24621629 | 4 days ago | IN | 0 ETH | 0.0001698 | ||||
| Secondary Reserv... | 24621629 | 4 days ago | IN | 0 ETH | 0.0001698 | ||||
| Secondary Reserv... | 24621629 | 4 days ago | IN | 0 ETH | 0.00016983 | ||||
| Secondary Reserv... | 24621627 | 4 days ago | IN | 0 ETH | 0.00017033 | ||||
| Secondary Reserv... | 24621625 | 4 days ago | IN | 0 ETH | 0.00016989 | ||||
| Secondary Reserv... | 24621625 | 4 days ago | IN | 0 ETH | 0.00017604 | ||||
| Secondary Reserv... | 24621625 | 4 days ago | IN | 0 ETH | 0.00013976 | ||||
| Secondary Reserv... | 24621623 | 4 days ago | IN | 0 ETH | 0.00017027 | ||||
| Secondary Reserv... | 24621623 | 4 days ago | IN | 0 ETH | 0.00017027 | ||||
| Secondary Reserv... | 24621623 | 4 days ago | IN | 0 ETH | 0.00013391 | ||||
| Secondary Reserv... | 24621621 | 4 days ago | IN | 0 ETH | 0.00017059 | ||||
| Secondary Reserv... | 24621621 | 4 days ago | IN | 0 ETH | 0.00017056 | ||||
| Secondary Reserv... | 24621621 | 4 days ago | IN | 0 ETH | 0.00017056 | ||||
| Secondary Reserv... | 24621621 | 4 days ago | IN | 0 ETH | 0.00017059 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Self_Portraits_Vol_One
Compiler Version
v0.8.30+commit.73712a01
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2026-03-04
*/
// File: @openzeppelin/contracts/cryptography/MerkleProof.sol
pragma solidity ^0.8.25;
/**
* @dev These functions deal with verification of Merkle trees (hash trees),
*/
library MerkleProof {
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*/
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
if (computedHash <= proofElement) {
// Hash(current computed hash + current element of the proof)
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
} else {
// Hash(current element of the proof + current computed hash)
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
}
}
// Check if the computed hash (root) is equal to the provided root
return computedHash == root;
}
}
// File: @openzeppelin/contracts/utils/Panic.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)
pragma solidity ^0.8.20;
/**
* @dev Helper library for emitting standardized panic codes.
*
* ```solidity
* contract Example {
* using Panic for uint256;
*
* // Use any of the declared internal constants
* function foo() { Panic.GENERIC.panic(); }
*
* // Alternatively
* function foo() { Panic.panic(Panic.GENERIC); }
* }
* ```
*
* Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
*
* _Available since v5.1._
*/
// slither-disable-next-line unused-state
library Panic {
/// @dev generic / unspecified error
uint256 internal constant GENERIC = 0x00;
/// @dev used by the assert() builtin
uint256 internal constant ASSERT = 0x01;
/// @dev arithmetic underflow or overflow
uint256 internal constant UNDER_OVERFLOW = 0x11;
/// @dev division or modulo by zero
uint256 internal constant DIVISION_BY_ZERO = 0x12;
/// @dev enum conversion error
uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
/// @dev invalid encoding in storage
uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
/// @dev empty array pop
uint256 internal constant EMPTY_ARRAY_POP = 0x31;
/// @dev array out of bounds access
uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
/// @dev resource error (too large allocation or too large array)
uint256 internal constant RESOURCE_ERROR = 0x41;
/// @dev calling invalid internal function
uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;
/// @dev Reverts with a panic code. Recommended to use with
/// the internal constants with predefined codes.
function panic(uint256 code) internal pure {
assembly ("memory-safe") {
mstore(0x00, 0x4e487b71)
mstore(0x20, code)
revert(0x1c, 0x24)
}
}
}
// File: @openzeppelin/contracts/utils/math/SafeCast.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toUint8(uint256 value) internal pure returns (uint8) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}
// File: @openzeppelin/contracts/utils/math/Math.sol
// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Return the 512-bit addition of two uint256.
*
* The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
*/
function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
assembly ("memory-safe") {
low := add(a, b)
high := lt(low, a)
}
}
/**
* @dev Return the 512-bit multiplication of two uint256.
*
* The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
*/
function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
// 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
// the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = high * 2²⁵⁶ + low.
assembly ("memory-safe") {
let mm := mulmod(a, b, not(0))
low := mul(a, b)
high := sub(sub(mm, low), lt(mm, low))
}
}
/**
* @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a + b;
success = c >= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a - b;
success = c <= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a * b;
assembly ("memory-safe") {
// Only true when the multiplication doesn't overflow
// (c / a == b) || (a == 0)
success := or(eq(div(c, a), b), iszero(a))
}
// equivalent to: success ? c : 0
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `DIV` opcode returns zero when the denominator is 0.
result := div(a, b)
}
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `MOD` opcode returns zero when the denominator is 0.
result := mod(a, b)
}
}
}
/**
* @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryAdd(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
*/
function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {
(, uint256 result) = trySub(a, b);
return result;
}
/**
* @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryMul(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * SafeCast.toUint(condition));
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
Panic.panic(Panic.DIVISION_BY_ZERO);
}
// The following calculation ensures accurate ceiling division without overflow.
// Since a is non-zero, (a - 1) / b will not overflow.
// The largest possible result occurs when (a - 1) / b is type(uint256).max,
// but the largest value we can obtain is type(uint256).max - 1, which happens
// when a = type(uint256).max and b = 1.
unchecked {
return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
}
}
/**
* @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
*
* 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 {
(uint256 high, uint256 low) = mul512(x, y);
// Handle non-overflow cases, 256 by 256 division.
if (high == 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 low / denominator;
}
// Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
if (denominator <= high) {
Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [high low].
uint256 remainder;
assembly ("memory-safe") {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
high := sub(high, gt(remainder, low))
low := sub(low, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly ("memory-safe") {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [high low] by twos.
low := div(low, twos)
// Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from high into low.
low |= high * twos;
// Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
// that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv ≡ 1 mod 2⁴.
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⁸
inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
inverse *= 2 - denominator * inverse; // inverse mod 2³²
inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶
// 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²⁵⁶. Since the preconditions guarantee that the outcome is
// less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high
// is no longer required.
result = low * inverse;
return result;
}
}
/**
* @dev 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) {
return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
}
/**
* @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
*/
function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
if (high >= 1 << n) {
Panic.panic(Panic.UNDER_OVERFLOW);
}
return (high << (256 - n)) | (low >> n);
}
}
/**
* @dev Calculates x * y >> n with full precision, following the selected rounding direction.
*/
function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {
return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);
}
/**
* @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
*
* If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
* If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
*
* If the input value is not inversible, 0 is returned.
*
* NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
* inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
*/
function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
unchecked {
if (n == 0) return 0;
// The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
// Used to compute integers x and y such that: ax + ny = gcd(a, n).
// When the gcd is 1, then the inverse of a modulo n exists and it's x.
// ax + ny = 1
// ax = 1 + (-y)n
// ax ≡ 1 (mod n) # x is the inverse of a modulo n
// If the remainder is 0 the gcd is n right away.
uint256 remainder = a % n;
uint256 gcd = n;
// Therefore the initial coefficients are:
// ax + ny = gcd(a, n) = n
// 0a + 1n = n
int256 x = 0;
int256 y = 1;
while (remainder != 0) {
uint256 quotient = gcd / remainder;
(gcd, remainder) = (
// The old remainder is the next gcd to try.
remainder,
// Compute the next remainder.
// Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
// where gcd is at most n (capped to type(uint256).max)
gcd - remainder * quotient
);
(x, y) = (
// Increment the coefficient of a.
y,
// Decrement the coefficient of n.
// Can overflow, but the result is casted to uint256 so that the
// next value of y is "wrapped around" to a value between 0 and n - 1.
x - y * int256(quotient)
);
}
if (gcd != 1) return 0; // No inverse exists.
return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
}
}
/**
* @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
*
* From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
* prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
* `a**(p-2)` is the modular multiplicative inverse of a in Fp.
*
* NOTE: this function does NOT check that `p` is a prime greater than `2`.
*/
function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
unchecked {
return Math.modExp(a, p - 2, p);
}
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
*
* Requirements:
* - modulus can't be zero
* - underlying staticcall to precompile must succeed
*
* IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
* sure the chain you're using it on supports the precompiled contract for modular exponentiation
* at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
* the underlying function will succeed given the lack of a revert, but the result may be incorrectly
* interpreted as 0.
*/
function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
(bool success, uint256 result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
* It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
* to operate modulo 0 or if the underlying precompile reverted.
*
* IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
* you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
* https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
* of a revert, but the result may be incorrectly interpreted as 0.
*/
function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
if (m == 0) return (false, 0);
assembly ("memory-safe") {
let ptr := mload(0x40)
// | Offset | Content | Content (Hex) |
// |-----------|------------|--------------------------------------------------------------------|
// | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x60:0x7f | value of b | 0x<.............................................................b> |
// | 0x80:0x9f | value of e | 0x<.............................................................e> |
// | 0xa0:0xbf | value of m | 0x<.............................................................m> |
mstore(ptr, 0x20)
mstore(add(ptr, 0x20), 0x20)
mstore(add(ptr, 0x40), 0x20)
mstore(add(ptr, 0x60), b)
mstore(add(ptr, 0x80), e)
mstore(add(ptr, 0xa0), m)
// Given the result < m, it's guaranteed to fit in 32 bytes,
// so we can use the memory scratch space located at offset 0.
success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
result := mload(0x00)
}
}
/**
* @dev Variant of {modExp} that supports inputs of arbitrary length.
*/
function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
(bool success, bytes memory result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Variant of {tryModExp} that supports inputs of arbitrary length.
*/
function tryModExp(
bytes memory b,
bytes memory e,
bytes memory m
) internal view returns (bool success, bytes memory result) {
if (_zeroBytes(m)) return (false, new bytes(0));
uint256 mLen = m.length;
// Encode call args in result and move the free memory pointer
result = abi.encodePacked(b.length, e.length, mLen, b, e, m);
assembly ("memory-safe") {
let dataPtr := add(result, 0x20)
// Write result on top of args to avoid allocating extra memory.
success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
// Overwrite the length.
// result.length > returndatasize() is guaranteed because returndatasize() == m.length
mstore(result, mLen)
// Set the memory pointer after the returned data.
mstore(0x40, add(dataPtr, mLen))
}
}
/**
* @dev Returns whether the provided byte array is zero.
*/
function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
for (uint256 i = 0; i < byteArray.length; ++i) {
if (byteArray[i] != 0) {
return false;
}
}
return true;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* This method is based on Newton's method for computing square roots; the algorithm is restricted to only
* using integer operations.
*/
function sqrt(uint256 a) internal pure returns (uint256) {
unchecked {
// Take care of easy edge cases when a == 0 or a == 1
if (a <= 1) {
return a;
}
// In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
// sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
// the current value as `ε_n = | x_n - sqrt(a) |`.
//
// For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
// of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
// bigger than any uint256.
//
// By noticing that
// `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
// we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
// to the msb function.
uint256 aa = a;
uint256 xn = 1;
if (aa >= (1 << 128)) {
aa >>= 128;
xn <<= 64;
}
if (aa >= (1 << 64)) {
aa >>= 64;
xn <<= 32;
}
if (aa >= (1 << 32)) {
aa >>= 32;
xn <<= 16;
}
if (aa >= (1 << 16)) {
aa >>= 16;
xn <<= 8;
}
if (aa >= (1 << 8)) {
aa >>= 8;
xn <<= 4;
}
if (aa >= (1 << 4)) {
aa >>= 4;
xn <<= 2;
}
if (aa >= (1 << 2)) {
xn <<= 1;
}
// We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
//
// We can refine our estimation by noticing that the middle of that interval minimizes the error.
// If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
// This is going to be our x_0 (and ε_0)
xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)
// From here, Newton's method give us:
// x_{n+1} = (x_n + a / x_n) / 2
//
// One should note that:
// x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
// = ((x_n² + a) / (2 * x_n))² - a
// = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
// = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
// = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
// = (x_n² - a)² / (2 * x_n)²
// = ((x_n² - a) / (2 * x_n))²
// ≥ 0
// Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
//
// This gives us the proof of quadratic convergence of the sequence:
// ε_{n+1} = | x_{n+1} - sqrt(a) |
// = | (x_n + a / x_n) / 2 - sqrt(a) |
// = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
// = | (x_n - sqrt(a))² / (2 * x_n) |
// = | ε_n² / (2 * x_n) |
// = ε_n² / | (2 * x_n) |
//
// For the first iteration, we have a special case where x_0 is known:
// ε_1 = ε_0² / | (2 * x_0) |
// ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
// ≤ 2**(2*e-4) / (3 * 2**(e-1))
// ≤ 2**(e-3) / 3
// ≤ 2**(e-3-log2(3))
// ≤ 2**(e-4.5)
//
// For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
// ε_{n+1} = ε_n² / | (2 * x_n) |
// ≤ (2**(e-k))² / (2 * 2**(e-1))
// ≤ 2**(2*e-2*k) / 2**e
// ≤ 2**(e-2*k)
xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above
xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5
xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9
xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18
xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36
xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72
// Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
// ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
// sqrt(a) or sqrt(a) + 1.
return xn - SafeCast.toUint(xn > a / xn);
}
}
/**
* @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// If upper 8 bits of 16-bit half set, add 8 to result
r |= SafeCast.toUint((x >> r) > 0xff) << 3;
// If upper 4 bits of 8-bit half set, add 4 to result
r |= SafeCast.toUint((x >> r) > 0xf) << 2;
// Shifts value right by the current result and use it as an index into this lookup table:
//
// | x (4 bits) | index | table[index] = MSB position |
// |------------|---------|-----------------------------|
// | 0000 | 0 | table[0] = 0 |
// | 0001 | 1 | table[1] = 0 |
// | 0010 | 2 | table[2] = 1 |
// | 0011 | 3 | table[3] = 1 |
// | 0100 | 4 | table[4] = 2 |
// | 0101 | 5 | table[5] = 2 |
// | 0110 | 6 | table[6] = 2 |
// | 0111 | 7 | table[7] = 2 |
// | 1000 | 8 | table[8] = 3 |
// | 1001 | 9 | table[9] = 3 |
// | 1010 | 10 | table[10] = 3 |
// | 1011 | 11 | table[11] = 3 |
// | 1100 | 12 | table[12] = 3 |
// | 1101 | 13 | table[13] = 3 |
// | 1110 | 14 | table[14] = 3 |
// | 1111 | 15 | table[15] = 3 |
//
// The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
assembly ("memory-safe") {
r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))
}
}
/**
* @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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
}
/**
* @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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}
// File: @openzeppelin/contracts/utils/math/SignedMath.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
}
}
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return ternary(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 {
// Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson.
// Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,
// taking advantage of the most significant (or "sign" bit) in two's complement representation.
// This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,
// the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).
int256 mask = n >> 255;
// A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.
return uint256((n + mask) ^ mask);
}
}
}
// File: @openzeppelin/contracts/utils/Strings.sol
// OpenZeppelin Contracts (last updated v5.3.0) (utils/Strings.sol)
pragma solidity ^0.8.20;
/**
* @dev String operations.
*/
library Strings {
using SafeCast for *;
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
uint256 private constant SPECIAL_CHARS_LOOKUP =
(1 << 0x08) | // backspace
(1 << 0x09) | // tab
(1 << 0x0a) | // newline
(1 << 0x0c) | // form feed
(1 << 0x0d) | // carriage return
(1 << 0x22) | // double quote
(1 << 0x5c); // backslash
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev The string being parsed contains characters that are not in scope of the given base.
*/
error StringsInvalidChar();
/**
* @dev The string being parsed is not a properly formatted address.
*/
error StringsInvalidAddressFormat();
/**
* @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;
assembly ("memory-safe") {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
assembly ("memory-safe") {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
* representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal
* representation, according to EIP-55.
*/
function toChecksumHexString(address addr) internal pure returns (string memory) {
bytes memory buffer = bytes(toHexString(addr));
// hash the hex part of buffer (skip length + 2 bytes, length 40)
uint256 hashValue;
assembly ("memory-safe") {
hashValue := shr(96, keccak256(add(buffer, 0x22), 40))
}
for (uint256 i = 41; i > 1; --i) {
// possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)
if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {
// case shift by xoring with 0x20
buffer[i] ^= 0x20;
}
hashValue >>= 4;
}
return string(buffer);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
/**
* @dev Parse a decimal string and returns the value as a `uint256`.
*
* Requirements:
* - The string must be formatted as `[0-9]*`
* - The result must fit into an `uint256` type
*/
function parseUint(string memory input) internal pure returns (uint256) {
return parseUint(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `[0-9]*`
* - The result must fit into an `uint256` type
*/
function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
(bool success, uint256 value) = tryParseUint(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {
return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid
* character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseUint(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, uint256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseUintUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseUintUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, uint256 value) {
bytes memory buffer = bytes(input);
uint256 result = 0;
for (uint256 i = begin; i < end; ++i) {
uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
if (chr > 9) return (false, 0);
result *= 10;
result += chr;
}
return (true, result);
}
/**
* @dev Parse a decimal string and returns the value as a `int256`.
*
* Requirements:
* - The string must be formatted as `[-+]?[0-9]*`
* - The result must fit in an `int256` type.
*/
function parseInt(string memory input) internal pure returns (int256) {
return parseInt(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `[-+]?[0-9]*`
* - The result must fit in an `int256` type.
*/
function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {
(bool success, int256 value) = tryParseInt(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if
* the result does not fit in a `int256`.
*
* NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
*/
function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {
return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);
}
uint256 private constant ABS_MIN_INT256 = 2 ** 255;
/**
* @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid
* character or if the result does not fit in a `int256`.
*
* NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
*/
function tryParseInt(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, int256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseIntUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseIntUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, int256 value) {
bytes memory buffer = bytes(input);
// Check presence of a negative sign.
bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
bool positiveSign = sign == bytes1("+");
bool negativeSign = sign == bytes1("-");
uint256 offset = (positiveSign || negativeSign).toUint();
(bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);
if (absSuccess && absValue < ABS_MIN_INT256) {
return (true, negativeSign ? -int256(absValue) : int256(absValue));
} else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {
return (true, type(int256).min);
} else return (false, 0);
}
/**
* @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`.
*
* Requirements:
* - The string must be formatted as `(0x)?[0-9a-fA-F]*`
* - The result must fit in an `uint256` type.
*/
function parseHexUint(string memory input) internal pure returns (uint256) {
return parseHexUint(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `(0x)?[0-9a-fA-F]*`
* - The result must fit in an `uint256` type.
*/
function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
(bool success, uint256 value) = tryParseHexUint(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {
return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an
* invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseHexUint(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, uint256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseHexUintUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseHexUintUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, uint256 value) {
bytes memory buffer = bytes(input);
// skip 0x prefix if present
bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
uint256 offset = hasPrefix.toUint() * 2;
uint256 result = 0;
for (uint256 i = begin + offset; i < end; ++i) {
uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
if (chr > 15) return (false, 0);
result *= 16;
unchecked {
// Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).
// This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.
result += chr;
}
}
return (true, result);
}
/**
* @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`.
*
* Requirements:
* - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`
*/
function parseAddress(string memory input) internal pure returns (address) {
return parseAddress(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`
*/
function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {
(bool success, address value) = tryParseAddress(input, begin, end);
if (!success) revert StringsInvalidAddressFormat();
return value;
}
/**
* @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly
* formatted address. See {parseAddress-string} requirements.
*/
function tryParseAddress(string memory input) internal pure returns (bool success, address value) {
return tryParseAddress(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly
* formatted address. See {parseAddress-string-uint256-uint256} requirements.
*/
function tryParseAddress(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, address value) {
if (end > bytes(input).length || begin > end) return (false, address(0));
bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
uint256 expectedLength = 40 + hasPrefix.toUint() * 2;
// check that input is the correct length
if (end - begin == expectedLength) {
// length guarantees that this does not overflow, and value is at most type(uint160).max
(bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);
return (s, address(uint160(v)));
} else {
return (false, address(0));
}
}
function _tryParseChr(bytes1 chr) private pure returns (uint8) {
uint8 value = uint8(chr);
// Try to parse `chr`:
// - Case 1: [0-9]
// - Case 2: [a-f]
// - Case 3: [A-F]
// - otherwise not supported
unchecked {
if (value > 47 && value < 58) value -= 48;
else if (value > 96 && value < 103) value -= 87;
else if (value > 64 && value < 71) value -= 55;
else return type(uint8).max;
}
return value;
}
/**
* @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.
*
* WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.
*
* NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of
* RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode
* characters that are not in this range, but other tooling may provide different results.
*/
function escapeJSON(string memory input) internal pure returns (string memory) {
bytes memory buffer = bytes(input);
bytes memory output = new bytes(2 * buffer.length); // worst case scenario
uint256 outputLength = 0;
for (uint256 i; i < buffer.length; ++i) {
bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));
if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {
output[outputLength++] = "\\";
if (char == 0x08) output[outputLength++] = "b";
else if (char == 0x09) output[outputLength++] = "t";
else if (char == 0x0a) output[outputLength++] = "n";
else if (char == 0x0c) output[outputLength++] = "f";
else if (char == 0x0d) output[outputLength++] = "r";
else if (char == 0x5c) output[outputLength++] = "\\";
else if (char == 0x22) {
// solhint-disable-next-line quotes
output[outputLength++] = '"';
}
} else {
output[outputLength++] = char;
}
}
// write the actual length and deallocate unused memory
assembly ("memory-safe") {
mstore(output, outputLength)
mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))
}
return string(output);
}
/**
* @dev Reads a bytes32 from a bytes array without bounds checking.
*
* NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the
* assembly block as such would prevent some optimizations.
*/
function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {
// This is not memory safe in the general case, but all calls to this private function are within bounds.
assembly ("memory-safe") {
value := mload(add(buffer, add(0x20, offset)))
}
}
}
// File: @openzeppelin/contracts/utils/Context.sol
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
// File: https://github.com/limitbreakinc/creator-token-contracts/blob/main/contracts/access/OwnablePermissions.sol
pragma solidity ^0.8.4;
abstract contract OwnablePermissions is Context {
function _requireCallerIsContractOwner() internal view virtual;
}
// File: @openzeppelin/contracts/access/Ownable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// File: https://github.com/limitbreakinc/creator-token-contracts/blob/main/contracts/access/OwnableBasic.sol
pragma solidity ^0.8.4;
abstract contract OwnableBasic is OwnablePermissions, Ownable {
function _requireCallerIsContractOwner() internal view virtual override {
_checkOwner();
}
}
// File: @openzeppelin/contracts/utils/introspection/IERC165.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* 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[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File: https://github.com/limitbreakinc/creator-token-contracts/blob/main/contracts/interfaces/IEOARegistry.sol
pragma solidity ^0.8.4;
interface IEOARegistry is IERC165 {
function isVerifiedEOA(address account) external view returns (bool);
}
// File: https://github.com/limitbreakinc/creator-token-contracts/blob/main/contracts/utils/TransferPolicy.sol
pragma solidity ^0.8.4;
enum AllowlistTypes {
Operators,
PermittedContractReceivers
}
enum ReceiverConstraints {
None,
NoCode,
EOA
}
enum CallerConstraints {
None,
OperatorWhitelistEnableOTC,
OperatorWhitelistDisableOTC
}
enum StakerConstraints {
None,
CallerIsTxOrigin,
EOA
}
enum TransferSecurityLevels {
Zero,
One,
Two,
Three,
Four,
Five,
Six
}
struct TransferSecurityPolicy {
CallerConstraints callerConstraints;
ReceiverConstraints receiverConstraints;
}
struct CollectionSecurityPolicy {
TransferSecurityLevels transferSecurityLevel;
uint120 operatorWhitelistId;
uint120 permittedContractReceiversId;
}
// File: https://github.com/limitbreakinc/creator-token-contracts/blob/main/contracts/interfaces/ITransferSecurityRegistry.sol
pragma solidity ^0.8.4;
interface ITransferSecurityRegistry {
event AddedToAllowlist(AllowlistTypes indexed kind, uint256 indexed id, address indexed account);
event CreatedAllowlist(AllowlistTypes indexed kind, uint256 indexed id, string indexed name);
event ReassignedAllowlistOwnership(AllowlistTypes indexed kind, uint256 indexed id, address indexed newOwner);
event RemovedFromAllowlist(AllowlistTypes indexed kind, uint256 indexed id, address indexed account);
event SetAllowlist(AllowlistTypes indexed kind, address indexed collection, uint120 indexed id);
event SetTransferSecurityLevel(address indexed collection, TransferSecurityLevels level);
function createOperatorWhitelist(string calldata name) external returns (uint120);
function createPermittedContractReceiverAllowlist(string calldata name) external returns (uint120);
function reassignOwnershipOfOperatorWhitelist(uint120 id, address newOwner) external;
function reassignOwnershipOfPermittedContractReceiverAllowlist(uint120 id, address newOwner) external;
function renounceOwnershipOfOperatorWhitelist(uint120 id) external;
function renounceOwnershipOfPermittedContractReceiverAllowlist(uint120 id) external;
function setTransferSecurityLevelOfCollection(address collection, TransferSecurityLevels level) external;
function setOperatorWhitelistOfCollection(address collection, uint120 id) external;
function setPermittedContractReceiverAllowlistOfCollection(address collection, uint120 id) external;
function addOperatorToWhitelist(uint120 id, address operator) external;
function addPermittedContractReceiverToAllowlist(uint120 id, address receiver) external;
function removeOperatorFromWhitelist(uint120 id, address operator) external;
function removePermittedContractReceiverFromAllowlist(uint120 id, address receiver) external;
function getCollectionSecurityPolicy(address collection) external view returns (CollectionSecurityPolicy memory);
function getWhitelistedOperators(uint120 id) external view returns (address[] memory);
function getPermittedContractReceivers(uint120 id) external view returns (address[] memory);
function isOperatorWhitelisted(uint120 id, address operator) external view returns (bool);
function isContractReceiverPermitted(uint120 id, address receiver) external view returns (bool);
}
// File: https://github.com/limitbreakinc/creator-token-contracts/blob/main/contracts/interfaces/ITransferValidator.sol
pragma solidity ^0.8.4;
interface ITransferValidator {
function applyCollectionTransferPolicy(address caller, address from, address to) external view;
}
// File: https://github.com/limitbreakinc/creator-token-contracts/blob/main/contracts/interfaces/ICreatorTokenTransferValidator.sol
pragma solidity ^0.8.4;
interface ICreatorTokenTransferValidator is ITransferSecurityRegistry, ITransferValidator, IEOARegistry {}
// File: https://github.com/limitbreakinc/creator-token-contracts/blob/main/contracts/interfaces/ICreatorToken.sol
pragma solidity ^0.8.4;
interface ICreatorToken {
event TransferValidatorUpdated(address oldValidator, address newValidator);
function getTransferValidator() external view returns (ICreatorTokenTransferValidator);
function getSecurityPolicy() external view returns (CollectionSecurityPolicy memory);
function getWhitelistedOperators() external view returns (address[] memory);
function getPermittedContractReceivers() external view returns (address[] memory);
function isOperatorWhitelisted(address operator) external view returns (bool);
function isContractReceiverPermitted(address receiver) external view returns (bool);
function isTransferAllowed(address caller, address from, address to) external view returns (bool);
}
// File: https://github.com/limitbreakinc/creator-token-contracts/blob/main/contracts/utils/TransferValidation.sol
pragma solidity ^0.8.4;
/**
* @title TransferValidation
* @author Limit Break, Inc.
* @notice A mix-in that can be combined with ERC-721 contracts to provide more granular hooks.
* Openzeppelin's ERC721 contract only provides hooks for before and after transfer. This allows
* developers to validate or customize transfers within the context of a mint, a burn, or a transfer.
*/
abstract contract TransferValidation is Context {
error ShouldNotMintToBurnAddress();
/// @dev Inheriting contracts should call this function in the _beforeTokenTransfer function to get more granular hooks.
function _validateBeforeTransfer(address from, address to, uint256 tokenId) internal virtual {
bool fromZeroAddress = from == address(0);
bool toZeroAddress = to == address(0);
if(fromZeroAddress && toZeroAddress) {
revert ShouldNotMintToBurnAddress();
} else if(fromZeroAddress) {
_preValidateMint(_msgSender(), to, tokenId, msg.value);
} else if(toZeroAddress) {
_preValidateBurn(_msgSender(), from, tokenId, msg.value);
} else {
_preValidateTransfer(_msgSender(), from, to, tokenId, msg.value);
}
}
/// @dev Inheriting contracts should call this function in the _afterTokenTransfer function to get more granular hooks.
function _validateAfterTransfer(address from, address to, uint256 tokenId) internal virtual {
bool fromZeroAddress = from == address(0);
bool toZeroAddress = to == address(0);
if(fromZeroAddress && toZeroAddress) {
revert ShouldNotMintToBurnAddress();
} else if(fromZeroAddress) {
_postValidateMint(_msgSender(), to, tokenId, msg.value);
} else if(toZeroAddress) {
_postValidateBurn(_msgSender(), from, tokenId, msg.value);
} else {
_postValidateTransfer(_msgSender(), from, to, tokenId, msg.value);
}
}
/// @dev Optional validation hook that fires before a mint
function _preValidateMint(address caller, address to, uint256 tokenId, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires after a mint
function _postValidateMint(address caller, address to, uint256 tokenId, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires before a burn
function _preValidateBurn(address caller, address from, uint256 tokenId, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires after a burn
function _postValidateBurn(address caller, address from, uint256 tokenId, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires before a transfer
function _preValidateTransfer(address caller, address from, address to, uint256 tokenId, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires after a transfer
function _postValidateTransfer(address caller, address from, address to, uint256 tokenId, uint256 value) internal virtual {}
}
// File: @openzeppelin/contracts/interfaces/IERC165.sol
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
// File: https://github.com/limitbreakinc/creator-token-contracts/blob/main/contracts/utils/CreatorTokenBase.sol
pragma solidity ^0.8.4;
/**
* @title CreatorTokenBase
* @author Limit Break, Inc.
* @notice CreatorTokenBase is an abstract contract that provides basic functionality for managing token
* transfer policies through an implementation of ICreatorTokenTransferValidator. This contract is intended to be used
* as a base for creator-specific token contracts, enabling customizable transfer restrictions and security policies.
*
* <h4>Features:</h4>
* <ul>Ownable: This contract can have an owner who can set and update the transfer validator.</ul>
* <ul>TransferValidation: Implements the basic token transfer validation interface.</ul>
* <ul>ICreatorToken: Implements the interface for creator tokens, providing view functions for token security policies.</ul>
*
* <h4>Benefits:</h4>
* <ul>Provides a flexible and modular way to implement custom token transfer restrictions and security policies.</ul>
* <ul>Allows creators to enforce policies such as whitelisted operators and permitted contract receivers.</ul>
* <ul>Can be easily integrated into other token contracts as a base contract.</ul>
*
* <h4>Intended Usage:</h4>
* <ul>Use as a base contract for creator token implementations that require advanced transfer restrictions and
* security policies.</ul>
* <ul>Set and update the ICreatorTokenTransferValidator implementation contract to enforce desired policies for the
* creator token.</ul>
*/
abstract contract CreatorTokenBase is OwnablePermissions, TransferValidation, ICreatorToken {
error CreatorTokenBase__InvalidTransferValidatorContract();
error CreatorTokenBase__SetTransferValidatorFirst();
address public constant DEFAULT_TRANSFER_VALIDATOR = address(0x0000721C310194CcfC01E523fc93C9cCcFa2A0Ac);
TransferSecurityLevels public constant DEFAULT_TRANSFER_SECURITY_LEVEL = TransferSecurityLevels.One;
uint120 public constant DEFAULT_OPERATOR_WHITELIST_ID = uint120(1);
ICreatorTokenTransferValidator private transferValidator;
/**
* @notice Allows the contract owner to set the transfer validator to the official validator contract
* and set the security policy to the recommended default settings.
* @dev May be overridden to change the default behavior of an individual collection.
*/
function setToDefaultSecurityPolicy() public virtual {
_requireCallerIsContractOwner();
setTransferValidator(DEFAULT_TRANSFER_VALIDATOR);
ICreatorTokenTransferValidator(DEFAULT_TRANSFER_VALIDATOR).setTransferSecurityLevelOfCollection(address(this), DEFAULT_TRANSFER_SECURITY_LEVEL);
ICreatorTokenTransferValidator(DEFAULT_TRANSFER_VALIDATOR).setOperatorWhitelistOfCollection(address(this), DEFAULT_OPERATOR_WHITELIST_ID);
}
/**
* @notice Allows the contract owner to set the transfer validator to a custom validator contract
* and set the security policy to their own custom settings.
*/
function setToCustomValidatorAndSecurityPolicy(
address validator,
TransferSecurityLevels level,
uint120 operatorWhitelistId,
uint120 permittedContractReceiversAllowlistId) public {
_requireCallerIsContractOwner();
setTransferValidator(validator);
ICreatorTokenTransferValidator(validator).
setTransferSecurityLevelOfCollection(address(this), level);
ICreatorTokenTransferValidator(validator).
setOperatorWhitelistOfCollection(address(this), operatorWhitelistId);
ICreatorTokenTransferValidator(validator).
setPermittedContractReceiverAllowlistOfCollection(address(this), permittedContractReceiversAllowlistId);
}
/**
* @notice Allows the contract owner to set the security policy to their own custom settings.
* @dev Reverts if the transfer validator has not been set.
*/
function setToCustomSecurityPolicy(
TransferSecurityLevels level,
uint120 operatorWhitelistId,
uint120 permittedContractReceiversAllowlistId) public {
_requireCallerIsContractOwner();
ICreatorTokenTransferValidator validator = getTransferValidator();
if (address(validator) == address(0)) {
revert CreatorTokenBase__SetTransferValidatorFirst();
}
validator.setTransferSecurityLevelOfCollection(address(this), level);
validator.setOperatorWhitelistOfCollection(address(this), operatorWhitelistId);
validator.setPermittedContractReceiverAllowlistOfCollection(address(this), permittedContractReceiversAllowlistId);
}
/**
* @notice Sets the transfer validator for the token contract.
*
* @dev Throws when provided validator contract is not the zero address and doesn't support
* the ICreatorTokenTransferValidator interface.
* @dev Throws when the caller is not the contract owner.
*
* @dev <h4>Postconditions:</h4>
* 1. The transferValidator address is updated.
* 2. The `TransferValidatorUpdated` event is emitted.
*
* @param transferValidator_ The address of the transfer validator contract.
*/
function setTransferValidator(address transferValidator_) public {
_requireCallerIsContractOwner();
bool isValidTransferValidator = false;
if(transferValidator_.code.length > 0) {
try IERC165(transferValidator_).supportsInterface(type(ICreatorTokenTransferValidator).interfaceId)
returns (bool supportsInterface) {
isValidTransferValidator = supportsInterface;
} catch {}
}
if(transferValidator_ != address(0) && !isValidTransferValidator) {
revert CreatorTokenBase__InvalidTransferValidatorContract();
}
emit TransferValidatorUpdated(address(transferValidator), transferValidator_);
transferValidator = ICreatorTokenTransferValidator(transferValidator_);
}
/**
* @notice Returns the transfer validator contract address for this token contract.
*/
function getTransferValidator() public view override returns (ICreatorTokenTransferValidator) {
return transferValidator;
}
/**
* @notice Returns the security policy for this token contract, which includes:
* Transfer security level, operator whitelist id, permitted contract receiver allowlist id.
*/
function getSecurityPolicy() public view override returns (CollectionSecurityPolicy memory) {
if (address(transferValidator) != address(0)) {
return transferValidator.getCollectionSecurityPolicy(address(this));
}
return CollectionSecurityPolicy({
transferSecurityLevel: TransferSecurityLevels.Zero,
operatorWhitelistId: 0,
permittedContractReceiversId: 0
});
}
/**
* @notice Returns the list of all whitelisted operators for this token contract.
* @dev This can be an expensive call and should only be used in view-only functions.
*/
function getWhitelistedOperators() public view override returns (address[] memory) {
if (address(transferValidator) != address(0)) {
return transferValidator.getWhitelistedOperators(
transferValidator.getCollectionSecurityPolicy(address(this)).operatorWhitelistId);
}
return new address[](0);
}
/**
* @notice Returns the list of permitted contract receivers for this token contract.
* @dev This can be an expensive call and should only be used in view-only functions.
*/
function getPermittedContractReceivers() public view override returns (address[] memory) {
if (address(transferValidator) != address(0)) {
return transferValidator.getPermittedContractReceivers(
transferValidator.getCollectionSecurityPolicy(address(this)).permittedContractReceiversId);
}
return new address[](0);
}
/**
* @notice Checks if an operator is whitelisted for this token contract.
* @param operator The address of the operator to check.
*/
function isOperatorWhitelisted(address operator) public view override returns (bool) {
if (address(transferValidator) != address(0)) {
return transferValidator.isOperatorWhitelisted(
transferValidator.getCollectionSecurityPolicy(address(this)).operatorWhitelistId, operator);
}
return false;
}
/**
* @notice Checks if a contract receiver is permitted for this token contract.
* @param receiver The address of the receiver to check.
*/
function isContractReceiverPermitted(address receiver) public view override returns (bool) {
if (address(transferValidator) != address(0)) {
return transferValidator.isContractReceiverPermitted(
transferValidator.getCollectionSecurityPolicy(address(this)).permittedContractReceiversId, receiver);
}
return false;
}
/**
* @notice Determines if a transfer is allowed based on the token contract's security policy. Use this function
* to simulate whether or not a transfer made by the specified `caller` from the `from` address to the `to`
* address would be allowed by this token's security policy.
*
* @notice This function only checks the security policy restrictions and does not check whether token ownership
* or approvals are in place.
*
* @param caller The address of the simulated caller.
* @param from The address of the sender.
* @param to The address of the receiver.
* @return True if the transfer is allowed, false otherwise.
*/
function isTransferAllowed(address caller, address from, address to) public view override returns (bool) {
if (address(transferValidator) != address(0)) {
try transferValidator.applyCollectionTransferPolicy(caller, from, to) {
return true;
} catch {
return false;
}
}
return true;
}
/**
* @dev Pre-validates a token transfer, reverting if the transfer is not allowed by this token's security policy.
* Inheriting contracts are responsible for overriding the _beforeTokenTransfer function, or its equivalent
* and calling _validateBeforeTransfer so that checks can be properly applied during token transfers.
*
* @dev Throws when the transfer doesn't comply with the collection's transfer policy, if the transferValidator is
* set to a non-zero address.
*
* @param caller The address of the caller.
* @param from The address of the sender.
* @param to The address of the receiver.
*/
function _preValidateTransfer(
address caller,
address from,
address to,
uint256 /*tokenId*/,
uint256 /*value*/) internal virtual override {
if (address(transferValidator) != address(0)) {
transferValidator.applyCollectionTransferPolicy(caller, from, to);
}
}
}
// File: erc721a/contracts/IERC721A.sol
// ERC721A Contracts v4.3.0
// Creator: Chiru Labs
pragma solidity ^0.8.4;
/**
* @dev Interface of ERC721A.
*/
interface IERC721A {
/**
* The caller must own the token or be an approved operator.
*/
error ApprovalCallerNotOwnerNorApproved();
/**
* The token does not exist.
*/
error ApprovalQueryForNonexistentToken();
/**
* Cannot query the balance for the zero address.
*/
error BalanceQueryForZeroAddress();
/**
* Cannot mint to the zero address.
*/
error MintToZeroAddress();
/**
* The quantity of tokens minted must be more than zero.
*/
error MintZeroQuantity();
/**
* The token does not exist.
*/
error OwnerQueryForNonexistentToken();
/**
* The caller must own the token or be an approved operator.
*/
error TransferCallerNotOwnerNorApproved();
/**
* The token must be owned by `from`.
*/
error TransferFromIncorrectOwner();
/**
* Cannot safely transfer to a contract that does not implement the
* ERC721Receiver interface.
*/
error TransferToNonERC721ReceiverImplementer();
/**
* Cannot transfer to the zero address.
*/
error TransferToZeroAddress();
/**
* The token does not exist.
*/
error URIQueryForNonexistentToken();
/**
* The `quantity` minted with ERC2309 exceeds the safety limit.
*/
error MintERC2309QuantityExceedsLimit();
/**
* The `extraData` cannot be set on an unintialized ownership slot.
*/
error OwnershipNotInitializedForExtraData();
/**
* `_sequentialUpTo()` must be greater than `_startTokenId()`.
*/
error SequentialUpToTooSmall();
/**
* The `tokenId` of a sequential mint exceeds `_sequentialUpTo()`.
*/
error SequentialMintExceedsLimit();
/**
* Spot minting requires a `tokenId` greater than `_sequentialUpTo()`.
*/
error SpotMintTokenIdTooSmall();
/**
* Cannot mint over a token that already exists.
*/
error TokenAlreadyExists();
/**
* The feature is not compatible with spot mints.
*/
error NotCompatibleWithSpotMints();
// =============================================================
// STRUCTS
// =============================================================
struct TokenOwnership {
// The address of the owner.
address addr;
// Stores the start time of ownership with minimal overhead for tokenomics.
uint64 startTimestamp;
// Whether the token has been burned.
bool burned;
// Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.
uint24 extraData;
}
// =============================================================
// TOKEN COUNTERS
// =============================================================
/**
* @dev Returns the total number of tokens in existence.
* Burned tokens will reduce the count.
* To get the total number of tokens minted, please see {_totalMinted}.
*/
function totalSupply() external view returns (uint256);
// =============================================================
// IERC165
// =============================================================
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
* to learn more about how these ids are created.
*
* This function call must use less than 30000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
// =============================================================
// IERC721
// =============================================================
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables
* (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in `owner`'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`,
* checking first that contract recipients are aware of the ERC721 protocol
* to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move
* this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement
* {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external payable;
/**
* @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external payable;
/**
* @dev Transfers `tokenId` from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom}
* whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token
* by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external payable;
/**
* @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 payable;
/**
* @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);
// =============================================================
// IERC721Metadata
// =============================================================
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
// =============================================================
// IERC2309
// =============================================================
/**
* @dev Emitted when tokens in `fromTokenId` to `toTokenId`
* (inclusive) is transferred from `from` to `to`, as defined in the
* [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
*
* See {_mintERC2309} for more details.
*/
event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);
}
// File: erc721a/contracts/ERC721A.sol
// ERC721A Contracts v4.3.0
// Creator: Chiru Labs
pragma solidity ^0.8.4;
/**
* @dev Interface of ERC721 token receiver.
*/
interface ERC721A__IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
/**
* @title ERC721A
*
* @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721)
* Non-Fungible Token Standard, including the Metadata extension.
* Optimized for lower gas during batch mints.
*
* Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...)
* starting from `_startTokenId()`.
*
* The `_sequentialUpTo()` function can be overriden to enable spot mints
* (i.e. non-consecutive mints) for `tokenId`s greater than `_sequentialUpTo()`.
*
* Assumptions:
*
* - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply.
* - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256).
*/
contract ERC721A is IERC721A {
// Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364).
struct TokenApprovalRef {
address value;
}
// =============================================================
// CONSTANTS
// =============================================================
// Mask of an entry in packed address data.
uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1;
// The bit position of `numberMinted` in packed address data.
uint256 private constant _BITPOS_NUMBER_MINTED = 64;
// The bit position of `numberBurned` in packed address data.
uint256 private constant _BITPOS_NUMBER_BURNED = 128;
// The bit position of `aux` in packed address data.
uint256 private constant _BITPOS_AUX = 192;
// Mask of all 256 bits in packed address data except the 64 bits for `aux`.
uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1;
// The bit position of `startTimestamp` in packed ownership.
uint256 private constant _BITPOS_START_TIMESTAMP = 160;
// The bit mask of the `burned` bit in packed ownership.
uint256 private constant _BITMASK_BURNED = 1 << 224;
// The bit position of the `nextInitialized` bit in packed ownership.
uint256 private constant _BITPOS_NEXT_INITIALIZED = 225;
// The bit mask of the `nextInitialized` bit in packed ownership.
uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225;
// The bit position of `extraData` in packed ownership.
uint256 private constant _BITPOS_EXTRA_DATA = 232;
// Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`.
uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1;
// The mask of the lower 160 bits for addresses.
uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1;
// The maximum `quantity` that can be minted with {_mintERC2309}.
// This limit is to prevent overflows on the address data entries.
// For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309}
// is required to cause an overflow, which is unrealistic.
uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000;
// The `Transfer` event signature is given by:
// `keccak256(bytes("Transfer(address,address,uint256)"))`.
bytes32 private constant _TRANSFER_EVENT_SIGNATURE =
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
// =============================================================
// STORAGE
// =============================================================
// The next token ID to be minted.
uint256 private _currentIndex;
// The number of tokens burned.
uint256 private _burnCounter;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to ownership details
// An empty struct value does not necessarily mean the token is unowned.
// See {_packedOwnershipOf} implementation for details.
//
// Bits Layout:
// - [0..159] `addr`
// - [160..223] `startTimestamp`
// - [224] `burned`
// - [225] `nextInitialized`
// - [232..255] `extraData`
mapping(uint256 => uint256) private _packedOwnerships;
// Mapping owner address to address data.
//
// Bits Layout:
// - [0..63] `balance`
// - [64..127] `numberMinted`
// - [128..191] `numberBurned`
// - [192..255] `aux`
mapping(address => uint256) private _packedAddressData;
// Mapping from token ID to approved address.
mapping(uint256 => TokenApprovalRef) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
// The amount of tokens minted above `_sequentialUpTo()`.
// We call these spot mints (i.e. non-sequential mints).
uint256 private _spotMinted;
// =============================================================
// CONSTRUCTOR
// =============================================================
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
_currentIndex = _startTokenId();
if (_sequentialUpTo() < _startTokenId()) _revert(SequentialUpToTooSmall.selector);
}
// =============================================================
// TOKEN COUNTING OPERATIONS
// =============================================================
/**
* @dev Returns the starting token ID for sequential mints.
*
* Override this function to change the starting token ID for sequential mints.
*
* Note: The value returned must never change after any tokens have been minted.
*/
function _startTokenId() internal view virtual returns (uint256) {
return 1;
}
/**
* @dev Returns the maximum token ID (inclusive) for sequential mints.
*
* Override this function to return a value less than 2**256 - 1,
* but greater than `_startTokenId()`, to enable spot (non-sequential) mints.
*
* Note: The value returned must never change after any tokens have been minted.
*/
function _sequentialUpTo() internal view virtual returns (uint256) {
return type(uint256).max;
}
/**
* @dev Returns the next token ID to be minted.
*/
function _nextTokenId() internal view virtual returns (uint256) {
return _currentIndex;
}
/**
* @dev Returns the total number of tokens in existence.
* Burned tokens will reduce the count.
* To get the total number of tokens minted, please see {_totalMinted}.
*/
function totalSupply() public view virtual override returns (uint256 result) {
// Counter underflow is impossible as `_burnCounter` cannot be incremented
// more than `_currentIndex + _spotMinted - _startTokenId()` times.
unchecked {
// With spot minting, the intermediate `result` can be temporarily negative,
// and the computation must be unchecked.
result = _currentIndex - _burnCounter - _startTokenId();
if (_sequentialUpTo() != type(uint256).max) result += _spotMinted;
}
}
/**
* @dev Returns the total amount of tokens minted in the contract.
*/
function _totalMinted() internal view virtual returns (uint256 result) {
// Counter underflow is impossible as `_currentIndex` does not decrement,
// and it is initialized to `_startTokenId()`.
unchecked {
result = _currentIndex - _startTokenId();
if (_sequentialUpTo() != type(uint256).max) result += _spotMinted;
}
}
/**
* @dev Returns the total number of tokens burned.
*/
function _totalBurned() internal view virtual returns (uint256) {
return _burnCounter;
}
/**
* @dev Returns the total number of tokens that are spot-minted.
*/
function _totalSpotMinted() internal view virtual returns (uint256) {
return _spotMinted;
}
// =============================================================
// ADDRESS DATA OPERATIONS
// =============================================================
/**
* @dev Returns the number of tokens in `owner`'s account.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
if (owner == address(0)) _revert(BalanceQueryForZeroAddress.selector);
return _packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY;
}
/**
* Returns the number of tokens minted by `owner`.
*/
function _numberMinted(address owner) internal view returns (uint256) {
return (_packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY;
}
/**
* Returns the number of tokens burned by or on behalf of `owner`.
*/
function _numberBurned(address owner) internal view returns (uint256) {
return (_packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY;
}
/**
* Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
*/
function _getAux(address owner) internal view returns (uint64) {
return uint64(_packedAddressData[owner] >> _BITPOS_AUX);
}
/**
* Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
* If there are multiple variables, please pack them into a uint64.
*/
function _setAux(address owner, uint64 aux) internal virtual {
uint256 packed = _packedAddressData[owner];
uint256 auxCasted;
// Cast `aux` with assembly to avoid redundant masking.
assembly {
auxCasted := aux
}
packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX);
_packedAddressData[owner] = packed;
}
// =============================================================
// IERC165
// =============================================================
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
* to learn more about how these ids are created.
*
* This function call must use less than 30000 gas.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
// The interface IDs are constants representing the first 4 bytes
// of the XOR of all function selectors in the interface.
// See: [ERC165](https://eips.ethereum.org/EIPS/eip-165)
// (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`)
return
interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165.
interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721.
interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata.
}
// =============================================================
// IERC721Metadata
// =============================================================
/**
* @dev Returns the token collection name.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the token collection symbol.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
if (!_exists(tokenId)) _revert(URIQueryForNonexistentToken.selector);
string memory baseURI = _baseURI();
return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : '';
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, it can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return '';
}
// =============================================================
// OWNERSHIPS OPERATIONS
// =============================================================
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
return address(uint160(_packedOwnershipOf(tokenId)));
}
/**
* @dev Gas spent here starts off proportional to the maximum mint batch size.
* It gradually moves to O(1) as tokens get transferred around over time.
*/
function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) {
return _unpackedOwnership(_packedOwnershipOf(tokenId));
}
/**
* @dev Returns the unpacked `TokenOwnership` struct at `index`.
*/
function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) {
return _unpackedOwnership(_packedOwnerships[index]);
}
/**
* @dev Returns whether the ownership slot at `index` is initialized.
* An uninitialized slot does not necessarily mean that the slot has no owner.
*/
function _ownershipIsInitialized(uint256 index) internal view virtual returns (bool) {
return _packedOwnerships[index] != 0;
}
/**
* @dev Initializes the ownership slot minted at `index` for efficiency purposes.
*/
function _initializeOwnershipAt(uint256 index) internal virtual {
if (_packedOwnerships[index] == 0) {
_packedOwnerships[index] = _packedOwnershipOf(index);
}
}
/**
* @dev Returns the packed ownership data of `tokenId`.
*/
function _packedOwnershipOf(uint256 tokenId) private view returns (uint256 packed) {
if (_startTokenId() <= tokenId) {
packed = _packedOwnerships[tokenId];
if (tokenId > _sequentialUpTo()) {
if (_packedOwnershipExists(packed)) return packed;
_revert(OwnerQueryForNonexistentToken.selector);
}
// If the data at the starting slot does not exist, start the scan.
if (packed == 0) {
if (tokenId >= _currentIndex) _revert(OwnerQueryForNonexistentToken.selector);
// Invariant:
// There will always be an initialized ownership slot
// (i.e. `ownership.addr != address(0) && ownership.burned == false`)
// before an unintialized ownership slot
// (i.e. `ownership.addr == address(0) && ownership.burned == false`)
// Hence, `tokenId` will not underflow.
//
// We can directly compare the packed value.
// If the address is zero, packed will be zero.
for (;;) {
unchecked {
packed = _packedOwnerships[--tokenId];
}
if (packed == 0) continue;
if (packed & _BITMASK_BURNED == 0) return packed;
// Otherwise, the token is burned, and we must revert.
// This handles the case of batch burned tokens, where only the burned bit
// of the starting slot is set, and remaining slots are left uninitialized.
_revert(OwnerQueryForNonexistentToken.selector);
}
}
// Otherwise, the data exists and we can skip the scan.
// This is possible because we have already achieved the target condition.
// This saves 2143 gas on transfers of initialized tokens.
// If the token is not burned, return `packed`. Otherwise, revert.
if (packed & _BITMASK_BURNED == 0) return packed;
}
_revert(OwnerQueryForNonexistentToken.selector);
}
/**
* @dev Returns the unpacked `TokenOwnership` struct from `packed`.
*/
function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) {
ownership.addr = address(uint160(packed));
ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP);
ownership.burned = packed & _BITMASK_BURNED != 0;
ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA);
}
/**
* @dev Packs ownership data into a single uint256.
*/
function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) {
assembly {
// Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
owner := and(owner, _BITMASK_ADDRESS)
// `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`.
result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags))
}
}
/**
* @dev Returns the `nextInitialized` flag set if `quantity` equals 1.
*/
function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) {
// For branchless setting of the `nextInitialized` flag.
assembly {
// `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`.
result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1))
}
}
// =============================================================
// APPROVAL OPERATIONS
// =============================================================
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account. See {ERC721A-_approve}.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
*/
function approve(address to, uint256 tokenId) public payable virtual override {
_approve(to, tokenId, true);
}
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
if (!_exists(tokenId)) _revert(ApprovalQueryForNonexistentToken.selector);
return _tokenApprovals[tokenId].value;
}
/**
* @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) public virtual override {
_operatorApprovals[_msgSenderERC721A()][operator] = approved;
emit ApprovalForAll(_msgSenderERC721A(), operator, approved);
}
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted. See {_mint}.
*/
function _exists(uint256 tokenId) internal view virtual returns (bool result) {
if (_startTokenId() <= tokenId) {
if (tokenId > _sequentialUpTo()) return _packedOwnershipExists(_packedOwnerships[tokenId]);
if (tokenId < _currentIndex) {
uint256 packed;
while ((packed = _packedOwnerships[tokenId]) == 0) --tokenId;
result = packed & _BITMASK_BURNED == 0;
}
}
}
/**
* @dev Returns whether `packed` represents a token that exists.
*/
function _packedOwnershipExists(uint256 packed) private pure returns (bool result) {
assembly {
// The following is equivalent to `owner != address(0) && burned == false`.
// Symbolically tested.
result := gt(and(packed, _BITMASK_ADDRESS), and(packed, _BITMASK_BURNED))
}
}
/**
* @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`.
*/
function _isSenderApprovedOrOwner(
address approvedAddress,
address owner,
address msgSender
) private pure returns (bool result) {
assembly {
// Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
owner := and(owner, _BITMASK_ADDRESS)
// Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean.
msgSender := and(msgSender, _BITMASK_ADDRESS)
// `msgSender == owner || msgSender == approvedAddress`.
result := or(eq(msgSender, owner), eq(msgSender, approvedAddress))
}
}
/**
* @dev Returns the storage slot and value for the approved address of `tokenId`.
*/
function _getApprovedSlotAndAddress(uint256 tokenId)
private
view
returns (uint256 approvedAddressSlot, address approvedAddress)
{
TokenApprovalRef storage tokenApproval = _tokenApprovals[tokenId];
// The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`.
assembly {
approvedAddressSlot := tokenApproval.slot
approvedAddress := sload(approvedAddressSlot)
}
}
// =============================================================
// TRANSFER OPERATIONS
// =============================================================
/**
* @dev Transfers `tokenId` from `from` to `to`.
*
* 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
) public payable virtual override {
uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);
// Mask `from` to the lower 160 bits, in case the upper bits somehow aren't clean.
from = address(uint160(uint256(uint160(from)) & _BITMASK_ADDRESS));
if (address(uint160(prevOwnershipPacked)) != from) _revert(TransferFromIncorrectOwner.selector);
(uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);
// The nested ifs save around 20+ gas over a compound boolean condition.
if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector);
_beforeTokenTransfers(from, to, tokenId, 1);
// Clear approvals from the previous owner.
assembly {
if approvedAddress {
// This is equivalent to `delete _tokenApprovals[tokenId]`.
sstore(approvedAddressSlot, 0)
}
}
// Underflow of the sender's balance is impossible because we check for
// ownership above and the recipient's balance can't realistically overflow.
// Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
unchecked {
// We can directly increment and decrement the balances.
--_packedAddressData[from]; // Updates: `balance -= 1`.
++_packedAddressData[to]; // Updates: `balance += 1`.
// Updates:
// - `address` to the next owner.
// - `startTimestamp` to the timestamp of transfering.
// - `burned` to `false`.
// - `nextInitialized` to `true`.
_packedOwnerships[tokenId] = _packOwnershipData(
to,
_BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked)
);
// If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
uint256 nextTokenId = tokenId + 1;
// If the next slot's address is zero and not burned (i.e. packed value is zero).
if (_packedOwnerships[nextTokenId] == 0) {
// If the next slot is within bounds.
if (nextTokenId != _currentIndex) {
// Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
_packedOwnerships[nextTokenId] = prevOwnershipPacked;
}
}
}
}
// Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS;
assembly {
// Emit the `Transfer` event.
log4(
0, // Start of data (0, since no data).
0, // End of data (0, since no data).
_TRANSFER_EVENT_SIGNATURE, // Signature.
from, // `from`.
toMasked, // `to`.
tokenId // `tokenId`.
)
}
if (toMasked == 0) _revert(TransferToZeroAddress.selector);
_afterTokenTransfers(from, to, tokenId, 1);
}
/**
* @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public payable virtual override {
safeTransferFrom(from, to, tokenId, '');
}
/**
* @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 memory _data
) public payable virtual override {
transferFrom(from, to, tokenId);
if (to.code.length != 0)
if (!_checkContractOnERC721Received(from, to, tokenId, _data)) {
_revert(TransferToNonERC721ReceiverImplementer.selector);
}
}
/**
* @dev Hook that is called before a set of serially-ordered token IDs
* are about to be transferred. This includes minting.
* And also called before burning one token.
*
* `startTokenId` - the first token ID to be transferred.
* `quantity` - the amount to be transferred.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, `tokenId` will be burned by `from`.
* - `from` and `to` are never both zero.
*/
function _beforeTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual {}
/**
* @dev Hook that is called after a set of serially-ordered token IDs
* have been transferred. This includes minting.
* And also called after one token has been burned.
*
* `startTokenId` - the first token ID to be transferred.
* `quantity` - the amount to be transferred.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, `from`'s `tokenId` has been
* transferred to `to`.
* - When `from` is zero, `tokenId` has been minted for `to`.
* - When `to` is zero, `tokenId` has been burned by `from`.
* - `from` and `to` are never both zero.
*/
function _afterTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual {}
/**
* @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract.
*
* `from` - Previous owner of the given token ID.
* `to` - Target address that will receive the token.
* `tokenId` - Token ID to be transferred.
* `_data` - Optional data to send along with the call.
*
* Returns whether the call correctly returned the expected magic value.
*/
function _checkContractOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns (
bytes4 retval
) {
return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
_revert(TransferToNonERC721ReceiverImplementer.selector);
}
assembly {
revert(add(32, reason), mload(reason))
}
}
}
// =============================================================
// MINT OPERATIONS
// =============================================================
/**
* @dev Mints `quantity` tokens and transfers them to `to`.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `quantity` must be greater than 0.
*
* Emits a {Transfer} event for each mint.
*/
function _mint(address to, uint256 quantity) internal virtual {
uint256 startTokenId = _currentIndex;
if (quantity == 0) _revert(MintZeroQuantity.selector);
_beforeTokenTransfers(address(0), to, startTokenId, quantity);
// Overflows are incredibly unrealistic.
// `balance` and `numberMinted` have a maximum limit of 2**64.
// `tokenId` has a maximum limit of 2**256.
unchecked {
// Updates:
// - `address` to the owner.
// - `startTimestamp` to the timestamp of minting.
// - `burned` to `false`.
// - `nextInitialized` to `quantity == 1`.
_packedOwnerships[startTokenId] = _packOwnershipData(
to,
_nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
);
// Updates:
// - `balance += quantity`.
// - `numberMinted += quantity`.
//
// We can directly add to the `balance` and `numberMinted`.
_packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);
// Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS;
if (toMasked == 0) _revert(MintToZeroAddress.selector);
uint256 end = startTokenId + quantity;
uint256 tokenId = startTokenId;
if (end - 1 > _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector);
do {
assembly {
// Emit the `Transfer` event.
log4(
0, // Start of data (0, since no data).
0, // End of data (0, since no data).
_TRANSFER_EVENT_SIGNATURE, // Signature.
0, // `address(0)`.
toMasked, // `to`.
tokenId // `tokenId`.
)
}
// The `!=` check ensures that large values of `quantity`
// that overflows uint256 will make the loop run out of gas.
} while (++tokenId != end);
_currentIndex = end;
}
_afterTokenTransfers(address(0), to, startTokenId, quantity);
}
/**
* @dev Mints `quantity` tokens and transfers them to `to`.
*
* This function is intended for efficient minting only during contract creation.
*
* It emits only one {ConsecutiveTransfer} as defined in
* [ERC2309](https://eips.ethereum.org/EIPS/eip-2309),
* instead of a sequence of {Transfer} event(s).
*
* Calling this function outside of contract creation WILL make your contract
* non-compliant with the ERC721 standard.
* For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309
* {ConsecutiveTransfer} event is only permissible during contract creation.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `quantity` must be greater than 0.
*
* Emits a {ConsecutiveTransfer} event.
*/
function _mintERC2309(address to, uint256 quantity) internal virtual {
uint256 startTokenId = _currentIndex;
if (to == address(0)) _revert(MintToZeroAddress.selector);
if (quantity == 0) _revert(MintZeroQuantity.selector);
if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) _revert(MintERC2309QuantityExceedsLimit.selector);
_beforeTokenTransfers(address(0), to, startTokenId, quantity);
// Overflows are unrealistic due to the above check for `quantity` to be below the limit.
unchecked {
// Updates:
// - `balance += quantity`.
// - `numberMinted += quantity`.
//
// We can directly add to the `balance` and `numberMinted`.
_packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);
// Updates:
// - `address` to the owner.
// - `startTimestamp` to the timestamp of minting.
// - `burned` to `false`.
// - `nextInitialized` to `quantity == 1`.
_packedOwnerships[startTokenId] = _packOwnershipData(
to,
_nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
);
if (startTokenId + quantity - 1 > _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector);
emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to);
_currentIndex = startTokenId + quantity;
}
_afterTokenTransfers(address(0), to, startTokenId, quantity);
}
/**
* @dev Safely mints `quantity` tokens and transfers them to `to`.
*
* Requirements:
*
* - If `to` refers to a smart contract, it must implement
* {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
* - `quantity` must be greater than 0.
*
* See {_mint}.
*
* Emits a {Transfer} event for each mint.
*/
function _safeMint(
address to,
uint256 quantity,
bytes memory _data
) internal virtual {
_mint(to, quantity);
unchecked {
if (to.code.length != 0) {
uint256 end = _currentIndex;
uint256 index = end - quantity;
do {
if (!_checkContractOnERC721Received(address(0), to, index++, _data)) {
_revert(TransferToNonERC721ReceiverImplementer.selector);
}
} while (index < end);
// This prevents reentrancy to `_safeMint`.
// It does not prevent reentrancy to `_safeMintSpot`.
if (_currentIndex != end) revert();
}
}
}
/**
* @dev Equivalent to `_safeMint(to, quantity, '')`.
*/
function _safeMint(address to, uint256 quantity) internal virtual {
_safeMint(to, quantity, '');
}
/**
* @dev Mints a single token at `tokenId`.
*
* Note: A spot-minted `tokenId` that has been burned can be re-minted again.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` must be greater than `_sequentialUpTo()`.
* - `tokenId` must not exist.
*
* Emits a {Transfer} event for each mint.
*/
function _mintSpot(address to, uint256 tokenId) internal virtual {
if (tokenId <= _sequentialUpTo()) _revert(SpotMintTokenIdTooSmall.selector);
uint256 prevOwnershipPacked = _packedOwnerships[tokenId];
if (_packedOwnershipExists(prevOwnershipPacked)) _revert(TokenAlreadyExists.selector);
_beforeTokenTransfers(address(0), to, tokenId, 1);
// Overflows are incredibly unrealistic.
// The `numberMinted` for `to` is incremented by 1, and has a max limit of 2**64 - 1.
// `_spotMinted` is incremented by 1, and has a max limit of 2**256 - 1.
unchecked {
// Updates:
// - `address` to the owner.
// - `startTimestamp` to the timestamp of minting.
// - `burned` to `false`.
// - `nextInitialized` to `true` (as `quantity == 1`).
_packedOwnerships[tokenId] = _packOwnershipData(
to,
_nextInitializedFlag(1) | _nextExtraData(address(0), to, prevOwnershipPacked)
);
// Updates:
// - `balance += 1`.
// - `numberMinted += 1`.
//
// We can directly add to the `balance` and `numberMinted`.
_packedAddressData[to] += (1 << _BITPOS_NUMBER_MINTED) | 1;
// Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS;
if (toMasked == 0) _revert(MintToZeroAddress.selector);
assembly {
// Emit the `Transfer` event.
log4(
0, // Start of data (0, since no data).
0, // End of data (0, since no data).
_TRANSFER_EVENT_SIGNATURE, // Signature.
0, // `address(0)`.
toMasked, // `to`.
tokenId // `tokenId`.
)
}
++_spotMinted;
}
_afterTokenTransfers(address(0), to, tokenId, 1);
}
/**
* @dev Safely mints a single token at `tokenId`.
*
* Note: A spot-minted `tokenId` that has been burned can be re-minted again.
*
* Requirements:
*
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}.
* - `tokenId` must be greater than `_sequentialUpTo()`.
* - `tokenId` must not exist.
*
* See {_mintSpot}.
*
* Emits a {Transfer} event.
*/
function _safeMintSpot(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mintSpot(to, tokenId);
unchecked {
if (to.code.length != 0) {
uint256 currentSpotMinted = _spotMinted;
if (!_checkContractOnERC721Received(address(0), to, tokenId, _data)) {
_revert(TransferToNonERC721ReceiverImplementer.selector);
}
// This prevents reentrancy to `_safeMintSpot`.
// It does not prevent reentrancy to `_safeMint`.
if (_spotMinted != currentSpotMinted) revert();
}
}
}
/**
* @dev Equivalent to `_safeMintSpot(to, tokenId, '')`.
*/
function _safeMintSpot(address to, uint256 tokenId) internal virtual {
_safeMintSpot(to, tokenId, '');
}
// =============================================================
// APPROVAL OPERATIONS
// =============================================================
/**
* @dev Equivalent to `_approve(to, tokenId, false)`.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_approve(to, tokenId, false);
}
/**
* @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:
*
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function _approve(
address to,
uint256 tokenId,
bool approvalCheck
) internal virtual {
address owner = ownerOf(tokenId);
if (approvalCheck && _msgSenderERC721A() != owner)
if (!isApprovedForAll(owner, _msgSenderERC721A())) {
_revert(ApprovalCallerNotOwnerNorApproved.selector);
}
_tokenApprovals[tokenId].value = to;
emit Approval(owner, to, tokenId);
}
// =============================================================
// BURN OPERATIONS
// =============================================================
/**
* @dev Equivalent to `_burn(tokenId, false)`.
*/
function _burn(uint256 tokenId) internal virtual {
_burn(tokenId, false);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId, bool approvalCheck) internal virtual {
uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);
address from = address(uint160(prevOwnershipPacked));
(uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);
if (approvalCheck) {
// The nested ifs save around 20+ gas over a compound boolean condition.
if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector);
}
_beforeTokenTransfers(from, address(0), tokenId, 1);
// Clear approvals from the previous owner.
assembly {
if approvedAddress {
// This is equivalent to `delete _tokenApprovals[tokenId]`.
sstore(approvedAddressSlot, 0)
}
}
// Underflow of the sender's balance is impossible because we check for
// ownership above and the recipient's balance can't realistically overflow.
// Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
unchecked {
// Updates:
// - `balance -= 1`.
// - `numberBurned += 1`.
//
// We can directly decrement the balance, and increment the number burned.
// This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`.
_packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1;
// Updates:
// - `address` to the last owner.
// - `startTimestamp` to the timestamp of burning.
// - `burned` to `true`.
// - `nextInitialized` to `true`.
_packedOwnerships[tokenId] = _packOwnershipData(
from,
(_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked)
);
// If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
uint256 nextTokenId = tokenId + 1;
// If the next slot's address is zero and not burned (i.e. packed value is zero).
if (_packedOwnerships[nextTokenId] == 0) {
// If the next slot is within bounds.
if (nextTokenId != _currentIndex) {
// Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
_packedOwnerships[nextTokenId] = prevOwnershipPacked;
}
}
}
}
emit Transfer(from, address(0), tokenId);
_afterTokenTransfers(from, address(0), tokenId, 1);
// Overflow not possible, as `_burnCounter` cannot be exceed `_currentIndex + _spotMinted` times.
unchecked {
_burnCounter++;
}
}
// =============================================================
// EXTRA DATA OPERATIONS
// =============================================================
/**
* @dev Directly sets the extra data for the ownership data `index`.
*/
function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual {
uint256 packed = _packedOwnerships[index];
if (packed == 0) _revert(OwnershipNotInitializedForExtraData.selector);
uint256 extraDataCasted;
// Cast `extraData` with assembly to avoid redundant masking.
assembly {
extraDataCasted := extraData
}
packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA);
_packedOwnerships[index] = packed;
}
/**
* @dev Called during each token transfer to set the 24bit `extraData` field.
* Intended to be overridden by the cosumer contract.
*
* `previousExtraData` - the value of `extraData` before transfer.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, `tokenId` will be burned by `from`.
* - `from` and `to` are never both zero.
*/
function _extraData(
address from,
address to,
uint24 previousExtraData
) internal view virtual returns (uint24) {}
/**
* @dev Returns the next extra data for the packed ownership data.
* The returned result is shifted into position.
*/
function _nextExtraData(
address from,
address to,
uint256 prevOwnershipPacked
) private view returns (uint256) {
uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA);
return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA;
}
// =============================================================
// OTHER OPERATIONS
// =============================================================
/**
* @dev Returns the message sender (defaults to `msg.sender`).
*
* If you are writing GSN compatible contracts, you need to override this function.
*/
function _msgSenderERC721A() internal view virtual returns (address) {
return msg.sender;
}
/**
* @dev Converts a uint256 to its ASCII string decimal representation.
*/
function _toString(uint256 value) internal pure virtual returns (string memory str) {
assembly {
// The maximum value of a uint256 contains 78 digits (1 byte per digit), but
// we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.
// We will need 1 word for the trailing zeros padding, 1 word for the length,
// and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0.
let m := add(mload(0x40), 0xa0)
// Update the free memory pointer to allocate.
mstore(0x40, m)
// Assign the `str` to the end.
str := sub(m, 0x20)
// Zeroize the slot after the string.
mstore(str, 0)
// Cache the end of the memory to calculate the length later.
let end := str
// We write the string from rightmost digit to leftmost digit.
// The following is essentially a do-while loop that also handles the zero case.
// prettier-ignore
for { let temp := value } 1 {} {
str := sub(str, 1)
// Write the character to the pointer.
// The ASCII index of the '0' character is 48.
mstore8(str, add(48, mod(temp, 10)))
// Keep dividing `temp` until zero.
temp := div(temp, 10)
// prettier-ignore
if iszero(temp) { break }
}
let length := sub(end, str)
// Move the pointer 32 bytes leftwards to make room for the length.
str := sub(str, 0x20)
// Store the length.
mstore(str, length)
}
}
/**
* @dev For more efficient reverts.
*/
function _revert(bytes4 errorSelector) internal pure {
assembly {
mstore(0x00, errorSelector)
revert(0x00, 0x04)
}
}
}
// File: https://github.com/limitbreakinc/creator-token-contracts/blob/main/contracts/erc721c/ERC721AC.sol
pragma solidity ^0.8.4;
/**
* @title ERC721AC
* @author Limit Break, Inc.
* @notice Extends Azuki's ERC721-A implementation with Creator Token functionality, which
* allows the contract owner to update the transfer validation logic by managing a security policy in
* an external transfer validation security policy registry. See {CreatorTokenTransferValidator}.
*/
abstract contract ERC721AC is ERC721A, CreatorTokenBase {
constructor(string memory name_, string memory symbol_) CreatorTokenBase() ERC721A(name_, symbol_) {}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(ICreatorToken).interfaceId || super.supportsInterface(interfaceId);
}
/// @dev Ties the erc721a _beforeTokenTransfers hook to more granular transfer validation logic
function _beforeTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual override {
for (uint256 i = 0; i < quantity;) {
_validateBeforeTransfer(from, to, startTokenId + i);
unchecked {
++i;
}
}
}
/// @dev Ties the erc721a _afterTokenTransfer hook to more granular transfer validation logic
function _afterTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual override {
for (uint256 i = 0; i < quantity;) {
_validateAfterTransfer(from, to, startTokenId + i);
unchecked {
++i;
}
}
}
function _msgSenderERC721A() internal view virtual override returns (address) {
return _msgSender();
}
}
// File: @openzeppelin/contracts/interfaces/IERC2981.sol
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC2981.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface for the NFT Royalty Standard.
*
* A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
* support for royalty payments across all NFT marketplaces and ecosystem participants.
*/
interface IERC2981 is IERC165 {
/**
* @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
* exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
*
* NOTE: ERC-2981 allows setting the royalty to 100% of the price. In that case all the price would be sent to the
* royalty receiver and 0 tokens to the seller. Contracts dealing with royalty should consider empty transfers.
*/
function royaltyInfo(
uint256 tokenId,
uint256 salePrice
) external view returns (address receiver, uint256 royaltyAmount);
}
// File: @openzeppelin/contracts/utils/introspection/ERC165.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
// File: @openzeppelin/contracts/token/common/ERC2981.sol
// OpenZeppelin Contracts (last updated v5.3.0) (token/common/ERC2981.sol)
pragma solidity ^0.8.20;
/**
* @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
*
* Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
* specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
*
* Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
* fee is specified in basis points by default.
*
* IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
* https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the ERC. Marketplaces are expected to
* voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
*/
abstract contract ERC2981 is IERC2981, ERC165 {
struct RoyaltyInfo {
address receiver;
uint96 royaltyFraction;
}
RoyaltyInfo private _defaultRoyaltyInfo;
mapping(uint256 tokenId => RoyaltyInfo) private _tokenRoyaltyInfo;
/**
* @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1).
*/
error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator);
/**
* @dev The default royalty receiver is invalid.
*/
error ERC2981InvalidDefaultRoyaltyReceiver(address receiver);
/**
* @dev The royalty set for a specific `tokenId` is invalid (eg. (numerator / denominator) >= 1).
*/
error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);
/**
* @dev The royalty receiver for `tokenId` is invalid.
*/
error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver);
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @inheritdoc IERC2981
*/
function royaltyInfo(
uint256 tokenId,
uint256 salePrice
) public view virtual returns (address receiver, uint256 amount) {
RoyaltyInfo storage _royaltyInfo = _tokenRoyaltyInfo[tokenId];
address royaltyReceiver = _royaltyInfo.receiver;
uint96 royaltyFraction = _royaltyInfo.royaltyFraction;
if (royaltyReceiver == address(0)) {
royaltyReceiver = _defaultRoyaltyInfo.receiver;
royaltyFraction = _defaultRoyaltyInfo.royaltyFraction;
}
uint256 royaltyAmount = (salePrice * royaltyFraction) / _feeDenominator();
return (royaltyReceiver, royaltyAmount);
}
/**
* @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
* fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
* override.
*/
function _feeDenominator() internal pure virtual returns (uint96) {
return 10000;
}
/**
* @dev Sets the royalty information that all ids in this contract will default to.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
uint256 denominator = _feeDenominator();
if (feeNumerator > denominator) {
// Royalty fee will exceed the sale price
revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator);
}
if (receiver == address(0)) {
revert ERC2981InvalidDefaultRoyaltyReceiver(address(0));
}
_defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Removes default royalty information.
*/
function _deleteDefaultRoyalty() internal virtual {
delete _defaultRoyaltyInfo;
}
/**
* @dev Sets the royalty information for a specific token id, overriding the global default.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/
function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual {
uint256 denominator = _feeDenominator();
if (feeNumerator > denominator) {
// Royalty fee will exceed the sale price
revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator);
}
if (receiver == address(0)) {
revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0));
}
_tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Resets royalty information for the token id back to the global default.
*/
function _resetTokenRoyalty(uint256 tokenId) internal virtual {
delete _tokenRoyaltyInfo[tokenId];
}
}
// File: https://github.com/limitbreakinc/creator-token-contracts/blob/main/contracts/programmable-royalties/BasicRoyalties.sol
pragma solidity ^0.8.4;
/**
* @title BasicRoyaltiesBase
* @author Limit Break, Inc.
* @dev Base functionality of an NFT mix-in contract implementing the most basic form of programmable royalties.
*/
abstract contract BasicRoyaltiesBase is ERC2981 {
event DefaultRoyaltySet(address indexed receiver, uint96 feeNumerator);
event TokenRoyaltySet(uint256 indexed tokenId, address indexed receiver, uint96 feeNumerator);
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual override {
super._setDefaultRoyalty(receiver, feeNumerator);
emit DefaultRoyaltySet(receiver, feeNumerator);
}
function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual override {
super._setTokenRoyalty(tokenId, receiver, feeNumerator);
emit TokenRoyaltySet(tokenId, receiver, feeNumerator);
}
}
/**
* @title BasicRoyalties
* @author Limit Break, Inc.
* @notice Constructable BasicRoyalties Contract implementation.
*/
abstract contract BasicRoyalties is BasicRoyaltiesBase {
constructor(address receiver, uint96 feeNumerator) {
_setDefaultRoyalty(receiver, feeNumerator);
}
}
/**
* @title BasicRoyaltiesInitializable
* @author Limit Break, Inc.
* @notice Initializable BasicRoyalties Contract implementation to allow for EIP-1167 clones.
*/
abstract contract BasicRoyaltiesInitializable is BasicRoyaltiesBase {}
// File: portraitsseries1.sol
/**
*Submitted for verification at Etherscan.io on 2024-04-03
*/
pragma solidity ^0.8.25;
error AlreadyReservedTokens();
error CallerNotOffsetter();
error FunctionLocked();
error InsufficientValue();
error InsufficientMints();
error InsufficientSupply();
error InvalidSignature();
error NoContractMinting();
error ProvenanceHashAlreadySet();
error ProvenanceHashNotSet();
error TokenOffsetAlreadySet();
error TokenOffsetNotSet();
error WithdrawFailed();
interface Offsetable {
function setOffset(uint256 randomness) external;
}
contract Self_Portraits_Vol_One is ERC721AC, BasicRoyalties, Ownable, OwnableBasic {
string private _baseTokenURI;
uint256 public publicMintPrice = 0.08 ether;
uint256 public constant RESERVED = 14;
uint256 public MAX_SUPPLY = 170;
uint256 public mintStartTime;
uint256 public mintDuration;
bool public publicMintActive;
//mappings
mapping(bytes4 => bool) public functionLocked;
mapping(address => bool) public minter;
constructor(address initialOwner, address royaltyReceiver, uint96 royaltyFeeNumerator, address _minter) ERC721AC("Self-Portraits Vol.1", "Self-Portraits Vol.1")
BasicRoyalties(royaltyReceiver, royaltyFeeNumerator) Ownable(initialOwner){
minter[_minter] = true;
}
struct MintConfig {
bool enablePublic;
uint256 durationHours;
uint256 publicPrice;
}
function enableMint(MintConfig calldata config) external onlyOwner {
publicMintActive = config.enablePublic;
if (config.enablePublic) {
mintStartTime = block.timestamp;
mintDuration = config.durationHours * 1 hours;
}
if (config.publicPrice > 0) publicMintPrice = config.publicPrice;
}
modifier lockable() {
if (functionLocked[msg.sig]) revert FunctionLocked();
_;
}
modifier onlyMinter() {
require(minter[msg.sender] == true, "You're not a minter");
_;
}
function reserve(address to) external lockable onlyOwner {
if (_totalMinted() >= RESERVED) revert AlreadyReservedTokens();
_mint(to, RESERVED);
}
function secondaryReserve(address to, uint256 _quantity) external onlyOwner {
require(_totalMinted() + _quantity <= MAX_SUPPLY, "supply exceed");
_mint(to, _quantity);
}
function cardMint(address to, uint256 _quantity) external onlyMinter {
require(
block.timestamp <= mintStartTime + mintDuration,
"Minting period ended"
);
require(_totalMinted() + _quantity <= MAX_SUPPLY, "supply exceed");
_mint(to, _quantity);
}
function publicMint(address to, uint256 _quantity) external payable {
require(
publicMintActive && block.timestamp <= mintStartTime + mintDuration,
"Public minting inactive or ended"
);
require(_totalMinted() + _quantity <= MAX_SUPPLY, "supply exceed");
uint256 totalCost = _quantity * publicMintPrice;
require(msg.value >= totalCost, "Insufficient ETH");
_mint(to, _quantity);
if (msg.value > totalCost) {
payable(msg.sender).transfer(msg.value - totalCost);
}
}
function setMaxSupply(uint256 _newsupply) public onlyOwner{
MAX_SUPPLY = _newsupply;
}
function setDefaultRoyalty(address receiver, uint96 feeNumerator) public onlyOwner{
_requireCallerIsContractOwner();
_setDefaultRoyalty(receiver, feeNumerator);
}
function setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) public onlyOwner{
_requireCallerIsContractOwner();
_setTokenRoyalty(tokenId, receiver, feeNumerator);
}
function assignMinterRole(address _minter) external onlyOwner {
minter[_minter] = true;
}
function revokeMinterRole(address _minter) external onlyOwner {
minter[_minter] = false;
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721AC, ERC2981)
returns (bool)
{
return
ERC721AC.supportsInterface(interfaceId);
}
function _baseURI() internal view virtual override returns (string memory) {
return _baseTokenURI;
}
function tokenURI(uint256 tokenId)
public
view
virtual
override
returns (string memory)
{
require(
_exists(tokenId),
"ERC721Metadata: URI query for nonexistent token"
);
string memory currentBaseURI = _baseURI();
return
bytes(currentBaseURI).length > 0
? string(
abi.encodePacked(
currentBaseURI,
Strings.toString(tokenId)
)
)
: "";
}
function numberMinted(address account) external view returns (uint256) {
return _numberMinted(account);
}
function lockFunction(bytes4 id) external onlyOwner {
functionLocked[id] = true;
}
function setBaseURI(string calldata _newBaseURI)
external
lockable
onlyOwner
{
_baseTokenURI = _newBaseURI;
}
function withdraw() external onlyOwner {
(bool success, ) = payable(msg.sender).call{
value: address(this).balance
}("");
if (!success) revert WithdrawFailed();
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"address","name":"royaltyReceiver","type":"address"},{"internalType":"uint96","name":"royaltyFeeNumerator","type":"uint96"},{"internalType":"address","name":"_minter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyReservedTokens","type":"error"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"CreatorTokenBase__InvalidTransferValidatorContract","type":"error"},{"inputs":[],"name":"CreatorTokenBase__SetTransferValidatorFirst","type":"error"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"inputs":[],"name":"FunctionLocked","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"NotCompatibleWithSpotMints","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"SequentialMintExceedsLimit","type":"error"},{"inputs":[],"name":"SequentialUpToTooSmall","type":"error"},{"inputs":[],"name":"ShouldNotMintToBurnAddress","type":"error"},{"inputs":[],"name":"SpotMintTokenIdTooSmall","type":"error"},{"inputs":[],"name":"TokenAlreadyExists","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"WithdrawFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"DefaultRoyaltySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"TokenRoyaltySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldValidator","type":"address"},{"indexed":false,"internalType":"address","name":"newValidator","type":"address"}],"name":"TransferValidatorUpdated","type":"event"},{"inputs":[],"name":"DEFAULT_OPERATOR_WHITELIST_ID","outputs":[{"internalType":"uint120","name":"","type":"uint120"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_TRANSFER_SECURITY_LEVEL","outputs":[{"internalType":"enum TransferSecurityLevels","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_TRANSFER_VALIDATOR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESERVED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"assignMinterRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"cardMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"enablePublic","type":"bool"},{"internalType":"uint256","name":"durationHours","type":"uint256"},{"internalType":"uint256","name":"publicPrice","type":"uint256"}],"internalType":"struct Self_Portraits_Vol_One.MintConfig","name":"config","type":"tuple"}],"name":"enableMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"functionLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPermittedContractReceivers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSecurityPolicy","outputs":[{"components":[{"internalType":"enum TransferSecurityLevels","name":"transferSecurityLevel","type":"uint8"},{"internalType":"uint120","name":"operatorWhitelistId","type":"uint120"},{"internalType":"uint120","name":"permittedContractReceiversId","type":"uint120"}],"internalType":"struct CollectionSecurityPolicy","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransferValidator","outputs":[{"internalType":"contract ICreatorTokenTransferValidator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWhitelistedOperators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"isContractReceiverPermitted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isOperatorWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"isTransferAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"id","type":"bytes4"}],"name":"lockFunction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"minter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"numberMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"publicMintActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicMintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"reserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"revokeMinterRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"secondaryReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newBaseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newsupply","type":"uint256"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum TransferSecurityLevels","name":"level","type":"uint8"},{"internalType":"uint120","name":"operatorWhitelistId","type":"uint120"},{"internalType":"uint120","name":"permittedContractReceiversAllowlistId","type":"uint120"}],"name":"setToCustomSecurityPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"validator","type":"address"},{"internalType":"enum TransferSecurityLevels","name":"level","type":"uint8"},{"internalType":"uint120","name":"operatorWhitelistId","type":"uint120"},{"internalType":"uint120","name":"permittedContractReceiversAllowlistId","type":"uint120"}],"name":"setToCustomValidatorAndSecurityPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setToDefaultSecurityPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setTokenRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"transferValidator_","type":"address"}],"name":"setTransferValidator","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":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405267011c37937e080000600e5560aa600f55348015610020575f5ffd5b506040516163d83803806163d8833981810160405281019061004291906105b8565b8383836040518060400160405280601481526020017f53656c662d506f7274726169747320566f6c2e310000000000000000000000008152506040518060400160405280601481526020017f53656c662d506f7274726169747320566f6c2e31000000000000000000000000815250818181600290816100c29190610859565b5080600390816100d29190610859565b506100e161021360201b60201c565b5f819055506100f461021360201b60201c565b61010261021b60201b60201c565b101561011f5761011e63fed8210f60e01b61024260201b60201c565b5b50505050610133828261024a60201b60201c565b50505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036101a5575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161019c9190610937565b60405180910390fd5b6101b4816102ac60201b60201c565b50600160145f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550505050506109de565b5f6001905090565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b805f5260045ffd5b61025a828261036f60201b60201c565b8173ffffffffffffffffffffffffffffffffffffffff167f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef826040516102a0919061095f565b60405180910390a25050565b5f600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f61037e61051060201b60201c565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff1611156103e35781816040517f6f483d090000000000000000000000000000000000000000000000000000000081526004016103da9291906109b7565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610453575f6040517fb6d9900a00000000000000000000000000000000000000000000000000000000815260040161044a9190610937565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff16815250600a5f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f612710905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6105468261051d565b9050919050565b6105568161053c565b8114610560575f5ffd5b50565b5f815190506105718161054d565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b61059781610577565b81146105a1575f5ffd5b50565b5f815190506105b28161058e565b92915050565b5f5f5f5f608085870312156105d0576105cf610519565b5b5f6105dd87828801610563565b94505060206105ee87828801610563565b93505060406105ff878288016105a4565b925050606061061087828801610563565b91505092959194509250565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061069757607f821691505b6020821081036106aa576106a9610653565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261070c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826106d1565b61071686836106d1565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f61075a6107556107508461072e565b610737565b61072e565b9050919050565b5f819050919050565b61077383610740565b61078761077f82610761565b8484546106dd565b825550505050565b5f5f905090565b61079e61078f565b6107a981848461076a565b505050565b5b818110156107cc576107c15f82610796565b6001810190506107af565b5050565b601f821115610811576107e2816106b0565b6107eb846106c2565b810160208510156107fa578190505b61080e610806856106c2565b8301826107ae565b50505b505050565b5f82821c905092915050565b5f6108315f1984600802610816565b1980831691505092915050565b5f6108498383610822565b9150826002028217905092915050565b6108628261061c565b67ffffffffffffffff81111561087b5761087a610626565b5b6108858254610680565b6108908282856107d0565b5f60209050601f8311600181146108c1575f84156108af578287015190505b6108b9858261083e565b865550610920565b601f1984166108cf866106b0565b5f5b828110156108f6578489015182556001820191506020850194506020810190506108d1565b86831015610913578489015161090f601f891682610822565b8355505b6001600288020188555050505b505050505050565b6109318161053c565b82525050565b5f60208201905061094a5f830184610928565b92915050565b61095981610577565b82525050565b5f6020820190506109725f830184610950565b92915050565b5f61099261098d61098884610577565b610737565b61072e565b9050919050565b6109a281610978565b82525050565b6109b18161072e565b82525050565b5f6040820190506109ca5f830185610999565b6109d760208301846109a8565b9392505050565b6159ed806109eb5f395ff3fe608060405260043610610334575f3560e01c80636f8b44b0116101aa578063b67c25a3116100f6578063d007af5c11610094578063e75179a41161006e578063e75179a414610ba9578063e985e9c514610bd1578063f2fde38b14610c0d578063fd762d9214610c3557610334565b8063d007af5c14610b19578063dc33e68114610b43578063dc53fd9214610b7f57610334565b8063be537f43116100d0578063be537f4314610a6f578063c25dff9c14610a99578063c87b56dd14610ac1578063ce6df2b914610afd57610334565b8063b67c25a3146109ed578063b88d4fde14610a17578063bbadfe7614610a3357610334565b806395d89b4111610163578063a83ef5151161013d578063a83ef51514610949578063a9fc664e14610973578063aa592f251461099b578063b366d613146109c557610334565b806395d89b41146108bb5780639d645a44146108e5578063a22cb4651461092157610334565b80636f8b44b0146107c557806370a08231146107ed578063715018a61461082957806374d0101d1461083f5780638da5cb5b14610867578063931e2e491461089157610334565b806332cb6b0c1161028457806355f804b31161022257806361347162116101fc57806361347162146107235780636352211e1461074b57806369e2f0fb146107875780636c3b8699146107af57610334565b806355f804b3146106a95780635944c753146106d15780635d4c1d46146106f957610334565b80633dd08c381161025e5780633dd08c38146105ff57806342842e0e1461063b578063495c8bf9146106575780634f9d2c0c1461068157610334565b806332cb6b0c1461059757806334531828146105c15780633ccfd60b146105e957610334565b8063098144d4116102f15780631c33b328116102cb5780631c33b328146104d857806323b872dd146105025780632a55205a1461051e5780632e8da8291461055b57610334565b8063098144d41461044857806318160ddd146104725780631b25b0771461049c57610334565b8063014635461461033857806301ffc9a71461036257806304634d8d1461039e57806306fdde03146103c6578063081812fc146103f0578063095ea7b31461042c575b5f5ffd5b348015610343575f5ffd5b5061034c610c5d565b6040516103599190614242565b60405180910390f35b34801561036d575f5ffd5b50610388600480360381019061038391906142c1565b610c73565b6040516103959190614306565b60405180910390f35b3480156103a9575f5ffd5b506103c460048036038101906103bf919061438a565b610c84565b005b3480156103d1575f5ffd5b506103da610ca2565b6040516103e79190614438565b60405180910390f35b3480156103fb575f5ffd5b506104166004803603810190610411919061448b565b610d32565b6040516104239190614242565b60405180910390f35b610446600480360381019061044191906144b6565b610d8b565b005b348015610453575f5ffd5b5061045c610d9b565b604051610469919061454f565b60405180910390f35b34801561047d575f5ffd5b50610486610dc3565b6040516104939190614577565b60405180910390f35b3480156104a7575f5ffd5b506104c260048036038101906104bd9190614590565b610e0e565b6040516104cf9190614306565b60405180910390f35b3480156104e3575f5ffd5b506104ec610f09565b6040516104f99190614653565b60405180910390f35b61051c6004803603810190610517919061466c565b610f0e565b005b348015610529575f5ffd5b50610544600480360381019061053f91906146bc565b6111b9565b6040516105529291906146fa565b60405180910390f35b348015610566575f5ffd5b50610581600480360381019061057c9190614721565b6112db565b60405161058e9190614306565b60405180910390f35b3480156105a2575f5ffd5b506105ab611477565b6040516105b89190614577565b60405180910390f35b3480156105cc575f5ffd5b506105e760048036038101906105e291906142c1565b61147d565b005b3480156105f4575f5ffd5b506105fd6114ef565b005b34801561060a575f5ffd5b5061062560048036038101906106209190614721565b611599565b6040516106329190614306565b60405180910390f35b6106556004803603810190610650919061466c565b6115b6565b005b348015610662575f5ffd5b5061066b6115d5565b6040516106789190614803565b60405180910390f35b34801561068c575f5ffd5b506106a760048036038101906106a291906144b6565b6117b9565b005b3480156106b4575f5ffd5b506106cf60048036038101906106ca9190614884565b611900565b005b3480156106dc575f5ffd5b506106f760048036038101906106f291906148cf565b6119d4565b005b348015610704575f5ffd5b5061070d6119f4565b60405161071a9190614948565b60405180910390f35b34801561072e575f5ffd5b50610749600480360381019061074491906149ae565b6119f9565b005b348015610756575f5ffd5b50610771600480360381019061076c919061448b565b611baf565b60405161077e9190614242565b60405180910390f35b348015610792575f5ffd5b506107ad60048036038101906107a89190614721565b611bc0565b005b3480156107ba575f5ffd5b506107c3611c1f565b005b3480156107d0575f5ffd5b506107eb60048036038101906107e6919061448b565b611d3a565b005b3480156107f8575f5ffd5b50610813600480360381019061080e9190614721565b611d4c565b6040516108209190614577565b60405180910390f35b348015610834575f5ffd5b5061083d611de0565b005b34801561084a575f5ffd5b50610865600480360381019061086091906144b6565b611df3565b005b348015610872575f5ffd5b5061087b611e60565b6040516108889190614242565b60405180910390f35b34801561089c575f5ffd5b506108a5611e88565b6040516108b29190614577565b60405180910390f35b3480156108c6575f5ffd5b506108cf611e8e565b6040516108dc9190614438565b60405180910390f35b3480156108f0575f5ffd5b5061090b60048036038101906109069190614721565b611f1e565b6040516109189190614306565b60405180910390f35b34801561092c575f5ffd5b5061094760048036038101906109429190614a28565b6120ba565b005b348015610954575f5ffd5b5061095d6121c0565b60405161096a9190614577565b60405180910390f35b34801561097e575f5ffd5b5061099960048036038101906109949190614721565b6121c6565b005b3480156109a6575f5ffd5b506109af61237e565b6040516109bc9190614577565b60405180910390f35b3480156109d0575f5ffd5b506109eb60048036038101906109e69190614721565b612383565b005b3480156109f8575f5ffd5b50610a016123e3565b604051610a0e9190614306565b60405180910390f35b610a316004803603810190610a2c9190614b8e565b6123f5565b005b348015610a3e575f5ffd5b50610a596004803603810190610a5491906142c1565b612446565b604051610a669190614306565b60405180910390f35b348015610a7a575f5ffd5b50610a83612463565b604051610a909190614c6c565b60405180910390f35b348015610aa4575f5ffd5b50610abf6004803603810190610aba9190614ca7565b6125b4565b005b348015610acc575f5ffd5b50610ae76004803603810190610ae2919061448b565b612638565b604051610af49190614438565b60405180910390f35b610b176004803603810190610b1291906144b6565b6126dc565b005b348015610b24575f5ffd5b50610b2d612857565b604051610b3a9190614803565b60405180910390f35b348015610b4e575f5ffd5b50610b696004803603810190610b649190614721565b612a3b565b604051610b769190614577565b60405180910390f35b348015610b8a575f5ffd5b50610b93612a4c565b604051610ba09190614577565b60405180910390f35b348015610bb4575f5ffd5b50610bcf6004803603810190610bca9190614721565b612a52565b005b348015610bdc575f5ffd5b50610bf76004803603810190610bf29190614cd2565b612b5f565b604051610c049190614306565b60405180910390f35b348015610c18575f5ffd5b50610c336004803603810190610c2e9190614721565b612bed565b005b348015610c40575f5ffd5b50610c5b6004803603810190610c569190614d10565b612c71565b005b71721c310194ccfc01e523fc93c9cccfa2a0ac81565b5f610c7d82612dc0565b9050919050565b610c8c612e39565b610c94612ec0565b610c9e8282612eca565b5050565b606060028054610cb190614da1565b80601f0160208091040260200160405190810160405280929190818152602001828054610cdd90614da1565b8015610d285780601f10610cff57610100808354040283529160200191610d28565b820191905f5260205f20905b815481529060010190602001808311610d0b57829003601f168201915b5050505050905090565b5f610d3c82612f26565b610d5157610d5063cf4700e460e01b612fc9565b5b60065f8381526020019081526020015f205f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610d9782826001612fd1565b5050565b5f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f610dcc6130fb565b6001545f54030390507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610dfe613103565b14610e0b57600854810190505b90565b5f5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610efd5760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663285fb8c88585856040518463ffffffff1660e01b8152600401610ec193929190614dd1565b5f6040518083038186803b158015610ed7575f5ffd5b505afa925050508015610ee8575060015b610ef4575f9050610f02565b60019050610f02565b600190505b9392505050565b600181565b5f610f188261312a565b905073ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161693508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610f8d57610f8c63a114810060e01b612fc9565b5b5f5f610f9884613239565b91509150610fae8187610fa961325c565b61326a565b610fd957610fc386610fbe61325c565b612b5f565b610fd857610fd76359c896be60e01b612fc9565b5b5b610fe686868660016132ad565b8015610ff0575f82555b60055f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154600190039190508190555060055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154600101919050819055506110b8856110948888876132e2565b7c020000000000000000000000000000000000000000000000000000000017613309565b60045f8681526020019081526020015f20819055505f7c0200000000000000000000000000000000000000000000000000000000841603611134575f6001850190505f60045f8381526020019081526020015f205403611132575f548114611131578360045f8381526020019081526020015f20819055505b5b505b5f73ffffffffffffffffffffffffffffffffffffffff8673ffffffffffffffffffffffffffffffffffffffff161690508481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f5fa45f81036111a3576111a263ea553b3460e01b612fc9565b5b6111b08787876001613333565b50505050505050565b5f5f5f600b5f8681526020019081526020015f2090505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f825f0160149054906101000a90046bffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361128d57600a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150600a5f0160149054906101000a90046bffffffffffffffffffffffff1690505b5f611296613368565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff16886112be9190614e33565b6112c89190614ea1565b9050828195509550505050509250929050565b5f5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461146e5760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d72dde5e60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b81526004016113c79190614242565b606060405180830381865afa1580156113e2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114069190614f5e565b60200151846040518363ffffffff1660e01b8152600401611428929190614f89565b602060405180830381865afa158015611443573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114679190614fc4565b9050611472565b5f90505b919050565b600f5481565b611485612e39565b600160135f837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f6101000a81548160ff02191690831515021790555050565b6114f7612e39565b5f3373ffffffffffffffffffffffffffffffffffffffff164760405161151c9061501c565b5f6040518083038185875af1925050503d805f8114611556576040519150601f19603f3d011682016040523d82523d5f602084013e61155b565b606091505b5050905080611596576040517f750b219c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b6014602052805f5260405f205f915054906101000a900460ff1681565b6115d083838360405180602001604052805f8152506123f5565b505050565b60605f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461176a5760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633fe5df9960095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b81526004016116c29190614242565b606060405180830381865afa1580156116dd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117019190614f5e565b602001516040518263ffffffff1660e01b81526004016117219190614948565b5f60405180830381865afa15801561173b573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906117639190615104565b90506117b6565b5f67ffffffffffffffff81111561178457611783614a6a565b5b6040519080825280602002602001820160405280156117b25781602001602082028036833780820191505090505b5090505b90565b6001151560145f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16151514611849576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161184090615195565b60405180910390fd5b60115460105461185991906151b3565b42111561189b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161189290615230565b60405180910390fd5b600f54816118a7613371565b6118b191906151b3565b11156118f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118e990615298565b60405180910390fd5b6118fc82826133b8565b5050565b60135f5f357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff16156119b6576040517f8bf9b99f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119be612e39565b8181600d91826119cf929190615457565b505050565b6119dc612e39565b6119e4612ec0565b6119ef83838361352c565b505050565b600181565b611a01612ec0565b5f611a0a610d9b565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611a71576040517f39ffc7ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663da0194c030866040518363ffffffff1660e01b8152600401611aac929190615524565b5f604051808303815f87803b158015611ac3575f5ffd5b505af1158015611ad5573d5f5f3e3d5ffd5b505050508073ffffffffffffffffffffffffffffffffffffffff16632304aa0230856040518363ffffffff1660e01b8152600401611b1492919061554b565b5f604051808303815f87803b158015611b2b575f5ffd5b505af1158015611b3d573d5f5f3e3d5ffd5b505050508073ffffffffffffffffffffffffffffffffffffffff16638d74431430846040518363ffffffff1660e01b8152600401611b7c92919061554b565b5f604051808303815f87803b158015611b93575f5ffd5b505af1158015611ba5573d5f5f3e3d5ffd5b5050505050505050565b5f611bb98261312a565b9050919050565b611bc8612e39565b5f60145f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555050565b611c27612ec0565b611c4271721c310194ccfc01e523fc93c9cccfa2a0ac6121c6565b71721c310194ccfc01e523fc93c9cccfa2a0ac73ffffffffffffffffffffffffffffffffffffffff1663da0194c03060016040518363ffffffff1660e01b8152600401611c90929190615524565b5f604051808303815f87803b158015611ca7575f5ffd5b505af1158015611cb9573d5f5f3e3d5ffd5b5050505071721c310194ccfc01e523fc93c9cccfa2a0ac73ffffffffffffffffffffffffffffffffffffffff16632304aa023060016040518363ffffffff1660e01b8152600401611d0b92919061554b565b5f604051808303815f87803b158015611d22575f5ffd5b505af1158015611d34573d5f5f3e3d5ffd5b50505050565b611d42612e39565b80600f8190555050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611d9157611d90638f4eb60460e01b612fc9565b5b67ffffffffffffffff60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054169050919050565b611de8612e39565b611df15f61358b565b565b611dfb612e39565b600f5481611e07613371565b611e1191906151b3565b1115611e52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e4990615298565b60405180910390fd5b611e5c82826133b8565b5050565b5f600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60105481565b606060038054611e9d90614da1565b80601f0160208091040260200160405190810160405280929190818152602001828054611ec990614da1565b8015611f145780601f10611eeb57610100808354040283529160200191611f14565b820191905f5260205f20905b815481529060010190602001808311611ef757829003601f168201915b5050505050905090565b5f5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146120b15760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639445f53060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b815260040161200a9190614242565b606060405180830381865afa158015612025573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120499190614f5e565b60400151846040518363ffffffff1660e01b815260040161206b929190614f89565b602060405180830381865afa158015612086573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120aa9190614fc4565b90506120b5565b5f90505b919050565b8060075f6120c661325c565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1661216f61325c565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516121b49190614306565b60405180910390a35050565b60115481565b6121ce612ec0565b5f5f90505f8273ffffffffffffffffffffffffffffffffffffffff163b111561226f578173ffffffffffffffffffffffffffffffffffffffff166301ffc9a75f6040518263ffffffff1660e01b815260040161222a9190615581565b602060405180830381865afa92505050801561226457506040513d601f19601f820116820180604052508101906122619190614fc4565b60015b1561226e57809150505b5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156122a9575080155b156122e0576040517f32483afb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fcc5dc080ff977b3c3a211fa63ab74f90f658f5ba9d3236e92c8f59570f442aac60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168360405161233292919061559a565b60405180910390a18160095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600e81565b61238b612e39565b600160145f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555050565b60125f9054906101000a900460ff1681565b612400848484610f0e565b5f8373ffffffffffffffffffffffffffffffffffffffff163b146124405761242a8484848461364e565b61243f5761243e63d1a57ed660e01b612fc9565b5b5b50505050565b6013602052805f5260405f205f915054906101000a900460ff1681565b61246b6141b1565b5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461255f5760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b81526004016125199190614242565b606060405180830381865afa158015612534573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125589190614f5e565b90506125b1565b60405180606001604052805f600681111561257d5761257c6145e0565b5b81526020015f6effffffffffffffffffffffffffffff1681526020015f6effffffffffffffffffffffffffffff1681525090505b90565b6125bc612e39565b805f0160208101906125ce91906155c1565b60125f6101000a81548160ff021916908315150217905550805f0160208101906125f891906155c1565b1561261d5742601081905550610e1081602001356126169190614e33565b6011819055505b5f81604001351115612635578060400135600e819055505b50565b606061264382612f26565b612682576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126799061565c565b60405180910390fd5b5f61268b613778565b90505f8151116126a95760405180602001604052805f8152506126d4565b806126b384613808565b6040516020016126c49291906156b4565b6040516020818303038152906040525b915050919050565b60125f9054906101000a900460ff168015612706575060115460105461270291906151b3565b4211155b612745576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161273c90615721565b60405180910390fd5b600f5481612751613371565b61275b91906151b3565b111561279c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161279390615298565b60405180910390fd5b5f600e54826127ab9190614e33565b9050803410156127f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127e790615789565b60405180910390fd5b6127fa83836133b8565b80341115612852573373ffffffffffffffffffffffffffffffffffffffff166108fc823461282891906157a7565b90811502906040515f60405180830381858888f19350505050158015612850573d5f5f3e3d5ffd5b505b505050565b60605f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146129ec5760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166317e94a6c60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b81526004016129449190614242565b606060405180830381865afa15801561295f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129839190614f5e565b604001516040518263ffffffff1660e01b81526004016129a39190614948565b5f60405180830381865afa1580156129bd573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906129e59190615104565b9050612a38565b5f67ffffffffffffffff811115612a0657612a05614a6a565b5b604051908082528060200260200182016040528015612a345781602001602082028036833780820191505090505b5090505b90565b5f612a45826138d2565b9050919050565b600e5481565b60135f5f357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff1615612b08576040517f8bf9b99f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b10612e39565b600e612b1a613371565b10612b51576040517f1f0f14ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b5c81600e6133b8565b50565b5f60075f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b612bf5612e39565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612c65575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401612c5c9190614242565b60405180910390fd5b612c6e8161358b565b50565b612c79612ec0565b612c82846121c6565b8373ffffffffffffffffffffffffffffffffffffffff1663da0194c030856040518363ffffffff1660e01b8152600401612cbd929190615524565b5f604051808303815f87803b158015612cd4575f5ffd5b505af1158015612ce6573d5f5f3e3d5ffd5b505050508373ffffffffffffffffffffffffffffffffffffffff16632304aa0230846040518363ffffffff1660e01b8152600401612d2592919061554b565b5f604051808303815f87803b158015612d3c575f5ffd5b505af1158015612d4e573d5f5f3e3d5ffd5b505050508373ffffffffffffffffffffffffffffffffffffffff16638d74431430836040518363ffffffff1660e01b8152600401612d8d92919061554b565b5f604051808303815f87803b158015612da4575f5ffd5b505af1158015612db6573d5f5f3e3d5ffd5b5050505050505050565b5f7f86455d28000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612e325750612e3182613926565b5b9050919050565b612e416139b7565b73ffffffffffffffffffffffffffffffffffffffff16612e5f611e60565b73ffffffffffffffffffffffffffffffffffffffff1614612ebe57612e826139b7565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401612eb59190614242565b60405180910390fd5b565b612ec8612e39565b565b612ed482826139be565b8173ffffffffffffffffffffffffffffffffffffffff167f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef82604051612f1a91906157e9565b60405180910390a25050565b5f81612f306130fb565b11612fc357612f3d613103565b821115612f6557612f5e60045f8481526020019081526020015f2054613b59565b9050612fc4565b5f54821015612fc2575f5b5f60045f8581526020019081526020015f205491508103612f9c5782612f9590615802565b9250612f70565b5f7c01000000000000000000000000000000000000000000000000000000008216149150505b5b5b919050565b805f5260045ffd5b5f612fdb83611baf565b905081801561301d57508073ffffffffffffffffffffffffffffffffffffffff1661300461325c565b73ffffffffffffffffffffffffffffffffffffffff1614155b15613049576130338161302e61325c565b612b5f565b6130485761304763cfb3b94260e01b612fc9565b5b5b8360065f8581526020019081526020015f205f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a450505050565b5f6001905090565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b5f816131346130fb565b116132235760045f8381526020019081526020015f20549050613155613103565b82111561317a5761316581613b59565b6132345761317963df2d9b4260e01b612fc9565b5b5f81036131fb575f54821061319a5761319963df2d9b4260e01b612fc9565b5b5b60045f836001900393508381526020019081526020015f205490505f8103156131f6575f7c010000000000000000000000000000000000000000000000000000000082160315613234576131f563df2d9b4260e01b612fc9565b5b61319b565b5f7c010000000000000000000000000000000000000000000000000000000082160315613234575b61323363df2d9b4260e01b612fc9565b5b919050565b5f5f5f60065f8581526020019081526020015f2090508092508254915050915091565b5f6132656139b7565b905090565b5f73ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b5f5f90505b818110156132db576132d0858583866132cb91906151b3565b613b99565b8060010190506132b2565b5050505050565b5f5f60e883901c905060e86132f8868684613c97565b62ffffff16901b9150509392505050565b5f73ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b5f5f90505b81811015613361576133568585838661335191906151b3565b613c9f565b806001019050613338565b5050505050565b5f612710905090565b5f61337a6130fb565b5f540390507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6133a8613103565b146133b557600854810190505b90565b5f5f5490505f82036133d5576133d463b562e8dd60e01b612fc9565b5b6133e15f8483856132ad565b6133ff836133f05f865f6132e2565b6133f985613d9d565b17613309565b60045f8381526020019081526020015f2081905550600160406001901b17820260055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505f73ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161690505f81036134b0576134af632e07630060e01b612fc9565b5b5f83830190505f8390506134c2613103565b6001830311156134dd576134dc6381647e3a60e01b612fc9565b5b5b80835f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f5fa48181600101915081036134de57815f819055505050506135275f848385613333565b505050565b613537838383613dac565b8173ffffffffffffffffffffffffffffffffffffffff16837f7f5b076c952c0ec86e5425963c1326dd0f03a3595c19f81d765e8ff559a6e33c8360405161357e91906157e9565b60405180910390a3505050565b5f600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f8373ffffffffffffffffffffffffffffffffffffffff1663150b7a0261367361325c565b8786866040518563ffffffff1660e01b8152600401613695949392919061587b565b6020604051808303815f875af19250505080156136d057506040513d601f19601f820116820180604052508101906136cd91906158d9565b60015b613725573d805f81146136fe576040519150601f19603f3d011682016040523d82523d5f602084013e613703565b606091505b505f81510361371d5761371c63d1a57ed660e01b612fc9565b5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b6060600d805461378790614da1565b80601f01602080910402602001604051908101604052809291908181526020018280546137b390614da1565b80156137fe5780601f106137d5576101008083540402835291602001916137fe565b820191905f5260205f20905b8154815290600101906020018083116137e157829003601f168201915b5050505050905090565b60605f600161381684613f5b565b0190505f8167ffffffffffffffff81111561383457613833614a6a565b5b6040519080825280601f01601f1916602001820160405280156138665781602001600182028036833780820191505090505b5090505f82602001820190505b6001156138c7578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85816138bc576138bb614e74565b5b0494505f8503613873575b819350505050919050565b5f67ffffffffffffffff604060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054901c169050919050565b5f6301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061398057506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806139b05750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b5f33905090565b5f6139c7613368565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff161115613a2c5781816040517f6f483d09000000000000000000000000000000000000000000000000000000008152600401613a23929190615934565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603613a9c575f6040517fb6d9900a000000000000000000000000000000000000000000000000000000008152600401613a939190614242565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff16815250600a5f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f7c0100000000000000000000000000000000000000000000000000000000821673ffffffffffffffffffffffffffffffffffffffff8316119050919050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161490505f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16149050818015613c075750805b15613c3e576040517f5cbd944100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8115613c5c57613c57613c4f6139b7565b8585346140ac565b613c90565b8015613c7a57613c75613c6d6139b7565b8685346140b2565b613c8f565b613c8e613c856139b7565b868686346140b8565b5b5b5050505050565b5f9392505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161490505f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16149050818015613d0d5750805b15613d44576040517f5cbd944100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8115613d6257613d5d613d556139b7565b85853461419e565b613d96565b8015613d8057613d7b613d736139b7565b8685346141a4565b613d95565b613d94613d8b6139b7565b868686346141aa565b5b5b5050505050565b5f6001821460e11b9050919050565b5f613db5613368565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff161115613e1c578382826040517fdfd1fc1b000000000000000000000000000000000000000000000000000000008152600401613e139392919061595b565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603613e8e57835f6040517f969f0852000000000000000000000000000000000000000000000000000000008152600401613e85929190615990565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff16815250600b5f8681526020019081526020015f205f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555090505050505050565b5f5f5f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310613fb7577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381613fad57613fac614e74565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310613ff4576d04ee2d6d415b85acef81000000008381613fea57613fe9614e74565b5b0492506020810190505b662386f26fc10000831061402357662386f26fc10000838161401957614018614e74565b5b0492506010810190505b6305f5e100831061404c576305f5e100838161404257614041614e74565b5b0492506008810190505b612710831061407157612710838161406757614066614e74565b5b0492506004810190505b60648310614094576064838161408a57614089614e74565b5b0492506002810190505b600a83106140a3576001810190505b80915050919050565b50505050565b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146141975760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663285fb8c88686866040518463ffffffff1660e01b815260040161416a93929190614dd1565b5f6040518083038186803b158015614180575f5ffd5b505afa158015614192573d5f5f3e3d5ffd5b505050505b5050505050565b50505050565b50505050565b5050505050565b60405180606001604052805f60068111156141cf576141ce6145e0565b5b81526020015f6effffffffffffffffffffffffffffff1681526020015f6effffffffffffffffffffffffffffff1681525090565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61422c82614203565b9050919050565b61423c81614222565b82525050565b5f6020820190506142555f830184614233565b92915050565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6142a08161426c565b81146142aa575f5ffd5b50565b5f813590506142bb81614297565b92915050565b5f602082840312156142d6576142d5614264565b5b5f6142e3848285016142ad565b91505092915050565b5f8115159050919050565b614300816142ec565b82525050565b5f6020820190506143195f8301846142f7565b92915050565b61432881614222565b8114614332575f5ffd5b50565b5f813590506143438161431f565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b61436981614349565b8114614373575f5ffd5b50565b5f8135905061438481614360565b92915050565b5f5f604083850312156143a05761439f614264565b5b5f6143ad85828601614335565b92505060206143be85828601614376565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61440a826143c8565b61441481856143d2565b93506144248185602086016143e2565b61442d816143f0565b840191505092915050565b5f6020820190508181035f8301526144508184614400565b905092915050565b5f819050919050565b61446a81614458565b8114614474575f5ffd5b50565b5f8135905061448581614461565b92915050565b5f602082840312156144a05761449f614264565b5b5f6144ad84828501614477565b91505092915050565b5f5f604083850312156144cc576144cb614264565b5b5f6144d985828601614335565b92505060206144ea85828601614477565b9150509250929050565b5f819050919050565b5f61451761451261450d84614203565b6144f4565b614203565b9050919050565b5f614528826144fd565b9050919050565b5f6145398261451e565b9050919050565b6145498161452f565b82525050565b5f6020820190506145625f830184614540565b92915050565b61457181614458565b82525050565b5f60208201905061458a5f830184614568565b92915050565b5f5f5f606084860312156145a7576145a6614264565b5b5f6145b486828701614335565b93505060206145c586828701614335565b92505060406145d686828701614335565b9150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6007811061461e5761461d6145e0565b5b50565b5f81905061462e8261460d565b919050565b5f61463d82614621565b9050919050565b61464d81614633565b82525050565b5f6020820190506146665f830184614644565b92915050565b5f5f5f6060848603121561468357614682614264565b5b5f61469086828701614335565b93505060206146a186828701614335565b92505060406146b286828701614477565b9150509250925092565b5f5f604083850312156146d2576146d1614264565b5b5f6146df85828601614477565b92505060206146f085828601614477565b9150509250929050565b5f60408201905061470d5f830185614233565b61471a6020830184614568565b9392505050565b5f6020828403121561473657614735614264565b5b5f61474384828501614335565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61477e81614222565b82525050565b5f61478f8383614775565b60208301905092915050565b5f602082019050919050565b5f6147b18261474c565b6147bb8185614756565b93506147c683614766565b805f5b838110156147f65781516147dd8882614784565b97506147e88361479b565b9250506001810190506147c9565b5085935050505092915050565b5f6020820190508181035f83015261481b81846147a7565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f84011261484457614843614823565b5b8235905067ffffffffffffffff81111561486157614860614827565b5b60208301915083600182028301111561487d5761487c61482b565b5b9250929050565b5f5f6020838503121561489a57614899614264565b5b5f83013567ffffffffffffffff8111156148b7576148b6614268565b5b6148c38582860161482f565b92509250509250929050565b5f5f5f606084860312156148e6576148e5614264565b5b5f6148f386828701614477565b935050602061490486828701614335565b925050604061491586828701614376565b9150509250925092565b5f6effffffffffffffffffffffffffffff82169050919050565b6149428161491f565b82525050565b5f60208201905061495b5f830184614939565b92915050565b6007811061496d575f5ffd5b50565b5f8135905061497e81614961565b92915050565b61498d8161491f565b8114614997575f5ffd5b50565b5f813590506149a881614984565b92915050565b5f5f5f606084860312156149c5576149c4614264565b5b5f6149d286828701614970565b93505060206149e38682870161499a565b92505060406149f48682870161499a565b9150509250925092565b614a07816142ec565b8114614a11575f5ffd5b50565b5f81359050614a22816149fe565b92915050565b5f5f60408385031215614a3e57614a3d614264565b5b5f614a4b85828601614335565b9250506020614a5c85828601614a14565b9150509250929050565b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b614aa0826143f0565b810181811067ffffffffffffffff82111715614abf57614abe614a6a565b5b80604052505050565b5f614ad161425b565b9050614add8282614a97565b919050565b5f67ffffffffffffffff821115614afc57614afb614a6a565b5b614b05826143f0565b9050602081019050919050565b828183375f83830152505050565b5f614b32614b2d84614ae2565b614ac8565b905082815260208101848484011115614b4e57614b4d614a66565b5b614b59848285614b12565b509392505050565b5f82601f830112614b7557614b74614823565b5b8135614b85848260208601614b20565b91505092915050565b5f5f5f5f60808587031215614ba657614ba5614264565b5b5f614bb387828801614335565b9450506020614bc487828801614335565b9350506040614bd587828801614477565b925050606085013567ffffffffffffffff811115614bf657614bf5614268565b5b614c0287828801614b61565b91505092959194509250565b614c1781614633565b82525050565b614c268161491f565b82525050565b606082015f820151614c405f850182614c0e565b506020820151614c536020850182614c1d565b506040820151614c666040850182614c1d565b50505050565b5f606082019050614c7f5f830184614c2c565b92915050565b5f5ffd5b5f60608284031215614c9e57614c9d614c85565b5b81905092915050565b5f60608284031215614cbc57614cbb614264565b5b5f614cc984828501614c89565b91505092915050565b5f5f60408385031215614ce857614ce7614264565b5b5f614cf585828601614335565b9250506020614d0685828601614335565b9150509250929050565b5f5f5f5f60808587031215614d2857614d27614264565b5b5f614d3587828801614335565b9450506020614d4687828801614970565b9350506040614d578782880161499a565b9250506060614d688782880161499a565b91505092959194509250565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680614db857607f821691505b602082108103614dcb57614dca614d74565b5b50919050565b5f606082019050614de45f830186614233565b614df16020830185614233565b614dfe6040830184614233565b949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f614e3d82614458565b9150614e4883614458565b9250828202614e5681614458565b91508282048414831517614e6d57614e6c614e06565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f614eab82614458565b9150614eb683614458565b925082614ec657614ec5614e74565b5b828204905092915050565b5f5ffd5b5f81519050614ee381614961565b92915050565b5f81519050614ef781614984565b92915050565b5f60608284031215614f1257614f11614ed1565b5b614f1c6060614ac8565b90505f614f2b84828501614ed5565b5f830152506020614f3e84828501614ee9565b6020830152506040614f5284828501614ee9565b60408301525092915050565b5f60608284031215614f7357614f72614264565b5b5f614f8084828501614efd565b91505092915050565b5f604082019050614f9c5f830185614939565b614fa96020830184614233565b9392505050565b5f81519050614fbe816149fe565b92915050565b5f60208284031215614fd957614fd8614264565b5b5f614fe684828501614fb0565b91505092915050565b5f81905092915050565b50565b5f6150075f83614fef565b915061501282614ff9565b5f82019050919050565b5f61502682614ffc565b9150819050919050565b5f67ffffffffffffffff82111561504a57615049614a6a565b5b602082029050602081019050919050565b5f815190506150698161431f565b92915050565b5f61508161507c84615030565b614ac8565b905080838252602082019050602084028301858111156150a4576150a361482b565b5b835b818110156150cd57806150b9888261505b565b8452602084019350506020810190506150a6565b5050509392505050565b5f82601f8301126150eb576150ea614823565b5b81516150fb84826020860161506f565b91505092915050565b5f6020828403121561511957615118614264565b5b5f82015167ffffffffffffffff81111561513657615135614268565b5b615142848285016150d7565b91505092915050565b7f596f75277265206e6f742061206d696e746572000000000000000000000000005f82015250565b5f61517f6013836143d2565b915061518a8261514b565b602082019050919050565b5f6020820190508181035f8301526151ac81615173565b9050919050565b5f6151bd82614458565b91506151c883614458565b92508282019050808211156151e0576151df614e06565b5b92915050565b7f4d696e74696e6720706572696f6420656e6465640000000000000000000000005f82015250565b5f61521a6014836143d2565b9150615225826151e6565b602082019050919050565b5f6020820190508181035f8301526152478161520e565b9050919050565b7f737570706c7920657863656564000000000000000000000000000000000000005f82015250565b5f615282600d836143d2565b915061528d8261524e565b602082019050919050565b5f6020820190508181035f8301526152af81615276565b9050919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261531c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826152e1565b61532686836152e1565b95508019841693508086168417925050509392505050565b5f61535861535361534e84614458565b6144f4565b614458565b9050919050565b5f819050919050565b6153718361533e565b61538561537d8261535f565b8484546152ed565b825550505050565b5f5f905090565b61539c61538d565b6153a7818484615368565b505050565b5b818110156153ca576153bf5f82615394565b6001810190506153ad565b5050565b601f82111561540f576153e0816152c0565b6153e9846152d2565b810160208510156153f8578190505b61540c615404856152d2565b8301826153ac565b50505b505050565b5f82821c905092915050565b5f61542f5f1984600802615414565b1980831691505092915050565b5f6154478383615420565b9150826002028217905092915050565b61546183836152b6565b67ffffffffffffffff81111561547a57615479614a6a565b5b6154848254614da1565b61548f8282856153ce565b5f601f8311600181146154bc575f84156154aa578287013590505b6154b4858261543c565b86555061551b565b601f1984166154ca866152c0565b5f5b828110156154f1578489013582556001820191506020850194506020810190506154cc565b8683101561550e578489013561550a601f891682615420565b8355505b6001600288020188555050505b50505050505050565b5f6040820190506155375f830185614233565b6155446020830184614644565b9392505050565b5f60408201905061555e5f830185614233565b61556b6020830184614939565b9392505050565b61557b8161426c565b82525050565b5f6020820190506155945f830184615572565b92915050565b5f6040820190506155ad5f830185614233565b6155ba6020830184614233565b9392505050565b5f602082840312156155d6576155d5614264565b5b5f6155e384828501614a14565b91505092915050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f5f8201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b5f615646602f836143d2565b9150615651826155ec565b604082019050919050565b5f6020820190508181035f8301526156738161563a565b9050919050565b5f81905092915050565b5f61568e826143c8565b615698818561567a565b93506156a88185602086016143e2565b80840191505092915050565b5f6156bf8285615684565b91506156cb8284615684565b91508190509392505050565b7f5075626c6963206d696e74696e6720696e616374697665206f7220656e6465645f82015250565b5f61570b6020836143d2565b9150615716826156d7565b602082019050919050565b5f6020820190508181035f830152615738816156ff565b9050919050565b7f496e73756666696369656e7420455448000000000000000000000000000000005f82015250565b5f6157736010836143d2565b915061577e8261573f565b602082019050919050565b5f6020820190508181035f8301526157a081615767565b9050919050565b5f6157b182614458565b91506157bc83614458565b92508282039050818111156157d4576157d3614e06565b5b92915050565b6157e381614349565b82525050565b5f6020820190506157fc5f8301846157da565b92915050565b5f61580c82614458565b91505f820361581e5761581d614e06565b5b600182039050919050565b5f81519050919050565b5f82825260208201905092915050565b5f61584d82615829565b6158578185615833565b93506158678185602086016143e2565b615870816143f0565b840191505092915050565b5f60808201905061588e5f830187614233565b61589b6020830186614233565b6158a86040830185614568565b81810360608301526158ba8184615843565b905095945050505050565b5f815190506158d381614297565b92915050565b5f602082840312156158ee576158ed614264565b5b5f6158fb848285016158c5565b91505092915050565b5f61591e61591961591484614349565b6144f4565b614458565b9050919050565b61592e81615904565b82525050565b5f6040820190506159475f830185615925565b6159546020830184614568565b9392505050565b5f60608201905061596e5f830186614568565b61597b6020830185615925565b6159886040830184614568565b949350505050565b5f6040820190506159a35f830185614568565b6159b06020830184614233565b939250505056fea26469706673582212204be061c49f8b5c8f0349383a037e60d786b365c67bfea838b0779a39d8f7fe2164736f6c634300081e003300000000000000000000000059de7273191e6bf1907d614e94ecfbe8e5fb7318000000000000000000000000841e2562ea2d59dad03f8a51a874133043a27e7400000000000000000000000000000000000000000000000000000000000001f40000000000000000000000003bdc72443bd7fe4ab1ecbbfe04389e3b4197941b
Deployed Bytecode
0x608060405260043610610334575f3560e01c80636f8b44b0116101aa578063b67c25a3116100f6578063d007af5c11610094578063e75179a41161006e578063e75179a414610ba9578063e985e9c514610bd1578063f2fde38b14610c0d578063fd762d9214610c3557610334565b8063d007af5c14610b19578063dc33e68114610b43578063dc53fd9214610b7f57610334565b8063be537f43116100d0578063be537f4314610a6f578063c25dff9c14610a99578063c87b56dd14610ac1578063ce6df2b914610afd57610334565b8063b67c25a3146109ed578063b88d4fde14610a17578063bbadfe7614610a3357610334565b806395d89b4111610163578063a83ef5151161013d578063a83ef51514610949578063a9fc664e14610973578063aa592f251461099b578063b366d613146109c557610334565b806395d89b41146108bb5780639d645a44146108e5578063a22cb4651461092157610334565b80636f8b44b0146107c557806370a08231146107ed578063715018a61461082957806374d0101d1461083f5780638da5cb5b14610867578063931e2e491461089157610334565b806332cb6b0c1161028457806355f804b31161022257806361347162116101fc57806361347162146107235780636352211e1461074b57806369e2f0fb146107875780636c3b8699146107af57610334565b806355f804b3146106a95780635944c753146106d15780635d4c1d46146106f957610334565b80633dd08c381161025e5780633dd08c38146105ff57806342842e0e1461063b578063495c8bf9146106575780634f9d2c0c1461068157610334565b806332cb6b0c1461059757806334531828146105c15780633ccfd60b146105e957610334565b8063098144d4116102f15780631c33b328116102cb5780631c33b328146104d857806323b872dd146105025780632a55205a1461051e5780632e8da8291461055b57610334565b8063098144d41461044857806318160ddd146104725780631b25b0771461049c57610334565b8063014635461461033857806301ffc9a71461036257806304634d8d1461039e57806306fdde03146103c6578063081812fc146103f0578063095ea7b31461042c575b5f5ffd5b348015610343575f5ffd5b5061034c610c5d565b6040516103599190614242565b60405180910390f35b34801561036d575f5ffd5b50610388600480360381019061038391906142c1565b610c73565b6040516103959190614306565b60405180910390f35b3480156103a9575f5ffd5b506103c460048036038101906103bf919061438a565b610c84565b005b3480156103d1575f5ffd5b506103da610ca2565b6040516103e79190614438565b60405180910390f35b3480156103fb575f5ffd5b506104166004803603810190610411919061448b565b610d32565b6040516104239190614242565b60405180910390f35b610446600480360381019061044191906144b6565b610d8b565b005b348015610453575f5ffd5b5061045c610d9b565b604051610469919061454f565b60405180910390f35b34801561047d575f5ffd5b50610486610dc3565b6040516104939190614577565b60405180910390f35b3480156104a7575f5ffd5b506104c260048036038101906104bd9190614590565b610e0e565b6040516104cf9190614306565b60405180910390f35b3480156104e3575f5ffd5b506104ec610f09565b6040516104f99190614653565b60405180910390f35b61051c6004803603810190610517919061466c565b610f0e565b005b348015610529575f5ffd5b50610544600480360381019061053f91906146bc565b6111b9565b6040516105529291906146fa565b60405180910390f35b348015610566575f5ffd5b50610581600480360381019061057c9190614721565b6112db565b60405161058e9190614306565b60405180910390f35b3480156105a2575f5ffd5b506105ab611477565b6040516105b89190614577565b60405180910390f35b3480156105cc575f5ffd5b506105e760048036038101906105e291906142c1565b61147d565b005b3480156105f4575f5ffd5b506105fd6114ef565b005b34801561060a575f5ffd5b5061062560048036038101906106209190614721565b611599565b6040516106329190614306565b60405180910390f35b6106556004803603810190610650919061466c565b6115b6565b005b348015610662575f5ffd5b5061066b6115d5565b6040516106789190614803565b60405180910390f35b34801561068c575f5ffd5b506106a760048036038101906106a291906144b6565b6117b9565b005b3480156106b4575f5ffd5b506106cf60048036038101906106ca9190614884565b611900565b005b3480156106dc575f5ffd5b506106f760048036038101906106f291906148cf565b6119d4565b005b348015610704575f5ffd5b5061070d6119f4565b60405161071a9190614948565b60405180910390f35b34801561072e575f5ffd5b50610749600480360381019061074491906149ae565b6119f9565b005b348015610756575f5ffd5b50610771600480360381019061076c919061448b565b611baf565b60405161077e9190614242565b60405180910390f35b348015610792575f5ffd5b506107ad60048036038101906107a89190614721565b611bc0565b005b3480156107ba575f5ffd5b506107c3611c1f565b005b3480156107d0575f5ffd5b506107eb60048036038101906107e6919061448b565b611d3a565b005b3480156107f8575f5ffd5b50610813600480360381019061080e9190614721565b611d4c565b6040516108209190614577565b60405180910390f35b348015610834575f5ffd5b5061083d611de0565b005b34801561084a575f5ffd5b50610865600480360381019061086091906144b6565b611df3565b005b348015610872575f5ffd5b5061087b611e60565b6040516108889190614242565b60405180910390f35b34801561089c575f5ffd5b506108a5611e88565b6040516108b29190614577565b60405180910390f35b3480156108c6575f5ffd5b506108cf611e8e565b6040516108dc9190614438565b60405180910390f35b3480156108f0575f5ffd5b5061090b60048036038101906109069190614721565b611f1e565b6040516109189190614306565b60405180910390f35b34801561092c575f5ffd5b5061094760048036038101906109429190614a28565b6120ba565b005b348015610954575f5ffd5b5061095d6121c0565b60405161096a9190614577565b60405180910390f35b34801561097e575f5ffd5b5061099960048036038101906109949190614721565b6121c6565b005b3480156109a6575f5ffd5b506109af61237e565b6040516109bc9190614577565b60405180910390f35b3480156109d0575f5ffd5b506109eb60048036038101906109e69190614721565b612383565b005b3480156109f8575f5ffd5b50610a016123e3565b604051610a0e9190614306565b60405180910390f35b610a316004803603810190610a2c9190614b8e565b6123f5565b005b348015610a3e575f5ffd5b50610a596004803603810190610a5491906142c1565b612446565b604051610a669190614306565b60405180910390f35b348015610a7a575f5ffd5b50610a83612463565b604051610a909190614c6c565b60405180910390f35b348015610aa4575f5ffd5b50610abf6004803603810190610aba9190614ca7565b6125b4565b005b348015610acc575f5ffd5b50610ae76004803603810190610ae2919061448b565b612638565b604051610af49190614438565b60405180910390f35b610b176004803603810190610b1291906144b6565b6126dc565b005b348015610b24575f5ffd5b50610b2d612857565b604051610b3a9190614803565b60405180910390f35b348015610b4e575f5ffd5b50610b696004803603810190610b649190614721565b612a3b565b604051610b769190614577565b60405180910390f35b348015610b8a575f5ffd5b50610b93612a4c565b604051610ba09190614577565b60405180910390f35b348015610bb4575f5ffd5b50610bcf6004803603810190610bca9190614721565b612a52565b005b348015610bdc575f5ffd5b50610bf76004803603810190610bf29190614cd2565b612b5f565b604051610c049190614306565b60405180910390f35b348015610c18575f5ffd5b50610c336004803603810190610c2e9190614721565b612bed565b005b348015610c40575f5ffd5b50610c5b6004803603810190610c569190614d10565b612c71565b005b71721c310194ccfc01e523fc93c9cccfa2a0ac81565b5f610c7d82612dc0565b9050919050565b610c8c612e39565b610c94612ec0565b610c9e8282612eca565b5050565b606060028054610cb190614da1565b80601f0160208091040260200160405190810160405280929190818152602001828054610cdd90614da1565b8015610d285780601f10610cff57610100808354040283529160200191610d28565b820191905f5260205f20905b815481529060010190602001808311610d0b57829003601f168201915b5050505050905090565b5f610d3c82612f26565b610d5157610d5063cf4700e460e01b612fc9565b5b60065f8381526020019081526020015f205f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610d9782826001612fd1565b5050565b5f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f610dcc6130fb565b6001545f54030390507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610dfe613103565b14610e0b57600854810190505b90565b5f5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610efd5760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663285fb8c88585856040518463ffffffff1660e01b8152600401610ec193929190614dd1565b5f6040518083038186803b158015610ed7575f5ffd5b505afa925050508015610ee8575060015b610ef4575f9050610f02565b60019050610f02565b600190505b9392505050565b600181565b5f610f188261312a565b905073ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161693508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610f8d57610f8c63a114810060e01b612fc9565b5b5f5f610f9884613239565b91509150610fae8187610fa961325c565b61326a565b610fd957610fc386610fbe61325c565b612b5f565b610fd857610fd76359c896be60e01b612fc9565b5b5b610fe686868660016132ad565b8015610ff0575f82555b60055f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154600190039190508190555060055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154600101919050819055506110b8856110948888876132e2565b7c020000000000000000000000000000000000000000000000000000000017613309565b60045f8681526020019081526020015f20819055505f7c0200000000000000000000000000000000000000000000000000000000841603611134575f6001850190505f60045f8381526020019081526020015f205403611132575f548114611131578360045f8381526020019081526020015f20819055505b5b505b5f73ffffffffffffffffffffffffffffffffffffffff8673ffffffffffffffffffffffffffffffffffffffff161690508481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f5fa45f81036111a3576111a263ea553b3460e01b612fc9565b5b6111b08787876001613333565b50505050505050565b5f5f5f600b5f8681526020019081526020015f2090505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f825f0160149054906101000a90046bffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361128d57600a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150600a5f0160149054906101000a90046bffffffffffffffffffffffff1690505b5f611296613368565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff16886112be9190614e33565b6112c89190614ea1565b9050828195509550505050509250929050565b5f5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461146e5760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d72dde5e60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b81526004016113c79190614242565b606060405180830381865afa1580156113e2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114069190614f5e565b60200151846040518363ffffffff1660e01b8152600401611428929190614f89565b602060405180830381865afa158015611443573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114679190614fc4565b9050611472565b5f90505b919050565b600f5481565b611485612e39565b600160135f837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f6101000a81548160ff02191690831515021790555050565b6114f7612e39565b5f3373ffffffffffffffffffffffffffffffffffffffff164760405161151c9061501c565b5f6040518083038185875af1925050503d805f8114611556576040519150601f19603f3d011682016040523d82523d5f602084013e61155b565b606091505b5050905080611596576040517f750b219c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b6014602052805f5260405f205f915054906101000a900460ff1681565b6115d083838360405180602001604052805f8152506123f5565b505050565b60605f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461176a5760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633fe5df9960095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b81526004016116c29190614242565b606060405180830381865afa1580156116dd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117019190614f5e565b602001516040518263ffffffff1660e01b81526004016117219190614948565b5f60405180830381865afa15801561173b573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906117639190615104565b90506117b6565b5f67ffffffffffffffff81111561178457611783614a6a565b5b6040519080825280602002602001820160405280156117b25781602001602082028036833780820191505090505b5090505b90565b6001151560145f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16151514611849576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161184090615195565b60405180910390fd5b60115460105461185991906151b3565b42111561189b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161189290615230565b60405180910390fd5b600f54816118a7613371565b6118b191906151b3565b11156118f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118e990615298565b60405180910390fd5b6118fc82826133b8565b5050565b60135f5f357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff16156119b6576040517f8bf9b99f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119be612e39565b8181600d91826119cf929190615457565b505050565b6119dc612e39565b6119e4612ec0565b6119ef83838361352c565b505050565b600181565b611a01612ec0565b5f611a0a610d9b565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611a71576040517f39ffc7ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663da0194c030866040518363ffffffff1660e01b8152600401611aac929190615524565b5f604051808303815f87803b158015611ac3575f5ffd5b505af1158015611ad5573d5f5f3e3d5ffd5b505050508073ffffffffffffffffffffffffffffffffffffffff16632304aa0230856040518363ffffffff1660e01b8152600401611b1492919061554b565b5f604051808303815f87803b158015611b2b575f5ffd5b505af1158015611b3d573d5f5f3e3d5ffd5b505050508073ffffffffffffffffffffffffffffffffffffffff16638d74431430846040518363ffffffff1660e01b8152600401611b7c92919061554b565b5f604051808303815f87803b158015611b93575f5ffd5b505af1158015611ba5573d5f5f3e3d5ffd5b5050505050505050565b5f611bb98261312a565b9050919050565b611bc8612e39565b5f60145f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555050565b611c27612ec0565b611c4271721c310194ccfc01e523fc93c9cccfa2a0ac6121c6565b71721c310194ccfc01e523fc93c9cccfa2a0ac73ffffffffffffffffffffffffffffffffffffffff1663da0194c03060016040518363ffffffff1660e01b8152600401611c90929190615524565b5f604051808303815f87803b158015611ca7575f5ffd5b505af1158015611cb9573d5f5f3e3d5ffd5b5050505071721c310194ccfc01e523fc93c9cccfa2a0ac73ffffffffffffffffffffffffffffffffffffffff16632304aa023060016040518363ffffffff1660e01b8152600401611d0b92919061554b565b5f604051808303815f87803b158015611d22575f5ffd5b505af1158015611d34573d5f5f3e3d5ffd5b50505050565b611d42612e39565b80600f8190555050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611d9157611d90638f4eb60460e01b612fc9565b5b67ffffffffffffffff60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054169050919050565b611de8612e39565b611df15f61358b565b565b611dfb612e39565b600f5481611e07613371565b611e1191906151b3565b1115611e52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e4990615298565b60405180910390fd5b611e5c82826133b8565b5050565b5f600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60105481565b606060038054611e9d90614da1565b80601f0160208091040260200160405190810160405280929190818152602001828054611ec990614da1565b8015611f145780601f10611eeb57610100808354040283529160200191611f14565b820191905f5260205f20905b815481529060010190602001808311611ef757829003601f168201915b5050505050905090565b5f5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146120b15760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639445f53060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b815260040161200a9190614242565b606060405180830381865afa158015612025573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120499190614f5e565b60400151846040518363ffffffff1660e01b815260040161206b929190614f89565b602060405180830381865afa158015612086573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120aa9190614fc4565b90506120b5565b5f90505b919050565b8060075f6120c661325c565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1661216f61325c565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516121b49190614306565b60405180910390a35050565b60115481565b6121ce612ec0565b5f5f90505f8273ffffffffffffffffffffffffffffffffffffffff163b111561226f578173ffffffffffffffffffffffffffffffffffffffff166301ffc9a75f6040518263ffffffff1660e01b815260040161222a9190615581565b602060405180830381865afa92505050801561226457506040513d601f19601f820116820180604052508101906122619190614fc4565b60015b1561226e57809150505b5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156122a9575080155b156122e0576040517f32483afb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fcc5dc080ff977b3c3a211fa63ab74f90f658f5ba9d3236e92c8f59570f442aac60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168360405161233292919061559a565b60405180910390a18160095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600e81565b61238b612e39565b600160145f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555050565b60125f9054906101000a900460ff1681565b612400848484610f0e565b5f8373ffffffffffffffffffffffffffffffffffffffff163b146124405761242a8484848461364e565b61243f5761243e63d1a57ed660e01b612fc9565b5b5b50505050565b6013602052805f5260405f205f915054906101000a900460ff1681565b61246b6141b1565b5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461255f5760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b81526004016125199190614242565b606060405180830381865afa158015612534573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125589190614f5e565b90506125b1565b60405180606001604052805f600681111561257d5761257c6145e0565b5b81526020015f6effffffffffffffffffffffffffffff1681526020015f6effffffffffffffffffffffffffffff1681525090505b90565b6125bc612e39565b805f0160208101906125ce91906155c1565b60125f6101000a81548160ff021916908315150217905550805f0160208101906125f891906155c1565b1561261d5742601081905550610e1081602001356126169190614e33565b6011819055505b5f81604001351115612635578060400135600e819055505b50565b606061264382612f26565b612682576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126799061565c565b60405180910390fd5b5f61268b613778565b90505f8151116126a95760405180602001604052805f8152506126d4565b806126b384613808565b6040516020016126c49291906156b4565b6040516020818303038152906040525b915050919050565b60125f9054906101000a900460ff168015612706575060115460105461270291906151b3565b4211155b612745576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161273c90615721565b60405180910390fd5b600f5481612751613371565b61275b91906151b3565b111561279c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161279390615298565b60405180910390fd5b5f600e54826127ab9190614e33565b9050803410156127f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127e790615789565b60405180910390fd5b6127fa83836133b8565b80341115612852573373ffffffffffffffffffffffffffffffffffffffff166108fc823461282891906157a7565b90811502906040515f60405180830381858888f19350505050158015612850573d5f5f3e3d5ffd5b505b505050565b60605f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146129ec5760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166317e94a6c60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b81526004016129449190614242565b606060405180830381865afa15801561295f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129839190614f5e565b604001516040518263ffffffff1660e01b81526004016129a39190614948565b5f60405180830381865afa1580156129bd573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906129e59190615104565b9050612a38565b5f67ffffffffffffffff811115612a0657612a05614a6a565b5b604051908082528060200260200182016040528015612a345781602001602082028036833780820191505090505b5090505b90565b5f612a45826138d2565b9050919050565b600e5481565b60135f5f357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff1615612b08576040517f8bf9b99f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b10612e39565b600e612b1a613371565b10612b51576040517f1f0f14ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b5c81600e6133b8565b50565b5f60075f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b612bf5612e39565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612c65575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401612c5c9190614242565b60405180910390fd5b612c6e8161358b565b50565b612c79612ec0565b612c82846121c6565b8373ffffffffffffffffffffffffffffffffffffffff1663da0194c030856040518363ffffffff1660e01b8152600401612cbd929190615524565b5f604051808303815f87803b158015612cd4575f5ffd5b505af1158015612ce6573d5f5f3e3d5ffd5b505050508373ffffffffffffffffffffffffffffffffffffffff16632304aa0230846040518363ffffffff1660e01b8152600401612d2592919061554b565b5f604051808303815f87803b158015612d3c575f5ffd5b505af1158015612d4e573d5f5f3e3d5ffd5b505050508373ffffffffffffffffffffffffffffffffffffffff16638d74431430836040518363ffffffff1660e01b8152600401612d8d92919061554b565b5f604051808303815f87803b158015612da4575f5ffd5b505af1158015612db6573d5f5f3e3d5ffd5b5050505050505050565b5f7f86455d28000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612e325750612e3182613926565b5b9050919050565b612e416139b7565b73ffffffffffffffffffffffffffffffffffffffff16612e5f611e60565b73ffffffffffffffffffffffffffffffffffffffff1614612ebe57612e826139b7565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401612eb59190614242565b60405180910390fd5b565b612ec8612e39565b565b612ed482826139be565b8173ffffffffffffffffffffffffffffffffffffffff167f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef82604051612f1a91906157e9565b60405180910390a25050565b5f81612f306130fb565b11612fc357612f3d613103565b821115612f6557612f5e60045f8481526020019081526020015f2054613b59565b9050612fc4565b5f54821015612fc2575f5b5f60045f8581526020019081526020015f205491508103612f9c5782612f9590615802565b9250612f70565b5f7c01000000000000000000000000000000000000000000000000000000008216149150505b5b5b919050565b805f5260045ffd5b5f612fdb83611baf565b905081801561301d57508073ffffffffffffffffffffffffffffffffffffffff1661300461325c565b73ffffffffffffffffffffffffffffffffffffffff1614155b15613049576130338161302e61325c565b612b5f565b6130485761304763cfb3b94260e01b612fc9565b5b5b8360065f8581526020019081526020015f205f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a450505050565b5f6001905090565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b5f816131346130fb565b116132235760045f8381526020019081526020015f20549050613155613103565b82111561317a5761316581613b59565b6132345761317963df2d9b4260e01b612fc9565b5b5f81036131fb575f54821061319a5761319963df2d9b4260e01b612fc9565b5b5b60045f836001900393508381526020019081526020015f205490505f8103156131f6575f7c010000000000000000000000000000000000000000000000000000000082160315613234576131f563df2d9b4260e01b612fc9565b5b61319b565b5f7c010000000000000000000000000000000000000000000000000000000082160315613234575b61323363df2d9b4260e01b612fc9565b5b919050565b5f5f5f60065f8581526020019081526020015f2090508092508254915050915091565b5f6132656139b7565b905090565b5f73ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b5f5f90505b818110156132db576132d0858583866132cb91906151b3565b613b99565b8060010190506132b2565b5050505050565b5f5f60e883901c905060e86132f8868684613c97565b62ffffff16901b9150509392505050565b5f73ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b5f5f90505b81811015613361576133568585838661335191906151b3565b613c9f565b806001019050613338565b5050505050565b5f612710905090565b5f61337a6130fb565b5f540390507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6133a8613103565b146133b557600854810190505b90565b5f5f5490505f82036133d5576133d463b562e8dd60e01b612fc9565b5b6133e15f8483856132ad565b6133ff836133f05f865f6132e2565b6133f985613d9d565b17613309565b60045f8381526020019081526020015f2081905550600160406001901b17820260055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505f73ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161690505f81036134b0576134af632e07630060e01b612fc9565b5b5f83830190505f8390506134c2613103565b6001830311156134dd576134dc6381647e3a60e01b612fc9565b5b5b80835f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f5fa48181600101915081036134de57815f819055505050506135275f848385613333565b505050565b613537838383613dac565b8173ffffffffffffffffffffffffffffffffffffffff16837f7f5b076c952c0ec86e5425963c1326dd0f03a3595c19f81d765e8ff559a6e33c8360405161357e91906157e9565b60405180910390a3505050565b5f600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f8373ffffffffffffffffffffffffffffffffffffffff1663150b7a0261367361325c565b8786866040518563ffffffff1660e01b8152600401613695949392919061587b565b6020604051808303815f875af19250505080156136d057506040513d601f19601f820116820180604052508101906136cd91906158d9565b60015b613725573d805f81146136fe576040519150601f19603f3d011682016040523d82523d5f602084013e613703565b606091505b505f81510361371d5761371c63d1a57ed660e01b612fc9565b5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b6060600d805461378790614da1565b80601f01602080910402602001604051908101604052809291908181526020018280546137b390614da1565b80156137fe5780601f106137d5576101008083540402835291602001916137fe565b820191905f5260205f20905b8154815290600101906020018083116137e157829003601f168201915b5050505050905090565b60605f600161381684613f5b565b0190505f8167ffffffffffffffff81111561383457613833614a6a565b5b6040519080825280601f01601f1916602001820160405280156138665781602001600182028036833780820191505090505b5090505f82602001820190505b6001156138c7578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85816138bc576138bb614e74565b5b0494505f8503613873575b819350505050919050565b5f67ffffffffffffffff604060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054901c169050919050565b5f6301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061398057506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806139b05750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b5f33905090565b5f6139c7613368565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff161115613a2c5781816040517f6f483d09000000000000000000000000000000000000000000000000000000008152600401613a23929190615934565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603613a9c575f6040517fb6d9900a000000000000000000000000000000000000000000000000000000008152600401613a939190614242565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff16815250600a5f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f7c0100000000000000000000000000000000000000000000000000000000821673ffffffffffffffffffffffffffffffffffffffff8316119050919050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161490505f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16149050818015613c075750805b15613c3e576040517f5cbd944100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8115613c5c57613c57613c4f6139b7565b8585346140ac565b613c90565b8015613c7a57613c75613c6d6139b7565b8685346140b2565b613c8f565b613c8e613c856139b7565b868686346140b8565b5b5b5050505050565b5f9392505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161490505f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16149050818015613d0d5750805b15613d44576040517f5cbd944100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8115613d6257613d5d613d556139b7565b85853461419e565b613d96565b8015613d8057613d7b613d736139b7565b8685346141a4565b613d95565b613d94613d8b6139b7565b868686346141aa565b5b5b5050505050565b5f6001821460e11b9050919050565b5f613db5613368565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff161115613e1c578382826040517fdfd1fc1b000000000000000000000000000000000000000000000000000000008152600401613e139392919061595b565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603613e8e57835f6040517f969f0852000000000000000000000000000000000000000000000000000000008152600401613e85929190615990565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff16815250600b5f8681526020019081526020015f205f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555090505050505050565b5f5f5f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310613fb7577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381613fad57613fac614e74565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310613ff4576d04ee2d6d415b85acef81000000008381613fea57613fe9614e74565b5b0492506020810190505b662386f26fc10000831061402357662386f26fc10000838161401957614018614e74565b5b0492506010810190505b6305f5e100831061404c576305f5e100838161404257614041614e74565b5b0492506008810190505b612710831061407157612710838161406757614066614e74565b5b0492506004810190505b60648310614094576064838161408a57614089614e74565b5b0492506002810190505b600a83106140a3576001810190505b80915050919050565b50505050565b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146141975760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663285fb8c88686866040518463ffffffff1660e01b815260040161416a93929190614dd1565b5f6040518083038186803b158015614180575f5ffd5b505afa158015614192573d5f5f3e3d5ffd5b505050505b5050505050565b50505050565b50505050565b5050505050565b60405180606001604052805f60068111156141cf576141ce6145e0565b5b81526020015f6effffffffffffffffffffffffffffff1681526020015f6effffffffffffffffffffffffffffff1681525090565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61422c82614203565b9050919050565b61423c81614222565b82525050565b5f6020820190506142555f830184614233565b92915050565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6142a08161426c565b81146142aa575f5ffd5b50565b5f813590506142bb81614297565b92915050565b5f602082840312156142d6576142d5614264565b5b5f6142e3848285016142ad565b91505092915050565b5f8115159050919050565b614300816142ec565b82525050565b5f6020820190506143195f8301846142f7565b92915050565b61432881614222565b8114614332575f5ffd5b50565b5f813590506143438161431f565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b61436981614349565b8114614373575f5ffd5b50565b5f8135905061438481614360565b92915050565b5f5f604083850312156143a05761439f614264565b5b5f6143ad85828601614335565b92505060206143be85828601614376565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61440a826143c8565b61441481856143d2565b93506144248185602086016143e2565b61442d816143f0565b840191505092915050565b5f6020820190508181035f8301526144508184614400565b905092915050565b5f819050919050565b61446a81614458565b8114614474575f5ffd5b50565b5f8135905061448581614461565b92915050565b5f602082840312156144a05761449f614264565b5b5f6144ad84828501614477565b91505092915050565b5f5f604083850312156144cc576144cb614264565b5b5f6144d985828601614335565b92505060206144ea85828601614477565b9150509250929050565b5f819050919050565b5f61451761451261450d84614203565b6144f4565b614203565b9050919050565b5f614528826144fd565b9050919050565b5f6145398261451e565b9050919050565b6145498161452f565b82525050565b5f6020820190506145625f830184614540565b92915050565b61457181614458565b82525050565b5f60208201905061458a5f830184614568565b92915050565b5f5f5f606084860312156145a7576145a6614264565b5b5f6145b486828701614335565b93505060206145c586828701614335565b92505060406145d686828701614335565b9150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6007811061461e5761461d6145e0565b5b50565b5f81905061462e8261460d565b919050565b5f61463d82614621565b9050919050565b61464d81614633565b82525050565b5f6020820190506146665f830184614644565b92915050565b5f5f5f6060848603121561468357614682614264565b5b5f61469086828701614335565b93505060206146a186828701614335565b92505060406146b286828701614477565b9150509250925092565b5f5f604083850312156146d2576146d1614264565b5b5f6146df85828601614477565b92505060206146f085828601614477565b9150509250929050565b5f60408201905061470d5f830185614233565b61471a6020830184614568565b9392505050565b5f6020828403121561473657614735614264565b5b5f61474384828501614335565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61477e81614222565b82525050565b5f61478f8383614775565b60208301905092915050565b5f602082019050919050565b5f6147b18261474c565b6147bb8185614756565b93506147c683614766565b805f5b838110156147f65781516147dd8882614784565b97506147e88361479b565b9250506001810190506147c9565b5085935050505092915050565b5f6020820190508181035f83015261481b81846147a7565b905092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f84011261484457614843614823565b5b8235905067ffffffffffffffff81111561486157614860614827565b5b60208301915083600182028301111561487d5761487c61482b565b5b9250929050565b5f5f6020838503121561489a57614899614264565b5b5f83013567ffffffffffffffff8111156148b7576148b6614268565b5b6148c38582860161482f565b92509250509250929050565b5f5f5f606084860312156148e6576148e5614264565b5b5f6148f386828701614477565b935050602061490486828701614335565b925050604061491586828701614376565b9150509250925092565b5f6effffffffffffffffffffffffffffff82169050919050565b6149428161491f565b82525050565b5f60208201905061495b5f830184614939565b92915050565b6007811061496d575f5ffd5b50565b5f8135905061497e81614961565b92915050565b61498d8161491f565b8114614997575f5ffd5b50565b5f813590506149a881614984565b92915050565b5f5f5f606084860312156149c5576149c4614264565b5b5f6149d286828701614970565b93505060206149e38682870161499a565b92505060406149f48682870161499a565b9150509250925092565b614a07816142ec565b8114614a11575f5ffd5b50565b5f81359050614a22816149fe565b92915050565b5f5f60408385031215614a3e57614a3d614264565b5b5f614a4b85828601614335565b9250506020614a5c85828601614a14565b9150509250929050565b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b614aa0826143f0565b810181811067ffffffffffffffff82111715614abf57614abe614a6a565b5b80604052505050565b5f614ad161425b565b9050614add8282614a97565b919050565b5f67ffffffffffffffff821115614afc57614afb614a6a565b5b614b05826143f0565b9050602081019050919050565b828183375f83830152505050565b5f614b32614b2d84614ae2565b614ac8565b905082815260208101848484011115614b4e57614b4d614a66565b5b614b59848285614b12565b509392505050565b5f82601f830112614b7557614b74614823565b5b8135614b85848260208601614b20565b91505092915050565b5f5f5f5f60808587031215614ba657614ba5614264565b5b5f614bb387828801614335565b9450506020614bc487828801614335565b9350506040614bd587828801614477565b925050606085013567ffffffffffffffff811115614bf657614bf5614268565b5b614c0287828801614b61565b91505092959194509250565b614c1781614633565b82525050565b614c268161491f565b82525050565b606082015f820151614c405f850182614c0e565b506020820151614c536020850182614c1d565b506040820151614c666040850182614c1d565b50505050565b5f606082019050614c7f5f830184614c2c565b92915050565b5f5ffd5b5f60608284031215614c9e57614c9d614c85565b5b81905092915050565b5f60608284031215614cbc57614cbb614264565b5b5f614cc984828501614c89565b91505092915050565b5f5f60408385031215614ce857614ce7614264565b5b5f614cf585828601614335565b9250506020614d0685828601614335565b9150509250929050565b5f5f5f5f60808587031215614d2857614d27614264565b5b5f614d3587828801614335565b9450506020614d4687828801614970565b9350506040614d578782880161499a565b9250506060614d688782880161499a565b91505092959194509250565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680614db857607f821691505b602082108103614dcb57614dca614d74565b5b50919050565b5f606082019050614de45f830186614233565b614df16020830185614233565b614dfe6040830184614233565b949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f614e3d82614458565b9150614e4883614458565b9250828202614e5681614458565b91508282048414831517614e6d57614e6c614e06565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f614eab82614458565b9150614eb683614458565b925082614ec657614ec5614e74565b5b828204905092915050565b5f5ffd5b5f81519050614ee381614961565b92915050565b5f81519050614ef781614984565b92915050565b5f60608284031215614f1257614f11614ed1565b5b614f1c6060614ac8565b90505f614f2b84828501614ed5565b5f830152506020614f3e84828501614ee9565b6020830152506040614f5284828501614ee9565b60408301525092915050565b5f60608284031215614f7357614f72614264565b5b5f614f8084828501614efd565b91505092915050565b5f604082019050614f9c5f830185614939565b614fa96020830184614233565b9392505050565b5f81519050614fbe816149fe565b92915050565b5f60208284031215614fd957614fd8614264565b5b5f614fe684828501614fb0565b91505092915050565b5f81905092915050565b50565b5f6150075f83614fef565b915061501282614ff9565b5f82019050919050565b5f61502682614ffc565b9150819050919050565b5f67ffffffffffffffff82111561504a57615049614a6a565b5b602082029050602081019050919050565b5f815190506150698161431f565b92915050565b5f61508161507c84615030565b614ac8565b905080838252602082019050602084028301858111156150a4576150a361482b565b5b835b818110156150cd57806150b9888261505b565b8452602084019350506020810190506150a6565b5050509392505050565b5f82601f8301126150eb576150ea614823565b5b81516150fb84826020860161506f565b91505092915050565b5f6020828403121561511957615118614264565b5b5f82015167ffffffffffffffff81111561513657615135614268565b5b615142848285016150d7565b91505092915050565b7f596f75277265206e6f742061206d696e746572000000000000000000000000005f82015250565b5f61517f6013836143d2565b915061518a8261514b565b602082019050919050565b5f6020820190508181035f8301526151ac81615173565b9050919050565b5f6151bd82614458565b91506151c883614458565b92508282019050808211156151e0576151df614e06565b5b92915050565b7f4d696e74696e6720706572696f6420656e6465640000000000000000000000005f82015250565b5f61521a6014836143d2565b9150615225826151e6565b602082019050919050565b5f6020820190508181035f8301526152478161520e565b9050919050565b7f737570706c7920657863656564000000000000000000000000000000000000005f82015250565b5f615282600d836143d2565b915061528d8261524e565b602082019050919050565b5f6020820190508181035f8301526152af81615276565b9050919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261531c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826152e1565b61532686836152e1565b95508019841693508086168417925050509392505050565b5f61535861535361534e84614458565b6144f4565b614458565b9050919050565b5f819050919050565b6153718361533e565b61538561537d8261535f565b8484546152ed565b825550505050565b5f5f905090565b61539c61538d565b6153a7818484615368565b505050565b5b818110156153ca576153bf5f82615394565b6001810190506153ad565b5050565b601f82111561540f576153e0816152c0565b6153e9846152d2565b810160208510156153f8578190505b61540c615404856152d2565b8301826153ac565b50505b505050565b5f82821c905092915050565b5f61542f5f1984600802615414565b1980831691505092915050565b5f6154478383615420565b9150826002028217905092915050565b61546183836152b6565b67ffffffffffffffff81111561547a57615479614a6a565b5b6154848254614da1565b61548f8282856153ce565b5f601f8311600181146154bc575f84156154aa578287013590505b6154b4858261543c565b86555061551b565b601f1984166154ca866152c0565b5f5b828110156154f1578489013582556001820191506020850194506020810190506154cc565b8683101561550e578489013561550a601f891682615420565b8355505b6001600288020188555050505b50505050505050565b5f6040820190506155375f830185614233565b6155446020830184614644565b9392505050565b5f60408201905061555e5f830185614233565b61556b6020830184614939565b9392505050565b61557b8161426c565b82525050565b5f6020820190506155945f830184615572565b92915050565b5f6040820190506155ad5f830185614233565b6155ba6020830184614233565b9392505050565b5f602082840312156155d6576155d5614264565b5b5f6155e384828501614a14565b91505092915050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f5f8201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b5f615646602f836143d2565b9150615651826155ec565b604082019050919050565b5f6020820190508181035f8301526156738161563a565b9050919050565b5f81905092915050565b5f61568e826143c8565b615698818561567a565b93506156a88185602086016143e2565b80840191505092915050565b5f6156bf8285615684565b91506156cb8284615684565b91508190509392505050565b7f5075626c6963206d696e74696e6720696e616374697665206f7220656e6465645f82015250565b5f61570b6020836143d2565b9150615716826156d7565b602082019050919050565b5f6020820190508181035f830152615738816156ff565b9050919050565b7f496e73756666696369656e7420455448000000000000000000000000000000005f82015250565b5f6157736010836143d2565b915061577e8261573f565b602082019050919050565b5f6020820190508181035f8301526157a081615767565b9050919050565b5f6157b182614458565b91506157bc83614458565b92508282039050818111156157d4576157d3614e06565b5b92915050565b6157e381614349565b82525050565b5f6020820190506157fc5f8301846157da565b92915050565b5f61580c82614458565b91505f820361581e5761581d614e06565b5b600182039050919050565b5f81519050919050565b5f82825260208201905092915050565b5f61584d82615829565b6158578185615833565b93506158678185602086016143e2565b615870816143f0565b840191505092915050565b5f60808201905061588e5f830187614233565b61589b6020830186614233565b6158a86040830185614568565b81810360608301526158ba8184615843565b905095945050505050565b5f815190506158d381614297565b92915050565b5f602082840312156158ee576158ed614264565b5b5f6158fb848285016158c5565b91505092915050565b5f61591e61591961591484614349565b6144f4565b614458565b9050919050565b61592e81615904565b82525050565b5f6040820190506159475f830185615925565b6159546020830184614568565b9392505050565b5f60608201905061596e5f830186614568565b61597b6020830185615925565b6159886040830184614568565b949350505050565b5f6040820190506159a35f830185614568565b6159b06020830184614233565b939250505056fea26469706673582212204be061c49f8b5c8f0349383a037e60d786b365c67bfea838b0779a39d8f7fe2164736f6c634300081e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000059de7273191e6bf1907d614e94ecfbe8e5fb7318000000000000000000000000841e2562ea2d59dad03f8a51a874133043a27e7400000000000000000000000000000000000000000000000000000000000001f40000000000000000000000003bdc72443bd7fe4ab1ecbbfe04389e3b4197941b
-----Decoded View---------------
Arg [0] : initialOwner (address): 0x59dE7273191E6bf1907d614e94eCFbe8e5FB7318
Arg [1] : royaltyReceiver (address): 0x841e2562Ea2d59Dad03f8A51A874133043A27E74
Arg [2] : royaltyFeeNumerator (uint96): 500
Arg [3] : _minter (address): 0x3bDC72443bD7fE4Ab1EcbBFE04389e3B4197941B
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000059de7273191e6bf1907d614e94ecfbe8e5fb7318
Arg [1] : 000000000000000000000000841e2562ea2d59dad03f8a51a874133043a27e74
Arg [2] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [3] : 0000000000000000000000003bdc72443bd7fe4ab1ecbbfe04389e3b4197941b
Deployed Bytecode Sourcemap
193011:5217:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110818:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;196650:221;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;196000:189;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;142059:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;149299:227;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;149016:124;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;115344:137;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;137261:573;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119128:387;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110929:99;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;153571:3523;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;187703:673;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;117473:357;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;193231:31;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;197748:97;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;198018:207;;;;;;;;;;;;;:::i;:::-;;193447:38;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;157190:193;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;116360:358;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;194960:318;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;197853:155;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;196198:208;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;111035:66;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;113084:727;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;143461:152;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;196537:105;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;111475:464;;;;;;;;;;;;;:::i;:::-;;195883:108;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;138985:242;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;98350:103;;;;;;;;;;;;;:::i;:::-;;194747:201;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;97675:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;193269:28;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;142235:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;118002:378;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;149866:234;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;193304:27;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;114411:818;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;193187:37;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;196424:104;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;193338:28;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;157981:416;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;193395:45;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;115698:455;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;193926:358;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;197001:609;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;195289:582;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;116928:379;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;197619:120;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;193137:43;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;194564:171;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;150257:164;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;98608:220;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;112142:749;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;110818:104;110879:42;110818:104;:::o;196650:221::-;196782:4;196824:39;196851:11;196824:26;:39::i;:::-;196804:59;;196650:221;;;:::o;196000:189::-;97561:13;:11;:13::i;:::-;196093:31:::1;:29;:31::i;:::-;196135:42;196154:8;196164:12;196135:18;:42::i;:::-;196000:189:::0;;:::o;142059:100::-;142113:13;142146:5;142139:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;142059:100;:::o;149299:227::-;149375:7;149400:16;149408:7;149400;:16::i;:::-;149395:73;;149418:50;149426:41;;;149418:7;:50::i;:::-;149395:73;149488:15;:24;149504:7;149488:24;;;;;;;;;;;:30;;;;;;;;;;;;149481:37;;149299:227;;;:::o;149016:124::-;149105:27;149114:2;149118:7;149127:4;149105:8;:27::i;:::-;149016:124;;:::o;115344:137::-;115406:30;115456:17;;;;;;;;;;;115449:24;;115344:137;:::o;137261:573::-;137322:14;137720:15;:13;:15::i;:::-;137705:12;;137689:13;;:28;:46;137680:55;;137775:17;137754;:15;:17::i;:::-;:38;137750:65;;137804:11;;137794:21;;;;137750:65;137261:573;:::o;119128:387::-;119227:4;119286:1;119248:40;;119256:17;;;;;;;;;;;119248:40;;;119244:242;;119309:17;;;;;;;;;;;:47;;;119357:6;119365:4;119371:2;119309:65;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119305:170;;119454:5;119447:12;;;;119305:170;119401:4;119394:11;;;;119244:242;119503:4;119496:11;;119128:387;;;;;;:::o;110929:99::-;111002:26;110929:99;:::o;153571:3523::-;153713:27;153743;153762:7;153743:18;:27::i;:::-;153713:57;;133203:14;153914:4;153898:22;;:41;153875:66;;153999:4;153958:45;;153974:19;153958:45;;;153954:95;;154005:44;154013:35;;;154005:7;:44::i;:::-;153954:95;154063:27;154092:23;154119:35;154146:7;154119:26;:35::i;:::-;154062:92;;;;154254:68;154279:15;154296:4;154302:19;:17;:19::i;:::-;154254:24;:68::i;:::-;154249:189;;154342:43;154359:4;154365:19;:17;:19::i;:::-;154342:16;:43::i;:::-;154337:101;;154387:51;154395:42;;;154387:7;:51::i;:::-;154337:101;154249:189;154451:43;154473:4;154479:2;154483:7;154492:1;154451:21;:43::i;:::-;154587:15;154584:160;;;154727:1;154706:19;154699:30;154584:160;155124:18;:24;155143:4;155124:24;;;;;;;;;;;;;;;;155122:26;;;;;;;;;;;;155193:18;:22;155212:2;155193:22;;;;;;;;;;;;;;;;155191:24;;;;;;;;;;;155515:146;155552:2;155601:45;155616:4;155622:2;155626:19;155601:14;:45::i;:::-;132801:8;155573:73;155515:18;:146::i;:::-;155486:17;:26;155504:7;155486:26;;;;;;;;;;;:175;;;;155832:1;132801:8;155781:19;:47;:52;155777:627;;155854:19;155886:1;155876:7;:11;155854:33;;156043:1;156009:17;:30;156027:11;156009:30;;;;;;;;;;;;:35;156005:384;;156147:13;;156132:11;:28;156128:242;;156327:19;156294:17;:30;156312:11;156294:30;;;;;;;;;;;:52;;;;156128:242;156005:384;155835:569;155777:627;156517:16;133203:14;156552:2;156536:20;;:39;156517:58;;156916:7;156880:8;156846:4;156788:25;156733:1;156676;156653:299;156989:1;156977:8;:13;156973:58;;156992:39;157000:30;;;156992:7;:39::i;:::-;156973:58;157044:42;157065:4;157071:2;157075:7;157084:1;157044:20;:42::i;:::-;153702:3392;;;;153571:3523;;;:::o;187703:673::-;187814:16;187832:14;187859:32;187894:17;:26;187912:7;187894:26;;;;;;;;;;;187859:61;;187931:23;187957:12;:21;;;;;;;;;;;;187931:47;;187989:22;188014:12;:28;;;;;;;;;;;;187989:53;;188086:1;188059:29;;:15;:29;;;188055:176;;188123:19;:28;;;;;;;;;;;;188105:46;;188184:19;:35;;;;;;;;;;;;188166:53;;188055:176;188243:21;188299:17;:15;:17::i;:::-;188267:49;;188280:15;188268:27;;:9;:27;;;;:::i;:::-;188267:49;;;;:::i;:::-;188243:73;;188337:15;188354:13;188329:39;;;;;;;;187703:673;;;;;:::o;117473:357::-;117552:4;117611:1;117573:40;;117581:17;;;;;;;;;;;117573:40;;;117569:229;;117637:17;;;;;;;;;;;:39;;;117695:17;;;;;;;;;;;:45;;;117749:4;117695:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:80;;;117777:8;117637:149;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;117630:156;;;;117569:229;117817:5;117810:12;;117473:357;;;;:::o;193231:31::-;;;;:::o;197748:97::-;97561:13;:11;:13::i;:::-;197832:4:::1;197811:14;:18;197826:2;197811:18;;;;;;;;;;;;;;;;;;:25;;;;;;;;;;;;;;;;;;197748:97:::0;:::o;198018:207::-;97561:13;:11;:13::i;:::-;198069:12:::1;198095:10;198087:24;;198133:21;198087:82;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;198068:101;;;198185:7;198180:37;;198201:16;;;;;;;;;;;;;;198180:37;198057:168;198018:207::o:0;193447:38::-;;;;;;;;;;;;;;;;;;;;;;:::o;157190:193::-;157336:39;157353:4;157359:2;157363:7;157336:39;;;;;;;;;;;;:16;:39::i;:::-;157190:193;;;:::o;116360:358::-;116425:16;116496:1;116458:40;;116466:17;;;;;;;;;;;116458:40;;;116454:221;;116522:17;;;;;;;;;;;:41;;;116582:17;;;;;;;;;;;:45;;;116636:4;116582:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:80;;;116522:141;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;116515:148;;;;116454:221;116708:1;116694:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;116687:23;;116360:358;;:::o;194960:318::-;194483:4;194461:26;;:6;:18;194468:10;194461:18;;;;;;;;;;;;;;;;;;;;;;;;;:26;;;194453:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;195098:12:::1;;195082:13;;:28;;;;:::i;:::-;195063:15;:47;;195041:117;;;;;;;;;;;;:::i;:::-;;;;;;;;;195207:10;;195194:9;195177:14;:12;:14::i;:::-;:26;;;;:::i;:::-;:40;;195169:66;;;;;;;;;;;;:::i;:::-;;;;;;;;;195246:20;195252:2;195256:9;195246:5;:20::i;:::-;194960:318:::0;;:::o;197853:155::-;194336:14;:23;194351:7;;;;194336:23;;;;;;;;;;;;;;;;;;;;;;;;;;;194332:52;;;194368:16;;;;;;;;;;;;;;194332:52;97561:13:::1;:11;:13::i;:::-;197989:11:::2;;197973:13;:27;;;;;;;:::i;:::-;;197853:155:::0;;:::o;196198:208::-;97561:13;:11;:13::i;:::-;196306:31:::1;:29;:31::i;:::-;196348:49;196365:7;196374:8;196384:12;196348:16;:49::i;:::-;196198:208:::0;;;:::o;111035:66::-;111099:1;111035:66;:::o;113084:727::-;113273:31;:29;:31::i;:::-;113317:40;113360:22;:20;:22::i;:::-;113317:65;;113427:1;113397:32;;113405:9;113397:32;;;113393:117;;113453:45;;;;;;;;;;;;;;113393:117;113522:9;:46;;;113577:4;113584:5;113522:68;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;113601:9;:42;;;113652:4;113659:19;113601:78;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;113690:9;:59;;;113758:4;113765:37;113690:113;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;113262:549;113084:727;;;:::o;143461:152::-;143533:7;143576:27;143595:7;143576:18;:27::i;:::-;143553:52;;143461:152;;;:::o;196537:105::-;97561:13;:11;:13::i;:::-;196628:5:::1;196610:6;:15;196617:7;196610:15;;;;;;;;;;;;;;;;:23;;;;;;;;;;;;;;;;;;196537:105:::0;:::o;111475:464::-;111539:31;:29;:31::i;:::-;111581:48;110879:42;111581:20;:48::i;:::-;110879:42;111640:95;;;111744:4;111002:26;111640:143;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110879:42;111794:91;;;111894:4;111099:1;111794:137;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;111475:464::o;195883:108::-;97561:13;:11;:13::i;:::-;195969:10:::1;195956;:23;;;;195883:108:::0;:::o;138985:242::-;139057:7;139098:1;139081:19;;:5;:19;;;139077:69;;139102:44;139110:35;;;139102:7;:44::i;:::-;139077:69;131745:13;139164:18;:25;139183:5;139164:25;;;;;;;;;;;;;;;;:55;139157:62;;138985:242;;;:::o;98350:103::-;97561:13;:11;:13::i;:::-;98415:30:::1;98442:1;98415:18;:30::i;:::-;98350:103::o:0;194747:201::-;97561:13;:11;:13::i;:::-;194877:10:::1;;194864:9;194847:14;:12;:14::i;:::-;:26;;;;:::i;:::-;:40;;194839:66;;;;;;;;;;;;:::i;:::-;;;;;;;;;194916:20;194922:2;194926:9;194916:5;:20::i;:::-;194747:201:::0;;:::o;97675:87::-;97721:7;97748:6;;;;;;;;;;;97741:13;;97675:87;:::o;193269:28::-;;;;:::o;142235:104::-;142291:13;142324:7;142317:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;142235:104;:::o;118002:378::-;118087:4;118146:1;118108:40;;118116:17;;;;;;;;;;;118108:40;;;118104:244;;118172:17;;;;;;;;;;;:45;;;118236:17;;;;;;;;;;;:45;;;118290:4;118236:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:89;;;118327:8;118172:164;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118165:171;;;;118104:244;118367:5;118360:12;;118002:378;;;;:::o;149866:234::-;150013:8;149961:18;:39;149980:19;:17;:19::i;:::-;149961:39;;;;;;;;;;;;;;;:49;150001:8;149961:49;;;;;;;;;;;;;;;;:60;;;;;;;;;;;;;;;;;;150073:8;150037:55;;150052:19;:17;:19::i;:::-;150037:55;;;150083:8;150037:55;;;;;;:::i;:::-;;;;;;;;149866:234;;:::o;193304:27::-;;;;:::o;114411:818::-;114487:31;:29;:31::i;:::-;114531:29;114563:5;114531:37;;114617:1;114584:18;:30;;;:34;114581:304;;;114647:18;114639:45;;;114685:48;114639:95;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;114635:239;;;114832:17;114805:44;;114753:112;114635:239;114581:304;114930:1;114900:32;;:18;:32;;;;:61;;;;;114937:24;114936:25;114900:61;114897:152;;;114985:52;;;;;;;;;;;;;;114897:152;115066:72;115099:17;;;;;;;;;;;115119:18;115066:72;;;;;;;:::i;:::-;;;;;;;;115202:18;115151:17;;:70;;;;;;;;;;;;;;;;;;114476:753;114411:818;:::o;193187:37::-;193222:2;193187:37;:::o;196424:104::-;97561:13;:11;:13::i;:::-;196515:4:::1;196497:6;:15;196504:7;196497:15;;;;;;;;;;;;;;;;:22;;;;;;;;;;;;;;;;;;196424:104:::0;:::o;193338:28::-;;;;;;;;;;;;;:::o;157981:416::-;158156:31;158169:4;158175:2;158179:7;158156:12;:31::i;:::-;158220:1;158202:2;:14;;;:19;158198:192;;158241:56;158272:4;158278:2;158282:7;158291:5;158241:30;:56::i;:::-;158236:154;;158318:56;158326:47;;;158318:7;:56::i;:::-;158236:154;158198:192;157981:416;;;;:::o;193395:45::-;;;;;;;;;;;;;;;;;;;;;;:::o;115698:455::-;115757:31;;:::i;:::-;115843:1;115805:40;;115813:17;;;;;;;;;;;115805:40;;;115801:140;;115869:17;;;;;;;;;;;:45;;;115923:4;115869:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;115862:67;;;;115801:140;115960:185;;;;;;;;116023:27;115960:185;;;;;;;;:::i;:::-;;;;;;116086:1;115960:185;;;;;;116132:1;115960:185;;;;;115953:192;;115698:455;;:::o;193926:358::-;97561:13;:11;:13::i;:::-;194023:6:::1;:19;;;;;;;;;;:::i;:::-;194004:16;;:38;;;;;;;;;;;;;;;;;;194059:6;:19;;;;;;;;;;:::i;:::-;194055:143;;;194111:15;194095:13;:31;;;;194179:7;194156:6;:20;;;:30;;;;:::i;:::-;194141:12;:45;;;;194055:143;194235:1;194214:6;:18;;;:22;194210:64;;;194256:6;:18;;;194238:15;:36;;;;194210:64;193926:358:::0;:::o;197001:609::-;197119:13;197172:16;197180:7;197172;:16::i;:::-;197150:113;;;;;;;;;;;;:::i;:::-;;;;;;;;;197276:28;197307:10;:8;:10::i;:::-;197276:41;;197379:1;197354:14;197348:28;:32;:254;;;;;;;;;;;;;;;;;197472:14;197513:25;197530:7;197513:16;:25::i;:::-;197429:132;;;;;;;;;:::i;:::-;;;;;;;;;;;;;197348:254;197328:274;;;197001:609;;;:::o;195289:582::-;195389:16;;;;;;;;;;;:67;;;;;195444:12;;195428:13;;:28;;;;:::i;:::-;195409:15;:47;;195389:67;195367:149;;;;;;;;;;;;:::i;:::-;;;;;;;;;195565:10;;195552:9;195535:14;:12;:14::i;:::-;:26;;;;:::i;:::-;:40;;195527:66;;;;;;;;;;;;:::i;:::-;;;;;;;;;195604:17;195636:15;;195624:9;:27;;;;:::i;:::-;195604:47;;195683:9;195670;:22;;195662:51;;;;;;;;;;;;:::i;:::-;;;;;;;;;195724:20;195730:2;195734:9;195724:5;:20::i;:::-;195771:9;195759;:21;195755:105;;;195805:10;195797:28;;:51;195838:9;195826;:21;;;;:::i;:::-;195797:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;195755:105;195357:514;195289:582;;:::o;116928:379::-;116999:16;117070:1;117032:40;;117040:17;;;;;;;;;;;117032:40;;;117028:236;;117096:17;;;;;;;;;;;:47;;;117162:17;;;;;;;;;;;:45;;;117216:4;117162:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:89;;;117096:156;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;117089:163;;;;117028:236;117297:1;117283:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;117276:23;;116928:379;;:::o;197619:120::-;197681:7;197708:22;197722:7;197708:13;:22::i;:::-;197701:29;;197619:120;;;:::o;193137:43::-;;;;:::o;194564:171::-;194336:14;:23;194351:7;;;;194336:23;;;;;;;;;;;;;;;;;;;;;;;;;;;194332:52;;;194368:16;;;;;;;;;;;;;;194332:52;97561:13:::1;:11;:13::i;:::-;193222:2:::2;194636:14;:12;:14::i;:::-;:26;194632:62;;194671:23;;;;;;;;;;;;;;194632:62;194705:19;194711:2;193222;194705:5;:19::i;:::-;194564:171:::0;:::o;150257:164::-;150354:4;150378:18;:25;150397:5;150378:25;;;;;;;;;;;;;;;:35;150404:8;150378:35;;;;;;;;;;;;;;;;;;;;;;;;;150371:42;;150257:164;;;;:::o;98608:220::-;97561:13;:11;:13::i;:::-;98713:1:::1;98693:22;;:8;:22;;::::0;98689:93:::1;;98767:1;98739:31;;;;;;;;;;;:::i;:::-;;;;;;;;98689:93;98792:28;98811:8;98792:18;:28::i;:::-;98608:220:::0;:::o;112142:749::-;112372:31;:29;:31::i;:::-;112416;112437:9;112416:20;:31::i;:::-;112491:9;112460:92;;;112561:4;112568:5;112460:114;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;112618:9;112587:88;;;112684:4;112691:19;112587:124;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;112755:9;112724:105;;;112838:4;112845:37;112724:159;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;112142:749;;;;:::o;182048:203::-;182133:4;182172:31;182157:46;;;:11;:46;;;;:86;;;;182207:36;182231:11;182207:23;:36::i;:::-;182157:86;182150:93;;182048:203;;;:::o;97840:166::-;97911:12;:10;:12::i;:::-;97900:23;;:7;:5;:7::i;:::-;:23;;;97896:103;;97974:12;:10;:12::i;:::-;97947:40;;;;;;;;;;;:::i;:::-;;;;;;;;97896:103;97840:166::o;99403:104::-;99486:13;:11;:13::i;:::-;99403:104::o;191363:217::-;191467:48;191492:8;191502:12;191467:24;:48::i;:::-;191549:8;191531:41;;;191559:12;191531:41;;;;;;:::i;:::-;;;;;;;;191363:217;;:::o;150679:475::-;150744:11;150791:7;150772:15;:13;:15::i;:::-;:26;150768:379;;150829:17;:15;:17::i;:::-;150819:7;:27;150815:90;;;150855:50;150878:17;:26;150896:7;150878:26;;;;;;;;;;;;150855:22;:50::i;:::-;150848:57;;;;150815:90;150936:13;;150926:7;:23;150922:214;;;150970:14;151003:60;151051:1;151020:17;:26;151038:7;151020:26;;;;;;;;;;;;151011:35;;;151010:42;151003:60;;151054:9;;;;:::i;:::-;;;151003:60;;;151119:1;132521:8;151091:6;:24;:29;151082:38;;150951:185;150922:214;150768:379;150679:475;;;;:::o;181188:165::-;181289:13;181283:4;181276:27;181330:4;181324;181317:18;172603:474;172732:13;172748:16;172756:7;172748;:16::i;:::-;172732:32;;172781:13;:45;;;;;172821:5;172798:28;;:19;:17;:19::i;:::-;:28;;;;172781:45;172777:201;;;172846:44;172863:5;172870:19;:17;:19::i;:::-;172846:16;:44::i;:::-;172841:137;;172911:51;172919:42;;;172911:7;:51::i;:::-;172841:137;172777:201;173023:2;172990:15;:24;173006:7;172990:24;;;;;;;;;;;:30;;;:35;;;;;;;;;;;;;;;;;;173061:7;173057:2;173041:28;;173050:5;173041:28;;;;;;;;;;;;172721:356;172603:474;;;:::o;136309:92::-;136365:7;136392:1;136385:8;;136309:92;:::o;136759:110::-;136817:7;136844:17;136837:24;;136759:110;:::o;144946:2213::-;145013:14;145063:7;145044:15;:13;:15::i;:::-;:26;145040:2054;;145096:17;:26;145114:7;145096:26;;;;;;;;;;;;145087:35;;145153:17;:15;:17::i;:::-;145143:7;:27;145139:183;;;145195:30;145218:6;145195:22;:30::i;:::-;145227:13;145191:49;145259:47;145267:38;;;145259:7;:47::i;:::-;145139:183;145433:1;145423:6;:11;145419:1292;;145470:13;;145459:7;:24;145455:77;;145485:47;145493:38;;;145485:7;:47::i;:::-;145455:77;146089:607;146167:17;:28;146185:9;;;;;;;146167:28;;;;;;;;;;;;146158:37;;146255:1;146245:6;:11;146241:25;146258:8;146241:25;146321:1;132521:8;146293:6;:24;:29;146289:48;146324:13;146289:48;146629:47;146637:38;;;146629:7;:47::i;:::-;146089:607;;;145419:1292;147066:1;132521:8;147038:6;:24;:29;147034:48;147069:13;147034:48;145040:2054;147104:47;147112:38;;;147104:7;:47::i;:::-;144946:2213;;;;:::o;152466:485::-;152568:27;152597:23;152638:38;152679:15;:24;152695:7;152679:24;;;;;;;;;;;152638:65;;152856:18;152833:41;;152913:19;152907:26;152888:45;;152818:126;152466:485;;;:::o;183191:116::-;183260:7;183287:12;:10;:12::i;:::-;183280:19;;183191:116;:::o;151694:659::-;151843:11;152008:16;152001:5;151997:28;151988:37;;152168:16;152157:9;152153:32;152140:45;;152318:15;152307:9;152304:30;152296:5;152285:9;152282:20;152279:56;152269:66;;151694:659;;;;;:::o;182360:359::-;182542:9;182554:1;182542:13;;182537:175;182561:8;182557:1;:12;182537:175;;;182587:51;182611:4;182617:2;182636:1;182621:12;:16;;;;:::i;:::-;182587:23;:51::i;:::-;182682:3;;;;;182537:175;;;;182360:359;;;;:::o;178478:311::-;178613:7;178633:16;132925:3;178659:19;:41;;178633:68;;132925:3;178727:31;178738:4;178744:2;178748:9;178727:10;:31::i;:::-;178719:40;;:62;;178712:69;;;178478:311;;;;;:::o;147707:450::-;147787:14;147955:16;147948:5;147944:28;147935:37;;148132:5;148118:11;148093:23;148089:41;148086:52;148079:5;148076:63;148066:73;;147707:450;;;;:::o;182826:357::-;183007:9;183019:1;183007:13;;183002:174;183026:8;183022:1;:12;183002:174;;;183052:50;183075:4;183081:2;183100:1;183085:12;:16;;;;:::i;:::-;183052:22;:50::i;:::-;183146:3;;;;;183002:174;;;;182826:357;;;;:::o;188658:97::-;188716:6;188742:5;188735:12;;188658:97;:::o;137932:385::-;137987:14;138203:15;:13;:15::i;:::-;138187:13;;:31;138178:40;;138258:17;138237;:15;:17::i;:::-;:38;138233:65;;138287:11;;138277:21;;;;138233:65;137932:385;:::o;161634:2399::-;161707:20;161730:13;;161707:36;;161770:1;161758:8;:13;161754:53;;161773:34;161781:25;;;161773:7;:34::i;:::-;161754:53;161820:61;161850:1;161854:2;161858:12;161872:8;161820:21;:61::i;:::-;162354:139;162391:2;162445:33;162468:1;162472:2;162476:1;162445:14;:33::i;:::-;162412:30;162433:8;162412:20;:30::i;:::-;:66;162354:18;:139::i;:::-;162320:17;:31;162338:12;162320:31;;;;;;;;;;;:173;;;;162780:1;131883:2;162750:1;:26;;162749:32;162737:8;:45;162711:18;:22;162730:2;162711:22;;;;;;;;;;;;;;;;:71;;;;;;;;;;;162893:16;133203:14;162928:2;162912:20;;:39;162893:58;;162984:1;162972:8;:13;162968:54;;162987:35;162995:26;;;162987:7;:35::i;:::-;162968:54;163039:11;163068:8;163053:12;:23;163039:37;;163091:15;163109:12;163091:30;;163152:17;:15;:17::i;:::-;163148:1;163142:3;:7;:27;163138:77;;;163171:44;163179:35;;;163171:7;:44::i;:::-;163138:77;163232:676;163651:7;163607:8;163562:1;163496:25;163433:1;163368;163337:358;163903:3;163890:9;;;;;;:16;163232:676;;163940:3;163924:13;:19;;;;162069:1886;;;163965:60;163994:1;163998:2;164002:12;164016:8;163965:20;:60::i;:::-;161696:2337;161634:2399;;:::o;191588:246::-;191707:55;191730:7;191739:8;191749:12;191707:22;:55::i;:::-;191803:8;191778:48;;191794:7;191778:48;191813:12;191778:48;;;;;;:::i;:::-;;;;;;;;191588:246;;;:::o;98988:191::-;99062:16;99081:6;;;;;;;;;;;99062:25;;99107:8;99098:6;;:17;;;;;;;;;;;;;;;;;;99162:8;99131:40;;99152:8;99131:40;;;;;;;;;;;;99051:128;98988:191;:::o;160481:691::-;160644:4;160690:2;160665:45;;;160711:19;:17;:19::i;:::-;160732:4;160738:7;160747:5;160665:88;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;160661:504;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;160965:1;160948:6;:13;:18;160944:115;;160987:56;160995:47;;;160987:7;:56::i;:::-;160944:115;161131:6;161125:13;161116:6;161112:2;161108:15;161101:38;160661:504;160834:54;;;160824:64;;;:6;:64;;;;160817:71;;;160481:691;;;;;;:::o;196879:114::-;196939:13;196972;196965:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;196879:114;:::o;76296:650::-;76352:13;76403:14;76440:1;76420:17;76431:5;76420:10;:17::i;:::-;:21;76403:38;;76456:20;76490:6;76479:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76456:41;;76512:11;76609:6;76605:2;76601:15;76593:6;76589:28;76582:35;;76646:254;76653:4;76646:254;;;76678:5;;;;;;;;76784:10;76779:2;76772:5;76768:14;76763:32;76758:3;76750:46;76842:2;76833:11;;;;;;:::i;:::-;;;;;76876:1;76867:5;:10;76646:254;76863:21;76646:254;76921:6;76914:13;;;;;76296:650;;;:::o;139309:178::-;139370:7;131745:13;131883:2;139398:18;:25;139417:5;139398:25;;;;;;;;;;;;;;;;:50;;139397:82;139390:89;;139309:178;;;:::o;141157:639::-;141242:4;141581:10;141566:25;;:11;:25;;;;:102;;;;141658:10;141643:25;;:11;:25;;;;141566:102;:179;;;;141735:10;141720:25;;:11;:25;;;;141566:179;141546:199;;141157:639;;;:::o;95409:98::-;95462:7;95489:10;95482:17;;95409:98;:::o;189026:518::-;189121:19;189143:17;:15;:17::i;:::-;189121:39;;;;189190:11;189175:12;:26;;;189171:176;;;189309:12;189323:11;189280:55;;;;;;;;;;;;:::i;:::-;;;;;;;;189171:176;189381:1;189361:22;;:8;:22;;;189357:110;;189452:1;189407:48;;;;;;;;;;;:::i;:::-;;;;;;;;189357:110;189501:35;;;;;;;;189513:8;189501:35;;;;;;189523:12;189501:35;;;;;189479:19;:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;189110:434;189026:518;;:::o;151250:335::-;151320:11;151550:15;151542:6;151538:28;151519:16;151511:6;151507:29;151504:63;151494:73;;151250:335;;;:::o;106341:623::-;106445:20;106484:1;106468:18;;:4;:18;;;106445:41;;106497:18;106532:1;106518:16;;:2;:16;;;106497:37;;106550:15;:32;;;;;106569:13;106550:32;106547:410;;;106606:28;;;;;;;;;;;;;;106547:410;106655:15;106652:305;;;106687:54;106704:12;:10;:12::i;:::-;106718:2;106722:7;106731:9;106687:16;:54::i;:::-;106652:305;;;106762:13;106759:198;;;106792:56;106809:12;:10;:12::i;:::-;106823:4;106829:7;106838:9;106792:16;:56::i;:::-;106759:198;;;106881:64;106902:12;:10;:12::i;:::-;106916:4;106922:2;106926:7;106935:9;106881:20;:64::i;:::-;106759:198;106652:305;106434:530;;106341:623;;;:::o;178179:147::-;178316:6;178179:147;;;;;:::o;107097:625::-;107200:20;107239:1;107223:18;;:4;:18;;;107200:41;;107252:18;107287:1;107273:16;;:2;:16;;;107252:37;;107305:15;:32;;;;;107324:13;107305:32;107302:413;;;107361:28;;;;;;;;;;;;;;107302:413;107410:15;107407:308;;;107442:55;107460:12;:10;:12::i;:::-;107474:2;107478:7;107487:9;107442:17;:55::i;:::-;107407:308;;;107518:13;107515:200;;;107548:57;107566:12;:10;:12::i;:::-;107580:4;107586:7;107595:9;107548:17;:57::i;:::-;107515:200;;;107638:65;107660:12;:10;:12::i;:::-;107674:4;107680:2;107684:7;107693:9;107638:21;:65::i;:::-;107515:200;107407:308;107189:533;;107097:625;;;:::o;148259:324::-;148329:14;148562:1;148552:8;148549:15;148523:24;148519:46;148509:56;;148259:324;;;:::o;189995:554::-;190105:19;190127:17;:15;:17::i;:::-;190105:39;;;;190174:11;190159:12;:26;;;190155:183;;;190291:7;190300:12;190314:11;190264:62;;;;;;;;;;;;;:::i;:::-;;;;;;;;190155:183;190372:1;190352:22;;:8;:22;;;190348:117;;190433:7;190450:1;190398:55;;;;;;;;;;;;:::i;:::-;;;;;;;;190348:117;190506:35;;;;;;;;190518:8;190506:35;;;;;;190528:12;190506:35;;;;;190477:17;:26;190495:7;190477:26;;;;;;;;;;;:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;190094:455;189995:554;;;:::o;69307:948::-;69360:7;69380:14;69397:1;69380:18;;69447:8;69438:5;:17;69434:106;;69485:8;69476:17;;;;;;:::i;:::-;;;;;69522:2;69512:12;;;;69434:106;69567:8;69558:5;:17;69554:106;;69605:8;69596:17;;;;;;:::i;:::-;;;;;69642:2;69632:12;;;;69554:106;69687:8;69678:5;:17;69674:106;;69725:8;69716:17;;;;;;:::i;:::-;;;;;69762:2;69752:12;;;;69674:106;69807:7;69798:5;:16;69794:103;;69844:7;69835:16;;;;;;:::i;:::-;;;;;69880:1;69870:11;;;;69794:103;69924:7;69915:5;:16;69911:103;;69961:7;69952:16;;;;;;:::i;:::-;;;;;69997:1;69987:11;;;;69911:103;70041:7;70032:5;:16;70028:103;;70078:7;70069:16;;;;;;:::i;:::-;;;;;70114:1;70104:11;;;;70028:103;70158:7;70149:5;:16;70145:68;;70196:1;70186:11;;;;70145:68;70241:6;70234:13;;;69307:948;;;:::o;107794:105::-;;;;;:::o;108148:107::-;;;;;:::o;120218:344::-;120459:1;120421:40;;120429:17;;;;;;;;;;;120421:40;;;120417:138;;120478:17;;;;;;;;;;;:47;;;120526:6;120534:4;120540:2;120478:65;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;120417:138;120218:344;;;;;:::o;107970:106::-;;;;;:::o;108326:108::-;;;;;:::o;108708:124::-;;;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;7:126:1:-;44:7;84:42;77:5;73:54;62:65;;7:126;;;:::o;139:96::-;176:7;205:24;223:5;205:24;:::i;:::-;194:35;;139:96;;;:::o;241:118::-;328:24;346:5;328:24;:::i;:::-;323:3;316:37;241:118;;:::o;365:222::-;458:4;496:2;485:9;481:18;473:26;;509:71;577:1;566:9;562:17;553:6;509:71;:::i;:::-;365:222;;;;:::o;593:75::-;626:6;659:2;653:9;643:19;;593:75;:::o;674:117::-;783:1;780;773:12;797:117;906:1;903;896:12;920:149;956:7;996:66;989:5;985:78;974:89;;920:149;;;:::o;1075:120::-;1147:23;1164:5;1147:23;:::i;:::-;1140:5;1137:34;1127:62;;1185:1;1182;1175:12;1127:62;1075:120;:::o;1201:137::-;1246:5;1284:6;1271:20;1262:29;;1300:32;1326:5;1300:32;:::i;:::-;1201:137;;;;:::o;1344:327::-;1402:6;1451:2;1439:9;1430:7;1426:23;1422:32;1419:119;;;1457:79;;:::i;:::-;1419:119;1577:1;1602:52;1646:7;1637:6;1626:9;1622:22;1602:52;:::i;:::-;1592:62;;1548:116;1344:327;;;;:::o;1677:90::-;1711:7;1754:5;1747:13;1740:21;1729:32;;1677:90;;;:::o;1773:109::-;1854:21;1869:5;1854:21;:::i;:::-;1849:3;1842:34;1773:109;;:::o;1888:210::-;1975:4;2013:2;2002:9;1998:18;1990:26;;2026:65;2088:1;2077:9;2073:17;2064:6;2026:65;:::i;:::-;1888:210;;;;:::o;2104:122::-;2177:24;2195:5;2177:24;:::i;:::-;2170:5;2167:35;2157:63;;2216:1;2213;2206:12;2157:63;2104:122;:::o;2232:139::-;2278:5;2316:6;2303:20;2294:29;;2332:33;2359:5;2332:33;:::i;:::-;2232:139;;;;:::o;2377:109::-;2413:7;2453:26;2446:5;2442:38;2431:49;;2377:109;;;:::o;2492:120::-;2564:23;2581:5;2564:23;:::i;:::-;2557:5;2554:34;2544:62;;2602:1;2599;2592:12;2544:62;2492:120;:::o;2618:137::-;2663:5;2701:6;2688:20;2679:29;;2717:32;2743:5;2717:32;:::i;:::-;2618:137;;;;:::o;2761:472::-;2828:6;2836;2885:2;2873:9;2864:7;2860:23;2856:32;2853:119;;;2891:79;;:::i;:::-;2853:119;3011:1;3036:53;3081:7;3072:6;3061:9;3057:22;3036:53;:::i;:::-;3026:63;;2982:117;3138:2;3164:52;3208:7;3199:6;3188:9;3184:22;3164:52;:::i;:::-;3154:62;;3109:117;2761:472;;;;;:::o;3239:99::-;3291:6;3325:5;3319:12;3309:22;;3239:99;;;:::o;3344:169::-;3428:11;3462:6;3457:3;3450:19;3502:4;3497:3;3493:14;3478:29;;3344:169;;;;:::o;3519:139::-;3608:6;3603:3;3598;3592:23;3649:1;3640:6;3635:3;3631:16;3624:27;3519:139;;;:::o;3664:102::-;3705:6;3756:2;3752:7;3747:2;3740:5;3736:14;3732:28;3722:38;;3664:102;;;:::o;3772:377::-;3860:3;3888:39;3921:5;3888:39;:::i;:::-;3943:71;4007:6;4002:3;3943:71;:::i;:::-;3936:78;;4023:65;4081:6;4076:3;4069:4;4062:5;4058:16;4023:65;:::i;:::-;4113:29;4135:6;4113:29;:::i;:::-;4108:3;4104:39;4097:46;;3864:285;3772:377;;;;:::o;4155:313::-;4268:4;4306:2;4295:9;4291:18;4283:26;;4355:9;4349:4;4345:20;4341:1;4330:9;4326:17;4319:47;4383:78;4456:4;4447:6;4383:78;:::i;:::-;4375:86;;4155:313;;;;:::o;4474:77::-;4511:7;4540:5;4529:16;;4474:77;;;:::o;4557:122::-;4630:24;4648:5;4630:24;:::i;:::-;4623:5;4620:35;4610:63;;4669:1;4666;4659:12;4610:63;4557:122;:::o;4685:139::-;4731:5;4769:6;4756:20;4747:29;;4785:33;4812:5;4785:33;:::i;:::-;4685:139;;;;:::o;4830:329::-;4889:6;4938:2;4926:9;4917:7;4913:23;4909:32;4906:119;;;4944:79;;:::i;:::-;4906:119;5064:1;5089:53;5134:7;5125:6;5114:9;5110:22;5089:53;:::i;:::-;5079:63;;5035:117;4830:329;;;;:::o;5165:474::-;5233:6;5241;5290:2;5278:9;5269:7;5265:23;5261:32;5258:119;;;5296:79;;:::i;:::-;5258:119;5416:1;5441:53;5486:7;5477:6;5466:9;5462:22;5441:53;:::i;:::-;5431:63;;5387:117;5543:2;5569:53;5614:7;5605:6;5594:9;5590:22;5569:53;:::i;:::-;5559:63;;5514:118;5165:474;;;;;:::o;5645:60::-;5673:3;5694:5;5687:12;;5645:60;;;:::o;5711:142::-;5761:9;5794:53;5812:34;5821:24;5839:5;5821:24;:::i;:::-;5812:34;:::i;:::-;5794:53;:::i;:::-;5781:66;;5711:142;;;:::o;5859:126::-;5909:9;5942:37;5973:5;5942:37;:::i;:::-;5929:50;;5859:126;;;:::o;5991:165::-;6080:9;6113:37;6144:5;6113:37;:::i;:::-;6100:50;;5991:165;;;:::o;6162:209::-;6288:76;6358:5;6288:76;:::i;:::-;6283:3;6276:89;6162:209;;:::o;6377:300::-;6509:4;6547:2;6536:9;6532:18;6524:26;;6560:110;6667:1;6656:9;6652:17;6643:6;6560:110;:::i;:::-;6377:300;;;;:::o;6683:118::-;6770:24;6788:5;6770:24;:::i;:::-;6765:3;6758:37;6683:118;;:::o;6807:222::-;6900:4;6938:2;6927:9;6923:18;6915:26;;6951:71;7019:1;7008:9;7004:17;6995:6;6951:71;:::i;:::-;6807:222;;;;:::o;7035:619::-;7112:6;7120;7128;7177:2;7165:9;7156:7;7152:23;7148:32;7145:119;;;7183:79;;:::i;:::-;7145:119;7303:1;7328:53;7373:7;7364:6;7353:9;7349:22;7328:53;:::i;:::-;7318:63;;7274:117;7430:2;7456:53;7501:7;7492:6;7481:9;7477:22;7456:53;:::i;:::-;7446:63;;7401:118;7558:2;7584:53;7629:7;7620:6;7609:9;7605:22;7584:53;:::i;:::-;7574:63;;7529:118;7035:619;;;;;:::o;7660:180::-;7708:77;7705:1;7698:88;7805:4;7802:1;7795:15;7829:4;7826:1;7819:15;7846:132;7946:1;7939:5;7936:12;7926:46;;7952:18;;:::i;:::-;7926:46;7846:132;:::o;7984:165::-;8048:7;8077:5;8066:16;;8083:60;8137:5;8083:60;:::i;:::-;7984:165;;;:::o;8155:::-;8230:9;8263:51;8308:5;8263:51;:::i;:::-;8250:64;;8155:165;;;:::o;8326:181::-;8438:62;8494:5;8438:62;:::i;:::-;8433:3;8426:75;8326:181;;:::o;8513:272::-;8631:4;8669:2;8658:9;8654:18;8646:26;;8682:96;8775:1;8764:9;8760:17;8751:6;8682:96;:::i;:::-;8513:272;;;;:::o;8791:619::-;8868:6;8876;8884;8933:2;8921:9;8912:7;8908:23;8904:32;8901:119;;;8939:79;;:::i;:::-;8901:119;9059:1;9084:53;9129:7;9120:6;9109:9;9105:22;9084:53;:::i;:::-;9074:63;;9030:117;9186:2;9212:53;9257:7;9248:6;9237:9;9233:22;9212:53;:::i;:::-;9202:63;;9157:118;9314:2;9340:53;9385:7;9376:6;9365:9;9361:22;9340:53;:::i;:::-;9330:63;;9285:118;8791:619;;;;;:::o;9416:474::-;9484:6;9492;9541:2;9529:9;9520:7;9516:23;9512:32;9509:119;;;9547:79;;:::i;:::-;9509:119;9667:1;9692:53;9737:7;9728:6;9717:9;9713:22;9692:53;:::i;:::-;9682:63;;9638:117;9794:2;9820:53;9865:7;9856:6;9845:9;9841:22;9820:53;:::i;:::-;9810:63;;9765:118;9416:474;;;;;:::o;9896:332::-;10017:4;10055:2;10044:9;10040:18;10032:26;;10068:71;10136:1;10125:9;10121:17;10112:6;10068:71;:::i;:::-;10149:72;10217:2;10206:9;10202:18;10193:6;10149:72;:::i;:::-;9896:332;;;;;:::o;10234:329::-;10293:6;10342:2;10330:9;10321:7;10317:23;10313:32;10310:119;;;10348:79;;:::i;:::-;10310:119;10468:1;10493:53;10538:7;10529:6;10518:9;10514:22;10493:53;:::i;:::-;10483:63;;10439:117;10234:329;;;;:::o;10569:114::-;10636:6;10670:5;10664:12;10654:22;;10569:114;;;:::o;10689:184::-;10788:11;10822:6;10817:3;10810:19;10862:4;10857:3;10853:14;10838:29;;10689:184;;;;:::o;10879:132::-;10946:4;10969:3;10961:11;;10999:4;10994:3;10990:14;10982:22;;10879:132;;;:::o;11017:108::-;11094:24;11112:5;11094:24;:::i;:::-;11089:3;11082:37;11017:108;;:::o;11131:179::-;11200:10;11221:46;11263:3;11255:6;11221:46;:::i;:::-;11299:4;11294:3;11290:14;11276:28;;11131:179;;;;:::o;11316:113::-;11386:4;11418;11413:3;11409:14;11401:22;;11316:113;;;:::o;11465:732::-;11584:3;11613:54;11661:5;11613:54;:::i;:::-;11683:86;11762:6;11757:3;11683:86;:::i;:::-;11676:93;;11793:56;11843:5;11793:56;:::i;:::-;11872:7;11903:1;11888:284;11913:6;11910:1;11907:13;11888:284;;;11989:6;11983:13;12016:63;12075:3;12060:13;12016:63;:::i;:::-;12009:70;;12102:60;12155:6;12102:60;:::i;:::-;12092:70;;11948:224;11935:1;11932;11928:9;11923:14;;11888:284;;;11892:14;12188:3;12181:10;;11589:608;;;11465:732;;;;:::o;12203:373::-;12346:4;12384:2;12373:9;12369:18;12361:26;;12433:9;12427:4;12423:20;12419:1;12408:9;12404:17;12397:47;12461:108;12564:4;12555:6;12461:108;:::i;:::-;12453:116;;12203:373;;;;:::o;12582:117::-;12691:1;12688;12681:12;12705:117;12814:1;12811;12804:12;12828:117;12937:1;12934;12927:12;12965:553;13023:8;13033:6;13083:3;13076:4;13068:6;13064:17;13060:27;13050:122;;13091:79;;:::i;:::-;13050:122;13204:6;13191:20;13181:30;;13234:18;13226:6;13223:30;13220:117;;;13256:79;;:::i;:::-;13220:117;13370:4;13362:6;13358:17;13346:29;;13424:3;13416:4;13408:6;13404:17;13394:8;13390:32;13387:41;13384:128;;;13431:79;;:::i;:::-;13384:128;12965:553;;;;;:::o;13524:529::-;13595:6;13603;13652:2;13640:9;13631:7;13627:23;13623:32;13620:119;;;13658:79;;:::i;:::-;13620:119;13806:1;13795:9;13791:17;13778:31;13836:18;13828:6;13825:30;13822:117;;;13858:79;;:::i;:::-;13822:117;13971:65;14028:7;14019:6;14008:9;14004:22;13971:65;:::i;:::-;13953:83;;;;13749:297;13524:529;;;;;:::o;14059:617::-;14135:6;14143;14151;14200:2;14188:9;14179:7;14175:23;14171:32;14168:119;;;14206:79;;:::i;:::-;14168:119;14326:1;14351:53;14396:7;14387:6;14376:9;14372:22;14351:53;:::i;:::-;14341:63;;14297:117;14453:2;14479:53;14524:7;14515:6;14504:9;14500:22;14479:53;:::i;:::-;14469:63;;14424:118;14581:2;14607:52;14651:7;14642:6;14631:9;14627:22;14607:52;:::i;:::-;14597:62;;14552:117;14059:617;;;;;:::o;14682:116::-;14719:7;14759:32;14752:5;14748:44;14737:55;;14682:116;;;:::o;14804:118::-;14891:24;14909:5;14891:24;:::i;:::-;14886:3;14879:37;14804:118;;:::o;14928:222::-;15021:4;15059:2;15048:9;15044:18;15036:26;;15072:71;15140:1;15129:9;15125:17;15116:6;15072:71;:::i;:::-;14928:222;;;;:::o;15156:126::-;15256:1;15249:5;15246:12;15236:40;;15272:1;15269;15262:12;15236:40;15156:126;:::o;15288:193::-;15361:5;15399:6;15386:20;15377:29;;15415:60;15469:5;15415:60;:::i;:::-;15288:193;;;;:::o;15487:122::-;15560:24;15578:5;15560:24;:::i;:::-;15553:5;15550:35;15540:63;;15599:1;15596;15589:12;15540:63;15487:122;:::o;15615:139::-;15661:5;15699:6;15686:20;15677:29;;15715:33;15742:5;15715:33;:::i;:::-;15615:139;;;;:::o;15760:673::-;15864:6;15872;15880;15929:2;15917:9;15908:7;15904:23;15900:32;15897:119;;;15935:79;;:::i;:::-;15897:119;16055:1;16080:80;16152:7;16143:6;16132:9;16128:22;16080:80;:::i;:::-;16070:90;;16026:144;16209:2;16235:53;16280:7;16271:6;16260:9;16256:22;16235:53;:::i;:::-;16225:63;;16180:118;16337:2;16363:53;16408:7;16399:6;16388:9;16384:22;16363:53;:::i;:::-;16353:63;;16308:118;15760:673;;;;;:::o;16439:116::-;16509:21;16524:5;16509:21;:::i;:::-;16502:5;16499:32;16489:60;;16545:1;16542;16535:12;16489:60;16439:116;:::o;16561:133::-;16604:5;16642:6;16629:20;16620:29;;16658:30;16682:5;16658:30;:::i;:::-;16561:133;;;;:::o;16700:468::-;16765:6;16773;16822:2;16810:9;16801:7;16797:23;16793:32;16790:119;;;16828:79;;:::i;:::-;16790:119;16948:1;16973:53;17018:7;17009:6;16998:9;16994:22;16973:53;:::i;:::-;16963:63;;16919:117;17075:2;17101:50;17143:7;17134:6;17123:9;17119:22;17101:50;:::i;:::-;17091:60;;17046:115;16700:468;;;;;:::o;17174:117::-;17283:1;17280;17273:12;17297:180;17345:77;17342:1;17335:88;17442:4;17439:1;17432:15;17466:4;17463:1;17456:15;17483:281;17566:27;17588:4;17566:27;:::i;:::-;17558:6;17554:40;17696:6;17684:10;17681:22;17660:18;17648:10;17645:34;17642:62;17639:88;;;17707:18;;:::i;:::-;17639:88;17747:10;17743:2;17736:22;17526:238;17483:281;;:::o;17770:129::-;17804:6;17831:20;;:::i;:::-;17821:30;;17860:33;17888:4;17880:6;17860:33;:::i;:::-;17770:129;;;:::o;17905:307::-;17966:4;18056:18;18048:6;18045:30;18042:56;;;18078:18;;:::i;:::-;18042:56;18116:29;18138:6;18116:29;:::i;:::-;18108:37;;18200:4;18194;18190:15;18182:23;;17905:307;;;:::o;18218:148::-;18316:6;18311:3;18306;18293:30;18357:1;18348:6;18343:3;18339:16;18332:27;18218:148;;;:::o;18372:423::-;18449:5;18474:65;18490:48;18531:6;18490:48;:::i;:::-;18474:65;:::i;:::-;18465:74;;18562:6;18555:5;18548:21;18600:4;18593:5;18589:16;18638:3;18629:6;18624:3;18620:16;18617:25;18614:112;;;18645:79;;:::i;:::-;18614:112;18735:54;18782:6;18777:3;18772;18735:54;:::i;:::-;18455:340;18372:423;;;;;:::o;18814:338::-;18869:5;18918:3;18911:4;18903:6;18899:17;18895:27;18885:122;;18926:79;;:::i;:::-;18885:122;19043:6;19030:20;19068:78;19142:3;19134:6;19127:4;19119:6;19115:17;19068:78;:::i;:::-;19059:87;;18875:277;18814:338;;;;:::o;19158:943::-;19253:6;19261;19269;19277;19326:3;19314:9;19305:7;19301:23;19297:33;19294:120;;;19333:79;;:::i;:::-;19294:120;19453:1;19478:53;19523:7;19514:6;19503:9;19499:22;19478:53;:::i;:::-;19468:63;;19424:117;19580:2;19606:53;19651:7;19642:6;19631:9;19627:22;19606:53;:::i;:::-;19596:63;;19551:118;19708:2;19734:53;19779:7;19770:6;19759:9;19755:22;19734:53;:::i;:::-;19724:63;;19679:118;19864:2;19853:9;19849:18;19836:32;19895:18;19887:6;19884:30;19881:117;;;19917:79;;:::i;:::-;19881:117;20022:62;20076:7;20067:6;20056:9;20052:22;20022:62;:::i;:::-;20012:72;;19807:287;19158:943;;;;;;;:::o;20107:171::-;20209:62;20265:5;20209:62;:::i;:::-;20204:3;20197:75;20107:171;;:::o;20284:108::-;20361:24;20379:5;20361:24;:::i;:::-;20356:3;20349:37;20284:108;;:::o;20472:796::-;20653:4;20648:3;20644:14;20757:4;20750:5;20746:16;20740:23;20776:88;20858:4;20853:3;20849:14;20835:12;20776:88;:::i;:::-;20668:206;20971:4;20964:5;20960:16;20954:23;20990:63;21047:4;21042:3;21038:14;21024:12;20990:63;:::i;:::-;20884:179;21169:4;21162:5;21158:16;21152:23;21188:63;21245:4;21240:3;21236:14;21222:12;21188:63;:::i;:::-;21073:188;20622:646;20472:796;;:::o;21274:390::-;21451:4;21489:2;21478:9;21474:18;21466:26;;21502:155;21654:1;21643:9;21639:17;21630:6;21502:155;:::i;:::-;21274:390;;;;:::o;21670:117::-;21779:1;21776;21769:12;21841:234;21917:5;21958:2;21949:6;21944:3;21940:16;21936:25;21933:112;;;21964:79;;:::i;:::-;21933:112;22063:6;22054:15;;21841:234;;;;:::o;22081:389::-;22170:6;22219:2;22207:9;22198:7;22194:23;22190:32;22187:119;;;22225:79;;:::i;:::-;22187:119;22345:1;22370:83;22445:7;22436:6;22425:9;22421:22;22370:83;:::i;:::-;22360:93;;22316:147;22081:389;;;;:::o;22476:474::-;22544:6;22552;22601:2;22589:9;22580:7;22576:23;22572:32;22569:119;;;22607:79;;:::i;:::-;22569:119;22727:1;22752:53;22797:7;22788:6;22777:9;22773:22;22752:53;:::i;:::-;22742:63;;22698:117;22854:2;22880:53;22925:7;22916:6;22905:9;22901:22;22880:53;:::i;:::-;22870:63;;22825:118;22476:474;;;;;:::o;22956:819::-;23069:6;23077;23085;23093;23142:3;23130:9;23121:7;23117:23;23113:33;23110:120;;;23149:79;;:::i;:::-;23110:120;23269:1;23294:53;23339:7;23330:6;23319:9;23315:22;23294:53;:::i;:::-;23284:63;;23240:117;23396:2;23422:80;23494:7;23485:6;23474:9;23470:22;23422:80;:::i;:::-;23412:90;;23367:145;23551:2;23577:53;23622:7;23613:6;23602:9;23598:22;23577:53;:::i;:::-;23567:63;;23522:118;23679:2;23705:53;23750:7;23741:6;23730:9;23726:22;23705:53;:::i;:::-;23695:63;;23650:118;22956:819;;;;;;;:::o;23781:180::-;23829:77;23826:1;23819:88;23926:4;23923:1;23916:15;23950:4;23947:1;23940:15;23967:320;24011:6;24048:1;24042:4;24038:12;24028:22;;24095:1;24089:4;24085:12;24116:18;24106:81;;24172:4;24164:6;24160:17;24150:27;;24106:81;24234:2;24226:6;24223:14;24203:18;24200:38;24197:84;;24253:18;;:::i;:::-;24197:84;24018:269;23967:320;;;:::o;24293:442::-;24442:4;24480:2;24469:9;24465:18;24457:26;;24493:71;24561:1;24550:9;24546:17;24537:6;24493:71;:::i;:::-;24574:72;24642:2;24631:9;24627:18;24618:6;24574:72;:::i;:::-;24656;24724:2;24713:9;24709:18;24700:6;24656:72;:::i;:::-;24293:442;;;;;;:::o;24741:180::-;24789:77;24786:1;24779:88;24886:4;24883:1;24876:15;24910:4;24907:1;24900:15;24927:410;24967:7;24990:20;25008:1;24990:20;:::i;:::-;24985:25;;25024:20;25042:1;25024:20;:::i;:::-;25019:25;;25079:1;25076;25072:9;25101:30;25119:11;25101:30;:::i;:::-;25090:41;;25280:1;25271:7;25267:15;25264:1;25261:22;25241:1;25234:9;25214:83;25191:139;;25310:18;;:::i;:::-;25191:139;24975:362;24927:410;;;;:::o;25343:180::-;25391:77;25388:1;25381:88;25488:4;25485:1;25478:15;25512:4;25509:1;25502:15;25529:185;25569:1;25586:20;25604:1;25586:20;:::i;:::-;25581:25;;25620:20;25638:1;25620:20;:::i;:::-;25615:25;;25659:1;25649:35;;25664:18;;:::i;:::-;25649:35;25706:1;25703;25699:9;25694:14;;25529:185;;;;:::o;25720:117::-;25829:1;25826;25819:12;25966:197;26050:5;26081:6;26075:13;26066:22;;26097:60;26151:5;26097:60;:::i;:::-;25966:197;;;;:::o;26169:143::-;26226:5;26257:6;26251:13;26242:22;;26273:33;26300:5;26273:33;:::i;:::-;26169:143;;;;:::o;26357:879::-;26459:5;26503:4;26491:9;26486:3;26482:19;26478:30;26475:117;;;26511:79;;:::i;:::-;26475:117;26610:21;26626:4;26610:21;:::i;:::-;26601:30;;26707:1;26747:87;26830:3;26821:6;26810:9;26806:22;26747:87;:::i;:::-;26740:4;26733:5;26729:16;26722:113;26641:205;26920:2;26961:60;27017:3;27008:6;26997:9;26993:22;26961:60;:::i;:::-;26954:4;26947:5;26943:16;26936:86;26856:177;27116:2;27157:60;27213:3;27204:6;27193:9;27189:22;27157:60;:::i;:::-;27150:4;27143:5;27139:16;27132:86;27043:186;26357:879;;;;:::o;27242:435::-;27354:6;27403:2;27391:9;27382:7;27378:23;27374:32;27371:119;;;27409:79;;:::i;:::-;27371:119;27529:1;27554:106;27652:7;27643:6;27632:9;27628:22;27554:106;:::i;:::-;27544:116;;27500:170;27242:435;;;;:::o;27683:332::-;27804:4;27842:2;27831:9;27827:18;27819:26;;27855:71;27923:1;27912:9;27908:17;27899:6;27855:71;:::i;:::-;27936:72;28004:2;27993:9;27989:18;27980:6;27936:72;:::i;:::-;27683:332;;;;;:::o;28021:137::-;28075:5;28106:6;28100:13;28091:22;;28122:30;28146:5;28122:30;:::i;:::-;28021:137;;;;:::o;28164:345::-;28231:6;28280:2;28268:9;28259:7;28255:23;28251:32;28248:119;;;28286:79;;:::i;:::-;28248:119;28406:1;28431:61;28484:7;28475:6;28464:9;28460:22;28431:61;:::i;:::-;28421:71;;28377:125;28164:345;;;;:::o;28515:147::-;28616:11;28653:3;28638:18;;28515:147;;;;:::o;28668:114::-;;:::o;28788:398::-;28947:3;28968:83;29049:1;29044:3;28968:83;:::i;:::-;28961:90;;29060:93;29149:3;29060:93;:::i;:::-;29178:1;29173:3;29169:11;29162:18;;28788:398;;;:::o;29192:379::-;29376:3;29398:147;29541:3;29398:147;:::i;:::-;29391:154;;29562:3;29555:10;;29192:379;;;:::o;29577:311::-;29654:4;29744:18;29736:6;29733:30;29730:56;;;29766:18;;:::i;:::-;29730:56;29816:4;29808:6;29804:17;29796:25;;29876:4;29870;29866:15;29858:23;;29577:311;;;:::o;29894:143::-;29951:5;29982:6;29976:13;29967:22;;29998:33;30025:5;29998:33;:::i;:::-;29894:143;;;;:::o;30060:732::-;30167:5;30192:81;30208:64;30265:6;30208:64;:::i;:::-;30192:81;:::i;:::-;30183:90;;30293:5;30322:6;30315:5;30308:21;30356:4;30349:5;30345:16;30338:23;;30409:4;30401:6;30397:17;30389:6;30385:30;30438:3;30430:6;30427:15;30424:122;;;30457:79;;:::i;:::-;30424:122;30572:6;30555:231;30589:6;30584:3;30581:15;30555:231;;;30664:3;30693:48;30737:3;30725:10;30693:48;:::i;:::-;30688:3;30681:61;30771:4;30766:3;30762:14;30755:21;;30631:155;30615:4;30610:3;30606:14;30599:21;;30555:231;;;30559:21;30173:619;;30060:732;;;;;:::o;30815:385::-;30897:5;30946:3;30939:4;30931:6;30927:17;30923:27;30913:122;;30954:79;;:::i;:::-;30913:122;31064:6;31058:13;31089:105;31190:3;31182:6;31175:4;31167:6;31163:17;31089:105;:::i;:::-;31080:114;;30903:297;30815:385;;;;:::o;31206:554::-;31301:6;31350:2;31338:9;31329:7;31325:23;31321:32;31318:119;;;31356:79;;:::i;:::-;31318:119;31497:1;31486:9;31482:17;31476:24;31527:18;31519:6;31516:30;31513:117;;;31549:79;;:::i;:::-;31513:117;31654:89;31735:7;31726:6;31715:9;31711:22;31654:89;:::i;:::-;31644:99;;31447:306;31206:554;;;;:::o;31766:169::-;31906:21;31902:1;31894:6;31890:14;31883:45;31766:169;:::o;31941:366::-;32083:3;32104:67;32168:2;32163:3;32104:67;:::i;:::-;32097:74;;32180:93;32269:3;32180:93;:::i;:::-;32298:2;32293:3;32289:12;32282:19;;31941:366;;;:::o;32313:419::-;32479:4;32517:2;32506:9;32502:18;32494:26;;32566:9;32560:4;32556:20;32552:1;32541:9;32537:17;32530:47;32594:131;32720:4;32594:131;:::i;:::-;32586:139;;32313:419;;;:::o;32738:191::-;32778:3;32797:20;32815:1;32797:20;:::i;:::-;32792:25;;32831:20;32849:1;32831:20;:::i;:::-;32826:25;;32874:1;32871;32867:9;32860:16;;32895:3;32892:1;32889:10;32886:36;;;32902:18;;:::i;:::-;32886:36;32738:191;;;;:::o;32935:170::-;33075:22;33071:1;33063:6;33059:14;33052:46;32935:170;:::o;33111:366::-;33253:3;33274:67;33338:2;33333:3;33274:67;:::i;:::-;33267:74;;33350:93;33439:3;33350:93;:::i;:::-;33468:2;33463:3;33459:12;33452:19;;33111:366;;;:::o;33483:419::-;33649:4;33687:2;33676:9;33672:18;33664:26;;33736:9;33730:4;33726:20;33722:1;33711:9;33707:17;33700:47;33764:131;33890:4;33764:131;:::i;:::-;33756:139;;33483:419;;;:::o;33908:163::-;34048:15;34044:1;34036:6;34032:14;34025:39;33908:163;:::o;34077:366::-;34219:3;34240:67;34304:2;34299:3;34240:67;:::i;:::-;34233:74;;34316:93;34405:3;34316:93;:::i;:::-;34434:2;34429:3;34425:12;34418:19;;34077:366;;;:::o;34449:419::-;34615:4;34653:2;34642:9;34638:18;34630:26;;34702:9;34696:4;34692:20;34688:1;34677:9;34673:17;34666:47;34730:131;34856:4;34730:131;:::i;:::-;34722:139;;34449:419;;;:::o;34874:97::-;34933:6;34961:3;34951:13;;34874:97;;;;:::o;34977:141::-;35026:4;35049:3;35041:11;;35072:3;35069:1;35062:14;35106:4;35103:1;35093:18;35085:26;;34977:141;;;:::o;35124:93::-;35161:6;35208:2;35203;35196:5;35192:14;35188:23;35178:33;;35124:93;;;:::o;35223:107::-;35267:8;35317:5;35311:4;35307:16;35286:37;;35223:107;;;;:::o;35336:393::-;35405:6;35455:1;35443:10;35439:18;35478:97;35508:66;35497:9;35478:97;:::i;:::-;35596:39;35626:8;35615:9;35596:39;:::i;:::-;35584:51;;35668:4;35664:9;35657:5;35653:21;35644:30;;35717:4;35707:8;35703:19;35696:5;35693:30;35683:40;;35412:317;;35336:393;;;;;:::o;35735:142::-;35785:9;35818:53;35836:34;35845:24;35863:5;35845:24;:::i;:::-;35836:34;:::i;:::-;35818:53;:::i;:::-;35805:66;;35735:142;;;:::o;35883:75::-;35926:3;35947:5;35940:12;;35883:75;;;:::o;35964:269::-;36074:39;36105:7;36074:39;:::i;:::-;36135:91;36184:41;36208:16;36184:41;:::i;:::-;36176:6;36169:4;36163:11;36135:91;:::i;:::-;36129:4;36122:105;36040:193;35964:269;;;:::o;36239:73::-;36284:3;36305:1;36298:8;;36239:73;:::o;36318:189::-;36395:32;;:::i;:::-;36436:65;36494:6;36486;36480:4;36436:65;:::i;:::-;36371:136;36318:189;;:::o;36513:186::-;36573:120;36590:3;36583:5;36580:14;36573:120;;;36644:39;36681:1;36674:5;36644:39;:::i;:::-;36617:1;36610:5;36606:13;36597:22;;36573:120;;;36513:186;;:::o;36705:543::-;36806:2;36801:3;36798:11;36795:446;;;36840:38;36872:5;36840:38;:::i;:::-;36924:29;36942:10;36924:29;:::i;:::-;36914:8;36910:44;37107:2;37095:10;37092:18;37089:49;;;37128:8;37113:23;;37089:49;37151:80;37207:22;37225:3;37207:22;:::i;:::-;37197:8;37193:37;37180:11;37151:80;:::i;:::-;36810:431;;36795:446;36705:543;;;:::o;37254:117::-;37308:8;37358:5;37352:4;37348:16;37327:37;;37254:117;;;;:::o;37377:169::-;37421:6;37454:51;37502:1;37498:6;37490:5;37487:1;37483:13;37454:51;:::i;:::-;37450:56;37535:4;37529;37525:15;37515:25;;37428:118;37377:169;;;;:::o;37551:295::-;37627:4;37773:29;37798:3;37792:4;37773:29;:::i;:::-;37765:37;;37835:3;37832:1;37828:11;37822:4;37819:21;37811:29;;37551:295;;;;:::o;37851:1403::-;37975:44;38015:3;38010;37975:44;:::i;:::-;38084:18;38076:6;38073:30;38070:56;;;38106:18;;:::i;:::-;38070:56;38150:38;38182:4;38176:11;38150:38;:::i;:::-;38235:67;38295:6;38287;38281:4;38235:67;:::i;:::-;38329:1;38358:2;38350:6;38347:14;38375:1;38370:632;;;;39046:1;39063:6;39060:84;;;39119:9;39114:3;39110:19;39097:33;39088:42;;39060:84;39170:67;39230:6;39223:5;39170:67;:::i;:::-;39164:4;39157:81;39019:229;38340:908;;38370:632;38422:4;38418:9;38410:6;38406:22;38456:37;38488:4;38456:37;:::i;:::-;38515:1;38529:215;38543:7;38540:1;38537:14;38529:215;;;38629:9;38624:3;38620:19;38607:33;38599:6;38592:49;38680:1;38672:6;38668:14;38658:24;;38727:2;38716:9;38712:18;38699:31;;38566:4;38563:1;38559:12;38554:17;;38529:215;;;38772:6;38763:7;38760:19;38757:186;;;38837:9;38832:3;38828:19;38815:33;38880:48;38922:4;38914:6;38910:17;38899:9;38880:48;:::i;:::-;38872:6;38865:64;38780:163;38757:186;38989:1;38985;38977:6;38973:14;38969:22;38963:4;38956:36;38377:625;;;38340:908;;37950:1304;;;37851:1403;;;:::o;39260:382::-;39406:4;39444:2;39433:9;39429:18;39421:26;;39457:71;39525:1;39514:9;39510:17;39501:6;39457:71;:::i;:::-;39538:97;39631:2;39620:9;39616:18;39607:6;39538:97;:::i;:::-;39260:382;;;;;:::o;39648:332::-;39769:4;39807:2;39796:9;39792:18;39784:26;;39820:71;39888:1;39877:9;39873:17;39864:6;39820:71;:::i;:::-;39901:72;39969:2;39958:9;39954:18;39945:6;39901:72;:::i;:::-;39648:332;;;;;:::o;39986:115::-;40071:23;40088:5;40071:23;:::i;:::-;40066:3;40059:36;39986:115;;:::o;40107:218::-;40198:4;40236:2;40225:9;40221:18;40213:26;;40249:69;40315:1;40304:9;40300:17;40291:6;40249:69;:::i;:::-;40107:218;;;;:::o;40331:332::-;40452:4;40490:2;40479:9;40475:18;40467:26;;40503:71;40571:1;40560:9;40556:17;40547:6;40503:71;:::i;:::-;40584:72;40652:2;40641:9;40637:18;40628:6;40584:72;:::i;:::-;40331:332;;;;;:::o;40669:323::-;40725:6;40774:2;40762:9;40753:7;40749:23;40745:32;40742:119;;;40780:79;;:::i;:::-;40742:119;40900:1;40925:50;40967:7;40958:6;40947:9;40943:22;40925:50;:::i;:::-;40915:60;;40871:114;40669:323;;;;:::o;40998:234::-;41138:34;41134:1;41126:6;41122:14;41115:58;41207:17;41202:2;41194:6;41190:15;41183:42;40998:234;:::o;41238:366::-;41380:3;41401:67;41465:2;41460:3;41401:67;:::i;:::-;41394:74;;41477:93;41566:3;41477:93;:::i;:::-;41595:2;41590:3;41586:12;41579:19;;41238:366;;;:::o;41610:419::-;41776:4;41814:2;41803:9;41799:18;41791:26;;41863:9;41857:4;41853:20;41849:1;41838:9;41834:17;41827:47;41891:131;42017:4;41891:131;:::i;:::-;41883:139;;41610:419;;;:::o;42035:148::-;42137:11;42174:3;42159:18;;42035:148;;;;:::o;42189:390::-;42295:3;42323:39;42356:5;42323:39;:::i;:::-;42378:89;42460:6;42455:3;42378:89;:::i;:::-;42371:96;;42476:65;42534:6;42529:3;42522:4;42515:5;42511:16;42476:65;:::i;:::-;42566:6;42561:3;42557:16;42550:23;;42299:280;42189:390;;;;:::o;42585:435::-;42765:3;42787:95;42878:3;42869:6;42787:95;:::i;:::-;42780:102;;42899:95;42990:3;42981:6;42899:95;:::i;:::-;42892:102;;43011:3;43004:10;;42585:435;;;;;:::o;43026:182::-;43166:34;43162:1;43154:6;43150:14;43143:58;43026:182;:::o;43214:366::-;43356:3;43377:67;43441:2;43436:3;43377:67;:::i;:::-;43370:74;;43453:93;43542:3;43453:93;:::i;:::-;43571:2;43566:3;43562:12;43555:19;;43214:366;;;:::o;43586:419::-;43752:4;43790:2;43779:9;43775:18;43767:26;;43839:9;43833:4;43829:20;43825:1;43814:9;43810:17;43803:47;43867:131;43993:4;43867:131;:::i;:::-;43859:139;;43586:419;;;:::o;44011:166::-;44151:18;44147:1;44139:6;44135:14;44128:42;44011:166;:::o;44183:366::-;44325:3;44346:67;44410:2;44405:3;44346:67;:::i;:::-;44339:74;;44422:93;44511:3;44422:93;:::i;:::-;44540:2;44535:3;44531:12;44524:19;;44183:366;;;:::o;44555:419::-;44721:4;44759:2;44748:9;44744:18;44736:26;;44808:9;44802:4;44798:20;44794:1;44783:9;44779:17;44772:47;44836:131;44962:4;44836:131;:::i;:::-;44828:139;;44555:419;;;:::o;44980:194::-;45020:4;45040:20;45058:1;45040:20;:::i;:::-;45035:25;;45074:20;45092:1;45074:20;:::i;:::-;45069:25;;45118:1;45115;45111:9;45103:17;;45142:1;45136:4;45133:11;45130:37;;;45147:18;;:::i;:::-;45130:37;44980:194;;;;:::o;45180:115::-;45265:23;45282:5;45265:23;:::i;:::-;45260:3;45253:36;45180:115;;:::o;45301:218::-;45392:4;45430:2;45419:9;45415:18;45407:26;;45443:69;45509:1;45498:9;45494:17;45485:6;45443:69;:::i;:::-;45301:218;;;;:::o;45525:171::-;45564:3;45587:24;45605:5;45587:24;:::i;:::-;45578:33;;45633:4;45626:5;45623:15;45620:41;;45641:18;;:::i;:::-;45620:41;45688:1;45681:5;45677:13;45670:20;;45525:171;;;:::o;45702:98::-;45753:6;45787:5;45781:12;45771:22;;45702:98;;;:::o;45806:168::-;45889:11;45923:6;45918:3;45911:19;45963:4;45958:3;45954:14;45939:29;;45806:168;;;;:::o;45980:373::-;46066:3;46094:38;46126:5;46094:38;:::i;:::-;46148:70;46211:6;46206:3;46148:70;:::i;:::-;46141:77;;46227:65;46285:6;46280:3;46273:4;46266:5;46262:16;46227:65;:::i;:::-;46317:29;46339:6;46317:29;:::i;:::-;46312:3;46308:39;46301:46;;46070:283;45980:373;;;;:::o;46359:640::-;46554:4;46592:3;46581:9;46577:19;46569:27;;46606:71;46674:1;46663:9;46659:17;46650:6;46606:71;:::i;:::-;46687:72;46755:2;46744:9;46740:18;46731:6;46687:72;:::i;:::-;46769;46837:2;46826:9;46822:18;46813:6;46769:72;:::i;:::-;46888:9;46882:4;46878:20;46873:2;46862:9;46858:18;46851:48;46916:76;46987:4;46978:6;46916:76;:::i;:::-;46908:84;;46359:640;;;;;;;:::o;47005:141::-;47061:5;47092:6;47086:13;47077:22;;47108:32;47134:5;47108:32;:::i;:::-;47005:141;;;;:::o;47152:349::-;47221:6;47270:2;47258:9;47249:7;47245:23;47241:32;47238:119;;;47276:79;;:::i;:::-;47238:119;47396:1;47421:63;47476:7;47467:6;47456:9;47452:22;47421:63;:::i;:::-;47411:73;;47367:127;47152:349;;;;:::o;47507:140::-;47556:9;47589:52;47607:33;47616:23;47633:5;47616:23;:::i;:::-;47607:33;:::i;:::-;47589:52;:::i;:::-;47576:65;;47507:140;;;:::o;47653:129::-;47739:36;47769:5;47739:36;:::i;:::-;47734:3;47727:49;47653:129;;:::o;47788:330::-;47908:4;47946:2;47935:9;47931:18;47923:26;;47959:70;48026:1;48015:9;48011:17;48002:6;47959:70;:::i;:::-;48039:72;48107:2;48096:9;48092:18;48083:6;48039:72;:::i;:::-;47788:330;;;;;:::o;48124:440::-;48272:4;48310:2;48299:9;48295:18;48287:26;;48323:71;48391:1;48380:9;48376:17;48367:6;48323:71;:::i;:::-;48404;48471:2;48460:9;48456:18;48447:6;48404:71;:::i;:::-;48485:72;48553:2;48542:9;48538:18;48529:6;48485:72;:::i;:::-;48124:440;;;;;;:::o;48570:332::-;48691:4;48729:2;48718:9;48714:18;48706:26;;48742:71;48810:1;48799:9;48795:17;48786:6;48742:71;:::i;:::-;48823:72;48891:2;48880:9;48876:18;48867:6;48823:72;:::i;:::-;48570:332;;;;;:::o
Swarm Source
ipfs://4be061c49f8b5c8f0349383a037e60d786b365c67bfea838b0779a39d8f7fe21
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.