Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 19 from a total of 19 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Safe Transfer Fr... | 24262246 | 35 days ago | IN | 0 ETH | 0.00021856 | ||||
| Safe Transfer Fr... | 24262240 | 35 days ago | IN | 0 ETH | 0.000218 | ||||
| Safe Transfer Fr... | 24262230 | 35 days ago | IN | 0 ETH | 0.00040778 | ||||
| Safe Transfer Fr... | 24262227 | 35 days ago | IN | 0 ETH | 0.00042083 | ||||
| Safe Transfer Fr... | 23959498 | 77 days ago | IN | 0 ETH | 0.00001175 | ||||
| Set Approval For... | 23528156 | 137 days ago | IN | 0 ETH | 0.00009385 | ||||
| Set Approval For... | 23471954 | 145 days ago | IN | 0 ETH | 0.00005787 | ||||
| Set Approval For... | 23461336 | 147 days ago | IN | 0 ETH | 0.00005272 | ||||
| Safe Transfer Fr... | 23332371 | 165 days ago | IN | 0 ETH | 0.00011165 | ||||
| Safe Transfer Fr... | 23332369 | 165 days ago | IN | 0 ETH | 0.00013328 | ||||
| Safe Transfer Fr... | 23332365 | 165 days ago | IN | 0 ETH | 0.00011042 | ||||
| Safe Transfer Fr... | 23332363 | 165 days ago | IN | 0 ETH | 0.00013226 | ||||
| Set Base URI | 23319286 | 167 days ago | IN | 0 ETH | 0.00012589 | ||||
| Set Transfer Val... | 23290290 | 171 days ago | IN | 0 ETH | 0.00008434 | ||||
| Set Transfer Val... | 23290242 | 171 days ago | IN | 0 ETH | 0.00012455 | ||||
| Set Approval For... | 23290203 | 171 days ago | IN | 0 ETH | 0.0000956 | ||||
| Secondary Reserv... | 23290117 | 171 days ago | IN | 0 ETH | 0.00083524 | ||||
| Secondary Reserv... | 23290114 | 171 days ago | IN | 0 ETH | 0.00023661 | ||||
| Set Base URI | 23290039 | 171 days ago | IN | 0 ETH | 0.00019467 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Mr_Bones_Mother
Compiler Version
v0.8.30+commit.73712a01
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2025-09-04
*/
// 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: mrbonesmother.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 Mr_Bones_Mother is ERC721AC, BasicRoyalties, Ownable, OwnableBasic{
string private _baseTokenURI;
string public provenanceHash;
bool public operatorFilteringEnabled;
mapping(bytes4 => bool) public functionLocked;
constructor(address initialOwner, address royaltyReceiver_, uint96 royaltyFeeNumerator_) ERC721AC("MR. Bone's Mother","MR. Bone's Mother")
BasicRoyalties(royaltyReceiver_, royaltyFeeNumerator_) Ownable(initialOwner){
}
/**
* @notice Modifier applied to functions that will be disabled when they're no longer needed
*/
modifier lockable() {
if (functionLocked[msg.sig]) revert FunctionLocked();
_;
}
function secondaryReserve(address to, uint256 quan) external lockable onlyOwner {
_mint(to, quan);
}
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);
}
/**
* @inheritdoc ERC721AC
*/
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721AC, ERC2981)
returns (bool)
{
return
ERC721AC.supportsInterface(interfaceId);
}
/**
* @notice Override ERC721AC _baseURI function to use base URI pattern
*/
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)
)
)
: "";
}
/**
* @notice Return the number of tokens an address has minted
* @param account Address to return the number of tokens minted for
*/
function numberMinted(address account) external view returns (uint256) {
return _numberMinted(account);
}
/**
* @notice Lock a function so that it can no longer be called
* @dev WARNING: THIS CANNOT BE UNDONE
* @param id Function signature
*/
function lockFunction(bytes4 id) external onlyOwner {
functionLocked[id] = true;
}
/**
* @notice Set the state of the OpenSea operator filter
* @param value Flag indicating if the operator filter should be applied to transfers and approvals
*/
function setOperatorFilteringEnabled(bool value)
external
lockable
onlyOwner
{
operatorFilteringEnabled = value;
}
/**
* @notice Set token metadata base URI
* @param _newBaseURI New base URI
*/
function setBaseURI(string calldata _newBaseURI)
external
lockable
onlyOwner
{
_baseTokenURI = _newBaseURI;
}
/**
* @notice Set provenance hash for the collection
* @param _provenanceHash New hash of the metadata
*/
function setProvenanceHash(string calldata _provenanceHash)
external
lockable
onlyOwner
{
if (bytes(provenanceHash).length != 0)
revert ProvenanceHashAlreadySet();
provenanceHash = _provenanceHash;
}
/**
* @notice Withdraw all ETH sent to the contract
*/
function withdraw() external onlyOwner {
(bool success, ) = payable(msg.sender).call{
value: address(this).balance
}("");
if (!success) revert WithdrawFailed();
}
function setApprovalForAll(address operator, bool approved)
public
override
{
super.setApprovalForAll(operator, approved);
}
function approve(address operator, uint256 tokenId)
public
payable
override
{
super.approve(operator, tokenId);
}
function transferFrom(
address from,
address to,
uint256 tokenId
)
public
payable
override
{
super.transferFrom(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
)
public
payable
override
{
super.safeTransferFrom(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory data
)
public
payable
override
{
super.safeTransferFrom(from, to, tokenId, data);
}
}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"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"ProvenanceHashAlreadySet","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":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"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":"operatorFilteringEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[],"name":"provenanceHash","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","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":"quan","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":"bool","name":"value","type":"bool"}],"name":"setOperatorFilteringEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_provenanceHash","type":"string"}],"name":"setProvenanceHash","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
608060405234801561000f575f5ffd5b50604051615bf0380380615bf083398181016040528101906100319190610551565b8282826040518060400160405280601181526020017f4d522e20426f6e652773204d6f746865720000000000000000000000000000008152506040518060400160405280601181526020017f4d522e20426f6e652773204d6f74686572000000000000000000000000000000815250818181600290816100b191906107de565b5080600390816100c191906107de565b506100d06101ac60201b60201c565b5f819055506100e36101ac60201b60201c565b6100f16101b460201b60201c565b101561010e5761010d63fed8210f60e01b6101db60201b60201c565b5b5050505061012282826101e360201b60201c565b50505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610194575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161018b91906108bc565b60405180910390fd5b6101a38161024560201b60201c565b50505050610963565b5f6001905090565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b805f5260045ffd5b6101f3828261030860201b60201c565b8173ffffffffffffffffffffffffffffffffffffffff167f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef8260405161023991906108e4565b60405180910390a25050565b5f600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f6103176104a960201b60201c565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff16111561037c5781816040517f6f483d0900000000000000000000000000000000000000000000000000000000815260040161037392919061093c565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036103ec575f6040517fb6d9900a0000000000000000000000000000000000000000000000000000000081526004016103e391906108bc565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff16815250600a5f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f612710905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6104df826104b6565b9050919050565b6104ef816104d5565b81146104f9575f5ffd5b50565b5f8151905061050a816104e6565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b61053081610510565b811461053a575f5ffd5b50565b5f8151905061054b81610527565b92915050565b5f5f5f60608486031215610568576105676104b2565b5b5f610575868287016104fc565b9350506020610586868287016104fc565b92505060406105978682870161053d565b9150509250925092565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061061c57607f821691505b60208210810361062f5761062e6105d8565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026106917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610656565b61069b8683610656565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6106df6106da6106d5846106b3565b6106bc565b6106b3565b9050919050565b5f819050919050565b6106f8836106c5565b61070c610704826106e6565b848454610662565b825550505050565b5f5f905090565b610723610714565b61072e8184846106ef565b505050565b5b81811015610751576107465f8261071b565b600181019050610734565b5050565b601f8211156107965761076781610635565b61077084610647565b8101602085101561077f578190505b61079361078b85610647565b830182610733565b50505b505050565b5f82821c905092915050565b5f6107b65f198460080261079b565b1980831691505092915050565b5f6107ce83836107a7565b9150826002028217905092915050565b6107e7826105a1565b67ffffffffffffffff811115610800576107ff6105ab565b5b61080a8254610605565b610815828285610755565b5f60209050601f831160018114610846575f8415610834578287015190505b61083e85826107c3565b8655506108a5565b601f19841661085486610635565b5f5b8281101561087b57848901518255600182019150602085019450602081019050610856565b868310156108985784890151610894601f8916826107a7565b8355505b6001600288020188555050505b505050505050565b6108b6816104d5565b82525050565b5f6020820190506108cf5f8301846108ad565b92915050565b6108de81610510565b82525050565b5f6020820190506108f75f8301846108d5565b92915050565b5f61091761091261090d84610510565b6106bc565b6106b3565b9050919050565b610927816108fd565b82525050565b610936816106b3565b82525050565b5f60408201905061094f5f83018561091e565b61095c602083018461092d565b9392505050565b615280806109705f395ff3fe608060405260043610610266575f3560e01c80636352211e11610143578063b88d4fde116100b5578063d007af5c11610079578063d007af5c146108d3578063dc33e681146108fd578063e985e9c514610939578063f2fde38b14610975578063fb796e6c1461099d578063fd762d92146109c757610266565b8063b88d4fde146107eb578063bbadfe7614610807578063be537f4314610843578063c6ab67a31461086d578063c87b56dd1461089757610266565b80638da5cb5b116101075780638da5cb5b146106e357806395d89b411461070d5780639d645a4414610737578063a22cb46514610773578063a9fc664e1461079b578063b7c0b8e8146107c357610266565b80636352211e146106175780636c3b86991461065357806370a0823114610669578063715018a6146106a557806374d0101d146106bb57610266565b806323b872dd116101dc57806342842e0e116101a057806342842e0e1461052f578063495c8bf91461054b57806355f804b3146105755780635944c7531461059d5780635d4c1d46146105c557806361347162146105ef57610266565b806323b872dd1461045c5780632a55205a146104785780632e8da829146104b557806334531828146104f15780633ccfd60b1461051957610266565b8063095ea7b31161022e578063095ea7b31461035e578063098144d41461037a57806310969523146103a457806318160ddd146103cc5780631b25b077146103f65780631c33b3281461043257610266565b8063014635461461026a57806301ffc9a71461029457806304634d8d146102d057806306fdde03146102f8578063081812fc14610322575b5f5ffd5b348015610275575f5ffd5b5061027e6109ef565b60405161028b9190613d5d565b60405180910390f35b34801561029f575f5ffd5b506102ba60048036038101906102b59190613ddc565b610a05565b6040516102c79190613e21565b60405180910390f35b3480156102db575f5ffd5b506102f660048036038101906102f19190613ea5565b610a16565b005b348015610303575f5ffd5b5061030c610a34565b6040516103199190613f53565b60405180910390f35b34801561032d575f5ffd5b5061034860048036038101906103439190613fa6565b610ac4565b6040516103559190613d5d565b60405180910390f35b61037860048036038101906103739190613fd1565b610b1d565b005b348015610385575f5ffd5b5061038e610b2b565b60405161039b919061406a565b60405180910390f35b3480156103af575f5ffd5b506103ca60048036038101906103c591906140e4565b610b53565b005b3480156103d7575f5ffd5b506103e0610c6e565b6040516103ed919061413e565b60405180910390f35b348015610401575f5ffd5b5061041c60048036038101906104179190614157565b610cb9565b6040516104299190613e21565b60405180910390f35b34801561043d575f5ffd5b50610446610db4565b604051610453919061421a565b60405180910390f35b61047660048036038101906104719190614233565b610db9565b005b348015610483575f5ffd5b5061049e60048036038101906104999190614283565b610dc9565b6040516104ac9291906142c1565b60405180910390f35b3480156104c0575f5ffd5b506104db60048036038101906104d691906142e8565b610eeb565b6040516104e89190613e21565b60405180910390f35b3480156104fc575f5ffd5b5061051760048036038101906105129190613ddc565b611087565b005b348015610524575f5ffd5b5061052d6110f9565b005b61054960048036038101906105449190614233565b6111a3565b005b348015610556575f5ffd5b5061055f6111b3565b60405161056c91906143ca565b60405180910390f35b348015610580575f5ffd5b5061059b600480360381019061059691906140e4565b611397565b005b3480156105a8575f5ffd5b506105c360048036038101906105be91906143ea565b61146b565b005b3480156105d0575f5ffd5b506105d961148b565b6040516105e69190614463565b60405180910390f35b3480156105fa575f5ffd5b50610615600480360381019061061091906144c9565b611490565b005b348015610622575f5ffd5b5061063d60048036038101906106389190613fa6565b611646565b60405161064a9190613d5d565b60405180910390f35b34801561065e575f5ffd5b50610667611657565b005b348015610674575f5ffd5b5061068f600480360381019061068a91906142e8565b611772565b60405161069c919061413e565b60405180910390f35b3480156106b0575f5ffd5b506106b9611806565b005b3480156106c6575f5ffd5b506106e160048036038101906106dc9190613fd1565b611819565b005b3480156106ee575f5ffd5b506106f76118e5565b6040516107049190613d5d565b60405180910390f35b348015610718575f5ffd5b5061072161190d565b60405161072e9190613f53565b60405180910390f35b348015610742575f5ffd5b5061075d600480360381019061075891906142e8565b61199d565b60405161076a9190613e21565b60405180910390f35b34801561077e575f5ffd5b5061079960048036038101906107949190614543565b611b39565b005b3480156107a6575f5ffd5b506107c160048036038101906107bc91906142e8565b611b47565b005b3480156107ce575f5ffd5b506107e960048036038101906107e49190614581565b611cff565b005b610805600480360381019061080091906146d4565b611dd9565b005b348015610812575f5ffd5b5061082d60048036038101906108289190613ddc565b611deb565b60405161083a9190613e21565b60405180910390f35b34801561084e575f5ffd5b50610857611e08565b60405161086491906147b2565b60405180910390f35b348015610878575f5ffd5b50610881611f59565b60405161088e9190613f53565b60405180910390f35b3480156108a2575f5ffd5b506108bd60048036038101906108b89190613fa6565b611fe5565b6040516108ca9190613f53565b60405180910390f35b3480156108de575f5ffd5b506108e7612089565b6040516108f491906143ca565b60405180910390f35b348015610908575f5ffd5b50610923600480360381019061091e91906142e8565b61226d565b604051610930919061413e565b60405180910390f35b348015610944575f5ffd5b5061095f600480360381019061095a91906147cb565b61227e565b60405161096c9190613e21565b60405180910390f35b348015610980575f5ffd5b5061099b600480360381019061099691906142e8565b61230c565b005b3480156109a8575f5ffd5b506109b1612390565b6040516109be9190613e21565b60405180910390f35b3480156109d2575f5ffd5b506109ed60048036038101906109e89190614809565b6123a2565b005b71721c310194ccfc01e523fc93c9cccfa2a0ac81565b5f610a0f826124f1565b9050919050565b610a1e61256a565b610a266125f1565b610a3082826125fb565b5050565b606060028054610a439061489a565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6f9061489a565b8015610aba5780601f10610a9157610100808354040283529160200191610aba565b820191905f5260205f20905b815481529060010190602001808311610a9d57829003601f168201915b5050505050905090565b5f610ace82612657565b610ae357610ae263cf4700e460e01b6126fa565b5b60065f8381526020019081526020015f205f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610b278282612702565b5050565b5f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60105f5f357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff1615610c09576040517f8bf9b99f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c1161256a565b5f600e8054610c1f9061489a565b905014610c58576040517f19e24c1100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8181600e9182610c69929190614a6b565b505050565b5f610c77612712565b6001545f54030390507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610ca961271a565b14610cb657600854810190505b90565b5f5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610da85760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663285fb8c88585856040518463ffffffff1660e01b8152600401610d6c93929190614b38565b5f6040518083038186803b158015610d82575f5ffd5b505afa925050508015610d93575060015b610d9f575f9050610dad565b60019050610dad565b600190505b9392505050565b600181565b610dc4838383612741565b505050565b5f5f5f600b5f8681526020019081526020015f2090505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f825f0160149054906101000a90046bffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610e9d57600a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150600a5f0160149054906101000a90046bffffffffffffffffffffffff1690505b5f610ea66129ec565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff1688610ece9190614b9a565b610ed89190614c08565b9050828195509550505050509250929050565b5f5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461107e5760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d72dde5e60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b8152600401610fd79190613d5d565b606060405180830381865afa158015610ff2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110169190614cc5565b60200151846040518363ffffffff1660e01b8152600401611038929190614cf0565b602060405180830381865afa158015611053573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110779190614d2b565b9050611082565b5f90505b919050565b61108f61256a565b600160105f837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f6101000a81548160ff02191690831515021790555050565b61110161256a565b5f3373ffffffffffffffffffffffffffffffffffffffff164760405161112690614d83565b5f6040518083038185875af1925050503d805f8114611160576040519150601f19603f3d011682016040523d82523d5f602084013e611165565b606091505b50509050806111a0576040517f750b219c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b6111ae8383836129f5565b505050565b60605f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146113485760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633fe5df9960095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b81526004016112a09190613d5d565b606060405180830381865afa1580156112bb573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112df9190614cc5565b602001516040518263ffffffff1660e01b81526004016112ff9190614463565b5f60405180830381865afa158015611319573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906113419190614e6b565b9050611394565b5f67ffffffffffffffff811115611362576113616145b0565b5b6040519080825280602002602001820160405280156113905781602001602082028036833780820191505090505b5090505b90565b60105f5f357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff161561144d576040517f8bf9b99f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61145561256a565b8181600d9182611466929190614a6b565b505050565b61147361256a565b61147b6125f1565b611486838383612a14565b505050565b600181565b6114986125f1565b5f6114a1610b2b565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611508576040517f39ffc7ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663da0194c030866040518363ffffffff1660e01b8152600401611543929190614eb2565b5f604051808303815f87803b15801561155a575f5ffd5b505af115801561156c573d5f5f3e3d5ffd5b505050508073ffffffffffffffffffffffffffffffffffffffff16632304aa0230856040518363ffffffff1660e01b81526004016115ab929190614ed9565b5f604051808303815f87803b1580156115c2575f5ffd5b505af11580156115d4573d5f5f3e3d5ffd5b505050508073ffffffffffffffffffffffffffffffffffffffff16638d74431430846040518363ffffffff1660e01b8152600401611613929190614ed9565b5f604051808303815f87803b15801561162a575f5ffd5b505af115801561163c573d5f5f3e3d5ffd5b5050505050505050565b5f61165082612a73565b9050919050565b61165f6125f1565b61167a71721c310194ccfc01e523fc93c9cccfa2a0ac611b47565b71721c310194ccfc01e523fc93c9cccfa2a0ac73ffffffffffffffffffffffffffffffffffffffff1663da0194c03060016040518363ffffffff1660e01b81526004016116c8929190614eb2565b5f604051808303815f87803b1580156116df575f5ffd5b505af11580156116f1573d5f5f3e3d5ffd5b5050505071721c310194ccfc01e523fc93c9cccfa2a0ac73ffffffffffffffffffffffffffffffffffffffff16632304aa023060016040518363ffffffff1660e01b8152600401611743929190614ed9565b5f604051808303815f87803b15801561175a575f5ffd5b505af115801561176c573d5f5f3e3d5ffd5b50505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036117b7576117b6638f4eb60460e01b6126fa565b5b67ffffffffffffffff60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054169050919050565b61180e61256a565b6118175f612b82565b565b60105f5f357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff16156118cf576040517f8bf9b99f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118d761256a565b6118e18282612c45565b5050565b5f600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606003805461191c9061489a565b80601f01602080910402602001604051908101604052809291908181526020018280546119489061489a565b80156119935780601f1061196a57610100808354040283529160200191611993565b820191905f5260205f20905b81548152906001019060200180831161197657829003601f168201915b5050505050905090565b5f5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611b305760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639445f53060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b8152600401611a899190613d5d565b606060405180830381865afa158015611aa4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ac89190614cc5565b60400151846040518363ffffffff1660e01b8152600401611aea929190614cf0565b602060405180830381865afa158015611b05573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b299190614d2b565b9050611b34565b5f90505b919050565b611b438282612db9565b5050565b611b4f6125f1565b5f5f90505f8273ffffffffffffffffffffffffffffffffffffffff163b1115611bf0578173ffffffffffffffffffffffffffffffffffffffff166301ffc9a75f6040518263ffffffff1660e01b8152600401611bab9190614f0f565b602060405180830381865afa925050508015611be557506040513d601f19601f82011682018060405250810190611be29190614d2b565b60015b15611bef57809150505b5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015611c2a575080155b15611c61576040517f32483afb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fcc5dc080ff977b3c3a211fa63ab74f90f658f5ba9d3236e92c8f59570f442aac60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683604051611cb3929190614f28565b60405180910390a18160095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b60105f5f357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff1615611db5576040517f8bf9b99f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbd61256a565b80600f5f6101000a81548160ff02191690831515021790555050565b611de584848484612ebf565b50505050565b6010602052805f5260405f205f915054906101000a900460ff1681565b611e10613ccc565b5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611f045760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b8152600401611ebe9190613d5d565b606060405180830381865afa158015611ed9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611efd9190614cc5565b9050611f56565b60405180606001604052805f6006811115611f2257611f216141a7565b5b81526020015f6effffffffffffffffffffffffffffff1681526020015f6effffffffffffffffffffffffffffff1681525090505b90565b600e8054611f669061489a565b80601f0160208091040260200160405190810160405280929190818152602001828054611f929061489a565b8015611fdd5780601f10611fb457610100808354040283529160200191611fdd565b820191905f5260205f20905b815481529060010190602001808311611fc057829003601f168201915b505050505081565b6060611ff082612657565b61202f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161202690614fbf565b60405180910390fd5b5f612038612f10565b90505f8151116120565760405180602001604052805f815250612081565b8061206084612fa0565b604051602001612071929190615017565b6040516020818303038152906040525b915050919050565b60605f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461221e5760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166317e94a6c60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b81526004016121769190613d5d565b606060405180830381865afa158015612191573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121b59190614cc5565b604001516040518263ffffffff1660e01b81526004016121d59190614463565b5f60405180830381865afa1580156121ef573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906122179190614e6b565b905061226a565b5f67ffffffffffffffff811115612238576122376145b0565b5b6040519080825280602002602001820160405280156122665781602001602082028036833780820191505090505b5090505b90565b5f6122778261306a565b9050919050565b5f60075f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b61231461256a565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612384575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161237b9190613d5d565b60405180910390fd5b61238d81612b82565b50565b600f5f9054906101000a900460ff1681565b6123aa6125f1565b6123b384611b47565b8373ffffffffffffffffffffffffffffffffffffffff1663da0194c030856040518363ffffffff1660e01b81526004016123ee929190614eb2565b5f604051808303815f87803b158015612405575f5ffd5b505af1158015612417573d5f5f3e3d5ffd5b505050508373ffffffffffffffffffffffffffffffffffffffff16632304aa0230846040518363ffffffff1660e01b8152600401612456929190614ed9565b5f604051808303815f87803b15801561246d575f5ffd5b505af115801561247f573d5f5f3e3d5ffd5b505050508373ffffffffffffffffffffffffffffffffffffffff16638d74431430836040518363ffffffff1660e01b81526004016124be929190614ed9565b5f604051808303815f87803b1580156124d5575f5ffd5b505af11580156124e7573d5f5f3e3d5ffd5b5050505050505050565b5f7f86455d28000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806125635750612562826130be565b5b9050919050565b61257261314f565b73ffffffffffffffffffffffffffffffffffffffff166125906118e5565b73ffffffffffffffffffffffffffffffffffffffff16146125ef576125b361314f565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016125e69190613d5d565b60405180910390fd5b565b6125f961256a565b565b6126058282613156565b8173ffffffffffffffffffffffffffffffffffffffff167f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef8260405161264b9190615049565b60405180910390a25050565b5f81612661612712565b116126f45761266e61271a565b8211156126965761268f60045f8481526020019081526020015f20546132f1565b90506126f5565b5f548210156126f3575f5b5f60045f8581526020019081526020015f2054915081036126cd57826126c690615062565b92506126a1565b5f7c01000000000000000000000000000000000000000000000000000000008216149150505b5b5b919050565b805f5260045ffd5b61270e82826001613331565b5050565b5f6001905090565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b5f61274b82612a73565b905073ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161693508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146127c0576127bf63a114810060e01b6126fa565b5b5f5f6127cb8461345b565b915091506127e181876127dc61347e565b61348c565b61280c576127f6866127f161347e565b61227e565b61280b5761280a6359c896be60e01b6126fa565b5b5b61281986868660016134cf565b8015612823575f82555b60055f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154600190039190508190555060055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154600101919050819055506128eb856128c7888887613504565b7c02000000000000000000000000000000000000000000000000000000001761352b565b60045f8681526020019081526020015f20819055505f7c0200000000000000000000000000000000000000000000000000000000841603612967575f6001850190505f60045f8381526020019081526020015f205403612965575f548114612964578360045f8381526020019081526020015f20819055505b5b505b5f73ffffffffffffffffffffffffffffffffffffffff8673ffffffffffffffffffffffffffffffffffffffff161690508481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f5fa45f81036129d6576129d563ea553b3460e01b6126fa565b5b6129e38787876001613555565b50505050505050565b5f612710905090565b612a0f83838360405180602001604052805f815250611dd9565b505050565b612a1f83838361358a565b8173ffffffffffffffffffffffffffffffffffffffff16837f7f5b076c952c0ec86e5425963c1326dd0f03a3595c19f81d765e8ff559a6e33c83604051612a669190615049565b60405180910390a3505050565b5f81612a7d612712565b11612b6c5760045f8381526020019081526020015f20549050612a9e61271a565b821115612ac357612aae816132f1565b612b7d57612ac263df2d9b4260e01b6126fa565b5b5f8103612b44575f548210612ae357612ae263df2d9b4260e01b6126fa565b5b5b60045f836001900393508381526020019081526020015f205490505f810315612b3f575f7c010000000000000000000000000000000000000000000000000000000082160315612b7d57612b3e63df2d9b4260e01b6126fa565b5b612ae4565b5f7c010000000000000000000000000000000000000000000000000000000082160315612b7d575b612b7c63df2d9b4260e01b6126fa565b5b919050565b5f600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f5f5490505f8203612c6257612c6163b562e8dd60e01b6126fa565b5b612c6e5f8483856134cf565b612c8c83612c7d5f865f613504565b612c8685613739565b1761352b565b60045f8381526020019081526020015f2081905550600160406001901b17820260055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505f73ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161690505f8103612d3d57612d3c632e07630060e01b6126fa565b5b5f83830190505f839050612d4f61271a565b600183031115612d6a57612d696381647e3a60e01b6126fa565b5b5b80835f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f5fa4818160010191508103612d6b57815f81905550505050612db45f848385613555565b505050565b8060075f612dc561347e565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16612e6e61347e565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051612eb39190613e21565b60405180910390a35050565b612eca848484610db9565b5f8373ffffffffffffffffffffffffffffffffffffffff163b14612f0a57612ef484848484613748565b612f0957612f0863d1a57ed660e01b6126fa565b5b5b50505050565b6060600d8054612f1f9061489a565b80601f0160208091040260200160405190810160405280929190818152602001828054612f4b9061489a565b8015612f965780601f10612f6d57610100808354040283529160200191612f96565b820191905f5260205f20905b815481529060010190602001808311612f7957829003601f168201915b5050505050905090565b60605f6001612fae84613872565b0190505f8167ffffffffffffffff811115612fcc57612fcb6145b0565b5b6040519080825280601f01601f191660200182016040528015612ffe5781602001600182028036833780820191505090505b5090505f82602001820190505b60011561305f578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161305457613053614bdb565b5b0494505f850361300b575b819350505050919050565b5f67ffffffffffffffff604060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054901c169050919050565b5f6301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061311857506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806131485750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b5f33905090565b5f61315f6129ec565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff1611156131c45781816040517f6f483d090000000000000000000000000000000000000000000000000000000081526004016131bb9291906150b9565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603613234575f6040517fb6d9900a00000000000000000000000000000000000000000000000000000000815260040161322b9190613d5d565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff16815250600a5f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f7c0100000000000000000000000000000000000000000000000000000000821673ffffffffffffffffffffffffffffffffffffffff8316119050919050565b5f61333b83611646565b905081801561337d57508073ffffffffffffffffffffffffffffffffffffffff1661336461347e565b73ffffffffffffffffffffffffffffffffffffffff1614155b156133a9576133938161338e61347e565b61227e565b6133a8576133a763cfb3b94260e01b6126fa565b5b5b8360065f8581526020019081526020015f205f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a450505050565b5f5f5f60065f8581526020019081526020015f2090508092508254915050915091565b5f61348761314f565b905090565b5f73ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b5f5f90505b818110156134fd576134f2858583866134ed91906150e0565b6139c3565b8060010190506134d4565b5050505050565b5f5f60e883901c905060e861351a868684613ac1565b62ffffff16901b9150509392505050565b5f73ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b5f5f90505b81811015613583576135788585838661357391906150e0565b613ac9565b80600101905061355a565b5050505050565b5f6135936129ec565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff1611156135fa578382826040517fdfd1fc1b0000000000000000000000000000000000000000000000000000000081526004016135f193929190615113565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361366c57835f6040517f969f0852000000000000000000000000000000000000000000000000000000008152600401613663929190615148565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff16815250600b5f8681526020019081526020015f205f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555090505050505050565b5f6001821460e11b9050919050565b5f8373ffffffffffffffffffffffffffffffffffffffff1663150b7a0261376d61347e565b8786866040518563ffffffff1660e01b815260040161378f94939291906151c1565b6020604051808303815f875af19250505080156137ca57506040513d601f19601f820116820180604052508101906137c7919061521f565b60015b61381f573d805f81146137f8576040519150601f19603f3d011682016040523d82523d5f602084013e6137fd565b606091505b505f8151036138175761381663d1a57ed660e01b6126fa565b5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b5f5f5f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106138ce577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816138c4576138c3614bdb565b5b0492506040810190505b6d04ee2d6d415b85acef8100000000831061390b576d04ee2d6d415b85acef8100000000838161390157613900614bdb565b5b0492506020810190505b662386f26fc10000831061393a57662386f26fc1000083816139305761392f614bdb565b5b0492506010810190505b6305f5e1008310613963576305f5e100838161395957613958614bdb565b5b0492506008810190505b612710831061398857612710838161397e5761397d614bdb565b5b0492506004810190505b606483106139ab57606483816139a1576139a0614bdb565b5b0492506002810190505b600a83106139ba576001810190505b80915050919050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161490505f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16149050818015613a315750805b15613a68576040517f5cbd944100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8115613a8657613a81613a7961314f565b858534613bc7565b613aba565b8015613aa457613a9f613a9761314f565b868534613bcd565b613ab9565b613ab8613aaf61314f565b86868634613bd3565b5b5b5050505050565b5f9392505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161490505f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16149050818015613b375750805b15613b6e576040517f5cbd944100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8115613b8c57613b87613b7f61314f565b858534613cb9565b613bc0565b8015613baa57613ba5613b9d61314f565b868534613cbf565b613bbf565b613bbe613bb561314f565b86868634613cc5565b5b5b5050505050565b50505050565b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613cb25760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663285fb8c88686866040518463ffffffff1660e01b8152600401613c8593929190614b38565b5f6040518083038186803b158015613c9b575f5ffd5b505afa158015613cad573d5f5f3e3d5ffd5b505050505b5050505050565b50505050565b50505050565b5050505050565b60405180606001604052805f6006811115613cea57613ce96141a7565b5b81526020015f6effffffffffffffffffffffffffffff1681526020015f6effffffffffffffffffffffffffffff1681525090565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613d4782613d1e565b9050919050565b613d5781613d3d565b82525050565b5f602082019050613d705f830184613d4e565b92915050565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613dbb81613d87565b8114613dc5575f5ffd5b50565b5f81359050613dd681613db2565b92915050565b5f60208284031215613df157613df0613d7f565b5b5f613dfe84828501613dc8565b91505092915050565b5f8115159050919050565b613e1b81613e07565b82525050565b5f602082019050613e345f830184613e12565b92915050565b613e4381613d3d565b8114613e4d575f5ffd5b50565b5f81359050613e5e81613e3a565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b613e8481613e64565b8114613e8e575f5ffd5b50565b5f81359050613e9f81613e7b565b92915050565b5f5f60408385031215613ebb57613eba613d7f565b5b5f613ec885828601613e50565b9250506020613ed985828601613e91565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f613f2582613ee3565b613f2f8185613eed565b9350613f3f818560208601613efd565b613f4881613f0b565b840191505092915050565b5f6020820190508181035f830152613f6b8184613f1b565b905092915050565b5f819050919050565b613f8581613f73565b8114613f8f575f5ffd5b50565b5f81359050613fa081613f7c565b92915050565b5f60208284031215613fbb57613fba613d7f565b5b5f613fc884828501613f92565b91505092915050565b5f5f60408385031215613fe757613fe6613d7f565b5b5f613ff485828601613e50565b925050602061400585828601613f92565b9150509250929050565b5f819050919050565b5f61403261402d61402884613d1e565b61400f565b613d1e565b9050919050565b5f61404382614018565b9050919050565b5f61405482614039565b9050919050565b6140648161404a565b82525050565b5f60208201905061407d5f83018461405b565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126140a4576140a3614083565b5b8235905067ffffffffffffffff8111156140c1576140c0614087565b5b6020830191508360018202830111156140dd576140dc61408b565b5b9250929050565b5f5f602083850312156140fa576140f9613d7f565b5b5f83013567ffffffffffffffff81111561411757614116613d83565b5b6141238582860161408f565b92509250509250929050565b61413881613f73565b82525050565b5f6020820190506141515f83018461412f565b92915050565b5f5f5f6060848603121561416e5761416d613d7f565b5b5f61417b86828701613e50565b935050602061418c86828701613e50565b925050604061419d86828701613e50565b9150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b600781106141e5576141e46141a7565b5b50565b5f8190506141f5826141d4565b919050565b5f614204826141e8565b9050919050565b614214816141fa565b82525050565b5f60208201905061422d5f83018461420b565b92915050565b5f5f5f6060848603121561424a57614249613d7f565b5b5f61425786828701613e50565b935050602061426886828701613e50565b925050604061427986828701613f92565b9150509250925092565b5f5f6040838503121561429957614298613d7f565b5b5f6142a685828601613f92565b92505060206142b785828601613f92565b9150509250929050565b5f6040820190506142d45f830185613d4e565b6142e1602083018461412f565b9392505050565b5f602082840312156142fd576142fc613d7f565b5b5f61430a84828501613e50565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61434581613d3d565b82525050565b5f614356838361433c565b60208301905092915050565b5f602082019050919050565b5f61437882614313565b614382818561431d565b935061438d8361432d565b805f5b838110156143bd5781516143a4888261434b565b97506143af83614362565b925050600181019050614390565b5085935050505092915050565b5f6020820190508181035f8301526143e2818461436e565b905092915050565b5f5f5f6060848603121561440157614400613d7f565b5b5f61440e86828701613f92565b935050602061441f86828701613e50565b925050604061443086828701613e91565b9150509250925092565b5f6effffffffffffffffffffffffffffff82169050919050565b61445d8161443a565b82525050565b5f6020820190506144765f830184614454565b92915050565b60078110614488575f5ffd5b50565b5f813590506144998161447c565b92915050565b6144a88161443a565b81146144b2575f5ffd5b50565b5f813590506144c38161449f565b92915050565b5f5f5f606084860312156144e0576144df613d7f565b5b5f6144ed8682870161448b565b93505060206144fe868287016144b5565b925050604061450f868287016144b5565b9150509250925092565b61452281613e07565b811461452c575f5ffd5b50565b5f8135905061453d81614519565b92915050565b5f5f6040838503121561455957614558613d7f565b5b5f61456685828601613e50565b92505060206145778582860161452f565b9150509250929050565b5f6020828403121561459657614595613d7f565b5b5f6145a38482850161452f565b91505092915050565b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6145e682613f0b565b810181811067ffffffffffffffff82111715614605576146046145b0565b5b80604052505050565b5f614617613d76565b905061462382826145dd565b919050565b5f67ffffffffffffffff821115614642576146416145b0565b5b61464b82613f0b565b9050602081019050919050565b828183375f83830152505050565b5f61467861467384614628565b61460e565b905082815260208101848484011115614694576146936145ac565b5b61469f848285614658565b509392505050565b5f82601f8301126146bb576146ba614083565b5b81356146cb848260208601614666565b91505092915050565b5f5f5f5f608085870312156146ec576146eb613d7f565b5b5f6146f987828801613e50565b945050602061470a87828801613e50565b935050604061471b87828801613f92565b925050606085013567ffffffffffffffff81111561473c5761473b613d83565b5b614748878288016146a7565b91505092959194509250565b61475d816141fa565b82525050565b61476c8161443a565b82525050565b606082015f8201516147865f850182614754565b5060208201516147996020850182614763565b5060408201516147ac6040850182614763565b50505050565b5f6060820190506147c55f830184614772565b92915050565b5f5f604083850312156147e1576147e0613d7f565b5b5f6147ee85828601613e50565b92505060206147ff85828601613e50565b9150509250929050565b5f5f5f5f6080858703121561482157614820613d7f565b5b5f61482e87828801613e50565b945050602061483f8782880161448b565b9350506040614850878288016144b5565b9250506060614861878288016144b5565b91505092959194509250565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806148b157607f821691505b6020821081036148c4576148c361486d565b5b50919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026149307fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826148f5565b61493a86836148f5565b95508019841693508086168417925050509392505050565b5f61496c61496761496284613f73565b61400f565b613f73565b9050919050565b5f819050919050565b61498583614952565b61499961499182614973565b848454614901565b825550505050565b5f5f905090565b6149b06149a1565b6149bb81848461497c565b505050565b5b818110156149de576149d35f826149a8565b6001810190506149c1565b5050565b601f821115614a23576149f4816148d4565b6149fd846148e6565b81016020851015614a0c578190505b614a20614a18856148e6565b8301826149c0565b50505b505050565b5f82821c905092915050565b5f614a435f1984600802614a28565b1980831691505092915050565b5f614a5b8383614a34565b9150826002028217905092915050565b614a7583836148ca565b67ffffffffffffffff811115614a8e57614a8d6145b0565b5b614a98825461489a565b614aa38282856149e2565b5f601f831160018114614ad0575f8415614abe578287013590505b614ac88582614a50565b865550614b2f565b601f198416614ade866148d4565b5f5b82811015614b0557848901358255600182019150602085019450602081019050614ae0565b86831015614b225784890135614b1e601f891682614a34565b8355505b6001600288020188555050505b50505050505050565b5f606082019050614b4b5f830186613d4e565b614b586020830185613d4e565b614b656040830184613d4e565b949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f614ba482613f73565b9150614baf83613f73565b9250828202614bbd81613f73565b91508282048414831517614bd457614bd3614b6d565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f614c1282613f73565b9150614c1d83613f73565b925082614c2d57614c2c614bdb565b5b828204905092915050565b5f5ffd5b5f81519050614c4a8161447c565b92915050565b5f81519050614c5e8161449f565b92915050565b5f60608284031215614c7957614c78614c38565b5b614c83606061460e565b90505f614c9284828501614c3c565b5f830152506020614ca584828501614c50565b6020830152506040614cb984828501614c50565b60408301525092915050565b5f60608284031215614cda57614cd9613d7f565b5b5f614ce784828501614c64565b91505092915050565b5f604082019050614d035f830185614454565b614d106020830184613d4e565b9392505050565b5f81519050614d2581614519565b92915050565b5f60208284031215614d4057614d3f613d7f565b5b5f614d4d84828501614d17565b91505092915050565b5f81905092915050565b50565b5f614d6e5f83614d56565b9150614d7982614d60565b5f82019050919050565b5f614d8d82614d63565b9150819050919050565b5f67ffffffffffffffff821115614db157614db06145b0565b5b602082029050602081019050919050565b5f81519050614dd081613e3a565b92915050565b5f614de8614de384614d97565b61460e565b90508083825260208201905060208402830185811115614e0b57614e0a61408b565b5b835b81811015614e345780614e208882614dc2565b845260208401935050602081019050614e0d565b5050509392505050565b5f82601f830112614e5257614e51614083565b5b8151614e62848260208601614dd6565b91505092915050565b5f60208284031215614e8057614e7f613d7f565b5b5f82015167ffffffffffffffff811115614e9d57614e9c613d83565b5b614ea984828501614e3e565b91505092915050565b5f604082019050614ec55f830185613d4e565b614ed2602083018461420b565b9392505050565b5f604082019050614eec5f830185613d4e565b614ef96020830184614454565b9392505050565b614f0981613d87565b82525050565b5f602082019050614f225f830184614f00565b92915050565b5f604082019050614f3b5f830185613d4e565b614f486020830184613d4e565b9392505050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f5f8201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b5f614fa9602f83613eed565b9150614fb482614f4f565b604082019050919050565b5f6020820190508181035f830152614fd681614f9d565b9050919050565b5f81905092915050565b5f614ff182613ee3565b614ffb8185614fdd565b935061500b818560208601613efd565b80840191505092915050565b5f6150228285614fe7565b915061502e8284614fe7565b91508190509392505050565b61504381613e64565b82525050565b5f60208201905061505c5f83018461503a565b92915050565b5f61506c82613f73565b91505f820361507e5761507d614b6d565b5b600182039050919050565b5f6150a361509e61509984613e64565b61400f565b613f73565b9050919050565b6150b381615089565b82525050565b5f6040820190506150cc5f8301856150aa565b6150d9602083018461412f565b9392505050565b5f6150ea82613f73565b91506150f583613f73565b925082820190508082111561510d5761510c614b6d565b5b92915050565b5f6060820190506151265f83018661412f565b61513360208301856150aa565b615140604083018461412f565b949350505050565b5f60408201905061515b5f83018561412f565b6151686020830184613d4e565b9392505050565b5f81519050919050565b5f82825260208201905092915050565b5f6151938261516f565b61519d8185615179565b93506151ad818560208601613efd565b6151b681613f0b565b840191505092915050565b5f6080820190506151d45f830187613d4e565b6151e16020830186613d4e565b6151ee604083018561412f565b81810360608301526152008184615189565b905095945050505050565b5f8151905061521981613db2565b92915050565b5f6020828403121561523457615233613d7f565b5b5f6152418482850161520b565b9150509291505056fea26469706673582212208d41f981a790e4b660c328ec8c35abe9134e13534a334d391c817be62a5a005664736f6c634300081e003300000000000000000000000059de7273191e6bf1907d614e94ecfbe8e5fb7318000000000000000000000000f8f8e62f0dd3dfda4635d75c5024251492ae73bd00000000000000000000000000000000000000000000000000000000000001f4
Deployed Bytecode
0x608060405260043610610266575f3560e01c80636352211e11610143578063b88d4fde116100b5578063d007af5c11610079578063d007af5c146108d3578063dc33e681146108fd578063e985e9c514610939578063f2fde38b14610975578063fb796e6c1461099d578063fd762d92146109c757610266565b8063b88d4fde146107eb578063bbadfe7614610807578063be537f4314610843578063c6ab67a31461086d578063c87b56dd1461089757610266565b80638da5cb5b116101075780638da5cb5b146106e357806395d89b411461070d5780639d645a4414610737578063a22cb46514610773578063a9fc664e1461079b578063b7c0b8e8146107c357610266565b80636352211e146106175780636c3b86991461065357806370a0823114610669578063715018a6146106a557806374d0101d146106bb57610266565b806323b872dd116101dc57806342842e0e116101a057806342842e0e1461052f578063495c8bf91461054b57806355f804b3146105755780635944c7531461059d5780635d4c1d46146105c557806361347162146105ef57610266565b806323b872dd1461045c5780632a55205a146104785780632e8da829146104b557806334531828146104f15780633ccfd60b1461051957610266565b8063095ea7b31161022e578063095ea7b31461035e578063098144d41461037a57806310969523146103a457806318160ddd146103cc5780631b25b077146103f65780631c33b3281461043257610266565b8063014635461461026a57806301ffc9a71461029457806304634d8d146102d057806306fdde03146102f8578063081812fc14610322575b5f5ffd5b348015610275575f5ffd5b5061027e6109ef565b60405161028b9190613d5d565b60405180910390f35b34801561029f575f5ffd5b506102ba60048036038101906102b59190613ddc565b610a05565b6040516102c79190613e21565b60405180910390f35b3480156102db575f5ffd5b506102f660048036038101906102f19190613ea5565b610a16565b005b348015610303575f5ffd5b5061030c610a34565b6040516103199190613f53565b60405180910390f35b34801561032d575f5ffd5b5061034860048036038101906103439190613fa6565b610ac4565b6040516103559190613d5d565b60405180910390f35b61037860048036038101906103739190613fd1565b610b1d565b005b348015610385575f5ffd5b5061038e610b2b565b60405161039b919061406a565b60405180910390f35b3480156103af575f5ffd5b506103ca60048036038101906103c591906140e4565b610b53565b005b3480156103d7575f5ffd5b506103e0610c6e565b6040516103ed919061413e565b60405180910390f35b348015610401575f5ffd5b5061041c60048036038101906104179190614157565b610cb9565b6040516104299190613e21565b60405180910390f35b34801561043d575f5ffd5b50610446610db4565b604051610453919061421a565b60405180910390f35b61047660048036038101906104719190614233565b610db9565b005b348015610483575f5ffd5b5061049e60048036038101906104999190614283565b610dc9565b6040516104ac9291906142c1565b60405180910390f35b3480156104c0575f5ffd5b506104db60048036038101906104d691906142e8565b610eeb565b6040516104e89190613e21565b60405180910390f35b3480156104fc575f5ffd5b5061051760048036038101906105129190613ddc565b611087565b005b348015610524575f5ffd5b5061052d6110f9565b005b61054960048036038101906105449190614233565b6111a3565b005b348015610556575f5ffd5b5061055f6111b3565b60405161056c91906143ca565b60405180910390f35b348015610580575f5ffd5b5061059b600480360381019061059691906140e4565b611397565b005b3480156105a8575f5ffd5b506105c360048036038101906105be91906143ea565b61146b565b005b3480156105d0575f5ffd5b506105d961148b565b6040516105e69190614463565b60405180910390f35b3480156105fa575f5ffd5b50610615600480360381019061061091906144c9565b611490565b005b348015610622575f5ffd5b5061063d60048036038101906106389190613fa6565b611646565b60405161064a9190613d5d565b60405180910390f35b34801561065e575f5ffd5b50610667611657565b005b348015610674575f5ffd5b5061068f600480360381019061068a91906142e8565b611772565b60405161069c919061413e565b60405180910390f35b3480156106b0575f5ffd5b506106b9611806565b005b3480156106c6575f5ffd5b506106e160048036038101906106dc9190613fd1565b611819565b005b3480156106ee575f5ffd5b506106f76118e5565b6040516107049190613d5d565b60405180910390f35b348015610718575f5ffd5b5061072161190d565b60405161072e9190613f53565b60405180910390f35b348015610742575f5ffd5b5061075d600480360381019061075891906142e8565b61199d565b60405161076a9190613e21565b60405180910390f35b34801561077e575f5ffd5b5061079960048036038101906107949190614543565b611b39565b005b3480156107a6575f5ffd5b506107c160048036038101906107bc91906142e8565b611b47565b005b3480156107ce575f5ffd5b506107e960048036038101906107e49190614581565b611cff565b005b610805600480360381019061080091906146d4565b611dd9565b005b348015610812575f5ffd5b5061082d60048036038101906108289190613ddc565b611deb565b60405161083a9190613e21565b60405180910390f35b34801561084e575f5ffd5b50610857611e08565b60405161086491906147b2565b60405180910390f35b348015610878575f5ffd5b50610881611f59565b60405161088e9190613f53565b60405180910390f35b3480156108a2575f5ffd5b506108bd60048036038101906108b89190613fa6565b611fe5565b6040516108ca9190613f53565b60405180910390f35b3480156108de575f5ffd5b506108e7612089565b6040516108f491906143ca565b60405180910390f35b348015610908575f5ffd5b50610923600480360381019061091e91906142e8565b61226d565b604051610930919061413e565b60405180910390f35b348015610944575f5ffd5b5061095f600480360381019061095a91906147cb565b61227e565b60405161096c9190613e21565b60405180910390f35b348015610980575f5ffd5b5061099b600480360381019061099691906142e8565b61230c565b005b3480156109a8575f5ffd5b506109b1612390565b6040516109be9190613e21565b60405180910390f35b3480156109d2575f5ffd5b506109ed60048036038101906109e89190614809565b6123a2565b005b71721c310194ccfc01e523fc93c9cccfa2a0ac81565b5f610a0f826124f1565b9050919050565b610a1e61256a565b610a266125f1565b610a3082826125fb565b5050565b606060028054610a439061489a565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6f9061489a565b8015610aba5780601f10610a9157610100808354040283529160200191610aba565b820191905f5260205f20905b815481529060010190602001808311610a9d57829003601f168201915b5050505050905090565b5f610ace82612657565b610ae357610ae263cf4700e460e01b6126fa565b5b60065f8381526020019081526020015f205f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610b278282612702565b5050565b5f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60105f5f357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff1615610c09576040517f8bf9b99f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c1161256a565b5f600e8054610c1f9061489a565b905014610c58576040517f19e24c1100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8181600e9182610c69929190614a6b565b505050565b5f610c77612712565b6001545f54030390507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610ca961271a565b14610cb657600854810190505b90565b5f5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610da85760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663285fb8c88585856040518463ffffffff1660e01b8152600401610d6c93929190614b38565b5f6040518083038186803b158015610d82575f5ffd5b505afa925050508015610d93575060015b610d9f575f9050610dad565b60019050610dad565b600190505b9392505050565b600181565b610dc4838383612741565b505050565b5f5f5f600b5f8681526020019081526020015f2090505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f825f0160149054906101000a90046bffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610e9d57600a5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150600a5f0160149054906101000a90046bffffffffffffffffffffffff1690505b5f610ea66129ec565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff1688610ece9190614b9a565b610ed89190614c08565b9050828195509550505050509250929050565b5f5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461107e5760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d72dde5e60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b8152600401610fd79190613d5d565b606060405180830381865afa158015610ff2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110169190614cc5565b60200151846040518363ffffffff1660e01b8152600401611038929190614cf0565b602060405180830381865afa158015611053573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110779190614d2b565b9050611082565b5f90505b919050565b61108f61256a565b600160105f837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f6101000a81548160ff02191690831515021790555050565b61110161256a565b5f3373ffffffffffffffffffffffffffffffffffffffff164760405161112690614d83565b5f6040518083038185875af1925050503d805f8114611160576040519150601f19603f3d011682016040523d82523d5f602084013e611165565b606091505b50509050806111a0576040517f750b219c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b6111ae8383836129f5565b505050565b60605f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146113485760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633fe5df9960095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b81526004016112a09190613d5d565b606060405180830381865afa1580156112bb573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112df9190614cc5565b602001516040518263ffffffff1660e01b81526004016112ff9190614463565b5f60405180830381865afa158015611319573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906113419190614e6b565b9050611394565b5f67ffffffffffffffff811115611362576113616145b0565b5b6040519080825280602002602001820160405280156113905781602001602082028036833780820191505090505b5090505b90565b60105f5f357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff161561144d576040517f8bf9b99f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61145561256a565b8181600d9182611466929190614a6b565b505050565b61147361256a565b61147b6125f1565b611486838383612a14565b505050565b600181565b6114986125f1565b5f6114a1610b2b565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611508576040517f39ffc7ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663da0194c030866040518363ffffffff1660e01b8152600401611543929190614eb2565b5f604051808303815f87803b15801561155a575f5ffd5b505af115801561156c573d5f5f3e3d5ffd5b505050508073ffffffffffffffffffffffffffffffffffffffff16632304aa0230856040518363ffffffff1660e01b81526004016115ab929190614ed9565b5f604051808303815f87803b1580156115c2575f5ffd5b505af11580156115d4573d5f5f3e3d5ffd5b505050508073ffffffffffffffffffffffffffffffffffffffff16638d74431430846040518363ffffffff1660e01b8152600401611613929190614ed9565b5f604051808303815f87803b15801561162a575f5ffd5b505af115801561163c573d5f5f3e3d5ffd5b5050505050505050565b5f61165082612a73565b9050919050565b61165f6125f1565b61167a71721c310194ccfc01e523fc93c9cccfa2a0ac611b47565b71721c310194ccfc01e523fc93c9cccfa2a0ac73ffffffffffffffffffffffffffffffffffffffff1663da0194c03060016040518363ffffffff1660e01b81526004016116c8929190614eb2565b5f604051808303815f87803b1580156116df575f5ffd5b505af11580156116f1573d5f5f3e3d5ffd5b5050505071721c310194ccfc01e523fc93c9cccfa2a0ac73ffffffffffffffffffffffffffffffffffffffff16632304aa023060016040518363ffffffff1660e01b8152600401611743929190614ed9565b5f604051808303815f87803b15801561175a575f5ffd5b505af115801561176c573d5f5f3e3d5ffd5b50505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036117b7576117b6638f4eb60460e01b6126fa565b5b67ffffffffffffffff60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054169050919050565b61180e61256a565b6118175f612b82565b565b60105f5f357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff16156118cf576040517f8bf9b99f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118d761256a565b6118e18282612c45565b5050565b5f600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606003805461191c9061489a565b80601f01602080910402602001604051908101604052809291908181526020018280546119489061489a565b80156119935780601f1061196a57610100808354040283529160200191611993565b820191905f5260205f20905b81548152906001019060200180831161197657829003601f168201915b5050505050905090565b5f5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611b305760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639445f53060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b8152600401611a899190613d5d565b606060405180830381865afa158015611aa4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ac89190614cc5565b60400151846040518363ffffffff1660e01b8152600401611aea929190614cf0565b602060405180830381865afa158015611b05573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b299190614d2b565b9050611b34565b5f90505b919050565b611b438282612db9565b5050565b611b4f6125f1565b5f5f90505f8273ffffffffffffffffffffffffffffffffffffffff163b1115611bf0578173ffffffffffffffffffffffffffffffffffffffff166301ffc9a75f6040518263ffffffff1660e01b8152600401611bab9190614f0f565b602060405180830381865afa925050508015611be557506040513d601f19601f82011682018060405250810190611be29190614d2b565b60015b15611bef57809150505b5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015611c2a575080155b15611c61576040517f32483afb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fcc5dc080ff977b3c3a211fa63ab74f90f658f5ba9d3236e92c8f59570f442aac60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683604051611cb3929190614f28565b60405180910390a18160095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b60105f5f357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff1615611db5576040517f8bf9b99f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbd61256a565b80600f5f6101000a81548160ff02191690831515021790555050565b611de584848484612ebf565b50505050565b6010602052805f5260405f205f915054906101000a900460ff1681565b611e10613ccc565b5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611f045760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b8152600401611ebe9190613d5d565b606060405180830381865afa158015611ed9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611efd9190614cc5565b9050611f56565b60405180606001604052805f6006811115611f2257611f216141a7565b5b81526020015f6effffffffffffffffffffffffffffff1681526020015f6effffffffffffffffffffffffffffff1681525090505b90565b600e8054611f669061489a565b80601f0160208091040260200160405190810160405280929190818152602001828054611f929061489a565b8015611fdd5780601f10611fb457610100808354040283529160200191611fdd565b820191905f5260205f20905b815481529060010190602001808311611fc057829003601f168201915b505050505081565b6060611ff082612657565b61202f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161202690614fbf565b60405180910390fd5b5f612038612f10565b90505f8151116120565760405180602001604052805f815250612081565b8061206084612fa0565b604051602001612071929190615017565b6040516020818303038152906040525b915050919050565b60605f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461221e5760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166317e94a6c60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9554552306040518263ffffffff1660e01b81526004016121769190613d5d565b606060405180830381865afa158015612191573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121b59190614cc5565b604001516040518263ffffffff1660e01b81526004016121d59190614463565b5f60405180830381865afa1580156121ef573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906122179190614e6b565b905061226a565b5f67ffffffffffffffff811115612238576122376145b0565b5b6040519080825280602002602001820160405280156122665781602001602082028036833780820191505090505b5090505b90565b5f6122778261306a565b9050919050565b5f60075f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b61231461256a565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612384575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161237b9190613d5d565b60405180910390fd5b61238d81612b82565b50565b600f5f9054906101000a900460ff1681565b6123aa6125f1565b6123b384611b47565b8373ffffffffffffffffffffffffffffffffffffffff1663da0194c030856040518363ffffffff1660e01b81526004016123ee929190614eb2565b5f604051808303815f87803b158015612405575f5ffd5b505af1158015612417573d5f5f3e3d5ffd5b505050508373ffffffffffffffffffffffffffffffffffffffff16632304aa0230846040518363ffffffff1660e01b8152600401612456929190614ed9565b5f604051808303815f87803b15801561246d575f5ffd5b505af115801561247f573d5f5f3e3d5ffd5b505050508373ffffffffffffffffffffffffffffffffffffffff16638d74431430836040518363ffffffff1660e01b81526004016124be929190614ed9565b5f604051808303815f87803b1580156124d5575f5ffd5b505af11580156124e7573d5f5f3e3d5ffd5b5050505050505050565b5f7f86455d28000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806125635750612562826130be565b5b9050919050565b61257261314f565b73ffffffffffffffffffffffffffffffffffffffff166125906118e5565b73ffffffffffffffffffffffffffffffffffffffff16146125ef576125b361314f565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016125e69190613d5d565b60405180910390fd5b565b6125f961256a565b565b6126058282613156565b8173ffffffffffffffffffffffffffffffffffffffff167f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef8260405161264b9190615049565b60405180910390a25050565b5f81612661612712565b116126f45761266e61271a565b8211156126965761268f60045f8481526020019081526020015f20546132f1565b90506126f5565b5f548210156126f3575f5b5f60045f8581526020019081526020015f2054915081036126cd57826126c690615062565b92506126a1565b5f7c01000000000000000000000000000000000000000000000000000000008216149150505b5b5b919050565b805f5260045ffd5b61270e82826001613331565b5050565b5f6001905090565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905090565b5f61274b82612a73565b905073ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161693508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146127c0576127bf63a114810060e01b6126fa565b5b5f5f6127cb8461345b565b915091506127e181876127dc61347e565b61348c565b61280c576127f6866127f161347e565b61227e565b61280b5761280a6359c896be60e01b6126fa565b5b5b61281986868660016134cf565b8015612823575f82555b60055f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154600190039190508190555060055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154600101919050819055506128eb856128c7888887613504565b7c02000000000000000000000000000000000000000000000000000000001761352b565b60045f8681526020019081526020015f20819055505f7c0200000000000000000000000000000000000000000000000000000000841603612967575f6001850190505f60045f8381526020019081526020015f205403612965575f548114612964578360045f8381526020019081526020015f20819055505b5b505b5f73ffffffffffffffffffffffffffffffffffffffff8673ffffffffffffffffffffffffffffffffffffffff161690508481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f5fa45f81036129d6576129d563ea553b3460e01b6126fa565b5b6129e38787876001613555565b50505050505050565b5f612710905090565b612a0f83838360405180602001604052805f815250611dd9565b505050565b612a1f83838361358a565b8173ffffffffffffffffffffffffffffffffffffffff16837f7f5b076c952c0ec86e5425963c1326dd0f03a3595c19f81d765e8ff559a6e33c83604051612a669190615049565b60405180910390a3505050565b5f81612a7d612712565b11612b6c5760045f8381526020019081526020015f20549050612a9e61271a565b821115612ac357612aae816132f1565b612b7d57612ac263df2d9b4260e01b6126fa565b5b5f8103612b44575f548210612ae357612ae263df2d9b4260e01b6126fa565b5b5b60045f836001900393508381526020019081526020015f205490505f810315612b3f575f7c010000000000000000000000000000000000000000000000000000000082160315612b7d57612b3e63df2d9b4260e01b6126fa565b5b612ae4565b5f7c010000000000000000000000000000000000000000000000000000000082160315612b7d575b612b7c63df2d9b4260e01b6126fa565b5b919050565b5f600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f5f5490505f8203612c6257612c6163b562e8dd60e01b6126fa565b5b612c6e5f8483856134cf565b612c8c83612c7d5f865f613504565b612c8685613739565b1761352b565b60045f8381526020019081526020015f2081905550600160406001901b17820260055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505f73ffffffffffffffffffffffffffffffffffffffff8473ffffffffffffffffffffffffffffffffffffffff161690505f8103612d3d57612d3c632e07630060e01b6126fa565b5b5f83830190505f839050612d4f61271a565b600183031115612d6a57612d696381647e3a60e01b6126fa565b5b5b80835f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f5fa4818160010191508103612d6b57815f81905550505050612db45f848385613555565b505050565b8060075f612dc561347e565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16612e6e61347e565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051612eb39190613e21565b60405180910390a35050565b612eca848484610db9565b5f8373ffffffffffffffffffffffffffffffffffffffff163b14612f0a57612ef484848484613748565b612f0957612f0863d1a57ed660e01b6126fa565b5b5b50505050565b6060600d8054612f1f9061489a565b80601f0160208091040260200160405190810160405280929190818152602001828054612f4b9061489a565b8015612f965780601f10612f6d57610100808354040283529160200191612f96565b820191905f5260205f20905b815481529060010190602001808311612f7957829003601f168201915b5050505050905090565b60605f6001612fae84613872565b0190505f8167ffffffffffffffff811115612fcc57612fcb6145b0565b5b6040519080825280601f01601f191660200182016040528015612ffe5781602001600182028036833780820191505090505b5090505f82602001820190505b60011561305f578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161305457613053614bdb565b5b0494505f850361300b575b819350505050919050565b5f67ffffffffffffffff604060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054901c169050919050565b5f6301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061311857506380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806131485750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b5f33905090565b5f61315f6129ec565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff1611156131c45781816040517f6f483d090000000000000000000000000000000000000000000000000000000081526004016131bb9291906150b9565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603613234575f6040517fb6d9900a00000000000000000000000000000000000000000000000000000000815260040161322b9190613d5d565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff16815250600a5f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f7c0100000000000000000000000000000000000000000000000000000000821673ffffffffffffffffffffffffffffffffffffffff8316119050919050565b5f61333b83611646565b905081801561337d57508073ffffffffffffffffffffffffffffffffffffffff1661336461347e565b73ffffffffffffffffffffffffffffffffffffffff1614155b156133a9576133938161338e61347e565b61227e565b6133a8576133a763cfb3b94260e01b6126fa565b5b5b8360065f8581526020019081526020015f205f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550828473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a450505050565b5f5f5f60065f8581526020019081526020015f2090508092508254915050915091565b5f61348761314f565b905090565b5f73ffffffffffffffffffffffffffffffffffffffff8316925073ffffffffffffffffffffffffffffffffffffffff821691508382148383141790509392505050565b5f5f90505b818110156134fd576134f2858583866134ed91906150e0565b6139c3565b8060010190506134d4565b5050505050565b5f5f60e883901c905060e861351a868684613ac1565b62ffffff16901b9150509392505050565b5f73ffffffffffffffffffffffffffffffffffffffff83169250814260a01b178317905092915050565b5f5f90505b81811015613583576135788585838661357391906150e0565b613ac9565b80600101905061355a565b5050505050565b5f6135936129ec565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff1611156135fa578382826040517fdfd1fc1b0000000000000000000000000000000000000000000000000000000081526004016135f193929190615113565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361366c57835f6040517f969f0852000000000000000000000000000000000000000000000000000000008152600401613663929190615148565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff16815250600b5f8681526020019081526020015f205f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555090505050505050565b5f6001821460e11b9050919050565b5f8373ffffffffffffffffffffffffffffffffffffffff1663150b7a0261376d61347e565b8786866040518563ffffffff1660e01b815260040161378f94939291906151c1565b6020604051808303815f875af19250505080156137ca57506040513d601f19601f820116820180604052508101906137c7919061521f565b60015b61381f573d805f81146137f8576040519150601f19603f3d011682016040523d82523d5f602084013e6137fd565b606091505b505f8151036138175761381663d1a57ed660e01b6126fa565b5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b5f5f5f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106138ce577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816138c4576138c3614bdb565b5b0492506040810190505b6d04ee2d6d415b85acef8100000000831061390b576d04ee2d6d415b85acef8100000000838161390157613900614bdb565b5b0492506020810190505b662386f26fc10000831061393a57662386f26fc1000083816139305761392f614bdb565b5b0492506010810190505b6305f5e1008310613963576305f5e100838161395957613958614bdb565b5b0492506008810190505b612710831061398857612710838161397e5761397d614bdb565b5b0492506004810190505b606483106139ab57606483816139a1576139a0614bdb565b5b0492506002810190505b600a83106139ba576001810190505b80915050919050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161490505f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16149050818015613a315750805b15613a68576040517f5cbd944100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8115613a8657613a81613a7961314f565b858534613bc7565b613aba565b8015613aa457613a9f613a9761314f565b868534613bcd565b613ab9565b613ab8613aaf61314f565b86868634613bd3565b5b5b5050505050565b5f9392505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161490505f5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16149050818015613b375750805b15613b6e576040517f5cbd944100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8115613b8c57613b87613b7f61314f565b858534613cb9565b613bc0565b8015613baa57613ba5613b9d61314f565b868534613cbf565b613bbf565b613bbe613bb561314f565b86868634613cc5565b5b5b5050505050565b50505050565b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff1660095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613cb25760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663285fb8c88686866040518463ffffffff1660e01b8152600401613c8593929190614b38565b5f6040518083038186803b158015613c9b575f5ffd5b505afa158015613cad573d5f5f3e3d5ffd5b505050505b5050505050565b50505050565b50505050565b5050505050565b60405180606001604052805f6006811115613cea57613ce96141a7565b5b81526020015f6effffffffffffffffffffffffffffff1681526020015f6effffffffffffffffffffffffffffff1681525090565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613d4782613d1e565b9050919050565b613d5781613d3d565b82525050565b5f602082019050613d705f830184613d4e565b92915050565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613dbb81613d87565b8114613dc5575f5ffd5b50565b5f81359050613dd681613db2565b92915050565b5f60208284031215613df157613df0613d7f565b5b5f613dfe84828501613dc8565b91505092915050565b5f8115159050919050565b613e1b81613e07565b82525050565b5f602082019050613e345f830184613e12565b92915050565b613e4381613d3d565b8114613e4d575f5ffd5b50565b5f81359050613e5e81613e3a565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b613e8481613e64565b8114613e8e575f5ffd5b50565b5f81359050613e9f81613e7b565b92915050565b5f5f60408385031215613ebb57613eba613d7f565b5b5f613ec885828601613e50565b9250506020613ed985828601613e91565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f613f2582613ee3565b613f2f8185613eed565b9350613f3f818560208601613efd565b613f4881613f0b565b840191505092915050565b5f6020820190508181035f830152613f6b8184613f1b565b905092915050565b5f819050919050565b613f8581613f73565b8114613f8f575f5ffd5b50565b5f81359050613fa081613f7c565b92915050565b5f60208284031215613fbb57613fba613d7f565b5b5f613fc884828501613f92565b91505092915050565b5f5f60408385031215613fe757613fe6613d7f565b5b5f613ff485828601613e50565b925050602061400585828601613f92565b9150509250929050565b5f819050919050565b5f61403261402d61402884613d1e565b61400f565b613d1e565b9050919050565b5f61404382614018565b9050919050565b5f61405482614039565b9050919050565b6140648161404a565b82525050565b5f60208201905061407d5f83018461405b565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126140a4576140a3614083565b5b8235905067ffffffffffffffff8111156140c1576140c0614087565b5b6020830191508360018202830111156140dd576140dc61408b565b5b9250929050565b5f5f602083850312156140fa576140f9613d7f565b5b5f83013567ffffffffffffffff81111561411757614116613d83565b5b6141238582860161408f565b92509250509250929050565b61413881613f73565b82525050565b5f6020820190506141515f83018461412f565b92915050565b5f5f5f6060848603121561416e5761416d613d7f565b5b5f61417b86828701613e50565b935050602061418c86828701613e50565b925050604061419d86828701613e50565b9150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b600781106141e5576141e46141a7565b5b50565b5f8190506141f5826141d4565b919050565b5f614204826141e8565b9050919050565b614214816141fa565b82525050565b5f60208201905061422d5f83018461420b565b92915050565b5f5f5f6060848603121561424a57614249613d7f565b5b5f61425786828701613e50565b935050602061426886828701613e50565b925050604061427986828701613f92565b9150509250925092565b5f5f6040838503121561429957614298613d7f565b5b5f6142a685828601613f92565b92505060206142b785828601613f92565b9150509250929050565b5f6040820190506142d45f830185613d4e565b6142e1602083018461412f565b9392505050565b5f602082840312156142fd576142fc613d7f565b5b5f61430a84828501613e50565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61434581613d3d565b82525050565b5f614356838361433c565b60208301905092915050565b5f602082019050919050565b5f61437882614313565b614382818561431d565b935061438d8361432d565b805f5b838110156143bd5781516143a4888261434b565b97506143af83614362565b925050600181019050614390565b5085935050505092915050565b5f6020820190508181035f8301526143e2818461436e565b905092915050565b5f5f5f6060848603121561440157614400613d7f565b5b5f61440e86828701613f92565b935050602061441f86828701613e50565b925050604061443086828701613e91565b9150509250925092565b5f6effffffffffffffffffffffffffffff82169050919050565b61445d8161443a565b82525050565b5f6020820190506144765f830184614454565b92915050565b60078110614488575f5ffd5b50565b5f813590506144998161447c565b92915050565b6144a88161443a565b81146144b2575f5ffd5b50565b5f813590506144c38161449f565b92915050565b5f5f5f606084860312156144e0576144df613d7f565b5b5f6144ed8682870161448b565b93505060206144fe868287016144b5565b925050604061450f868287016144b5565b9150509250925092565b61452281613e07565b811461452c575f5ffd5b50565b5f8135905061453d81614519565b92915050565b5f5f6040838503121561455957614558613d7f565b5b5f61456685828601613e50565b92505060206145778582860161452f565b9150509250929050565b5f6020828403121561459657614595613d7f565b5b5f6145a38482850161452f565b91505092915050565b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6145e682613f0b565b810181811067ffffffffffffffff82111715614605576146046145b0565b5b80604052505050565b5f614617613d76565b905061462382826145dd565b919050565b5f67ffffffffffffffff821115614642576146416145b0565b5b61464b82613f0b565b9050602081019050919050565b828183375f83830152505050565b5f61467861467384614628565b61460e565b905082815260208101848484011115614694576146936145ac565b5b61469f848285614658565b509392505050565b5f82601f8301126146bb576146ba614083565b5b81356146cb848260208601614666565b91505092915050565b5f5f5f5f608085870312156146ec576146eb613d7f565b5b5f6146f987828801613e50565b945050602061470a87828801613e50565b935050604061471b87828801613f92565b925050606085013567ffffffffffffffff81111561473c5761473b613d83565b5b614748878288016146a7565b91505092959194509250565b61475d816141fa565b82525050565b61476c8161443a565b82525050565b606082015f8201516147865f850182614754565b5060208201516147996020850182614763565b5060408201516147ac6040850182614763565b50505050565b5f6060820190506147c55f830184614772565b92915050565b5f5f604083850312156147e1576147e0613d7f565b5b5f6147ee85828601613e50565b92505060206147ff85828601613e50565b9150509250929050565b5f5f5f5f6080858703121561482157614820613d7f565b5b5f61482e87828801613e50565b945050602061483f8782880161448b565b9350506040614850878288016144b5565b9250506060614861878288016144b5565b91505092959194509250565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806148b157607f821691505b6020821081036148c4576148c361486d565b5b50919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026149307fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826148f5565b61493a86836148f5565b95508019841693508086168417925050509392505050565b5f61496c61496761496284613f73565b61400f565b613f73565b9050919050565b5f819050919050565b61498583614952565b61499961499182614973565b848454614901565b825550505050565b5f5f905090565b6149b06149a1565b6149bb81848461497c565b505050565b5b818110156149de576149d35f826149a8565b6001810190506149c1565b5050565b601f821115614a23576149f4816148d4565b6149fd846148e6565b81016020851015614a0c578190505b614a20614a18856148e6565b8301826149c0565b50505b505050565b5f82821c905092915050565b5f614a435f1984600802614a28565b1980831691505092915050565b5f614a5b8383614a34565b9150826002028217905092915050565b614a7583836148ca565b67ffffffffffffffff811115614a8e57614a8d6145b0565b5b614a98825461489a565b614aa38282856149e2565b5f601f831160018114614ad0575f8415614abe578287013590505b614ac88582614a50565b865550614b2f565b601f198416614ade866148d4565b5f5b82811015614b0557848901358255600182019150602085019450602081019050614ae0565b86831015614b225784890135614b1e601f891682614a34565b8355505b6001600288020188555050505b50505050505050565b5f606082019050614b4b5f830186613d4e565b614b586020830185613d4e565b614b656040830184613d4e565b949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f614ba482613f73565b9150614baf83613f73565b9250828202614bbd81613f73565b91508282048414831517614bd457614bd3614b6d565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f614c1282613f73565b9150614c1d83613f73565b925082614c2d57614c2c614bdb565b5b828204905092915050565b5f5ffd5b5f81519050614c4a8161447c565b92915050565b5f81519050614c5e8161449f565b92915050565b5f60608284031215614c7957614c78614c38565b5b614c83606061460e565b90505f614c9284828501614c3c565b5f830152506020614ca584828501614c50565b6020830152506040614cb984828501614c50565b60408301525092915050565b5f60608284031215614cda57614cd9613d7f565b5b5f614ce784828501614c64565b91505092915050565b5f604082019050614d035f830185614454565b614d106020830184613d4e565b9392505050565b5f81519050614d2581614519565b92915050565b5f60208284031215614d4057614d3f613d7f565b5b5f614d4d84828501614d17565b91505092915050565b5f81905092915050565b50565b5f614d6e5f83614d56565b9150614d7982614d60565b5f82019050919050565b5f614d8d82614d63565b9150819050919050565b5f67ffffffffffffffff821115614db157614db06145b0565b5b602082029050602081019050919050565b5f81519050614dd081613e3a565b92915050565b5f614de8614de384614d97565b61460e565b90508083825260208201905060208402830185811115614e0b57614e0a61408b565b5b835b81811015614e345780614e208882614dc2565b845260208401935050602081019050614e0d565b5050509392505050565b5f82601f830112614e5257614e51614083565b5b8151614e62848260208601614dd6565b91505092915050565b5f60208284031215614e8057614e7f613d7f565b5b5f82015167ffffffffffffffff811115614e9d57614e9c613d83565b5b614ea984828501614e3e565b91505092915050565b5f604082019050614ec55f830185613d4e565b614ed2602083018461420b565b9392505050565b5f604082019050614eec5f830185613d4e565b614ef96020830184614454565b9392505050565b614f0981613d87565b82525050565b5f602082019050614f225f830184614f00565b92915050565b5f604082019050614f3b5f830185613d4e565b614f486020830184613d4e565b9392505050565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f5f8201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b5f614fa9602f83613eed565b9150614fb482614f4f565b604082019050919050565b5f6020820190508181035f830152614fd681614f9d565b9050919050565b5f81905092915050565b5f614ff182613ee3565b614ffb8185614fdd565b935061500b818560208601613efd565b80840191505092915050565b5f6150228285614fe7565b915061502e8284614fe7565b91508190509392505050565b61504381613e64565b82525050565b5f60208201905061505c5f83018461503a565b92915050565b5f61506c82613f73565b91505f820361507e5761507d614b6d565b5b600182039050919050565b5f6150a361509e61509984613e64565b61400f565b613f73565b9050919050565b6150b381615089565b82525050565b5f6040820190506150cc5f8301856150aa565b6150d9602083018461412f565b9392505050565b5f6150ea82613f73565b91506150f583613f73565b925082820190508082111561510d5761510c614b6d565b5b92915050565b5f6060820190506151265f83018661412f565b61513360208301856150aa565b615140604083018461412f565b949350505050565b5f60408201905061515b5f83018561412f565b6151686020830184613d4e565b9392505050565b5f81519050919050565b5f82825260208201905092915050565b5f6151938261516f565b61519d8185615179565b93506151ad818560208601613efd565b6151b681613f0b565b840191505092915050565b5f6080820190506151d45f830187613d4e565b6151e16020830186613d4e565b6151ee604083018561412f565b81810360608301526152008184615189565b905095945050505050565b5f8151905061521981613db2565b92915050565b5f6020828403121561523457615233613d7f565b5b5f6152418482850161520b565b9150509291505056fea26469706673582212208d41f981a790e4b660c328ec8c35abe9134e13534a334d391c817be62a5a005664736f6c634300081e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000059de7273191e6bf1907d614e94ecfbe8e5fb7318000000000000000000000000f8f8e62f0dd3dfda4635d75c5024251492ae73bd00000000000000000000000000000000000000000000000000000000000001f4
-----Decoded View---------------
Arg [0] : initialOwner (address): 0x59dE7273191E6bf1907d614e94eCFbe8e5FB7318
Arg [1] : royaltyReceiver_ (address): 0xf8f8E62F0dD3dFDa4635d75C5024251492Ae73BD
Arg [2] : royaltyFeeNumerator_ (uint96): 500
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000059de7273191e6bf1907d614e94ecfbe8e5fb7318
Arg [1] : 000000000000000000000000f8f8e62f0dd3dfda4635d75c5024251492ae73bd
Arg [2] : 00000000000000000000000000000000000000000000000000000000000001f4
Deployed Bytecode Sourcemap
191657:5288:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109469:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;192972:221;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;192515:185;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;140710:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;147950:227;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;196069:159;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;113995:137;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;195332:269;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;135912:573;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;117779:387;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109580:99;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;196238:211;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;186354:673;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;116124:357;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;194484:96;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;195681:207;;;;;;;;;;;;;:::i;:::-;;196459:219;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;115011:358;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;195040:155;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;192708:207;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;109686:66;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;111735:727;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;142112:152;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110126:464;;;;;;;;;;;;;:::i;:::-;;137636:242;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;97001:103;;;;;;;;;;;;;:::i;:::-;;192392:115;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;96326:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;140886:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;116653:378;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;195898:161;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;113062:818;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;194772:160;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;196689:253;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;191854:45;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;114349:455;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;191776:28;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;193417:609;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;115579:379;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;194191:119;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;148908:164;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;97259:220;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;191811:36;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110793:749;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;109469:104;109530:42;109469:104;:::o;192972:221::-;193104:4;193146:39;193173:11;193146:26;:39::i;:::-;193126:59;;192972:221;;;:::o;192515:185::-;96212:13;:11;:13::i;:::-;192608:31:::1;:29;:31::i;:::-;192650:42;192669:8;192679:12;192650:18;:42::i;:::-;192515:185:::0;;:::o;140710:100::-;140764:13;140797:5;140790:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;140710:100;:::o;147950:227::-;148026:7;148051:16;148059:7;148051;:16::i;:::-;148046:73;;148069:50;148077:41;;;148069:7;:50::i;:::-;148046:73;148139:15;:24;148155:7;148139:24;;;;;;;;;;;:30;;;;;;;;;;;;148132:37;;147950:227;;;:::o;196069:159::-;196188:32;196202:8;196212:7;196188:13;:32::i;:::-;196069:159;;:::o;113995:137::-;114057:30;114107:17;;;;;;;;;;;114100:24;;113995:137;:::o;195332:269::-;192306:14;:23;192321:7;;;;192306:23;;;;;;;;;;;;;;;;;;;;;;;;;;;192302:52;;;192338:16;;;;;;;;;;;;;;192302:52;96212:13:::1;:11;:13::i;:::-;195499:1:::2;195473:14;195467:28;;;;;:::i;:::-;;;:33;195463:85;;195522:26;;;;;;;;;;;;;;195463:85;195578:15;;195561:14;:32;;;;;;;:::i;:::-;;195332:269:::0;;:::o;135912:573::-;135973:14;136371:15;:13;:15::i;:::-;136356:12;;136340:13;;:28;:46;136331:55;;136426:17;136405;:15;:17::i;:::-;:38;136401:65;;136455:11;;136445:21;;;;136401:65;135912:573;:::o;117779:387::-;117878:4;117937:1;117899:40;;117907:17;;;;;;;;;;;117899:40;;;117895:242;;117960:17;;;;;;;;;;;:47;;;118008:6;118016:4;118022:2;117960:65;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;117956:170;;118105:5;118098:12;;;;117956:170;118052:4;118045:11;;;;117895:242;118154:4;118147:11;;117779:387;;;;;;:::o;109580:99::-;109653:26;109580:99;:::o;196238:211::-;196404:37;196423:4;196429:2;196433:7;196404:18;:37::i;:::-;196238:211;;;:::o;186354:673::-;186465:16;186483:14;186510:32;186545:17;:26;186563:7;186545:26;;;;;;;;;;;186510:61;;186582:23;186608:12;:21;;;;;;;;;;;;186582:47;;186640:22;186665:12;:28;;;;;;;;;;;;186640:53;;186737:1;186710:29;;:15;:29;;;186706:176;;186774:19;:28;;;;;;;;;;;;186756:46;;186835:19;:35;;;;;;;;;;;;186817:53;;186706:176;186894:21;186950:17;:15;:17::i;:::-;186918:49;;186931:15;186919:27;;:9;:27;;;;:::i;:::-;186918:49;;;;:::i;:::-;186894:73;;186988:15;187005:13;186980:39;;;;;;;;186354:673;;;;;:::o;116124:357::-;116203:4;116262:1;116224:40;;116232:17;;;;;;;;;;;116224:40;;;116220:229;;116288:17;;;;;;;;;;;:39;;;116346:17;;;;;;;;;;;:45;;;116400:4;116346:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:80;;;116428:8;116288:149;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;116281:156;;;;116220:229;116468:5;116461:12;;116124:357;;;;:::o;194484:96::-;96212:13;:11;:13::i;:::-;194568:4:::1;194547:14;:18;194562:2;194547:18;;;;;;;;;;;;;;;;;;:25;;;;;;;;;;;;;;;;;;194484:96:::0;:::o;195681:207::-;96212:13;:11;:13::i;:::-;195732:12:::1;195758:10;195750:24;;195796:21;195750:82;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;195731:101;;;195848:7;195843:37;;195864:16;;;;;;;;;;;;;;195843:37;195720:168;195681:207::o:0;196459:219::-;196629:41;196652:4;196658:2;196662:7;196629:22;:41::i;:::-;196459:219;;;:::o;115011:358::-;115076:16;115147:1;115109:40;;115117:17;;;;;;;;;;;115109:40;;;115105:221;;115173:17;;;;;;;;;;;:41;;;115233:17;;;;;;;;;;;:45;;;115287:4;115233:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:80;;;115173:141;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;115166:148;;;;115105:221;115359:1;115345:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;115338:23;;115011:358;;:::o;195040:155::-;192306:14;:23;192321:7;;;;192306:23;;;;;;;;;;;;;;;;;;;;;;;;;;;192302:52;;;192338:16;;;;;;;;;;;;;;192302:52;96212:13:::1;:11;:13::i;:::-;195176:11:::2;;195160:13;:27;;;;;;;:::i;:::-;;195040:155:::0;;:::o;192708:207::-;96212:13;:11;:13::i;:::-;192816:31:::1;:29;:31::i;:::-;192858:49;192875:7;192884:8;192894:12;192858:16;:49::i;:::-;192708:207:::0;;;:::o;109686:66::-;109750:1;109686:66;:::o;111735:727::-;111924:31;:29;:31::i;:::-;111968:40;112011:22;:20;:22::i;:::-;111968:65;;112078:1;112048:32;;112056:9;112048:32;;;112044:117;;112104:45;;;;;;;;;;;;;;112044:117;112173:9;:46;;;112228:4;112235:5;112173:68;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;112252:9;:42;;;112303:4;112310:19;112252:78;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;112341:9;:59;;;112409:4;112416:37;112341:113;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;111913:549;111735:727;;;:::o;142112:152::-;142184:7;142227:27;142246:7;142227:18;:27::i;:::-;142204:52;;142112:152;;;:::o;110126:464::-;110190:31;:29;:31::i;:::-;110232:48;109530:42;110232:20;:48::i;:::-;109530:42;110291:95;;;110395:4;109653:26;110291:143;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109530:42;110445:91;;;110545:4;109750:1;110445:137;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110126:464::o;137636:242::-;137708:7;137749:1;137732:19;;:5;:19;;;137728:69;;137753:44;137761:35;;;137753:7;:44::i;:::-;137728:69;130396:13;137815:18;:25;137834:5;137815:25;;;;;;;;;;;;;;;;:55;137808:62;;137636:242;;;:::o;97001:103::-;96212:13;:11;:13::i;:::-;97066:30:::1;97093:1;97066:18;:30::i;:::-;97001:103::o:0;192392:115::-;192306:14;:23;192321:7;;;;192306:23;;;;;;;;;;;;;;;;;;;;;;;;;;;192302:52;;;192338:16;;;;;;;;;;;;;;192302:52;96212:13:::1;:11;:13::i;:::-;192484:15:::2;192490:2;192494:4;192484:5;:15::i;:::-;192392:115:::0;;:::o;96326:87::-;96372:7;96399:6;;;;;;;;;;;96392:13;;96326:87;:::o;140886:104::-;140942:13;140975:7;140968:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;140886:104;:::o;116653:378::-;116738:4;116797:1;116759:40;;116767:17;;;;;;;;;;;116759:40;;;116755:244;;116823:17;;;;;;;;;;;:45;;;116887:17;;;;;;;;;;;:45;;;116941:4;116887:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:89;;;116978:8;116823:164;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;116816:171;;;;116755:244;117018:5;117011:12;;116653:378;;;;:::o;195898:161::-;196008:43;196032:8;196042;196008:23;:43::i;:::-;195898:161;;:::o;113062:818::-;113138:31;:29;:31::i;:::-;113182:29;113214:5;113182:37;;113268:1;113235:18;:30;;;:34;113232:304;;;113298:18;113290:45;;;113336:48;113290:95;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;113286:239;;;113483:17;113456:44;;113404:112;113286:239;113232:304;113581:1;113551:32;;:18;:32;;;;:61;;;;;113588:24;113587:25;113551:61;113548:152;;;113636:52;;;;;;;;;;;;;;113548:152;113717:72;113750:17;;;;;;;;;;;113770:18;113717:72;;;;;;;:::i;:::-;;;;;;;;113853:18;113802:17;;:70;;;;;;;;;;;;;;;;;;113127:753;113062:818;:::o;194772:160::-;192306:14;:23;192321:7;;;;192306:23;;;;;;;;;;;;;;;;;;;;;;;;;;;192302:52;;;192338:16;;;;;;;;;;;;;;192302:52;96212:13:::1;:11;:13::i;:::-;194919:5:::2;194892:24;;:32;;;;;;;;;;;;;;;;;;194772:160:::0;:::o;196689:253::-;196887:47;196910:4;196916:2;196920:7;196929:4;196887:22;:47::i;:::-;196689:253;;;;:::o;191854:45::-;;;;;;;;;;;;;;;;;;;;;;:::o;114349:455::-;114408:31;;:::i;:::-;114494:1;114456:40;;114464:17;;;;;;;;;;;114456:40;;;114452:140;;114520:17;;;;;;;;;;;:45;;;114574:4;114520:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;114513:67;;;;114452:140;114611:185;;;;;;;;114674:27;114611:185;;;;;;;;:::i;:::-;;;;;;114737:1;114611:185;;;;;;114783:1;114611:185;;;;;114604:192;;114349:455;;:::o;191776:28::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;193417:609::-;193535:13;193588:16;193596:7;193588;:16::i;:::-;193566:113;;;;;;;;;;;;:::i;:::-;;;;;;;;;193692:28;193723:10;:8;:10::i;:::-;193692:41;;193795:1;193770:14;193764:28;:32;:254;;;;;;;;;;;;;;;;;193888:14;193929:25;193946:7;193929:16;:25::i;:::-;193845:132;;;;;;;;;:::i;:::-;;;;;;;;;;;;;193764:254;193744:274;;;193417:609;;;:::o;115579:379::-;115650:16;115721:1;115683:40;;115691:17;;;;;;;;;;;115683:40;;;115679:236;;115747:17;;;;;;;;;;;:47;;;115813:17;;;;;;;;;;;:45;;;115867:4;115813:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:89;;;115747:156;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;115740:163;;;;115679:236;115948:1;115934:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;115927:23;;115579:379;;:::o;194191:119::-;194253:7;194280:22;194294:7;194280:13;:22::i;:::-;194273:29;;194191:119;;;:::o;148908:164::-;149005:4;149029:18;:25;149048:5;149029:25;;;;;;;;;;;;;;;:35;149055:8;149029:35;;;;;;;;;;;;;;;;;;;;;;;;;149022:42;;148908:164;;;;:::o;97259:220::-;96212:13;:11;:13::i;:::-;97364:1:::1;97344:22;;:8;:22;;::::0;97340:93:::1;;97418:1;97390:31;;;;;;;;;;;:::i;:::-;;;;;;;;97340:93;97443:28;97462:8;97443:18;:28::i;:::-;97259:220:::0;:::o;191811:36::-;;;;;;;;;;;;;:::o;110793:749::-;111023:31;:29;:31::i;:::-;111067;111088:9;111067:20;:31::i;:::-;111142:9;111111:92;;;111212:4;111219:5;111111:114;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;111269:9;111238:88;;;111335:4;111342:19;111238:124;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;111406:9;111375:105;;;111489:4;111496:37;111375:159;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110793:749;;;;:::o;180699:203::-;180784:4;180823:31;180808:46;;;:11;:46;;;;:86;;;;180858:36;180882:11;180858:23;:36::i;:::-;180808:86;180801:93;;180699:203;;;:::o;96491:166::-;96562:12;:10;:12::i;:::-;96551:23;;:7;:5;:7::i;:::-;:23;;;96547:103;;96625:12;:10;:12::i;:::-;96598:40;;;;;;;;;;;:::i;:::-;;;;;;;;96547:103;96491:166::o;98054:104::-;98137:13;:11;:13::i;:::-;98054:104::o;190014:217::-;190118:48;190143:8;190153:12;190118:24;:48::i;:::-;190200:8;190182:41;;;190210:12;190182:41;;;;;;:::i;:::-;;;;;;;;190014:217;;:::o;149330:475::-;149395:11;149442:7;149423:15;:13;:15::i;:::-;:26;149419:379;;149480:17;:15;:17::i;:::-;149470:7;:27;149466:90;;;149506:50;149529:17;:26;149547:7;149529:26;;;;;;;;;;;;149506:22;:50::i;:::-;149499:57;;;;149466:90;149587:13;;149577:7;:23;149573:214;;;149621:14;149654:60;149702:1;149671:17;:26;149689:7;149671:26;;;;;;;;;;;;149662:35;;;149661:42;149654:60;;149705:9;;;;:::i;:::-;;;149654:60;;;149770:1;131172:8;149742:6;:24;:29;149733:38;;149602:185;149573:214;149419:379;149330:475;;;;:::o;179839:165::-;179940:13;179934:4;179927:27;179981:4;179975;179968:18;147667:124;147756:27;147765:2;147769:7;147778:4;147756:8;:27::i;:::-;147667:124;;:::o;134960:92::-;135016:7;135043:1;135036:8;;134960:92;:::o;135410:110::-;135468:7;135495:17;135488:24;;135410:110;:::o;152222:3523::-;152364:27;152394;152413:7;152394:18;:27::i;:::-;152364:57;;131854:14;152565:4;152549:22;;:41;152526:66;;152650:4;152609:45;;152625:19;152609:45;;;152605:95;;152656:44;152664:35;;;152656:7;:44::i;:::-;152605:95;152714:27;152743:23;152770:35;152797:7;152770:26;:35::i;:::-;152713:92;;;;152905:68;152930:15;152947:4;152953:19;:17;:19::i;:::-;152905:24;:68::i;:::-;152900:189;;152993:43;153010:4;153016:19;:17;:19::i;:::-;152993:16;:43::i;:::-;152988:101;;153038:51;153046:42;;;153038:7;:51::i;:::-;152988:101;152900:189;153102:43;153124:4;153130:2;153134:7;153143:1;153102:21;:43::i;:::-;153238:15;153235:160;;;153378:1;153357:19;153350:30;153235:160;153775:18;:24;153794:4;153775:24;;;;;;;;;;;;;;;;153773:26;;;;;;;;;;;;153844:18;:22;153863:2;153844:22;;;;;;;;;;;;;;;;153842:24;;;;;;;;;;;154166:146;154203:2;154252:45;154267:4;154273:2;154277:19;154252:14;:45::i;:::-;131452:8;154224:73;154166:18;:146::i;:::-;154137:17;:26;154155:7;154137:26;;;;;;;;;;;:175;;;;154483:1;131452:8;154432:19;:47;:52;154428:627;;154505:19;154537:1;154527:7;:11;154505:33;;154694:1;154660:17;:30;154678:11;154660:30;;;;;;;;;;;;:35;154656:384;;154798:13;;154783:11;:28;154779:242;;154978:19;154945:17;:30;154963:11;154945:30;;;;;;;;;;;:52;;;;154779:242;154656:384;154486:569;154428:627;155168:16;131854:14;155203:2;155187:20;;:39;155168:58;;155567:7;155531:8;155497:4;155439:25;155384:1;155327;155304:299;155640:1;155628:8;:13;155624:58;;155643:39;155651:30;;;155643:7;:39::i;:::-;155624:58;155695:42;155716:4;155722:2;155726:7;155735:1;155695:20;:42::i;:::-;152353:3392;;;;152222:3523;;;:::o;187309:97::-;187367:6;187393:5;187386:12;;187309:97;:::o;155841:193::-;155987:39;156004:4;156010:2;156014:7;155987:39;;;;;;;;;;;;:16;:39::i;:::-;155841:193;;;:::o;190239:246::-;190358:55;190381:7;190390:8;190400:12;190358:22;:55::i;:::-;190454:8;190429:48;;190445:7;190429:48;190464:12;190429:48;;;;;;:::i;:::-;;;;;;;;190239:246;;;:::o;143597:2213::-;143664:14;143714:7;143695:15;:13;:15::i;:::-;:26;143691:2054;;143747:17;:26;143765:7;143747:26;;;;;;;;;;;;143738:35;;143804:17;:15;:17::i;:::-;143794:7;:27;143790:183;;;143846:30;143869:6;143846:22;:30::i;:::-;143878:13;143842:49;143910:47;143918:38;;;143910:7;:47::i;:::-;143790:183;144084:1;144074:6;:11;144070:1292;;144121:13;;144110:7;:24;144106:77;;144136:47;144144:38;;;144136:7;:47::i;:::-;144106:77;144740:607;144818:17;:28;144836:9;;;;;;;144818:28;;;;;;;;;;;;144809:37;;144906:1;144896:6;:11;144892:25;144909:8;144892:25;144972:1;131172:8;144944:6;:24;:29;144940:48;144975:13;144940:48;145280:47;145288:38;;;145280:7;:47::i;:::-;144740:607;;;144070:1292;145717:1;131172:8;145689:6;:24;:29;145685:48;145720:13;145685:48;143691:2054;145755:47;145763:38;;;145755:7;:47::i;:::-;143597:2213;;;;:::o;97639:191::-;97713:16;97732:6;;;;;;;;;;;97713:25;;97758:8;97749:6;;:17;;;;;;;;;;;;;;;;;;97813:8;97782:40;;97803:8;97782:40;;;;;;;;;;;;97702:128;97639:191;:::o;160285:2399::-;160358:20;160381:13;;160358:36;;160421:1;160409:8;:13;160405:53;;160424:34;160432:25;;;160424:7;:34::i;:::-;160405:53;160471:61;160501:1;160505:2;160509:12;160523:8;160471:21;:61::i;:::-;161005:139;161042:2;161096:33;161119:1;161123:2;161127:1;161096:14;:33::i;:::-;161063:30;161084:8;161063:20;:30::i;:::-;:66;161005:18;:139::i;:::-;160971:17;:31;160989:12;160971:31;;;;;;;;;;;:173;;;;161431:1;130534:2;161401:1;:26;;161400:32;161388:8;:45;161362:18;:22;161381:2;161362:22;;;;;;;;;;;;;;;;:71;;;;;;;;;;;161544:16;131854:14;161579:2;161563:20;;:39;161544:58;;161635:1;161623:8;:13;161619:54;;161638:35;161646:26;;;161638:7;:35::i;:::-;161619:54;161690:11;161719:8;161704:12;:23;161690:37;;161742:15;161760:12;161742:30;;161803:17;:15;:17::i;:::-;161799:1;161793:3;:7;:27;161789:77;;;161822:44;161830:35;;;161822:7;:44::i;:::-;161789:77;161883:676;162302:7;162258:8;162213:1;162147:25;162084:1;162019;161988:358;162554:3;162541:9;;;;;;:16;161883:676;;162591:3;162575:13;:19;;;;160720:1886;;;162616:60;162645:1;162649:2;162653:12;162667:8;162616:20;:60::i;:::-;160347:2337;160285:2399;;:::o;148517:234::-;148664:8;148612:18;:39;148631:19;:17;:19::i;:::-;148612:39;;;;;;;;;;;;;;;:49;148652:8;148612:49;;;;;;;;;;;;;;;;:60;;;;;;;;;;;;;;;;;;148724:8;148688:55;;148703:19;:17;:19::i;:::-;148688:55;;;148734:8;148688:55;;;;;;:::i;:::-;;;;;;;;148517:234;;:::o;156632:416::-;156807:31;156820:4;156826:2;156830:7;156807:12;:31::i;:::-;156871:1;156853:2;:14;;;:19;156849:192;;156892:56;156923:4;156929:2;156933:7;156942:5;156892:30;:56::i;:::-;156887:154;;156969:56;156977:47;;;156969:7;:56::i;:::-;156887:154;156849:192;156632:416;;;;:::o;193295:114::-;193355:13;193388;193381:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;193295:114;:::o;74947:650::-;75003:13;75054:14;75091:1;75071:17;75082:5;75071:10;:17::i;:::-;:21;75054:38;;75107:20;75141:6;75130:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75107:41;;75163:11;75260:6;75256:2;75252:15;75244:6;75240:28;75233:35;;75297:254;75304:4;75297:254;;;75329:5;;;;;;;;75435:10;75430:2;75423:5;75419:14;75414:32;75409:3;75401:46;75493:2;75484:11;;;;;;:::i;:::-;;;;;75527:1;75518:5;:10;75297:254;75514:21;75297:254;75572:6;75565:13;;;;;74947:650;;;:::o;137960:178::-;138021:7;130396:13;130534:2;138049:18;:25;138068:5;138049:25;;;;;;;;;;;;;;;;:50;;138048:82;138041:89;;137960:178;;;:::o;139808:639::-;139893:4;140232:10;140217:25;;:11;:25;;;;:102;;;;140309:10;140294:25;;:11;:25;;;;140217:102;:179;;;;140386:10;140371:25;;:11;:25;;;;140217:179;140197:199;;139808:639;;;:::o;94060:98::-;94113:7;94140:10;94133:17;;94060:98;:::o;187677:518::-;187772:19;187794:17;:15;:17::i;:::-;187772:39;;;;187841:11;187826:12;:26;;;187822:176;;;187960:12;187974:11;187931:55;;;;;;;;;;;;:::i;:::-;;;;;;;;187822:176;188032:1;188012:22;;:8;:22;;;188008:110;;188103:1;188058:48;;;;;;;;;;;:::i;:::-;;;;;;;;188008:110;188152:35;;;;;;;;188164:8;188152:35;;;;;;188174:12;188152:35;;;;;188130:19;:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;187761:434;187677:518;;:::o;149901:335::-;149971:11;150201:15;150193:6;150189:28;150170:16;150162:6;150158:29;150155:63;150145:73;;149901:335;;;:::o;171254:474::-;171383:13;171399:16;171407:7;171399;:16::i;:::-;171383:32;;171432:13;:45;;;;;171472:5;171449:28;;:19;:17;:19::i;:::-;:28;;;;171432:45;171428:201;;;171497:44;171514:5;171521:19;:17;:19::i;:::-;171497:16;:44::i;:::-;171492:137;;171562:51;171570:42;;;171562:7;:51::i;:::-;171492:137;171428:201;171674:2;171641:15;:24;171657:7;171641:24;;;;;;;;;;;:30;;;:35;;;;;;;;;;;;;;;;;;171712:7;171708:2;171692:28;;171701:5;171692:28;;;;;;;;;;;;171372:356;171254:474;;;:::o;151117:485::-;151219:27;151248:23;151289:38;151330:15;:24;151346:7;151330:24;;;;;;;;;;;151289:65;;151507:18;151484:41;;151564:19;151558:26;151539:45;;151469:126;151117:485;;;:::o;181842:116::-;181911:7;181938:12;:10;:12::i;:::-;181931:19;;181842:116;:::o;150345:659::-;150494:11;150659:16;150652:5;150648:28;150639:37;;150819:16;150808:9;150804:32;150791:45;;150969:15;150958:9;150955:30;150947:5;150936:9;150933:20;150930:56;150920:66;;150345:659;;;;;:::o;181011:359::-;181193:9;181205:1;181193:13;;181188:175;181212:8;181208:1;:12;181188:175;;;181238:51;181262:4;181268:2;181287:1;181272:12;:16;;;;:::i;:::-;181238:23;:51::i;:::-;181333:3;;;;;181188:175;;;;181011:359;;;;:::o;177129:311::-;177264:7;177284:16;131576:3;177310:19;:41;;177284:68;;131576:3;177378:31;177389:4;177395:2;177399:9;177378:10;:31::i;:::-;177370:40;;:62;;177363:69;;;177129:311;;;;;:::o;146358:450::-;146438:14;146606:16;146599:5;146595:28;146586:37;;146783:5;146769:11;146744:23;146740:41;146737:52;146730:5;146727:63;146717:73;;146358:450;;;;:::o;181477:357::-;181658:9;181670:1;181658:13;;181653:174;181677:8;181673:1;:12;181653:174;;;181703:50;181726:4;181732:2;181751:1;181736:12;:16;;;;:::i;:::-;181703:22;:50::i;:::-;181797:3;;;;;181653:174;;;;181477:357;;;;:::o;188646:554::-;188756:19;188778:17;:15;:17::i;:::-;188756:39;;;;188825:11;188810:12;:26;;;188806:183;;;188942:7;188951:12;188965:11;188915:62;;;;;;;;;;;;;:::i;:::-;;;;;;;;188806:183;189023:1;189003:22;;:8;:22;;;188999:117;;189084:7;189101:1;189049:55;;;;;;;;;;;;:::i;:::-;;;;;;;;188999:117;189157:35;;;;;;;;189169:8;189157:35;;;;;;189179:12;189157:35;;;;;189128:17;:26;189146:7;189128:26;;;;;;;;;;;:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;188745:455;188646:554;;;:::o;146910:324::-;146980:14;147213:1;147203:8;147200:15;147174:24;147170:46;147160:56;;146910:324;;;:::o;159132:691::-;159295:4;159341:2;159316:45;;;159362:19;:17;:19::i;:::-;159383:4;159389:7;159398:5;159316:88;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;159312:504;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;159616:1;159599:6;:13;:18;159595:115;;159638:56;159646:47;;;159638:7;:56::i;:::-;159595:115;159782:6;159776:13;159767:6;159763:2;159759:15;159752:38;159312:504;159485:54;;;159475:64;;;:6;:64;;;;159468:71;;;159132:691;;;;;;:::o;67958:948::-;68011:7;68031:14;68048:1;68031:18;;68098:8;68089:5;:17;68085:106;;68136:8;68127:17;;;;;;:::i;:::-;;;;;68173:2;68163:12;;;;68085:106;68218:8;68209:5;:17;68205:106;;68256:8;68247:17;;;;;;:::i;:::-;;;;;68293:2;68283:12;;;;68205:106;68338:8;68329:5;:17;68325:106;;68376:8;68367:17;;;;;;:::i;:::-;;;;;68413:2;68403:12;;;;68325:106;68458:7;68449:5;:16;68445:103;;68495:7;68486:16;;;;;;:::i;:::-;;;;;68531:1;68521:11;;;;68445:103;68575:7;68566:5;:16;68562:103;;68612:7;68603:16;;;;;;:::i;:::-;;;;;68648:1;68638:11;;;;68562:103;68692:7;68683:5;:16;68679:103;;68729:7;68720:16;;;;;;:::i;:::-;;;;;68765:1;68755:11;;;;68679:103;68809:7;68800:5;:16;68796:68;;68847:1;68837:11;;;;68796:68;68892:6;68885:13;;;67958:948;;;:::o;104992:623::-;105096:20;105135:1;105119:18;;:4;:18;;;105096:41;;105148:18;105183:1;105169:16;;:2;:16;;;105148:37;;105201:15;:32;;;;;105220:13;105201:32;105198:410;;;105257:28;;;;;;;;;;;;;;105198:410;105306:15;105303:305;;;105338:54;105355:12;:10;:12::i;:::-;105369:2;105373:7;105382:9;105338:16;:54::i;:::-;105303:305;;;105413:13;105410:198;;;105443:56;105460:12;:10;:12::i;:::-;105474:4;105480:7;105489:9;105443:16;:56::i;:::-;105410:198;;;105532:64;105553:12;:10;:12::i;:::-;105567:4;105573:2;105577:7;105586:9;105532:20;:64::i;:::-;105410:198;105303:305;105085:530;;104992:623;;;:::o;176830:147::-;176967:6;176830:147;;;;;:::o;105748:625::-;105851:20;105890:1;105874:18;;:4;:18;;;105851:41;;105903:18;105938:1;105924:16;;:2;:16;;;105903:37;;105956:15;:32;;;;;105975:13;105956:32;105953:413;;;106012:28;;;;;;;;;;;;;;105953:413;106061:15;106058:308;;;106093:55;106111:12;:10;:12::i;:::-;106125:2;106129:7;106138:9;106093:17;:55::i;:::-;106058:308;;;106169:13;106166:200;;;106199:57;106217:12;:10;:12::i;:::-;106231:4;106237:7;106246:9;106199:17;:57::i;:::-;106166:200;;;106289:65;106311:12;:10;:12::i;:::-;106325:4;106331:2;106335:7;106344:9;106289:21;:65::i;:::-;106166:200;106058:308;105840:533;;105748:625;;;:::o;106445:105::-;;;;;:::o;106799:107::-;;;;;:::o;118869:344::-;119110:1;119072:40;;119080:17;;;;;;;;;;;119072:40;;;119068:138;;119129:17;;;;;;;;;;;:47;;;119177:6;119185:4;119191:2;119129:65;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119068:138;118869:344;;;;;:::o;106621:106::-;;;;;:::o;106977:108::-;;;;;:::o;107359: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:117::-;6792:1;6789;6782:12;6806:117;6915:1;6912;6905:12;6929:117;7038:1;7035;7028:12;7066:553;7124:8;7134:6;7184:3;7177:4;7169:6;7165:17;7161:27;7151:122;;7192:79;;:::i;:::-;7151:122;7305:6;7292:20;7282:30;;7335:18;7327:6;7324:30;7321:117;;;7357:79;;:::i;:::-;7321:117;7471:4;7463:6;7459:17;7447:29;;7525:3;7517:4;7509:6;7505:17;7495:8;7491:32;7488:41;7485:128;;;7532:79;;:::i;:::-;7485:128;7066:553;;;;;:::o;7625:529::-;7696:6;7704;7753:2;7741:9;7732:7;7728:23;7724:32;7721:119;;;7759:79;;:::i;:::-;7721:119;7907:1;7896:9;7892:17;7879:31;7937:18;7929:6;7926:30;7923:117;;;7959:79;;:::i;:::-;7923:117;8072:65;8129:7;8120:6;8109:9;8105:22;8072:65;:::i;:::-;8054:83;;;;7850:297;7625:529;;;;;:::o;8160:118::-;8247:24;8265:5;8247:24;:::i;:::-;8242:3;8235:37;8160:118;;:::o;8284:222::-;8377:4;8415:2;8404:9;8400:18;8392:26;;8428:71;8496:1;8485:9;8481:17;8472:6;8428:71;:::i;:::-;8284:222;;;;:::o;8512:619::-;8589:6;8597;8605;8654:2;8642:9;8633:7;8629:23;8625:32;8622:119;;;8660:79;;:::i;:::-;8622:119;8780:1;8805:53;8850:7;8841:6;8830:9;8826:22;8805:53;:::i;:::-;8795:63;;8751:117;8907:2;8933:53;8978:7;8969:6;8958:9;8954:22;8933:53;:::i;:::-;8923:63;;8878:118;9035:2;9061:53;9106:7;9097:6;9086:9;9082:22;9061:53;:::i;:::-;9051:63;;9006:118;8512:619;;;;;:::o;9137:180::-;9185:77;9182:1;9175:88;9282:4;9279:1;9272:15;9306:4;9303:1;9296:15;9323:132;9423:1;9416:5;9413:12;9403:46;;9429:18;;:::i;:::-;9403:46;9323:132;:::o;9461:165::-;9525:7;9554:5;9543:16;;9560:60;9614:5;9560:60;:::i;:::-;9461:165;;;:::o;9632:::-;9707:9;9740:51;9785:5;9740:51;:::i;:::-;9727:64;;9632:165;;;:::o;9803:181::-;9915:62;9971:5;9915:62;:::i;:::-;9910:3;9903:75;9803:181;;:::o;9990:272::-;10108:4;10146:2;10135:9;10131:18;10123:26;;10159:96;10252:1;10241:9;10237:17;10228:6;10159:96;:::i;:::-;9990:272;;;;:::o;10268:619::-;10345:6;10353;10361;10410:2;10398:9;10389:7;10385:23;10381:32;10378:119;;;10416:79;;:::i;:::-;10378:119;10536:1;10561:53;10606:7;10597:6;10586:9;10582:22;10561:53;:::i;:::-;10551:63;;10507:117;10663:2;10689:53;10734:7;10725:6;10714:9;10710:22;10689:53;:::i;:::-;10679:63;;10634:118;10791:2;10817:53;10862:7;10853:6;10842:9;10838:22;10817:53;:::i;:::-;10807:63;;10762:118;10268:619;;;;;:::o;10893:474::-;10961:6;10969;11018:2;11006:9;10997:7;10993:23;10989:32;10986:119;;;11024:79;;:::i;:::-;10986:119;11144:1;11169:53;11214:7;11205:6;11194:9;11190:22;11169:53;:::i;:::-;11159:63;;11115:117;11271:2;11297:53;11342:7;11333:6;11322:9;11318:22;11297:53;:::i;:::-;11287:63;;11242:118;10893:474;;;;;:::o;11373:332::-;11494:4;11532:2;11521:9;11517:18;11509:26;;11545:71;11613:1;11602:9;11598:17;11589:6;11545:71;:::i;:::-;11626:72;11694:2;11683:9;11679:18;11670:6;11626:72;:::i;:::-;11373:332;;;;;:::o;11711:329::-;11770:6;11819:2;11807:9;11798:7;11794:23;11790:32;11787:119;;;11825:79;;:::i;:::-;11787:119;11945:1;11970:53;12015:7;12006:6;11995:9;11991:22;11970:53;:::i;:::-;11960:63;;11916:117;11711:329;;;;:::o;12046:114::-;12113:6;12147:5;12141:12;12131:22;;12046:114;;;:::o;12166:184::-;12265:11;12299:6;12294:3;12287:19;12339:4;12334:3;12330:14;12315:29;;12166:184;;;;:::o;12356:132::-;12423:4;12446:3;12438:11;;12476:4;12471:3;12467:14;12459:22;;12356:132;;;:::o;12494:108::-;12571:24;12589:5;12571:24;:::i;:::-;12566:3;12559:37;12494:108;;:::o;12608:179::-;12677:10;12698:46;12740:3;12732:6;12698:46;:::i;:::-;12776:4;12771:3;12767:14;12753:28;;12608:179;;;;:::o;12793:113::-;12863:4;12895;12890:3;12886:14;12878:22;;12793:113;;;:::o;12942:732::-;13061:3;13090:54;13138:5;13090:54;:::i;:::-;13160:86;13239:6;13234:3;13160:86;:::i;:::-;13153:93;;13270:56;13320:5;13270:56;:::i;:::-;13349:7;13380:1;13365:284;13390:6;13387:1;13384:13;13365:284;;;13466:6;13460:13;13493:63;13552:3;13537:13;13493:63;:::i;:::-;13486:70;;13579:60;13632:6;13579:60;:::i;:::-;13569:70;;13425:224;13412:1;13409;13405:9;13400:14;;13365:284;;;13369:14;13665:3;13658:10;;13066:608;;;12942:732;;;;:::o;13680:373::-;13823:4;13861:2;13850:9;13846:18;13838:26;;13910:9;13904:4;13900:20;13896:1;13885:9;13881:17;13874:47;13938:108;14041:4;14032:6;13938:108;:::i;:::-;13930:116;;13680:373;;;;:::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:323::-;17230:6;17279:2;17267:9;17258:7;17254:23;17250:32;17247:119;;;17285:79;;:::i;:::-;17247:119;17405:1;17430:50;17472:7;17463:6;17452:9;17448:22;17430:50;:::i;:::-;17420:60;;17376:114;17174:323;;;;:::o;17503:117::-;17612:1;17609;17602:12;17626:180;17674:77;17671:1;17664:88;17771:4;17768:1;17761:15;17795:4;17792:1;17785:15;17812:281;17895:27;17917:4;17895:27;:::i;:::-;17887:6;17883:40;18025:6;18013:10;18010:22;17989:18;17977:10;17974:34;17971:62;17968:88;;;18036:18;;:::i;:::-;17968:88;18076:10;18072:2;18065:22;17855:238;17812:281;;:::o;18099:129::-;18133:6;18160:20;;:::i;:::-;18150:30;;18189:33;18217:4;18209:6;18189:33;:::i;:::-;18099:129;;;:::o;18234:307::-;18295:4;18385:18;18377:6;18374:30;18371:56;;;18407:18;;:::i;:::-;18371:56;18445:29;18467:6;18445:29;:::i;:::-;18437:37;;18529:4;18523;18519:15;18511:23;;18234:307;;;:::o;18547:148::-;18645:6;18640:3;18635;18622:30;18686:1;18677:6;18672:3;18668:16;18661:27;18547:148;;;:::o;18701:423::-;18778:5;18803:65;18819:48;18860:6;18819:48;:::i;:::-;18803:65;:::i;:::-;18794:74;;18891:6;18884:5;18877:21;18929:4;18922:5;18918:16;18967:3;18958:6;18953:3;18949:16;18946:25;18943:112;;;18974:79;;:::i;:::-;18943:112;19064:54;19111:6;19106:3;19101;19064:54;:::i;:::-;18784:340;18701:423;;;;;:::o;19143:338::-;19198:5;19247:3;19240:4;19232:6;19228:17;19224:27;19214:122;;19255:79;;:::i;:::-;19214:122;19372:6;19359:20;19397:78;19471:3;19463:6;19456:4;19448:6;19444:17;19397:78;:::i;:::-;19388:87;;19204:277;19143:338;;;;:::o;19487:943::-;19582:6;19590;19598;19606;19655:3;19643:9;19634:7;19630:23;19626:33;19623:120;;;19662:79;;:::i;:::-;19623:120;19782:1;19807:53;19852:7;19843:6;19832:9;19828:22;19807:53;:::i;:::-;19797:63;;19753:117;19909:2;19935:53;19980:7;19971:6;19960:9;19956:22;19935:53;:::i;:::-;19925:63;;19880:118;20037:2;20063:53;20108:7;20099:6;20088:9;20084:22;20063:53;:::i;:::-;20053:63;;20008:118;20193:2;20182:9;20178:18;20165:32;20224:18;20216:6;20213:30;20210:117;;;20246:79;;:::i;:::-;20210:117;20351:62;20405:7;20396:6;20385:9;20381:22;20351:62;:::i;:::-;20341:72;;20136:287;19487:943;;;;;;;:::o;20436:171::-;20538:62;20594:5;20538:62;:::i;:::-;20533:3;20526:75;20436:171;;:::o;20613:108::-;20690:24;20708:5;20690:24;:::i;:::-;20685:3;20678:37;20613:108;;:::o;20801:796::-;20982:4;20977:3;20973:14;21086:4;21079:5;21075:16;21069:23;21105:88;21187:4;21182:3;21178:14;21164:12;21105:88;:::i;:::-;20997:206;21300:4;21293:5;21289:16;21283:23;21319:63;21376:4;21371:3;21367:14;21353:12;21319:63;:::i;:::-;21213:179;21498:4;21491:5;21487:16;21481:23;21517:63;21574:4;21569:3;21565:14;21551:12;21517:63;:::i;:::-;21402:188;20951:646;20801:796;;:::o;21603:390::-;21780:4;21818:2;21807:9;21803:18;21795:26;;21831:155;21983:1;21972:9;21968:17;21959:6;21831:155;:::i;:::-;21603:390;;;;:::o;21999:474::-;22067:6;22075;22124:2;22112:9;22103:7;22099:23;22095:32;22092:119;;;22130:79;;:::i;:::-;22092:119;22250:1;22275:53;22320:7;22311:6;22300:9;22296:22;22275:53;:::i;:::-;22265:63;;22221:117;22377:2;22403:53;22448:7;22439:6;22428:9;22424:22;22403:53;:::i;:::-;22393:63;;22348:118;21999:474;;;;;:::o;22479:819::-;22592:6;22600;22608;22616;22665:3;22653:9;22644:7;22640:23;22636:33;22633:120;;;22672:79;;:::i;:::-;22633:120;22792:1;22817:53;22862:7;22853:6;22842:9;22838:22;22817:53;:::i;:::-;22807:63;;22763:117;22919:2;22945:80;23017:7;23008:6;22997:9;22993:22;22945:80;:::i;:::-;22935:90;;22890:145;23074:2;23100:53;23145:7;23136:6;23125:9;23121:22;23100:53;:::i;:::-;23090:63;;23045:118;23202:2;23228:53;23273:7;23264:6;23253:9;23249:22;23228:53;:::i;:::-;23218:63;;23173:118;22479:819;;;;;;;:::o;23304:180::-;23352:77;23349:1;23342:88;23449:4;23446:1;23439:15;23473:4;23470:1;23463:15;23490:320;23534:6;23571:1;23565:4;23561:12;23551:22;;23618:1;23612:4;23608:12;23639:18;23629:81;;23695:4;23687:6;23683:17;23673:27;;23629:81;23757:2;23749:6;23746:14;23726:18;23723:38;23720:84;;23776:18;;:::i;:::-;23720:84;23541:269;23490:320;;;:::o;23816:97::-;23875:6;23903:3;23893:13;;23816:97;;;;:::o;23919:141::-;23968:4;23991:3;23983:11;;24014:3;24011:1;24004:14;24048:4;24045:1;24035:18;24027:26;;23919:141;;;:::o;24066:93::-;24103:6;24150:2;24145;24138:5;24134:14;24130:23;24120:33;;24066:93;;;:::o;24165:107::-;24209:8;24259:5;24253:4;24249:16;24228:37;;24165:107;;;;:::o;24278:393::-;24347:6;24397:1;24385:10;24381:18;24420:97;24450:66;24439:9;24420:97;:::i;:::-;24538:39;24568:8;24557:9;24538:39;:::i;:::-;24526:51;;24610:4;24606:9;24599:5;24595:21;24586:30;;24659:4;24649:8;24645:19;24638:5;24635:30;24625:40;;24354:317;;24278:393;;;;;:::o;24677:142::-;24727:9;24760:53;24778:34;24787:24;24805:5;24787:24;:::i;:::-;24778:34;:::i;:::-;24760:53;:::i;:::-;24747:66;;24677:142;;;:::o;24825:75::-;24868:3;24889:5;24882:12;;24825:75;;;:::o;24906:269::-;25016:39;25047:7;25016:39;:::i;:::-;25077:91;25126:41;25150:16;25126:41;:::i;:::-;25118:6;25111:4;25105:11;25077:91;:::i;:::-;25071:4;25064:105;24982:193;24906:269;;;:::o;25181:73::-;25226:3;25247:1;25240:8;;25181:73;:::o;25260:189::-;25337:32;;:::i;:::-;25378:65;25436:6;25428;25422:4;25378:65;:::i;:::-;25313:136;25260:189;;:::o;25455:186::-;25515:120;25532:3;25525:5;25522:14;25515:120;;;25586:39;25623:1;25616:5;25586:39;:::i;:::-;25559:1;25552:5;25548:13;25539:22;;25515:120;;;25455:186;;:::o;25647:543::-;25748:2;25743:3;25740:11;25737:446;;;25782:38;25814:5;25782:38;:::i;:::-;25866:29;25884:10;25866:29;:::i;:::-;25856:8;25852:44;26049:2;26037:10;26034:18;26031:49;;;26070:8;26055:23;;26031:49;26093:80;26149:22;26167:3;26149:22;:::i;:::-;26139:8;26135:37;26122:11;26093:80;:::i;:::-;25752:431;;25737:446;25647:543;;;:::o;26196:117::-;26250:8;26300:5;26294:4;26290:16;26269:37;;26196:117;;;;:::o;26319:169::-;26363:6;26396:51;26444:1;26440:6;26432:5;26429:1;26425:13;26396:51;:::i;:::-;26392:56;26477:4;26471;26467:15;26457:25;;26370:118;26319:169;;;;:::o;26493:295::-;26569:4;26715:29;26740:3;26734:4;26715:29;:::i;:::-;26707:37;;26777:3;26774:1;26770:11;26764:4;26761:21;26753:29;;26493:295;;;;:::o;26793:1403::-;26917:44;26957:3;26952;26917:44;:::i;:::-;27026:18;27018:6;27015:30;27012:56;;;27048:18;;:::i;:::-;27012:56;27092:38;27124:4;27118:11;27092:38;:::i;:::-;27177:67;27237:6;27229;27223:4;27177:67;:::i;:::-;27271:1;27300:2;27292:6;27289:14;27317:1;27312:632;;;;27988:1;28005:6;28002:84;;;28061:9;28056:3;28052:19;28039:33;28030:42;;28002:84;28112:67;28172:6;28165:5;28112:67;:::i;:::-;28106:4;28099:81;27961:229;27282:908;;27312:632;27364:4;27360:9;27352:6;27348:22;27398:37;27430:4;27398:37;:::i;:::-;27457:1;27471:215;27485:7;27482:1;27479:14;27471:215;;;27571:9;27566:3;27562:19;27549:33;27541:6;27534:49;27622:1;27614:6;27610:14;27600:24;;27669:2;27658:9;27654:18;27641:31;;27508:4;27505:1;27501:12;27496:17;;27471:215;;;27714:6;27705:7;27702:19;27699:186;;;27779:9;27774:3;27770:19;27757:33;27822:48;27864:4;27856:6;27852:17;27841:9;27822:48;:::i;:::-;27814:6;27807:64;27722:163;27699:186;27931:1;27927;27919:6;27915:14;27911:22;27905:4;27898:36;27319:625;;;27282:908;;26892:1304;;;26793:1403;;;:::o;28202:442::-;28351:4;28389:2;28378:9;28374:18;28366:26;;28402:71;28470:1;28459:9;28455:17;28446:6;28402:71;:::i;:::-;28483:72;28551:2;28540:9;28536:18;28527:6;28483:72;:::i;:::-;28565;28633:2;28622:9;28618:18;28609:6;28565:72;:::i;:::-;28202:442;;;;;;:::o;28650:180::-;28698:77;28695:1;28688:88;28795:4;28792:1;28785:15;28819:4;28816:1;28809:15;28836:410;28876:7;28899:20;28917:1;28899:20;:::i;:::-;28894:25;;28933:20;28951:1;28933:20;:::i;:::-;28928:25;;28988:1;28985;28981:9;29010:30;29028:11;29010:30;:::i;:::-;28999:41;;29189:1;29180:7;29176:15;29173:1;29170:22;29150:1;29143:9;29123:83;29100:139;;29219:18;;:::i;:::-;29100:139;28884:362;28836:410;;;;:::o;29252:180::-;29300:77;29297:1;29290:88;29397:4;29394:1;29387:15;29421:4;29418:1;29411:15;29438:185;29478:1;29495:20;29513:1;29495:20;:::i;:::-;29490:25;;29529:20;29547:1;29529:20;:::i;:::-;29524:25;;29568:1;29558:35;;29573:18;;:::i;:::-;29558:35;29615:1;29612;29608:9;29603:14;;29438:185;;;;:::o;29629:117::-;29738:1;29735;29728:12;29875:197;29959:5;29990:6;29984:13;29975:22;;30006:60;30060:5;30006:60;:::i;:::-;29875:197;;;;:::o;30078:143::-;30135:5;30166:6;30160:13;30151:22;;30182:33;30209:5;30182:33;:::i;:::-;30078:143;;;;:::o;30266:879::-;30368:5;30412:4;30400:9;30395:3;30391:19;30387:30;30384:117;;;30420:79;;:::i;:::-;30384:117;30519:21;30535:4;30519:21;:::i;:::-;30510:30;;30616:1;30656:87;30739:3;30730:6;30719:9;30715:22;30656:87;:::i;:::-;30649:4;30642:5;30638:16;30631:113;30550:205;30829:2;30870:60;30926:3;30917:6;30906:9;30902:22;30870:60;:::i;:::-;30863:4;30856:5;30852:16;30845:86;30765:177;31025:2;31066:60;31122:3;31113:6;31102:9;31098:22;31066:60;:::i;:::-;31059:4;31052:5;31048:16;31041:86;30952:186;30266:879;;;;:::o;31151:435::-;31263:6;31312:2;31300:9;31291:7;31287:23;31283:32;31280:119;;;31318:79;;:::i;:::-;31280:119;31438:1;31463:106;31561:7;31552:6;31541:9;31537:22;31463:106;:::i;:::-;31453:116;;31409:170;31151:435;;;;:::o;31592:332::-;31713:4;31751:2;31740:9;31736:18;31728:26;;31764:71;31832:1;31821:9;31817:17;31808:6;31764:71;:::i;:::-;31845:72;31913:2;31902:9;31898:18;31889:6;31845:72;:::i;:::-;31592:332;;;;;:::o;31930:137::-;31984:5;32015:6;32009:13;32000:22;;32031:30;32055:5;32031:30;:::i;:::-;31930:137;;;;:::o;32073:345::-;32140:6;32189:2;32177:9;32168:7;32164:23;32160:32;32157:119;;;32195:79;;:::i;:::-;32157:119;32315:1;32340:61;32393:7;32384:6;32373:9;32369:22;32340:61;:::i;:::-;32330:71;;32286:125;32073:345;;;;:::o;32424:147::-;32525:11;32562:3;32547:18;;32424:147;;;;:::o;32577:114::-;;:::o;32697:398::-;32856:3;32877:83;32958:1;32953:3;32877:83;:::i;:::-;32870:90;;32969:93;33058:3;32969:93;:::i;:::-;33087:1;33082:3;33078:11;33071:18;;32697:398;;;:::o;33101:379::-;33285:3;33307:147;33450:3;33307:147;:::i;:::-;33300:154;;33471:3;33464:10;;33101:379;;;:::o;33486:311::-;33563:4;33653:18;33645:6;33642:30;33639:56;;;33675:18;;:::i;:::-;33639:56;33725:4;33717:6;33713:17;33705:25;;33785:4;33779;33775:15;33767:23;;33486:311;;;:::o;33803:143::-;33860:5;33891:6;33885:13;33876:22;;33907:33;33934:5;33907:33;:::i;:::-;33803:143;;;;:::o;33969:732::-;34076:5;34101:81;34117:64;34174:6;34117:64;:::i;:::-;34101:81;:::i;:::-;34092:90;;34202:5;34231:6;34224:5;34217:21;34265:4;34258:5;34254:16;34247:23;;34318:4;34310:6;34306:17;34298:6;34294:30;34347:3;34339:6;34336:15;34333:122;;;34366:79;;:::i;:::-;34333:122;34481:6;34464:231;34498:6;34493:3;34490:15;34464:231;;;34573:3;34602:48;34646:3;34634:10;34602:48;:::i;:::-;34597:3;34590:61;34680:4;34675:3;34671:14;34664:21;;34540:155;34524:4;34519:3;34515:14;34508:21;;34464:231;;;34468:21;34082:619;;33969:732;;;;;:::o;34724:385::-;34806:5;34855:3;34848:4;34840:6;34836:17;34832:27;34822:122;;34863:79;;:::i;:::-;34822:122;34973:6;34967:13;34998:105;35099:3;35091:6;35084:4;35076:6;35072:17;34998:105;:::i;:::-;34989:114;;34812:297;34724:385;;;;:::o;35115:554::-;35210:6;35259:2;35247:9;35238:7;35234:23;35230:32;35227:119;;;35265:79;;:::i;:::-;35227:119;35406:1;35395:9;35391:17;35385:24;35436:18;35428:6;35425:30;35422:117;;;35458:79;;:::i;:::-;35422:117;35563:89;35644:7;35635:6;35624:9;35620:22;35563:89;:::i;:::-;35553:99;;35356:306;35115:554;;;;:::o;35675:382::-;35821:4;35859:2;35848:9;35844:18;35836:26;;35872:71;35940:1;35929:9;35925:17;35916:6;35872:71;:::i;:::-;35953:97;36046:2;36035:9;36031:18;36022:6;35953:97;:::i;:::-;35675:382;;;;;:::o;36063:332::-;36184:4;36222:2;36211:9;36207:18;36199:26;;36235:71;36303:1;36292:9;36288:17;36279:6;36235:71;:::i;:::-;36316:72;36384:2;36373:9;36369:18;36360:6;36316:72;:::i;:::-;36063:332;;;;;:::o;36401:115::-;36486:23;36503:5;36486:23;:::i;:::-;36481:3;36474:36;36401:115;;:::o;36522:218::-;36613:4;36651:2;36640:9;36636:18;36628:26;;36664:69;36730:1;36719:9;36715:17;36706:6;36664:69;:::i;:::-;36522:218;;;;:::o;36746:332::-;36867:4;36905:2;36894:9;36890:18;36882:26;;36918:71;36986:1;36975:9;36971:17;36962:6;36918:71;:::i;:::-;36999:72;37067:2;37056:9;37052:18;37043:6;36999:72;:::i;:::-;36746:332;;;;;:::o;37084:234::-;37224:34;37220:1;37212:6;37208:14;37201:58;37293:17;37288:2;37280:6;37276:15;37269:42;37084:234;:::o;37324:366::-;37466:3;37487:67;37551:2;37546:3;37487:67;:::i;:::-;37480:74;;37563:93;37652:3;37563:93;:::i;:::-;37681:2;37676:3;37672:12;37665:19;;37324:366;;;:::o;37696:419::-;37862:4;37900:2;37889:9;37885:18;37877:26;;37949:9;37943:4;37939:20;37935:1;37924:9;37920:17;37913:47;37977:131;38103:4;37977:131;:::i;:::-;37969:139;;37696:419;;;:::o;38121:148::-;38223:11;38260:3;38245:18;;38121:148;;;;:::o;38275:390::-;38381:3;38409:39;38442:5;38409:39;:::i;:::-;38464:89;38546:6;38541:3;38464:89;:::i;:::-;38457:96;;38562:65;38620:6;38615:3;38608:4;38601:5;38597:16;38562:65;:::i;:::-;38652:6;38647:3;38643:16;38636:23;;38385:280;38275:390;;;;:::o;38671:435::-;38851:3;38873:95;38964:3;38955:6;38873:95;:::i;:::-;38866:102;;38985:95;39076:3;39067:6;38985:95;:::i;:::-;38978:102;;39097:3;39090:10;;38671:435;;;;;:::o;39112:115::-;39197:23;39214:5;39197:23;:::i;:::-;39192:3;39185:36;39112:115;;:::o;39233:218::-;39324:4;39362:2;39351:9;39347:18;39339:26;;39375:69;39441:1;39430:9;39426:17;39417:6;39375:69;:::i;:::-;39233:218;;;;:::o;39457:171::-;39496:3;39519:24;39537:5;39519:24;:::i;:::-;39510:33;;39565:4;39558:5;39555:15;39552:41;;39573:18;;:::i;:::-;39552:41;39620:1;39613:5;39609:13;39602:20;;39457:171;;;:::o;39634:140::-;39683:9;39716:52;39734:33;39743:23;39760:5;39743:23;:::i;:::-;39734:33;:::i;:::-;39716:52;:::i;:::-;39703:65;;39634:140;;;:::o;39780:129::-;39866:36;39896:5;39866:36;:::i;:::-;39861:3;39854:49;39780:129;;:::o;39915:330::-;40035:4;40073:2;40062:9;40058:18;40050:26;;40086:70;40153:1;40142:9;40138:17;40129:6;40086:70;:::i;:::-;40166:72;40234:2;40223:9;40219:18;40210:6;40166:72;:::i;:::-;39915:330;;;;;:::o;40251:191::-;40291:3;40310:20;40328:1;40310:20;:::i;:::-;40305:25;;40344:20;40362:1;40344:20;:::i;:::-;40339:25;;40387:1;40384;40380:9;40373:16;;40408:3;40405:1;40402:10;40399:36;;;40415:18;;:::i;:::-;40399:36;40251:191;;;;:::o;40448:440::-;40596:4;40634:2;40623:9;40619:18;40611:26;;40647:71;40715:1;40704:9;40700:17;40691:6;40647:71;:::i;:::-;40728;40795:2;40784:9;40780:18;40771:6;40728:71;:::i;:::-;40809:72;40877:2;40866:9;40862:18;40853:6;40809:72;:::i;:::-;40448:440;;;;;;:::o;40894:332::-;41015:4;41053:2;41042:9;41038:18;41030:26;;41066:71;41134:1;41123:9;41119:17;41110:6;41066:71;:::i;:::-;41147:72;41215:2;41204:9;41200:18;41191:6;41147:72;:::i;:::-;40894:332;;;;;:::o;41232:98::-;41283:6;41317:5;41311:12;41301:22;;41232:98;;;:::o;41336:168::-;41419:11;41453:6;41448:3;41441:19;41493:4;41488:3;41484:14;41469:29;;41336:168;;;;:::o;41510:373::-;41596:3;41624:38;41656:5;41624:38;:::i;:::-;41678:70;41741:6;41736:3;41678:70;:::i;:::-;41671:77;;41757:65;41815:6;41810:3;41803:4;41796:5;41792:16;41757:65;:::i;:::-;41847:29;41869:6;41847:29;:::i;:::-;41842:3;41838:39;41831:46;;41600:283;41510:373;;;;:::o;41889:640::-;42084:4;42122:3;42111:9;42107:19;42099:27;;42136:71;42204:1;42193:9;42189:17;42180:6;42136:71;:::i;:::-;42217:72;42285:2;42274:9;42270:18;42261:6;42217:72;:::i;:::-;42299;42367:2;42356:9;42352:18;42343:6;42299:72;:::i;:::-;42418:9;42412:4;42408:20;42403:2;42392:9;42388:18;42381:48;42446:76;42517:4;42508:6;42446:76;:::i;:::-;42438:84;;41889:640;;;;;;;:::o;42535:141::-;42591:5;42622:6;42616:13;42607:22;;42638:32;42664:5;42638:32;:::i;:::-;42535:141;;;;:::o;42682:349::-;42751:6;42800:2;42788:9;42779:7;42775:23;42771:32;42768:119;;;42806:79;;:::i;:::-;42768:119;42926:1;42951:63;43006:7;42997:6;42986:9;42982:22;42951:63;:::i;:::-;42941:73;;42897:127;42682:349;;;;:::o
Swarm Source
ipfs://8d41f981a790e4b660c328ec8c35abe9134e13534a334d391c817be62a5a0056
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 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.