ERC-721
Source Code
Overview
Max Total Supply
6,042 WOW
Holders
4,766
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 WOWLoading...
Loading
Loading...
Loading
Loading...
Loading
Contract Name:
WomexNFT721
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/
interface IPostDispatchHook {
enum Types {
UNUSED,
ROUTING,
AGGREGATION,
MERKLE_TREE,
INTERCHAIN_GAS_PAYMASTER,
FALLBACK_ROUTING,
ID_AUTH_ISM,
PAUSABLE,
PROTOCOL_FEE,
LAYER_ZERO_V1
}
/**
* @notice Returns an enum that represents the type of hook
*/
function hookType() external view returns (uint8);
/**
* @notice Returns whether the hook supports metadata
* @param metadata metadata
* @return Whether the hook supports metadata
*/
function supportsMetadata(
bytes calldata metadata
) external view returns (bool);
/**
* @notice Post action after a message is dispatched via the Mailbox
* @param metadata The metadata required for the hook
* @param message The message passed from the Mailbox.dispatch() call
*/
function postDispatch(
bytes calldata metadata,
bytes calldata message
) external payable;
/**
* @notice Compute the payment required by the postDispatch call
* @param metadata The metadata required for the hook
* @param message The message passed from the Mailbox.dispatch() call
* @return Quoted payment for the postDispatch call
*/
function quoteDispatch(
bytes calldata metadata,
bytes calldata message
) external view returns (uint256);
}
// File @hyperlane-xyz/core/contracts/interfaces/[email protected]
// Original license: SPDX_License_Identifier: MIT
pragma solidity >=0.6.11;
interface IInterchainSecurityModule {
enum Types {
UNUSED,
ROUTING,
AGGREGATION,
LEGACY_MULTISIG,
MERKLE_ROOT_MULTISIG,
MESSAGE_ID_MULTISIG,
NULL, // used with relayer carrying no metadata
CCIP_READ
}
/**
* @notice Returns an enum that represents the type of security model
* encoded by this ISM.
* @dev Relayers infer how to fetch and format metadata.
*/
function moduleType() external view returns (uint8);
/**
* @notice Defines a security model responsible for verifying interchain
* messages based on the provided metadata.
* @param _metadata Off-chain metadata provided by a relayer, specific to
* the security model encoded by the module (e.g. validator signatures)
* @param _message Hyperlane encoded interchain message
* @return True if the message was verified
*/
function verify(
bytes calldata _metadata,
bytes calldata _message
) external returns (bool);
}
interface ISpecifiesInterchainSecurityModule {
function interchainSecurityModule()
external
view
returns (IInterchainSecurityModule);
}
// File @hyperlane-xyz/core/contracts/interfaces/[email protected]
// Original license: SPDX_License_Identifier: MIT
pragma solidity >=0.8.0;
interface IMailbox {
// ============ Events ============
/**
* @notice Emitted when a new message is dispatched via Hyperlane
* @param sender The address that dispatched the message
* @param destination The destination domain of the message
* @param recipient The message recipient address on `destination`
* @param message Raw bytes of message
*/
event Dispatch(
address indexed sender,
uint32 indexed destination,
bytes32 indexed recipient,
bytes message
);
/**
* @notice Emitted when a new message is dispatched via Hyperlane
* @param messageId The unique message identifier
*/
event DispatchId(bytes32 indexed messageId);
/**
* @notice Emitted when a Hyperlane message is processed
* @param messageId The unique message identifier
*/
event ProcessId(bytes32 indexed messageId);
/**
* @notice Emitted when a Hyperlane message is delivered
* @param origin The origin domain of the message
* @param sender The message sender address on `origin`
* @param recipient The address that handled the message
*/
event Process(
uint32 indexed origin,
bytes32 indexed sender,
address indexed recipient
);
function localDomain() external view returns (uint32);
function delivered(bytes32 messageId) external view returns (bool);
function defaultIsm() external view returns (IInterchainSecurityModule);
function defaultHook() external view returns (IPostDispatchHook);
function requiredHook() external view returns (IPostDispatchHook);
function latestDispatchedId() external view returns (bytes32);
function dispatch(
uint32 destinationDomain,
bytes32 recipientAddress,
bytes calldata messageBody
) external payable returns (bytes32 messageId);
function quoteDispatch(
uint32 destinationDomain,
bytes32 recipientAddress,
bytes calldata messageBody
) external view returns (uint256 fee);
function dispatch(
uint32 destinationDomain,
bytes32 recipientAddress,
bytes calldata body,
bytes calldata defaultHookMetadata
) external payable returns (bytes32 messageId);
function quoteDispatch(
uint32 destinationDomain,
bytes32 recipientAddress,
bytes calldata messageBody,
bytes calldata defaultHookMetadata
) external view returns (uint256 fee);
function dispatch(
uint32 destinationDomain,
bytes32 recipientAddress,
bytes calldata body,
bytes calldata customHookMetadata,
IPostDispatchHook customHook
) external payable returns (bytes32 messageId);
function quoteDispatch(
uint32 destinationDomain,
bytes32 recipientAddress,
bytes calldata messageBody,
bytes calldata customHookMetadata,
IPostDispatchHook customHook
) external view returns (uint256 fee);
function process(
bytes calldata metadata,
bytes calldata message
) external payable;
function recipientIsm(
address recipient
) external view returns (IInterchainSecurityModule module);
}
// File @hyperlane-xyz/core/contracts/libs/[email protected]
// Original license: SPDX_License_Identifier: MIT
pragma solidity >=0.6.11;
library TypeCasts {
// alignment preserving cast
function addressToBytes32(address _addr) internal pure returns (bytes32) {
return bytes32(uint256(uint160(_addr)));
}
// alignment preserving cast
function bytes32ToAddress(bytes32 _buf) internal pure returns (address) {
return address(uint160(uint256(_buf)));
}
}
// File @hyperlane-xyz/core/contracts/libs/[email protected]
// Original license: SPDX_License_Identifier: MIT
pragma solidity >=0.8.0;
/**
* @title Hyperlane Message Library
* @notice Library for formatted messages used by Mailbox
**/
library Message {
using TypeCasts for bytes32;
uint256 private constant VERSION_OFFSET = 0;
uint256 private constant NONCE_OFFSET = 1;
uint256 private constant ORIGIN_OFFSET = 5;
uint256 private constant SENDER_OFFSET = 9;
uint256 private constant DESTINATION_OFFSET = 41;
uint256 private constant RECIPIENT_OFFSET = 45;
uint256 private constant BODY_OFFSET = 77;
/**
* @notice Returns formatted (packed) Hyperlane message with provided fields
* @dev This function should only be used in memory message construction.
* @param _version The version of the origin and destination Mailboxes
* @param _nonce A nonce to uniquely identify the message on its origin chain
* @param _originDomain Domain of origin chain
* @param _sender Address of sender as bytes32
* @param _destinationDomain Domain of destination chain
* @param _recipient Address of recipient on destination chain as bytes32
* @param _messageBody Raw bytes of message body
* @return Formatted message
*/
function formatMessage(
uint8 _version,
uint32 _nonce,
uint32 _originDomain,
bytes32 _sender,
uint32 _destinationDomain,
bytes32 _recipient,
bytes calldata _messageBody
) internal pure returns (bytes memory) {
return
abi.encodePacked(
_version,
_nonce,
_originDomain,
_sender,
_destinationDomain,
_recipient,
_messageBody
);
}
/**
* @notice Returns the message ID.
* @param _message ABI encoded Hyperlane message.
* @return ID of `_message`
*/
function id(bytes memory _message) internal pure returns (bytes32) {
return keccak256(_message);
}
/**
* @notice Returns the message version.
* @param _message ABI encoded Hyperlane message.
* @return Version of `_message`
*/
function version(bytes calldata _message) internal pure returns (uint8) {
return uint8(bytes1(_message[VERSION_OFFSET:NONCE_OFFSET]));
}
/**
* @notice Returns the message nonce.
* @param _message ABI encoded Hyperlane message.
* @return Nonce of `_message`
*/
function nonce(bytes calldata _message) internal pure returns (uint32) {
return uint32(bytes4(_message[NONCE_OFFSET:ORIGIN_OFFSET]));
}
/**
* @notice Returns the message origin domain.
* @param _message ABI encoded Hyperlane message.
* @return Origin domain of `_message`
*/
function origin(bytes calldata _message) internal pure returns (uint32) {
return uint32(bytes4(_message[ORIGIN_OFFSET:SENDER_OFFSET]));
}
/**
* @notice Returns the message sender as bytes32.
* @param _message ABI encoded Hyperlane message.
* @return Sender of `_message` as bytes32
*/
function sender(bytes calldata _message) internal pure returns (bytes32) {
return bytes32(_message[SENDER_OFFSET:DESTINATION_OFFSET]);
}
/**
* @notice Returns the message sender as address.
* @param _message ABI encoded Hyperlane message.
* @return Sender of `_message` as address
*/
function senderAddress(
bytes calldata _message
) internal pure returns (address) {
return sender(_message).bytes32ToAddress();
}
/**
* @notice Returns the message destination domain.
* @param _message ABI encoded Hyperlane message.
* @return Destination domain of `_message`
*/
function destination(
bytes calldata _message
) internal pure returns (uint32) {
return uint32(bytes4(_message[DESTINATION_OFFSET:RECIPIENT_OFFSET]));
}
/**
* @notice Returns the message recipient as bytes32.
* @param _message ABI encoded Hyperlane message.
* @return Recipient of `_message` as bytes32
*/
function recipient(
bytes calldata _message
) internal pure returns (bytes32) {
return bytes32(_message[RECIPIENT_OFFSET:BODY_OFFSET]);
}
/**
* @notice Returns the message recipient as address.
* @param _message ABI encoded Hyperlane message.
* @return Recipient of `_message` as address
*/
function recipientAddress(
bytes calldata _message
) internal pure returns (address) {
return recipient(_message).bytes32ToAddress();
}
/**
* @notice Returns the message body.
* @param _message ABI encoded Hyperlane message.
* @return Body of `_message`
*/
function body(
bytes calldata _message
) internal pure returns (bytes calldata) {
return bytes(_message[BODY_OFFSET:]);
}
}
// File @openzeppelin/contracts-upgradeable/utils/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
// File @openzeppelin/contracts-upgradeable/proxy/utils/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}
// File @openzeppelin/contracts-upgradeable/utils/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
// File @openzeppelin/contracts-upgradeable/access/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
/**
* @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.
*
* By default, the owner account will be the one that deploys the contract. 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 OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @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 {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @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 {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_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);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
// File @openzeppelin/contracts/utils/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
// File @hyperlane-xyz/core/contracts/client/[email protected]
// Original license: SPDX_License_Identifier: MIT
pragma solidity >=0.6.11;
// ============ Internal Imports ============
// ============ External Imports ============
abstract contract MailboxClient is OwnableUpgradeable {
using Message for bytes;
IMailbox public immutable mailbox;
uint32 public immutable localDomain;
IPostDispatchHook public hook;
IInterchainSecurityModule public interchainSecurityModule;
uint256[48] private __GAP; // gap for upgrade safety
// ============ Modifiers ============
modifier onlyContract(address _contract) {
require(
Address.isContract(_contract),
"MailboxClient: invalid mailbox"
);
_;
}
modifier onlyContractOrNull(address _contract) {
require(
Address.isContract(_contract) || _contract == address(0),
"MailboxClient: invalid contract setting"
);
_;
}
/**
* @notice Only accept messages from an Hyperlane Mailbox contract
*/
modifier onlyMailbox() {
require(
msg.sender == address(mailbox),
"MailboxClient: sender not mailbox"
);
_;
}
constructor(address _mailbox) onlyContract(_mailbox) {
mailbox = IMailbox(_mailbox);
localDomain = mailbox.localDomain();
_transferOwnership(msg.sender);
}
/**
* @notice Sets the address of the application's custom hook.
* @param _hook The address of the hook contract.
*/
function setHook(address _hook) public onlyContractOrNull(_hook) onlyOwner {
hook = IPostDispatchHook(_hook);
}
/**
* @notice Sets the address of the application's custom interchain security module.
* @param _module The address of the interchain security module contract.
*/
function setInterchainSecurityModule(
address _module
) public onlyContractOrNull(_module) onlyOwner {
interchainSecurityModule = IInterchainSecurityModule(_module);
}
// ======== Initializer =========
function _MailboxClient_initialize(
address _hook,
address _interchainSecurityModule,
address _owner
) internal onlyInitializing {
__Ownable_init();
setHook(_hook);
setInterchainSecurityModule(_interchainSecurityModule);
_transferOwnership(_owner);
}
function _isLatestDispatched(bytes32 id) internal view returns (bool) {
return mailbox.latestDispatchedId() == id;
}
function _metadata(
uint32 /*_destinationDomain*/
) internal view virtual returns (bytes memory) {
return "";
}
function _dispatch(
uint32 _destinationDomain,
bytes32 _recipient,
bytes memory _messageBody
) internal virtual returns (bytes32) {
return
_dispatch(_destinationDomain, _recipient, msg.value, _messageBody);
}
function _dispatch(
uint32 _destinationDomain,
bytes32 _recipient,
uint256 _value,
bytes memory _messageBody
) internal virtual returns (bytes32) {
return
mailbox.dispatch{value: _value}(
_destinationDomain,
_recipient,
_messageBody,
_metadata(_destinationDomain),
hook
);
}
function _quoteDispatch(
uint32 _destinationDomain,
bytes32 _recipient,
bytes memory _messageBody
) internal view virtual returns (uint256) {
return
mailbox.quoteDispatch(
_destinationDomain,
_recipient,
_messageBody,
_metadata(_destinationDomain),
hook
);
}
}
// File @hyperlane-xyz/core/contracts/interfaces/[email protected]
// Original license: SPDX_License_Identifier: MIT
pragma solidity >=0.6.11;
interface IMessageRecipient {
function handle(
uint32 _origin,
bytes32 _sender,
bytes calldata _message
) external payable;
}
// File @openzeppelin/contracts/utils/structs/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}
// File @openzeppelin/contracts/utils/structs/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableMap.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableMap.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing an enumerable variant of Solidity's
* https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
* type.
*
* Maps have the following properties:
*
* - Entries are added, removed, and checked for existence in constant time
* (O(1)).
* - Entries are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableMap for EnumerableMap.UintToAddressMap;
*
* // Declare a set state variable
* EnumerableMap.UintToAddressMap private myMap;
* }
* ```
*
* The following map types are supported:
*
* - `uint256 -> address` (`UintToAddressMap`) since v3.0.0
* - `address -> uint256` (`AddressToUintMap`) since v4.6.0
* - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0
* - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0
* - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableMap.
* ====
*/
library EnumerableMap {
using EnumerableSet for EnumerableSet.Bytes32Set;
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Map type with
// bytes32 keys and values.
// The Map implementation uses private functions, and user-facing
// implementations (such as Uint256ToAddressMap) are just wrappers around
// the underlying Map.
// This means that we can only create new EnumerableMaps for types that fit
// in bytes32.
struct Bytes32ToBytes32Map {
// Storage of keys
EnumerableSet.Bytes32Set _keys;
mapping(bytes32 => bytes32) _values;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) {
map._values[key] = value;
return map._keys.add(key);
}
/**
* @dev Removes a key-value pair from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {
delete map._values[key];
return map._keys.remove(key);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {
return map._keys.contains(key);
}
/**
* @dev Returns the number of key-value pairs in the map. O(1).
*/
function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {
return map._keys.length();
}
/**
* @dev Returns the key-value pair stored at position `index` in the map. O(1).
*
* Note that there are no guarantees on the ordering of entries inside the
* array, and it may change when more entries are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) {
bytes32 key = map._keys.at(index);
return (key, map._values[key]);
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) {
bytes32 value = map._values[key];
if (value == bytes32(0)) {
return (contains(map, key), bytes32(0));
} else {
return (true, value);
}
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key");
return value;
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
Bytes32ToBytes32Map storage map,
bytes32 key,
string memory errorMessage
) internal view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || contains(map, key), errorMessage);
return value;
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) {
return map._keys.values();
}
// UintToUintMap
struct UintToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(UintToUintMap storage map, uint256 key, uint256 value) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(value));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToUintMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), uint256(value));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, uint256(value));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key)));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(UintToUintMap storage map, uint256 key, string memory errorMessage) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key), errorMessage));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(UintToUintMap storage map) internal view returns (uint256[] memory) {
bytes32[] memory store = keys(map._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintToAddressMap
struct UintToAddressMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToAddressMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), address(uint160(uint256(value))));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, address(uint160(uint256(value))));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(key)))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
UintToAddressMap storage map,
uint256 key,
string memory errorMessage
) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage))));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(UintToAddressMap storage map) internal view returns (uint256[] memory) {
bytes32[] memory store = keys(map._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressToUintMap
struct AddressToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(AddressToUintMap storage map, address key, uint256 value) internal returns (bool) {
return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(AddressToUintMap storage map, address key) internal returns (bool) {
return remove(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(AddressToUintMap storage map, address key) internal view returns (bool) {
return contains(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(AddressToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (address(uint160(uint256(key))), uint256(value));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key))));
return (success, uint256(value));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(AddressToUintMap storage map, address key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(uint256(uint160(key)))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
AddressToUintMap storage map,
address key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(AddressToUintMap storage map) internal view returns (address[] memory) {
bytes32[] memory store = keys(map._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// Bytes32ToUintMap
struct Bytes32ToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) {
return set(map._inner, key, bytes32(value));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) {
return remove(map._inner, key);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) {
return contains(map._inner, key);
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(Bytes32ToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (key, uint256(value));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, key);
return (success, uint256(value));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) {
return uint256(get(map._inner, key));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
Bytes32ToUintMap storage map,
bytes32 key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, key, errorMessage));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) {
bytes32[] memory store = keys(map._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}
// File @hyperlane-xyz/core/contracts/libs/[email protected]
// Original license: SPDX_License_Identifier: MIT
pragma solidity >=0.6.11;
// ============ External Imports ============
// extends EnumerableMap with uint256 => bytes32 type
// modelled after https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.0/contracts/utils/structs/EnumerableMap.sol
library EnumerableMapExtended {
using EnumerableMap for EnumerableMap.Bytes32ToBytes32Map;
using EnumerableSet for EnumerableSet.Bytes32Set;
struct UintToBytes32Map {
EnumerableMap.Bytes32ToBytes32Map _inner;
}
// ============ Library Functions ============
function keys(
UintToBytes32Map storage map
) internal view returns (uint256[] memory _keys) {
uint256 _length = map._inner.length();
_keys = new uint256[](_length);
for (uint256 i = 0; i < _length; i++) {
_keys[i] = uint256(map._inner._keys.at(i));
}
}
function uint32Keys(
UintToBytes32Map storage map
) internal view returns (uint32[] memory _keys) {
uint256[] memory uint256keys = keys(map);
_keys = new uint32[](uint256keys.length);
for (uint256 i = 0; i < uint256keys.length; i++) {
_keys[i] = uint32(uint256keys[i]);
}
}
function set(
UintToBytes32Map storage map,
uint256 key,
bytes32 value
) internal {
map._inner.set(bytes32(key), value);
}
function get(
UintToBytes32Map storage map,
uint256 key
) internal view returns (bytes32) {
return map._inner.get(bytes32(key));
}
function tryGet(
UintToBytes32Map storage map,
uint256 key
) internal view returns (bool, bytes32) {
return map._inner.tryGet(bytes32(key));
}
function remove(
UintToBytes32Map storage map,
uint256 key
) internal returns (bool) {
return map._inner.remove(bytes32(key));
}
function contains(
UintToBytes32Map storage map,
uint256 key
) internal view returns (bool) {
return map._inner.contains(bytes32(key));
}
function length(
UintToBytes32Map storage map
) internal view returns (uint256) {
return map._inner.length();
}
function at(
UintToBytes32Map storage map,
uint256 index
) internal view returns (uint256, bytes32) {
(bytes32 key, bytes32 value) = map._inner.at(index);
return (uint256(key), value);
}
}
// File @openzeppelin/contracts/utils/math/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// тЖТ `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// тЖТ `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
// File @openzeppelin/contracts/utils/math/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}
// File @openzeppelin/contracts/utils/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}
// File @hyperlane-xyz/core/contracts/client/[email protected]
// Original license: SPDX_License_Identifier: MIT
pragma solidity >=0.6.11;
// ============ Internal Imports ============
// ============ External Imports ============
abstract contract Router is MailboxClient, IMessageRecipient {
using EnumerableMapExtended for EnumerableMapExtended.UintToBytes32Map;
using Strings for uint32;
// ============ Mutable Storage ============
EnumerableMapExtended.UintToBytes32Map internal _routers;
uint256[48] private __GAP; // gap for upgrade safety
constructor(address _mailbox) MailboxClient(_mailbox) {}
// ============ External functions ============
function domains() external view returns (uint32[] memory) {
return _routers.uint32Keys();
}
/**
* @notice Returns the address of the Router contract for the given domain
* @param _domain The remote domain ID.
* @dev Returns 0 address if no router is enrolled for the given domain
* @return router The address of the Router contract for the given domain
*/
function routers(uint32 _domain) public view virtual returns (bytes32) {
(, bytes32 _router) = _routers.tryGet(_domain);
return _router;
}
/**
* @notice Unregister the domain
* @param _domain The domain of the remote Application Router
*/
function unenrollRemoteRouter(uint32 _domain) external virtual onlyOwner {
_unenrollRemoteRouter(_domain);
}
/**
* @notice Register the address of a Router contract for the same Application on a remote chain
* @param _domain The domain of the remote Application Router
* @param _router The address of the remote Application Router
*/
function enrollRemoteRouter(
uint32 _domain,
bytes32 _router
) external virtual onlyOwner {
_enrollRemoteRouter(_domain, _router);
}
/**
* @notice Batch version of `enrollRemoteRouter`
* @param _domains The domains of the remote Application Routers
* @param _addresses The addresses of the remote Application Routers
*/
function enrollRemoteRouters(
uint32[] calldata _domains,
bytes32[] calldata _addresses
) external virtual onlyOwner {
require(_domains.length == _addresses.length, "!length");
uint256 length = _domains.length;
for (uint256 i = 0; i < length; i += 1) {
_enrollRemoteRouter(_domains[i], _addresses[i]);
}
}
/**
* @notice Batch version of `unenrollRemoteRouter`
* @param _domains The domains of the remote Application Routers
*/
function unenrollRemoteRouters(
uint32[] calldata _domains
) external virtual onlyOwner {
uint256 length = _domains.length;
for (uint256 i = 0; i < length; i += 1) {
_unenrollRemoteRouter(_domains[i]);
}
}
/**
* @notice Handles an incoming message
* @param _origin The origin domain
* @param _sender The sender address
* @param _message The message
*/
function handle(
uint32 _origin,
bytes32 _sender,
bytes calldata _message
) external payable virtual override onlyMailbox {
bytes32 _router = _mustHaveRemoteRouter(_origin);
require(_router == _sender, "Enrolled router does not match sender");
_handle(_origin, _sender, _message);
}
// ============ Virtual functions ============
function _handle(
uint32 _origin,
bytes32 _sender,
bytes calldata _message
) internal virtual;
// ============ Internal functions ============
/**
* @notice Set the router for a given domain
* @param _domain The domain
* @param _address The new router
*/
function _enrollRemoteRouter(
uint32 _domain,
bytes32 _address
) internal virtual {
_routers.set(_domain, _address);
}
/**
* @notice Remove the router for a given domain
* @param _domain The domain
*/
function _unenrollRemoteRouter(uint32 _domain) internal virtual {
require(_routers.remove(_domain), _domainNotFoundError(_domain));
}
/**
* @notice Return true if the given domain / router is the address of a remote Application Router
* @param _domain The domain of the potential remote Application Router
* @param _address The address of the potential remote Application Router
*/
function _isRemoteRouter(
uint32 _domain,
bytes32 _address
) internal view returns (bool) {
return routers(_domain) == _address;
}
/**
* @notice Assert that the given domain has a Application Router registered and return its address
* @param _domain The domain of the chain for which to get the Application Router
* @return _router The address of the remote Application Router on _domain
*/
function _mustHaveRemoteRouter(
uint32 _domain
) internal view returns (bytes32) {
(bool contained, bytes32 _router) = _routers.tryGet(_domain);
require(contained, _domainNotFoundError(_domain));
return _router;
}
function _domainNotFoundError(
uint32 _domain
) internal pure returns (string memory) {
return
string.concat(
"No router enrolled for domain: ",
_domain.toString()
);
}
function _dispatch(
uint32 _destinationDomain,
bytes memory _messageBody
) internal virtual returns (bytes32) {
return _dispatch(_destinationDomain, msg.value, _messageBody);
}
function _dispatch(
uint32 _destinationDomain,
uint256 _value,
bytes memory _messageBody
) internal virtual returns (bytes32) {
bytes32 _router = _mustHaveRemoteRouter(_destinationDomain);
return
super._dispatch(_destinationDomain, _router, _value, _messageBody);
}
function _quoteDispatch(
uint32 _destinationDomain,
bytes memory _messageBody
) internal view virtual returns (uint256) {
bytes32 _router = _mustHaveRemoteRouter(_destinationDomain);
return super._quoteDispatch(_destinationDomain, _router, _messageBody);
}
}
// File @hyperlane-xyz/core/contracts/hooks/libs/[email protected]
// Original license: SPDX_License_Identifier: MIT
pragma solidity >=0.8.0;
/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/
/**
* Format of metadata:
*
* [0:2] variant
* [2:34] msg.value
* [34:66] Gas limit for message (IGP)
* [66:86] Refund address for message (IGP)
* [86:] Custom metadata
*/
library StandardHookMetadata {
struct Metadata {
uint16 variant;
uint256 msgValue;
uint256 gasLimit;
address refundAddress;
}
uint8 private constant VARIANT_OFFSET = 0;
uint8 private constant MSG_VALUE_OFFSET = 2;
uint8 private constant GAS_LIMIT_OFFSET = 34;
uint8 private constant REFUND_ADDRESS_OFFSET = 66;
uint256 private constant MIN_METADATA_LENGTH = 86;
uint16 public constant VARIANT = 1;
/**
* @notice Returns the variant of the metadata.
* @param _metadata ABI encoded standard hook metadata.
* @return variant of the metadata as uint8.
*/
function variant(bytes calldata _metadata) internal pure returns (uint16) {
if (_metadata.length < VARIANT_OFFSET + 2) return 0;
return uint16(bytes2(_metadata[VARIANT_OFFSET:VARIANT_OFFSET + 2]));
}
/**
* @notice Returns the specified value for the message.
* @param _metadata ABI encoded standard hook metadata.
* @param _default Default fallback value.
* @return Value for the message as uint256.
*/
function msgValue(
bytes calldata _metadata,
uint256 _default
) internal pure returns (uint256) {
if (_metadata.length < MSG_VALUE_OFFSET + 32) return _default;
return
uint256(bytes32(_metadata[MSG_VALUE_OFFSET:MSG_VALUE_OFFSET + 32]));
}
/**
* @notice Returns the specified gas limit for the message.
* @param _metadata ABI encoded standard hook metadata.
* @param _default Default fallback gas limit.
* @return Gas limit for the message as uint256.
*/
function gasLimit(
bytes calldata _metadata,
uint256 _default
) internal pure returns (uint256) {
if (_metadata.length < GAS_LIMIT_OFFSET + 32) return _default;
return
uint256(bytes32(_metadata[GAS_LIMIT_OFFSET:GAS_LIMIT_OFFSET + 32]));
}
/**
* @notice Returns the specified refund address for the message.
* @param _metadata ABI encoded standard hook metadata.
* @param _default Default fallback refund address.
* @return Refund address for the message as address.
*/
function refundAddress(
bytes calldata _metadata,
address _default
) internal pure returns (address) {
if (_metadata.length < REFUND_ADDRESS_OFFSET + 20) return _default;
return
address(
bytes20(
_metadata[REFUND_ADDRESS_OFFSET:REFUND_ADDRESS_OFFSET + 20]
)
);
}
/**
* @notice Returns any custom metadata.
* @param _metadata ABI encoded standard hook metadata.
* @return Custom metadata.
*/
function getCustomMetadata(
bytes calldata _metadata
) internal pure returns (bytes calldata) {
if (_metadata.length < MIN_METADATA_LENGTH) return _metadata[0:0];
return _metadata[MIN_METADATA_LENGTH:];
}
/**
* @notice Formats the specified gas limit and refund address into standard hook metadata.
* @param _msgValue msg.value for the message.
* @param _gasLimit Gas limit for the message.
* @param _refundAddress Refund address for the message.
* @param _customMetadata Additional metadata to include in the standard hook metadata.
* @return ABI encoded standard hook metadata.
*/
function formatMetadata(
uint256 _msgValue,
uint256 _gasLimit,
address _refundAddress,
bytes memory _customMetadata
) internal pure returns (bytes memory) {
return
abi.encodePacked(
VARIANT,
_msgValue,
_gasLimit,
_refundAddress,
_customMetadata
);
}
/**
* @notice Formats the specified gas limit and refund address into standard hook metadata.
* @param _msgValue msg.value for the message.
* @return ABI encoded standard hook metadata.
*/
function overrideMsgValue(
uint256 _msgValue
) internal view returns (bytes memory) {
return formatMetadata(_msgValue, uint256(0), msg.sender, "");
}
/**
* @notice Formats the specified gas limit and refund address into standard hook metadata.
* @param _gasLimit Gas limit for the message.
* @return ABI encoded standard hook metadata.
*/
function overrideGasLimit(
uint256 _gasLimit
) internal view returns (bytes memory) {
return formatMetadata(uint256(0), _gasLimit, msg.sender, "");
}
/**
* @notice Formats the specified refund address into standard hook metadata.
* @param _refundAddress Refund address for the message.
* @return ABI encoded standard hook metadata.
*/
function overrideRefundAddress(
address _refundAddress
) internal pure returns (bytes memory) {
return formatMetadata(uint256(0), uint256(0), _refundAddress, "");
}
}
// File @hyperlane-xyz/core/contracts/client/[email protected]
// Original license: SPDX_License_Identifier: MIT
pragma solidity >=0.6.11;
abstract contract GasRouter is Router {
// ============ Mutable Storage ============
mapping(uint32 => uint256) public destinationGas;
struct GasRouterConfig {
uint32 domain;
uint256 gas;
}
constructor(address _mailbox) Router(_mailbox) {}
/**
* @notice Sets the gas amount dispatched for each configured domain.
* @param gasConfigs The array of GasRouterConfig structs
*/
function setDestinationGas(
GasRouterConfig[] calldata gasConfigs
) external onlyOwner {
for (uint256 i = 0; i < gasConfigs.length; i += 1) {
_setDestinationGas(gasConfigs[i].domain, gasConfigs[i].gas);
}
}
/**
* @notice Sets the gas amount dispatched for each configured domain.
* @param domain The destination domain ID
* @param gas The gas limit
*/
function setDestinationGas(uint32 domain, uint256 gas) external onlyOwner {
_setDestinationGas(domain, gas);
}
/**
* @notice Returns the gas payment required to dispatch a message to the given domain's router.
* @param _destinationDomain The domain of the router.
* @return _gasPayment Payment computed by the registered InterchainGasPaymaster.
*/
function quoteGasPayment(
uint32 _destinationDomain
) external view returns (uint256 _gasPayment) {
return _quoteDispatch(_destinationDomain, "");
}
function _metadata(
uint32 _destination
) internal view virtual override returns (bytes memory) {
return
StandardHookMetadata.overrideGasLimit(destinationGas[_destination]);
}
function _setDestinationGas(uint32 domain, uint256 gas) internal {
destinationGas[domain] = gas;
}
}
// File @hyperlane-xyz/core/contracts/token/libs/[email protected]
// Original license: SPDX_License_Identifier: MIT
pragma solidity >=0.8.0;
library TokenMessage {
function format(
bytes32 _recipient,
uint256 _amount,
bytes memory _metadata
) internal pure returns (bytes memory) {
return abi.encodePacked(_recipient, _amount, _metadata);
}
function recipient(bytes calldata message) internal pure returns (bytes32) {
return bytes32(message[0:32]);
}
function amount(bytes calldata message) internal pure returns (uint256) {
return uint256(bytes32(message[32:64]));
}
// alias for ERC721
function tokenId(bytes calldata message) internal pure returns (uint256) {
return amount(message);
}
function metadata(
bytes calldata message
) internal pure returns (bytes calldata) {
return message[64:];
}
}
// File @hyperlane-xyz/core/contracts/token/libs/[email protected]
// Original license: SPDX_License_Identifier: Apache-2.0
pragma solidity >=0.8.0;
/**
* @title Hyperlane Token Router that extends Router with abstract token (ERC20/ERC721) remote transfer functionality.
* @author Abacus Works
*/
abstract contract TokenRouter is GasRouter {
using TypeCasts for bytes32;
using TypeCasts for address;
using TokenMessage for bytes;
/**
* @dev Emitted on `transferRemote` when a transfer message is dispatched.
* @param destination The identifier of the destination chain.
* @param recipient The address of the recipient on the destination chain.
* @param amount The amount of tokens burnt on the origin chain.
*/
event SentTransferRemote(
uint32 indexed destination,
bytes32 indexed recipient,
uint256 amount
);
/**
* @dev Emitted on `_handle` when a transfer message is processed.
* @param origin The identifier of the origin chain.
* @param recipient The address of the recipient on the destination chain.
* @param amount The amount of tokens minted on the destination chain.
*/
event ReceivedTransferRemote(
uint32 indexed origin,
bytes32 indexed recipient,
uint256 amount
);
constructor(address _mailbox) GasRouter(_mailbox) {}
/**
* @notice Transfers `_amountOrId` token to `_recipient` on `_destination` domain.
* @dev Delegates transfer logic to `_transferFromSender` implementation.
* @dev Emits `SentTransferRemote` event on the origin chain.
* @param _destination The identifier of the destination chain.
* @param _recipient The address of the recipient on the destination chain.
* @param _amountOrId The amount or identifier of tokens to be sent to the remote recipient.
* @return messageId The identifier of the dispatched message.
*/
function transferRemote(
uint32 _destination,
bytes32 _recipient,
uint256 _amountOrId
) external payable virtual returns (bytes32 messageId) {
return
_transferRemote(_destination, _recipient, _amountOrId, msg.value);
}
/**
* @notice Transfers `_amountOrId` token to `_recipient` on `_destination` domain.
* @dev Delegates transfer logic to `_transferFromSender` implementation.
* @dev Emits `SentTransferRemote` event on the origin chain.
* @param _destination The identifier of the destination chain.
* @param _recipient The address of the recipient on the destination chain.
* @param _amountOrId The amount or identifier of tokens to be sent to the remote recipient.
* @param _gasPayment The amount of native token to pay for interchain gas.
* @return messageId The identifier of the dispatched message.
*/
function _transferRemote(
uint32 _destination,
bytes32 _recipient,
uint256 _amountOrId,
uint256 _gasPayment
) internal returns (bytes32 messageId) {
bytes memory metadata = _transferFromSender(_amountOrId);
messageId = _dispatch(
_destination,
_gasPayment,
TokenMessage.format(_recipient, _amountOrId, metadata)
);
emit SentTransferRemote(_destination, _recipient, _amountOrId);
}
/**
* @dev Should transfer `_amountOrId` of tokens from `msg.sender` to this token router.
* @dev Called by `transferRemote` before message dispatch.
* @dev Optionally returns `metadata` associated with the transfer to be passed in message.
*/
function _transferFromSender(
uint256 _amountOrId
) internal virtual returns (bytes memory metadata);
/**
* @notice Returns the balance of `account` on this token router.
* @param account The address to query the balance of.
* @return The balance of `account`.
*/
function balanceOf(address account) external virtual returns (uint256);
/**
* @dev Mints tokens to recipient when router receives transfer message.
* @dev Emits `ReceivedTransferRemote` event on the destination chain.
* @param _origin The identifier of the origin chain.
* @param _message The encoded remote transfer message containing the recipient address and amount.
*/
function _handle(
uint32 _origin,
bytes32,
bytes calldata _message
) internal virtual override {
bytes32 recipient = _message.recipient();
uint256 amount = _message.amount();
bytes calldata metadata = _message.metadata();
_transferTo(recipient.bytes32ToAddress(), amount, metadata);
emit ReceivedTransferRemote(_origin, recipient, amount);
}
/**
* @dev Should transfer `_amountOrId` of tokens from this token router to `_recipient`.
* @dev Called by `handle` after message decoding.
* @dev Optionally handles `metadata` associated with transfer passed in message.
*/
function _transferTo(
address _recipient,
uint256 _amountOrId,
bytes calldata metadata
) internal virtual;
}
// File @openzeppelin/contracts/utils/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
// File @openzeppelin/contracts/security/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
// File @openzeppelin/contracts/utils/introspection/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File @openzeppelin/contracts/token/ERC721/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
// File @openzeppelin/contracts/token/ERC721/extensions/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @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);
}
// File @openzeppelin/contracts/token/ERC721/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
// File @openzeppelin/contracts/utils/introspection/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
// File @openzeppelin/contracts/token/ERC721/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.0;
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: address zero is not a valid owner");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _ownerOf(tokenId);
require(owner != address(0), "ERC721: invalid token ID");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
_requireMinted(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @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, can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not token owner or approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
_requireMinted(tokenId);
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_safeTransfer(from, to, tokenId, data);
}
/**
* @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.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*/
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
/**
* @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 (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _ownerOf(tokenId) != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId, 1);
// Check that tokenId was not minted by `_beforeTokenTransfer` hook
require(!_exists(tokenId), "ERC721: token already minted");
unchecked {
// Will not overflow unless all 2**256 token ids are minted to the same owner.
// Given that tokens are minted one by one, it is impossible in practice that
// this ever happens. Might change if we allow batch minting.
// The ERC fails to describe this case.
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId, 1);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId, 1);
// Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
owner = ERC721.ownerOf(tokenId);
// Clear approvals
delete _tokenApprovals[tokenId];
unchecked {
// Cannot overflow, as that would require more tokens to be burned/transferred
// out than the owner initially received through minting and transferring in.
_balances[owner] -= 1;
}
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId, 1);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(address from, address to, uint256 tokenId) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId, 1);
// Check that tokenId was not transferred by `_beforeTokenTransfer` hook
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
// Clear approvals from the previous owner
delete _tokenApprovals[tokenId];
unchecked {
// `_balances[from]` cannot overflow for the same reason as described in `_burn`:
// `from`'s balance is the number of token held, which is at least one before the current
// transfer.
// `_balances[to]` could overflow in the conditions described in `_mint`. That would require
// all 2**256 token ids to be minted, which in practice is impossible.
_balances[from] -= 1;
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId, 1);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits an {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` has not been minted yet.
*/
function _requireMinted(uint256 tokenId) internal view virtual {
require(_exists(tokenId), "ERC721: invalid token ID");
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
* used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
* - When `from` is zero, the tokens will be minted for `to`.
* - When `to` is zero, ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
* - `batchSize` is non-zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}
/**
* @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
* used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
* - When `from` is zero, the tokens were minted for `to`.
* - When `to` is zero, ``from``'s tokens were burned.
* - `from` and `to` are never both zero.
* - `batchSize` is non-zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant
* being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such
* that `ownerOf(tokenId)` is `a`.
*/
// solhint-disable-next-line func-name-mixedcase
function __unsafe_increaseBalance(address account, uint256 amount) internal {
_balances[account] += amount;
}
}
// File @openzeppelin/contracts/token/ERC721/extensions/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.0;
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}
// File @openzeppelin/contracts/token/ERC721/extensions/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Enumerable.sol)
pragma solidity ^0.8.0;
/**
* @dev This implements an optional extension of {ERC721} defined in the EIP that adds
* enumerability of all the token ids in the contract as well as all token ids owned by each
* account.
*/
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
// Mapping from owner to list of owned token IDs
mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
// Mapping from token ID to index of the owner tokens list
mapping(uint256 => uint256) private _ownedTokensIndex;
// Array with all token ids, used for enumeration
uint256[] private _allTokens;
// Mapping from token id to position in the allTokens array
mapping(uint256 => uint256) private _allTokensIndex;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
/**
* @dev See {ERC721-_beforeTokenTransfer}.
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 firstTokenId,
uint256 batchSize
) internal virtual override {
super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
if (batchSize > 1) {
// Will only trigger during construction. Batch transferring (minting) is not available afterwards.
revert("ERC721Enumerable: consecutive transfers not supported");
}
uint256 tokenId = firstTokenId;
if (from == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (from != to) {
_removeTokenFromOwnerEnumeration(from, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (to != from) {
_addTokenToOwnerEnumeration(to, tokenId);
}
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = ERC721.balanceOf(to);
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
}
// File @openzeppelin/contracts/security/[email protected]
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}
// File contracts/HypERC721.sol
// Original license: SPDX_License_Identifier: MIT
pragma solidity =0.8.19;
/**
* @author Womex
* @title WomexNFT721
*/
contract WomexNFT721 is TokenRouter, ERC721Enumerable, Pausable, ReentrancyGuard {
event NFTMinted(address indexed minter, uint256 indexed itemId, uint256 feeEarnings, address indexed referrer, uint256 referrerEarnings);
event NFTSent(address indexed from, uint32 indexed dstChainId, address indexed receiver, uint256 tokenId, uint256 feeEarned);
event NFTReceived(bytes32 indexed srcAddress, uint32 indexed srcChainId, address indexed receiver, uint256 tokenId);
event FeeEarningsClaimed(address indexed collector, uint256 claimedAmount);
event ReferrerEarningsClaimed(address indexed referrer, uint256 claimedAmount);
uint256 public immutable minTokenId;
uint256 public immutable maxTokenId;
uint256 public tokenCounter;
string public _tokenBaseURI;
string public _tokenURIExtension;
address public feeCollector;
uint256 public bridgeFee;
uint256 public mintFee;
uint256 public feeToCollect;
uint256 public claimedFee;
uint16 public constant DENOMINATOR = 10000; // 100%
uint16 public commonRefBips;
mapping(address => uint16) public personalRefBips;
mapping(address => uint256) public refTxsCount;
mapping(address => uint256) public refAmountToClaim;
mapping(address => uint256) public refAmountClaimed;
constructor(
address _mailbox,
address _feeCollector,
uint256 _mintFee,
uint256 _bridgeFee,
uint256 _totalSupply,
uint256 _idMultiplier
) ERC721('Womex', 'WOW') TokenRouter(_mailbox) {
require(_feeCollector != address(0), 'Fee collector must be non-zero');
feeCollector = _feeCollector;
mintFee = _mintFee;
bridgeFee = _bridgeFee;
minTokenId = _totalSupply * _idMultiplier + 1;
maxTokenId = _totalSupply * (_idMultiplier + 1);
tokenCounter = _totalSupply * _idMultiplier + 1;
}
function pause() external onlyOwner whenNotPaused {
_pause();
}
function unpause() external onlyOwner whenPaused {
_unpause();
}
function setMintFee(uint256 _mintFee) external onlyOwner {
mintFee = _mintFee;
}
function setBridgeFee(uint256 _bridgeFee) external onlyOwner {
bridgeFee = _bridgeFee;
}
function setFeeCollector(address _feeCollector) external onlyOwner {
require(_feeCollector != address(0), 'WomexNFT721: Fee collector must be non-zero address');
feeCollector = _feeCollector;
}
function claimFees() external nonReentrant {
require(_msgSender() == feeCollector, 'WomexNFT721: Only fee collector allowed');
uint256 currentEarnings = feeToCollect;
require(currentEarnings != 0, 'WomexNFT721: Nothing to claim');
feeToCollect = 0;
claimedFee += currentEarnings;
(bool success, ) = payable(feeCollector).call{value: currentEarnings}('');
require(success, 'WomexNFT721: Failed to send Ether');
emit FeeEarningsClaimed(_msgSender(), currentEarnings);
}
function mint() external payable nonReentrant whenNotPaused {
require(msg.value == mintFee, 'WomexNFT721: Insufficient mint fee');
uint256 nextId = tokenCounter;
require(nextId <= maxTokenId, 'WomexNFT721: Mint exceeds limit');
++tokenCounter;
feeToCollect += msg.value;
_safeMint(_msgSender(), nextId);
emit NFTMinted(_msgSender(), nextId, mintFee, address(0), 0);
}
function batchMint(uint256 count) external payable nonReentrant whenNotPaused {
require(msg.value == mintFee * count, 'WomexNFT721: Insufficient mint fee');
for (uint256 i = 0; i < count; i++) {
uint256 nextId = tokenCounter;
require(nextId <= maxTokenId, 'WomexNFT721: Mint exceeds limit');
++tokenCounter;
feeToCollect += msg.value;
_safeMint(_msgSender(), nextId);
emit NFTMinted(_msgSender(), nextId, mintFee, address(0), 0);
}
}
function mintWithReferrer(address referrer) external payable nonReentrant whenNotPaused {
require(_msgSender() != referrer && referrer != address(0), 'WomexNFT721: Invalid referrer address');
require(msg.value == mintFee, 'WomexNFT721: Insufficient mint fee');
uint256 nextId = tokenCounter;
require(nextId <= maxTokenId, 'WomexNFT721: Mint exceeds limit');
uint256 fee = mintFee;
uint256 refShares = calculateRefShares(referrer, fee);
++tokenCounter;
feeToCollect += fee - refShares;
refAmountToClaim[referrer] += refShares;
++refTxsCount[referrer];
_safeMint(_msgSender(), nextId);
emit NFTMinted(_msgSender(), nextId, mintFee, referrer, refShares);
}
function batchMintWithReferrer(uint256 count, address referrer) external payable nonReentrant whenNotPaused {
require(_msgSender() != referrer && referrer != address(0), 'WomexNFT721: Invalid referrer address');
require(msg.value == mintFee * count, 'WomexNFT721: Insufficient mint fee');
for (uint256 i = 0; i < count; i++) {
uint256 nextId = tokenCounter;
require(nextId <= maxTokenId, 'WomexNFT721: Mint exceeds limit');
uint256 fee = mintFee;
uint256 refShares = calculateRefShares(referrer, fee);
++tokenCounter;
feeToCollect += fee - refShares;
refAmountToClaim[referrer] += refShares;
++refTxsCount[referrer];
_safeMint(_msgSender(), nextId);
emit NFTMinted(_msgSender(), nextId, mintFee, referrer, refShares);
}
}
function transferRemote(
uint32 _dstChain,
bytes32 _receiver,
uint256 _tokenId
) external payable override(TokenRouter) nonReentrant whenNotPaused returns (bytes32 messageId) {
require(_receiver != bytes32(0), 'WomexNFT721: Invalid receiver');
require(_isApprovedOrOwner(_msgSender(), _tokenId), 'WomexNFT721: send caller is not owner nor approved');
uint256 fee = getHyperlaneMessageFee(_dstChain);
require(msg.value >= fee + bridgeFee, 'WomexNFT721: Incorrect message value');
feeToCollect += bridgeFee;
messageId = _transferRemote(_dstChain, _receiver, _tokenId, msg.value - bridgeFee);
emit NFTSent(msg.sender, _dstChain, address(uint160(uint256(_receiver))), _tokenId, bridgeFee);
}
function getHyperlaneMessageFee(uint32 _dstChain) public view returns (uint256) {
uint256 fee = _quoteDispatch(_dstChain, "");
return fee;
}
///////////////
///// REF /////
///////////////
function setCommonRefBips(uint16 _bips) external onlyOwner {
require(_bips <= DENOMINATOR, 'ReferralSystem: Referral bips are too high');
commonRefBips = _bips;
}
function setPersonalRefBips(address referrer, uint16 bips) external onlyOwner {
require(bips <= DENOMINATOR, 'ReferralSystem: Referral bips are too high');
personalRefBips[referrer] = bips;
}
function setPersonalRefBipsBatch(address[] calldata referrers, uint16 bips) external onlyOwner {
require(bips <= DENOMINATOR, 'ReferralSystem: Referral bips are too high');
for (uint256 i = 0; i < referrers.length; i++) {
personalRefBips[referrers[i]] = bips;
}
}
function claimRefEarnings() external nonReentrant {
uint256 amountToClaim = refAmountToClaim[_msgSender()];
require(amountToClaim > 0, 'Nothing to claim');
address referrer = _msgSender();
refAmountToClaim[referrer] = 0;
refAmountClaimed[referrer] += amountToClaim;
(bool success, ) = payable(referrer).call{value: amountToClaim}('');
require(success, 'ReferralSystem: Failed to send Ether');
emit ReferrerEarningsClaimed(referrer, amountToClaim);
}
function calculateRefShares(address referrer, uint256 amount) public view virtual returns (uint256) {
uint256 referrerBips = personalRefBips[referrer];
uint256 referrerShareBips = referrerBips == 0 ? commonRefBips : referrerBips;
if (referrerShareBips == 0) {
return 0;
}
uint256 referrerEarnings = (amount * referrerShareBips) / DENOMINATOR;
return referrerEarnings;
}
//////////////////
//// override ////
//////////////////
function balanceOf(address _account) public view virtual override(TokenRouter, ERC721, IERC721) returns (uint256) {
return ERC721.balanceOf(_account);
}
function _transferFromSender(uint256 _tokenId) internal virtual override returns (bytes memory) {
require(ownerOf(_tokenId) == msg.sender, '!owner');
_burn(_tokenId);
return bytes(''); // no metadata
}
function _transferTo(
address _recipient,
uint256 _tokenId,
bytes calldata // no metadata
) internal virtual override {
_safeMint(_recipient, _tokenId);
}
function _contextSuffixLength() internal view override(Context, ContextUpgradeable) returns (uint256) {
return 0;
}
function _msgData() internal view override(Context, ContextUpgradeable) returns (bytes calldata) {
return msg.data;
}
function _msgSender() internal view override(Context, ContextUpgradeable) returns (address) {
return msg.sender;
}
//////////////////////////////
////////// URI ///////////////
/////////////////////////////
function setTokenBaseURI(
string calldata _newTokenBaseURI,
string calldata _fileExtension
) external onlyOwner {
_tokenBaseURI = _newTokenBaseURI;
_tokenURIExtension = _fileExtension;
}
function tokenURI(
uint256 tokenId
) public view override returns (string memory) {
return
string(
abi.encodePacked(
_tokenBaseURI,
Strings.toString(tokenId),
_tokenURIExtension
)
);
}
//////////////////////////////
////// escape mechanism //////
//////////////////////////////
function resqueFunds() external {
require(_msgSender() == feeCollector || _msgSender() == owner(), 'Resque: Only fee collector or owner allowed');
(bool success, ) = payable(msg.sender).call{value: address(this).balance}('');
require(success, 'Resque: Failed to send Ether');
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_mailbox","type":"address"},{"internalType":"address","name":"_feeCollector","type":"address"},{"internalType":"uint256","name":"_mintFee","type":"uint256"},{"internalType":"uint256","name":"_bridgeFee","type":"uint256"},{"internalType":"uint256","name":"_totalSupply","type":"uint256"},{"internalType":"uint256","name":"_idMultiplier","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"address","name":"collector","type":"address"},{"indexed":false,"internalType":"uint256","name":"claimedAmount","type":"uint256"}],"name":"FeeEarningsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":true,"internalType":"uint256","name":"itemId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeEarnings","type":"uint256"},{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":false,"internalType":"uint256","name":"referrerEarnings","type":"uint256"}],"name":"NFTMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"srcAddress","type":"bytes32"},{"indexed":true,"internalType":"uint32","name":"srcChainId","type":"uint32"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NFTReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"uint32","name":"dstChainId","type":"uint32"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeEarned","type":"uint256"}],"name":"NFTSent","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"origin","type":"uint32"},{"indexed":true,"internalType":"bytes32","name":"recipient","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReceivedTransferRemote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":false,"internalType":"uint256","name":"claimedAmount","type":"uint256"}],"name":"ReferrerEarningsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"destination","type":"uint32"},{"indexed":true,"internalType":"bytes32","name":"recipient","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SentTransferRemote","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":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DENOMINATOR","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_tokenBaseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_tokenURIExtension","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"name":"batchMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"}],"name":"batchMintWithReferrer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"bridgeFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"calculateRefShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRefEarnings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimedFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"commonRefBips","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"destinationGas","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"domains","outputs":[{"internalType":"uint32[]","name":"","type":"uint32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"bytes32","name":"_router","type":"bytes32"}],"name":"enrollRemoteRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"_domains","type":"uint32[]"},{"internalType":"bytes32[]","name":"_addresses","type":"bytes32[]"}],"name":"enrollRemoteRouters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeToCollect","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstChain","type":"uint32"}],"name":"getHyperlaneMessageFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_origin","type":"uint32"},{"internalType":"bytes32","name":"_sender","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"}],"name":"handle","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"hook","outputs":[{"internalType":"contract IPostDispatchHook","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interchainSecurityModule","outputs":[{"internalType":"contract IInterchainSecurityModule","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":[],"name":"localDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mailbox","outputs":[{"internalType":"contract IMailbox","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"mintWithReferrer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"personalRefBips","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_destinationDomain","type":"uint32"}],"name":"quoteGasPayment","outputs":[{"internalType":"uint256","name":"_gasPayment","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"refAmountClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"refAmountToClaim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"refTxsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resqueFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"}],"name":"routers","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"nonpayable","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":"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":"uint256","name":"_bridgeFee","type":"uint256"}],"name":"setBridgeFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_bips","type":"uint16"}],"name":"setCommonRefBips","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint256","name":"gas","type":"uint256"}],"name":"setDestinationGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint256","name":"gas","type":"uint256"}],"internalType":"struct GasRouter.GasRouterConfig[]","name":"gasConfigs","type":"tuple[]"}],"name":"setDestinationGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeCollector","type":"address"}],"name":"setFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_hook","type":"address"}],"name":"setHook","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_module","type":"address"}],"name":"setInterchainSecurityModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintFee","type":"uint256"}],"name":"setMintFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"},{"internalType":"uint16","name":"bips","type":"uint16"}],"name":"setPersonalRefBips","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"referrers","type":"address[]"},{"internalType":"uint16","name":"bips","type":"uint16"}],"name":"setPersonalRefBipsBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newTokenBaseURI","type":"string"},{"internalType":"string","name":"_fileExtension","type":"string"}],"name":"setTokenBaseURI","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":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"","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":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstChain","type":"uint32"},{"internalType":"bytes32","name":"_receiver","type":"bytes32"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"transferRemote","outputs":[{"internalType":"bytes32","name":"messageId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"}],"name":"unenrollRemoteRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"_domains","type":"uint32[]"}],"name":"unenrollRemoteRouters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6101006040523480156200001257600080fd5b5060405162004f3938038062004f398339810160408190526200003591620002ef565b604051806040016040528060058152602001640aededacaf60db1b81525060405180604001604052806003815260200162574f5760e81b815250878080808062000085816200027160201b60201c565b620000d75760405162461bcd60e51b815260206004820152601e60248201527f4d61696c626f78436c69656e743a20696e76616c6964206d61696c626f78000060448201526064015b60405180910390fd5b6001600160a01b03821660808190526040805163234d8e3d60e21b81529051638d3638f4916004808201926020929091908290030181865afa15801562000122573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200014891906200034c565b63ffffffff1660a0526200015c3362000280565b50505050508160cb908162000172919062000420565b5060cc62000181828262000420565b505060d5805460ff1916905550600160d6556001600160a01b038516620001eb5760405162461bcd60e51b815260206004820152601e60248201527f46656520636f6c6c6563746f72206d757374206265206e6f6e2d7a65726f00006044820152606401620000ce565b60da80546001600160a01b0319166001600160a01b03871617905560dc84905560db8390556200021c818362000502565b6200022990600162000522565b60c0526200023981600162000522565b62000245908362000502565b60e05262000254818362000502565b6200026190600162000522565b60d7555062000538945050505050565b6001600160a01b03163b151590565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b0381168114620002ea57600080fd5b919050565b60008060008060008060c087890312156200030957600080fd5b6200031487620002d2565b95506200032460208801620002d2565b945060408701519350606087015192506080870151915060a087015190509295509295509295565b6000602082840312156200035f57600080fd5b815163ffffffff811681146200037457600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620003a657607f821691505b602082108103620003c757634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200041b57600081815260208120601f850160051c81016020861015620003f65750805b601f850160051c820191505b81811015620004175782815560010162000402565b5050505b505050565b81516001600160401b038111156200043c576200043c6200037b565b62000454816200044d845462000391565b84620003cd565b602080601f8311600181146200048c5760008415620004735750858301515b600019600386901b1c1916600185901b17855562000417565b600085815260208120601f198616915b82811015620004bd578886015182559484019460019091019084016200049c565b5085821015620004dc5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176200051c576200051c620004ec565b92915050565b808201808211156200051c576200051c620004ec565b60805160a05160c05160e051614996620005a360003960008181610969015281816110f7015281816117c301528181611d9f0152611f1b01526000610b20015260006108d9015260008181610bac015281816116460152818161328b015261392a01526149966000f3fe60806040526004361061041b5760003560e01c806381b4e8b41161021e578063c415b95c11610123578063de523cf3116100ab578063eddd0d9c1161007a578063eddd0d9c14610c88578063efae508a14610ca8578063f2ed8c5314610cc8578063f2fde38b14610ce8578063f39c504c14610d0857600080fd5b8063de523cf314610bce578063e3d078dc14610bee578063e9198bf914610c1f578063e985e9c514610c3f57600080fd5b8063ce6e23b2116100f2578063ce6e23b214610b0e578063d082e38114610b42578063d11ba61414610b58578063d294f09314610b85578063d5438eae14610b9a57600080fd5b8063c415b95c14610a93578063c87b56dd14610ab3578063cb253c4614610ad3578063cbc1418a14610aee57600080fd5b80639236197a116101a6578063a22cb46511610175578063a22cb465146109f3578063a42dce8014610a13578063b1bd643614610a33578063b49c53a714610a53578063b88d4fde14610a7357600080fd5b80639236197a1461098b57806395d89b41146109ab578063998cdf83146109c0578063a14d4699146109e057600080fd5b80638cfd1a65116101ed5780638cfd1a65146108b25780638d3638f4146108c75780638da5cb5b14610910578063918f86741461092e57806391ba317a1461095757600080fd5b806381b4e8b41461086157806382b12dd7146108745780638456cb591461088a5780638467be0d1461089f57600080fd5b806342aeaaf9116103245780636141cc09116102ac578063715018a61161027b578063715018a6146107c957806371a15b38146107de578063775313a1146107fe578063777133dd1461082b5780637f5a7c7b1461084157600080fd5b80636141cc091461075e5780636352211e14610774578063641ddc2e1461079457806370a08231146107a957600080fd5b80634e886281116102f35780634e886281146106e05780634f6ccce71461070057806356d5d475146107205780635c975abb146107335780635f74172c1461074b57600080fd5b806342aeaaf914610651578063440df4f41461067e57806349d462ef146106a05780634b7784c1146106c057600080fd5b806323b872dd116103a757806337bb76dc1161037657806337bb76dc146105c75780633ca4fb76146105e75780633dfd3873146105fc5780633f4ba83a1461061c57806342842e0e1461063157600080fd5b806323b872dd146105475780632643bf5f146105675780632ead72f6146105875780632f745c59146105a757600080fd5b80630b2b1955116103ee5780630b2b1955146104d15780630e72cc06146104e65780631249c58b1461050657806313966db51461050e57806318160ddd1461053257600080fd5b806301ffc9a71461042057806306fdde0314610455578063081812fc14610477578063095ea7b3146104af575b600080fd5b34801561042c57600080fd5b5061044061043b366004613c26565b610d35565b60405190151581526020015b60405180910390f35b34801561046157600080fd5b5061046a610d60565b60405161044c9190613c93565b34801561048357600080fd5b50610497610492366004613ca6565b610df2565b6040516001600160a01b03909116815260200161044c565b3480156104bb57600080fd5b506104cf6104ca366004613cdb565b610e19565b005b3480156104dd57600080fd5b506104cf610f33565b3480156104f257600080fd5b506104cf610501366004613d05565b61105a565b6104cf6110c1565b34801561051a57600080fd5b5061052460dc5481565b60405190815260200161044c565b34801561053e57600080fd5b5060d354610524565b34801561055357600080fd5b506104cf610562366004613d20565b6111ac565b34801561057357600080fd5b506104cf610582366004613d6e565b6111dd565b34801561059357600080fd5b506105246105a2366004613d9d565b611223565b3480156105b357600080fd5b506105246105c2366004613cdb565b611242565b3480156105d357600080fd5b506104cf6105e2366004613db8565b6112d8565b3480156105f357600080fd5b5061046a611335565b34801561060857600080fd5b506104cf610617366004613d05565b6113c3565b34801561062857600080fd5b506104cf61142a565b34801561063d57600080fd5b506104cf61064c366004613d20565b611442565b34801561065d57600080fd5b5061052461066c366004613d05565b60e16020526000908152604090205481565b34801561068a57600080fd5b5061069361145d565b60405161044c9190613deb565b3480156106ac57600080fd5b506104cf6106bb366004613e35565b61146e565b3480156106cc57600080fd5b506104cf6106db366004613e95565b611494565b3480156106ec57600080fd5b506105246106fb366004613cdb565b61153e565b34801561070c57600080fd5b5061052461071b366004613ca6565b6115a8565b6104cf61072e366004613f29565b61163b565b34801561073f57600080fd5b5060d55460ff16610440565b6104cf610759366004613f82565b61173a565b34801561076a57600080fd5b5061052460de5481565b34801561078057600080fd5b5061049761078f366004613ca6565b611901565b3480156107a057600080fd5b506104cf611961565b3480156107b557600080fd5b506105246107c4366004613d05565b611ae7565b3480156107d557600080fd5b506104cf611af2565b3480156107ea57600080fd5b506104cf6107f9366004613fa5565b611b04565b34801561080a57600080fd5b50610524610819366004613d9d565b60ca6020526000908152604090205481565b34801561083757600080fd5b5061052460dd5481565b34801561084d57600080fd5b50606554610497906001600160a01b031681565b61052461086f366004613fe6565b611b59565b34801561088057600080fd5b5061052460db5481565b34801561089657600080fd5b506104cf611d3b565b6104cf6108ad366004613ca6565b611d53565b3480156108be57600080fd5b5061046a611e63565b3480156108d357600080fd5b506108fb7f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff909116815260200161044c565b34801561091c57600080fd5b506033546001600160a01b0316610497565b34801561093a57600080fd5b5061094461271081565b60405161ffff909116815260200161044c565b34801561096357600080fd5b506105247f000000000000000000000000000000000000000000000000000000000000000081565b34801561099757600080fd5b506105246109a6366004613d9d565b611e70565b3480156109b757600080fd5b5061046a611e8c565b3480156109cc57600080fd5b506104cf6109db366004613ca6565b611e9b565b6104cf6109ee366004613d05565b611ea8565b3480156109ff57600080fd5b506104cf610a0e366004614019565b612043565b348015610a1f57600080fd5b506104cf610a2e366004613d05565b61204e565b348015610a3f57600080fd5b506104cf610a4e366004614055565b6120ea565b348015610a5f57600080fd5b506104cf610a6e366004613e35565b61216f565b348015610a7f57600080fd5b506104cf610a8e3660046140df565b612181565b348015610a9f57600080fd5b5060da54610497906001600160a01b031681565b348015610abf57600080fd5b5061046a610ace366004613ca6565b6121b2565b348015610adf57600080fd5b5060df546109449061ffff1681565b348015610afa57600080fd5b506104cf610b093660046141ba565b6121e9565b348015610b1a57600080fd5b506105247f000000000000000000000000000000000000000000000000000000000000000081565b348015610b4e57600080fd5b5061052460d75481565b348015610b6457600080fd5b50610524610b73366004613d05565b60e26020526000908152604090205481565b348015610b9157600080fd5b506104cf61220c565b348015610ba657600080fd5b506104977f000000000000000000000000000000000000000000000000000000000000000081565b348015610bda57600080fd5b50606654610497906001600160a01b031681565b348015610bfa57600080fd5b50610944610c09366004613d05565b60e06020526000908152604090205461ffff1681565b348015610c2b57600080fd5b506104cf610c3a366004614219565b6123e8565b348015610c4b57600080fd5b50610440610c5a366004614278565b6001600160a01b03918216600090815260d06020908152604080832093909416825291909152205460ff1690565b348015610c9457600080fd5b506104cf610ca3366004613ca6565b612497565b348015610cb457600080fd5b506104cf610cc3366004613d9d565b6124a4565b348015610cd457600080fd5b50610524610ce3366004613d9d565b6124b5565b348015610cf457600080fd5b506104cf610d03366004613d05565b6124d0565b348015610d1457600080fd5b50610524610d23366004613d05565b60e36020526000908152604090205481565b60006001600160e01b0319821663780e9d6360e01b1480610d5a5750610d5a82612546565b92915050565b606060cb8054610d6f906142a2565b80601f0160208091040260200160405190810160405280929190818152602001828054610d9b906142a2565b8015610de85780601f10610dbd57610100808354040283529160200191610de8565b820191906000526020600020905b815481529060010190602001808311610dcb57829003601f168201915b5050505050905090565b6000610dfd82612596565b50600090815260cf60205260409020546001600160a01b031690565b6000610e2482611901565b9050806001600160a01b0316836001600160a01b031603610e965760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b0382161480610eb25750610eb28133610c5a565b610f245760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610e8d565b610f2e83836125f5565b505050565b60da546001600160a01b0316336001600160a01b03161480610f5f57506033546001600160a01b031633145b610fbf5760405162461bcd60e51b815260206004820152602b60248201527f5265737175653a204f6e6c792066656520636f6c6c6563746f72206f72206f7760448201526a1b995c88185b1b1bddd95960aa1b6064820152608401610e8d565b604051600090339047908381818185875af1925050503d8060008114611001576040519150601f19603f3d011682016040523d82523d6000602084013e611006565b606091505b50509050806110575760405162461bcd60e51b815260206004820152601d60248201527f5265737175653a20204661696c656420746f2073656e642045746865720000006044820152606401610e8d565b50565b806001600160a01b0381163b15158061107a57506001600160a01b038116155b6110965760405162461bcd60e51b8152600401610e8d906142dc565b61109e612663565b50606680546001600160a01b0319166001600160a01b0392909216919091179055565b6110c96126bd565b6110d1612716565b60dc5434146110f25760405162461bcd60e51b8152600401610e8d90614323565b60d7547f00000000000000000000000000000000000000000000000000000000000000008111156111355760405162461bcd60e51b8152600401610e8d90614365565b60d760008154611144906143b2565b919050819055503460dd600082825461115d91906143cb565b9091555061116e9050335b8261275c565b60dc54604080519182526000602083018190529183913391600080516020614941833981519152910160405180910390a4506111aa600160d655565b565b6111b63382612776565b6111d25760405162461bcd60e51b8152600401610e8d906143de565b610f2e8383836127f4565b6111e5612663565b61271061ffff8216111561120b5760405162461bcd60e51b8152600401610e8d9061442b565b60df805461ffff191661ffff92909216919091179055565b60008061123a609763ffffffff8086169061296516565b949350505050565b600061124d8361297e565b82106112af5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610e8d565b506001600160a01b0391909116600090815260d160209081526040808320938352929052205490565b6112e0612663565b61271061ffff821611156113065760405162461bcd60e51b8152600401610e8d9061442b565b6001600160a01b0391909116600090815260e060205260409020805461ffff191661ffff909216919091179055565b60d88054611342906142a2565b80601f016020809104026020016040519081016040528092919081815260200182805461136e906142a2565b80156113bb5780601f10611390576101008083540402835291602001916113bb565b820191906000526020600020905b81548152906001019060200180831161139e57829003601f168201915b505050505081565b806001600160a01b0381163b1515806113e357506001600160a01b038116155b6113ff5760405162461bcd60e51b8152600401610e8d906142dc565b611407612663565b50606580546001600160a01b0319166001600160a01b0392909216919091179055565b611432612663565b61143a612a04565b6111aa612a4d565b610f2e83838360405180602001604052806000815250612181565b60606114696097612a9f565b905090565b611476612663565b63ffffffff91909116600090815260ca6020526040902055565b5050565b61149c612663565b61271061ffff821611156114c25760405162461bcd60e51b8152600401610e8d9061442b565b60005b82811015611538578160e060008686858181106114e4576114e4614475565b90506020020160208101906114f99190613d05565b6001600160a01b031681526020810191909152604001600020805461ffff191661ffff9290921691909117905580611530816143b2565b9150506114c5565b50505050565b6001600160a01b038216600090815260e0602052604081205461ffff168181156115685781611570565b60df5461ffff165b90508060000361158557600092505050610d5a565b6000612710611594838761448b565b61159e91906144a2565b9695505050505050565b60006115b360d35490565b82106116165760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610e8d565b60d3828154811061162957611629614475565b90600052602060002001549050919050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146116bd5760405162461bcd60e51b815260206004820152602160248201527f4d61696c626f78436c69656e743a2073656e646572206e6f74206d61696c626f6044820152600f60fb1b6064820152608401610e8d565b60006116c885612b59565b90508381146117275760405162461bcd60e51b815260206004820152602560248201527f456e726f6c6c656420726f7574657220646f6573206e6f74206d61746368207360448201526432b73232b960d91b6064820152608401610e8d565b61173385858585612ba5565b5050505050565b6117426126bd565b61174a612716565b336001600160a01b0382161480159061176b57506001600160a01b03811615155b6117875760405162461bcd60e51b8152600401610e8d906144c4565b8160dc54611795919061448b565b34146117b35760405162461bcd60e51b8152600401610e8d90614323565b60005b828110156118f65760d7547f00000000000000000000000000000000000000000000000000000000000000008111156118015760405162461bcd60e51b8152600401610e8d90614365565b60dc546000611810858361153e565b905060d760008154611821906143b2565b9091555061182f8183614509565b60dd600082825461184091906143cb565b90915550506001600160a01b038516600090815260e260205260408120805483929061186d9084906143cb565b90915550506001600160a01b038516600090815260e1602052604081208054909190611898906143b2565b909155506118a7335b8461275c565b60dc5460408051918252602082018390526001600160a01b0387169185913391600080516020614941833981519152910160405180910390a450505080806118ee906143b2565b9150506117b6565b50611490600160d655565b600081815260cd60205260408120546001600160a01b031680610d5a5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b6119696126bd565b33600090815260e26020526040902054806119b95760405162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b6044820152606401610e8d565b33600081815260e26020908152604080832083905560e3909152812080548492906119e59084906143cb565b90915550506040516000906001600160a01b0383169084908381818185875af1925050503d8060008114611a35576040519150601f19603f3d011682016040523d82523d6000602084013e611a3a565b606091505b5050905080611a975760405162461bcd60e51b8152602060048201526024808201527f526566657272616c53797374656d3a204661696c656420746f2073656e6420456044820152633a3432b960e11b6064820152608401610e8d565b816001600160a01b03167fa6183a81b1ce4e0d90156f6ec9b6f2d13c204d11884302b40b47bb456fb5915684604051611ad291815260200190565b60405180910390a25050506111aa600160d655565b6000610d5a8261297e565b611afa612663565b6111aa6000612c2f565b611b0c612663565b8060005b8181101561153857611b47848483818110611b2d57611b2d614475565b9050602002016020810190611b429190613d9d565b612c81565b611b526001826143cb565b9050611b10565b6000611b636126bd565b611b6b612716565b82611bb85760405162461bcd60e51b815260206004820152601d60248201527f576f6d65784e46543732313a20496e76616c69642072656365697665720000006044820152606401610e8d565b611bc3335b83612776565b611c2a5760405162461bcd60e51b815260206004820152603260248201527f576f6d65784e46543732313a2073656e642063616c6c6572206973206e6f74206044820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b6064820152608401610e8d565b6000611c3585611e70565b905060db5481611c4591906143cb565b341015611ca05760405162461bcd60e51b8152602060048201526024808201527f576f6d65784e46543732313a20496e636f7272656374206d6573736167652076604482015263616c756560e01b6064820152608401610e8d565b60db5460dd6000828254611cb491906143cb565b92505081905550611cd485858560db5434611ccf9190614509565b612cbc565b60db546040805186815260208101929092529193506001600160a01b0386169163ffffffff88169133917f8c76f9a0946e85f2e4c199f247a3436d1766156d4ce90144bf16dfb353878ade910160405180910390a450611d34600160d655565b9392505050565b611d43612663565b611d4b612716565b6111aa612d2b565b611d5b6126bd565b611d63612716565b8060dc54611d71919061448b565b3414611d8f5760405162461bcd60e51b8152600401610e8d90614323565b60005b81811015611e585760d7547f0000000000000000000000000000000000000000000000000000000000000000811115611ddd5760405162461bcd60e51b8152600401610e8d90614365565b60d760008154611dec906143b2565b919050819055503460dd6000828254611e0591906143cb565b90915550611e14905033611168565b60dc54604080519182526000602083018190529183913391600080516020614941833981519152910160405180910390a45080611e50816143b2565b915050611d92565b50611057600160d655565b60d98054611342906142a2565b600080611d348360405180602001604052806000815250612d68565b606060cc8054610d6f906142a2565b611ea3612663565b60db55565b611eb06126bd565b611eb8612716565b336001600160a01b03821614801590611ed957506001600160a01b03811615155b611ef55760405162461bcd60e51b8152600401610e8d906144c4565b60dc543414611f165760405162461bcd60e51b8152600401610e8d90614323565b60d7547f0000000000000000000000000000000000000000000000000000000000000000811115611f595760405162461bcd60e51b8152600401610e8d90614365565b60dc546000611f68848361153e565b905060d760008154611f79906143b2565b90915550611f878183614509565b60dd6000828254611f9891906143cb565b90915550506001600160a01b038416600090815260e2602052604081208054839290611fc59084906143cb565b90915550506001600160a01b038416600090815260e1602052604081208054909190611ff0906143b2565b90915550611ffd336118a1565b60dc5460408051918252602082018390526001600160a01b0386169185913391600080516020614941833981519152910160405180910390a4505050611057600160d655565b611490338383612d81565b612056612663565b6001600160a01b0381166120c85760405162461bcd60e51b815260206004820152603360248201527f576f6d65784e46543732313a2046656520636f6c6c6563746f72206d757374206044820152726265206e6f6e2d7a65726f206164647265737360681b6064820152608401610e8d565b60da80546001600160a01b0319166001600160a01b0392909216919091179055565b6120f2612663565b60005b81811015610f2e5761215d83838381811061211257612112614475565b6121289260206040909202019081019150613d9d565b84848481811061213a5761213a614475565b9050604002016020013563ffffffff909116600090815260ca6020526040902055565b6121686001826143cb565b90506120f5565b612177612663565b6114908282612e4f565b61218a33611bbd565b6121a65760405162461bcd60e51b8152600401610e8d906143de565b61153884848484612e65565b606060d86121bf83612e98565b60d96040516020016121d39392919061458f565b6040516020818303038152906040529050919050565b6121f1612663565b60d86121fe848683614608565b5060d9611733828483614608565b6122146126bd565b60da546001600160a01b0316336001600160a01b0316146122875760405162461bcd60e51b815260206004820152602760248201527f576f6d65784e46543732313a204f6e6c792066656520636f6c6c6563746f7220604482015266185b1b1bddd95960ca1b6064820152608401610e8d565b60dd5460008190036122db5760405162461bcd60e51b815260206004820152601d60248201527f576f6d65784e46543732313a204e6f7468696e6720746f20636c61696d0000006044820152606401610e8d565b600060dd819055508060de60008282546122f591906143cb565b909155505060da546040516000916001600160a01b03169083908381818185875af1925050503d8060008114612347576040519150601f19603f3d011682016040523d82523d6000602084013e61234c565b606091505b50509050806123a75760405162461bcd60e51b815260206004820152602160248201527f576f6d65784e46543732313a204661696c656420746f2073656e6420457468656044820152603960f91b6064820152608401610e8d565b60405182815233907f582c87414358df39212a275853c71633d2dc65d15ae92cc5718e7438766bea769060200160405180910390a250506111aa600160d655565b6123f0612663565b8281146124295760405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b6044820152606401610e8d565b8260005b8181101561248f5761247d86868381811061244a5761244a614475565b905060200201602081019061245f9190613d9d565b85858481811061247157612471614475565b90506020020135612e4f565b6124886001826143cb565b905061242d565b505050505050565b61249f612663565b60dc55565b6124ac612663565b61105781612c81565b6000610d5a8260405180602001604052806000815250612d68565b6124d8612663565b6001600160a01b03811661253d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e8d565b61105781612c2f565b60006001600160e01b031982166380ac58cd60e01b148061257757506001600160e01b03198216635b5e139f60e01b145b80610d5a57506301ffc9a760e01b6001600160e01b0319831614610d5a565b600081815260cd60205260409020546001600160a01b03166110575760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b600081815260cf6020526040902080546001600160a01b0319166001600160a01b038416908117909155819061262a82611901565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6033546001600160a01b031633146111aa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e8d565b600260d6540361270f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610e8d565b600260d655565b60d55460ff16156111aa5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610e8d565b611490828260405180602001604052806000815250612f2a565b60008061278283611901565b9050806001600160a01b0316846001600160a01b031614806127c957506001600160a01b03808216600090815260d0602090815260408083209388168352929052205460ff165b8061123a5750836001600160a01b03166127e284610df2565b6001600160a01b031614949350505050565b826001600160a01b031661280782611901565b6001600160a01b03161461282d5760405162461bcd60e51b8152600401610e8d906146c7565b6001600160a01b03821661288f5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610e8d565b61289c8383836001612f5d565b826001600160a01b03166128af82611901565b6001600160a01b0316146128d55760405162461bcd60e51b8152600401610e8d906146c7565b600081815260cf6020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260ce855283862080546000190190559087168086528386208054600101905586865260cd90945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600080612972848461308a565b915091505b9250929050565b60006001600160a01b0382166129e85760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610e8d565b506001600160a01b0316600090815260ce602052604090205490565b60d55460ff166111aa5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610e8d565b612a55612a04565b60d5805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60606000612aac836130c4565b905080516001600160401b03811115612ac757612ac76140c9565b604051908082528060200260200182016040528015612af0578160200160208202803683370190505b50915060005b8151811015612b5257818181518110612b1157612b11614475565b6020026020010151838281518110612b2b57612b2b614475565b63ffffffff9092166020928302919091019091015280612b4a816143b2565b915050612af6565b5050919050565b60008080612b71609763ffffffff8087169061296516565b9150915081612b7f8561315e565b90612b9d5760405162461bcd60e51b8152600401610e8d9190613c93565b509392505050565b6000612bb1838361317f565b90506000612bbf8484613197565b9050366000612bce86866131a7565b91509150612be4612bdc8590565b8484846131b7565b838863ffffffff167fba20947a325f450d232530e5f5fce293e7963499d5309a07cee84a269f2f15a685604051612c1d91815260200190565b60405180910390a35050505050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b612c95609763ffffffff808416906131c116565b612c9e8261315e565b906114905760405162461bcd60e51b8152600401610e8d9190613c93565b600080612cc8846131cd565b9050612cdf8684612cda888886613235565b613264565b9150848663ffffffff167fd229aacb94204188fe8042965fa6b269c62dc5818b21238779ab64bdd17efeec86604051612d1a91815260200190565b60405180910390a350949350505050565b612d33612716565b60d5805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612a823390565b600080612d7484612b59565b905061123a848285613287565b816001600160a01b0316836001600160a01b031603612de25760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610e8d565b6001600160a01b03838116600081815260d06020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b611490609763ffffffff80851690849061333616565b612e708484846127f4565b612e7c84848484613341565b6115385760405162461bcd60e51b8152600401610e8d9061470c565b60606000612ea583613442565b60010190506000816001600160401b03811115612ec457612ec46140c9565b6040519080825280601f01601f191660200182016040528015612eee576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612ef857509392505050565b612f34838361351a565b612f416000848484613341565b610f2e5760405162461bcd60e51b8152600401610e8d9061470c565b6001811115612fcc5760405162461bcd60e51b815260206004820152603560248201527f455243373231456e756d657261626c653a20636f6e7365637574697665207472604482015274185b9cd9995c9cc81b9bdd081cdd5c1c1bdc9d1959605a1b6064820152608401610e8d565b816001600160a01b038516613028576130238160d38054600083815260d460205260408120829055600182018355919091527f915c3eb987b20e1af620c1403197bf687fb7f18513b3a73fde6e78c7072c41a60155565b61304b565b836001600160a01b0316856001600160a01b03161461304b5761304b85826136b3565b6001600160a01b0384166130675761306281613750565b611733565b846001600160a01b0316846001600160a01b0316146117335761173384826137ff565b60008181526002830160205260408120548190806130b9576130ac8585613843565b9250600091506129779050565b600192509050612977565b606060006130d18361384f565b9050806001600160401b038111156130eb576130eb6140c9565b604051908082528060200260200182016040528015613114578160200160208202803683370190505b50915060005b81811015612b525761312c848261385a565b60001c83828151811061314157613141614475565b602090810291909101015280613156816143b2565b91505061311a565b606061316f8263ffffffff16612e98565b6040516020016121d3919061475e565b600061318e60208284866147a3565b611d34916147cd565b600061318e6040602084866147a3565b36600061297283604081876147a3565b611538848461275c565b6000611d348383613866565b6060336131d983611901565b6001600160a01b0316146132185760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610e8d565b61322182613883565b505060408051602081019091526000815290565b606083838360405160200161324c939291906147eb565b60405160208183030381529060405290509392505050565b60008061327085612b59565b905061327e85828686613926565b95945050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166381d2ea958585856132c4896139d8565b6065546040516001600160e01b031960e088901b1681526132f595949392916001600160a01b031690600401614818565b602060405180830381865afa158015613312573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123a919061486a565b6115388383836139fa565b60006001600160a01b0384163b1561343757604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290613385903390899088908890600401614883565b6020604051808303816000875af19250505080156133c0575060408051601f3d908101601f191682019092526133bd918101906148b6565b60015b61341d573d8080156133ee576040519150601f19603f3d011682016040523d82523d6000602084013e6133f3565b606091505b5080516000036134155760405162461bcd60e51b8152600401610e8d9061470c565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061123a565b506001949350505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106134815772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106134ad576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106134cb57662386f26fc10000830492506010015b6305f5e10083106134e3576305f5e100830492506008015b61271083106134f757612710830492506004015b60648310613509576064830492506002015b600a8310610d5a5760010192915050565b6001600160a01b0382166135705760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610e8d565b600081815260cd60205260409020546001600160a01b0316156135d55760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610e8d565b6135e3600083836001612f5d565b600081815260cd60205260409020546001600160a01b0316156136485760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610e8d565b6001600160a01b038216600081815260ce602090815260408083208054600101905584835260cd90915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600060016136c08461297e565b6136ca9190614509565b600083815260d2602052604090205490915080821461371d576001600160a01b038416600090815260d160209081526040808320858452825280832054848452818420819055835260d290915290208190555b50600091825260d2602090815260408084208490556001600160a01b03909416835260d181528383209183525290812055565b60d35460009061376290600190614509565b600083815260d4602052604081205460d3805493945090928490811061378a5761378a614475565b906000526020600020015490508060d383815481106137ab576137ab614475565b600091825260208083209091019290925582815260d4909152604080822084905585825281205560d38054806137e3576137e36148d3565b6001900381819060005260206000200160009055905550505050565b600061380a8361297e565b6001600160a01b03909316600090815260d160209081526040808320868452825280832085905593825260d29052919091209190915550565b6000611d348383613a17565b6000610d5a82613a2f565b6000611d348383613a39565b60008181526002830160205260408120819055611d348383613a63565b600061388e82611901565b905061389e816000846001612f5d565b6138a782611901565b600083815260cf6020908152604080832080546001600160a01b03199081169091556001600160a01b03851680855260ce8452828520805460001901905587855260cd909352818420805490911690555192935084927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166310b83dc0848787866139648b6139d8565b6065546040516001600160e01b031960e089901b16815261399595949392916001600160a01b031690600401614818565b60206040518083038185885af11580156139b3573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061327e919061486a565b63ffffffff8116600090815260ca6020526040902054606090610d5a90613a6f565b6000828152600284016020526040812082905561123a8484613a8d565b60008181526001830160205260408120541515611d34565b6000610d5a825490565b6000826000018281548110613a5057613a50614475565b9060005260206000200154905092915050565b6000611d348383613a99565b6060610d5a6000833360405180602001604052806000815250613b8c565b6000611d348383613bc1565b60008181526001830160205260408120548015613b82576000613abd600183614509565b8554909150600090613ad190600190614509565b9050818114613b36576000866000018281548110613af157613af1614475565b9060005260206000200154905080876000018481548110613b1457613b14614475565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613b4757613b476148d3565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610d5a565b6000915050610d5a565b6060600185858585604051602001613ba89594939291906148e9565b6040516020818303038152906040529050949350505050565b6000818152600183016020526040812054613c0857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d5a565b506000610d5a565b6001600160e01b03198116811461105757600080fd5b600060208284031215613c3857600080fd5b8135611d3481613c10565b60005b83811015613c5e578181015183820152602001613c46565b50506000910152565b60008151808452613c7f816020860160208601613c43565b601f01601f19169290920160200192915050565b602081526000611d346020830184613c67565b600060208284031215613cb857600080fd5b5035919050565b80356001600160a01b0381168114613cd657600080fd5b919050565b60008060408385031215613cee57600080fd5b613cf783613cbf565b946020939093013593505050565b600060208284031215613d1757600080fd5b611d3482613cbf565b600080600060608486031215613d3557600080fd5b613d3e84613cbf565b9250613d4c60208501613cbf565b9150604084013590509250925092565b803561ffff81168114613cd657600080fd5b600060208284031215613d8057600080fd5b611d3482613d5c565b803563ffffffff81168114613cd657600080fd5b600060208284031215613daf57600080fd5b611d3482613d89565b60008060408385031215613dcb57600080fd5b613dd483613cbf565b9150613de260208401613d5c565b90509250929050565b6020808252825182820181905260009190848201906040850190845b81811015613e2957835163ffffffff1683529284019291840191600101613e07565b50909695505050505050565b60008060408385031215613e4857600080fd5b613cf783613d89565b60008083601f840112613e6357600080fd5b5081356001600160401b03811115613e7a57600080fd5b6020830191508360208260051b850101111561297757600080fd5b600080600060408486031215613eaa57600080fd5b83356001600160401b03811115613ec057600080fd5b613ecc86828701613e51565b9094509250613edf905060208501613d5c565b90509250925092565b60008083601f840112613efa57600080fd5b5081356001600160401b03811115613f1157600080fd5b60208301915083602082850101111561297757600080fd5b60008060008060608587031215613f3f57600080fd5b613f4885613d89565b93506020850135925060408501356001600160401b03811115613f6a57600080fd5b613f7687828801613ee8565b95989497509550505050565b60008060408385031215613f9557600080fd5b82359150613de260208401613cbf565b60008060208385031215613fb857600080fd5b82356001600160401b03811115613fce57600080fd5b613fda85828601613e51565b90969095509350505050565b600080600060608486031215613ffb57600080fd5b61400484613d89565b95602085013595506040909401359392505050565b6000806040838503121561402c57600080fd5b61403583613cbf565b91506020830135801515811461404a57600080fd5b809150509250929050565b6000806020838503121561406857600080fd5b82356001600160401b038082111561407f57600080fd5b818501915085601f83011261409357600080fd5b8135818111156140a257600080fd5b8660208260061b85010111156140b757600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052604160045260246000fd5b600080600080608085870312156140f557600080fd5b6140fe85613cbf565b935061410c60208601613cbf565b92506040850135915060608501356001600160401b038082111561412f57600080fd5b818701915087601f83011261414357600080fd5b813581811115614155576141556140c9565b604051601f8201601f19908116603f0116810190838211818310171561417d5761417d6140c9565b816040528281528a602084870101111561419657600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600080600080604085870312156141d057600080fd5b84356001600160401b03808211156141e757600080fd5b6141f388838901613ee8565b9096509450602087013591508082111561420c57600080fd5b50613f7687828801613ee8565b6000806000806040858703121561422f57600080fd5b84356001600160401b038082111561424657600080fd5b61425288838901613e51565b9096509450602087013591508082111561426b57600080fd5b50613f7687828801613e51565b6000806040838503121561428b57600080fd5b61429483613cbf565b9150613de260208401613cbf565b600181811c908216806142b657607f821691505b6020821081036142d657634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526027908201527f4d61696c626f78436c69656e743a20696e76616c696420636f6e74726163742060408201526673657474696e6760c81b606082015260800190565b60208082526022908201527f576f6d65784e46543732313a20496e73756666696369656e74206d696e742066604082015261656560f01b606082015260800190565b6020808252601f908201527f576f6d65784e46543732313a204d696e742065786365656473206c696d697400604082015260600190565b634e487b7160e01b600052601160045260246000fd5b6000600182016143c4576143c461439c565b5060010190565b80820180821115610d5a57610d5a61439c565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b6020808252602a908201527f526566657272616c53797374656d3a20526566657272616c20626970732061726040820152690ca40e8dede40d0d2ced60b31b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417610d5a57610d5a61439c565b6000826144bf57634e487b7160e01b600052601260045260246000fd5b500490565b60208082526025908201527f576f6d65784e46543732313a20496e76616c6964207265666572726572206164604082015264647265737360d81b606082015260800190565b81810381811115610d5a57610d5a61439c565b60008154614529816142a2565b60018281168015614541576001811461455657614585565b60ff1984168752821515830287019450614585565b8560005260208060002060005b8581101561457c5781548a820152908401908201614563565b50505082870194505b5050505092915050565b600061459b828661451c565b84516145ab818360208901613c43565b6145b78183018661451c565b979650505050505050565b601f821115610f2e57600081815260208120601f850160051c810160208610156145e95750805b601f850160051c820191505b8181101561248f578281556001016145f5565b6001600160401b0383111561461f5761461f6140c9565b6146338361462d83546142a2565b836145c2565b6000601f841160018114614667576000851561464f5750838201355b600019600387901b1c1916600186901b178355611733565b600083815260209020601f19861690835b828110156146985786850135825560209485019460019092019101614678565b50868210156146b55760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b7f4e6f20726f7574657220656e726f6c6c656420666f7220646f6d61696e3a200081526000825161479681601f850160208701613c43565b91909101601f0192915050565b600080858511156147b357600080fd5b838611156147c057600080fd5b5050820193919092039150565b80356020831015610d5a57600019602084900360031b1b1692915050565b83815282602082015260008251614809816040850160208701613c43565b91909101604001949350505050565b63ffffffff8616815284602082015260a06040820152600061483d60a0830186613c67565b828103606084015261484f8186613c67565b91505060018060a01b03831660808301529695505050505050565b60006020828403121561487c57600080fd5b5051919050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061159e90830184613c67565b6000602082840312156148c857600080fd5b8151611d3481613c10565b634e487b7160e01b600052603160045260246000fd5b61ffff60f01b8660f01b1681528460028201528360228201526bffffffffffffffffffffffff198360601b1660428201526000825161492f816056850160208701613c43565b91909101605601969550505050505056fedc9e7f115f499a243fe74d676de78b20c5c147ba36ff1e3bfc8d9f1821d30385a264697066735822122081f2f8538eb61e6f15f384445725e8e2fceccd7afe6cf02bd4e43a3f53607c0664736f6c63430008130033000000000000000000000000d4c1905bb1d26bc93dac913e13cacc278cdcc80d000000000000000000000000149676d254f9c01f1011c580b8f3dfd702da333300000000000000000000000000000000000000000000000000003faa2522600000000000000000000000000000000000000000000000000000001fd5129130000000000000000000000000000000000000000000000000000000000005f5e1000000000000000000000000000000000000000000000000000000000000000003
Deployed Bytecode
0x60806040526004361061041b5760003560e01c806381b4e8b41161021e578063c415b95c11610123578063de523cf3116100ab578063eddd0d9c1161007a578063eddd0d9c14610c88578063efae508a14610ca8578063f2ed8c5314610cc8578063f2fde38b14610ce8578063f39c504c14610d0857600080fd5b8063de523cf314610bce578063e3d078dc14610bee578063e9198bf914610c1f578063e985e9c514610c3f57600080fd5b8063ce6e23b2116100f2578063ce6e23b214610b0e578063d082e38114610b42578063d11ba61414610b58578063d294f09314610b85578063d5438eae14610b9a57600080fd5b8063c415b95c14610a93578063c87b56dd14610ab3578063cb253c4614610ad3578063cbc1418a14610aee57600080fd5b80639236197a116101a6578063a22cb46511610175578063a22cb465146109f3578063a42dce8014610a13578063b1bd643614610a33578063b49c53a714610a53578063b88d4fde14610a7357600080fd5b80639236197a1461098b57806395d89b41146109ab578063998cdf83146109c0578063a14d4699146109e057600080fd5b80638cfd1a65116101ed5780638cfd1a65146108b25780638d3638f4146108c75780638da5cb5b14610910578063918f86741461092e57806391ba317a1461095757600080fd5b806381b4e8b41461086157806382b12dd7146108745780638456cb591461088a5780638467be0d1461089f57600080fd5b806342aeaaf9116103245780636141cc09116102ac578063715018a61161027b578063715018a6146107c957806371a15b38146107de578063775313a1146107fe578063777133dd1461082b5780637f5a7c7b1461084157600080fd5b80636141cc091461075e5780636352211e14610774578063641ddc2e1461079457806370a08231146107a957600080fd5b80634e886281116102f35780634e886281146106e05780634f6ccce71461070057806356d5d475146107205780635c975abb146107335780635f74172c1461074b57600080fd5b806342aeaaf914610651578063440df4f41461067e57806349d462ef146106a05780634b7784c1146106c057600080fd5b806323b872dd116103a757806337bb76dc1161037657806337bb76dc146105c75780633ca4fb76146105e75780633dfd3873146105fc5780633f4ba83a1461061c57806342842e0e1461063157600080fd5b806323b872dd146105475780632643bf5f146105675780632ead72f6146105875780632f745c59146105a757600080fd5b80630b2b1955116103ee5780630b2b1955146104d15780630e72cc06146104e65780631249c58b1461050657806313966db51461050e57806318160ddd1461053257600080fd5b806301ffc9a71461042057806306fdde0314610455578063081812fc14610477578063095ea7b3146104af575b600080fd5b34801561042c57600080fd5b5061044061043b366004613c26565b610d35565b60405190151581526020015b60405180910390f35b34801561046157600080fd5b5061046a610d60565b60405161044c9190613c93565b34801561048357600080fd5b50610497610492366004613ca6565b610df2565b6040516001600160a01b03909116815260200161044c565b3480156104bb57600080fd5b506104cf6104ca366004613cdb565b610e19565b005b3480156104dd57600080fd5b506104cf610f33565b3480156104f257600080fd5b506104cf610501366004613d05565b61105a565b6104cf6110c1565b34801561051a57600080fd5b5061052460dc5481565b60405190815260200161044c565b34801561053e57600080fd5b5060d354610524565b34801561055357600080fd5b506104cf610562366004613d20565b6111ac565b34801561057357600080fd5b506104cf610582366004613d6e565b6111dd565b34801561059357600080fd5b506105246105a2366004613d9d565b611223565b3480156105b357600080fd5b506105246105c2366004613cdb565b611242565b3480156105d357600080fd5b506104cf6105e2366004613db8565b6112d8565b3480156105f357600080fd5b5061046a611335565b34801561060857600080fd5b506104cf610617366004613d05565b6113c3565b34801561062857600080fd5b506104cf61142a565b34801561063d57600080fd5b506104cf61064c366004613d20565b611442565b34801561065d57600080fd5b5061052461066c366004613d05565b60e16020526000908152604090205481565b34801561068a57600080fd5b5061069361145d565b60405161044c9190613deb565b3480156106ac57600080fd5b506104cf6106bb366004613e35565b61146e565b3480156106cc57600080fd5b506104cf6106db366004613e95565b611494565b3480156106ec57600080fd5b506105246106fb366004613cdb565b61153e565b34801561070c57600080fd5b5061052461071b366004613ca6565b6115a8565b6104cf61072e366004613f29565b61163b565b34801561073f57600080fd5b5060d55460ff16610440565b6104cf610759366004613f82565b61173a565b34801561076a57600080fd5b5061052460de5481565b34801561078057600080fd5b5061049761078f366004613ca6565b611901565b3480156107a057600080fd5b506104cf611961565b3480156107b557600080fd5b506105246107c4366004613d05565b611ae7565b3480156107d557600080fd5b506104cf611af2565b3480156107ea57600080fd5b506104cf6107f9366004613fa5565b611b04565b34801561080a57600080fd5b50610524610819366004613d9d565b60ca6020526000908152604090205481565b34801561083757600080fd5b5061052460dd5481565b34801561084d57600080fd5b50606554610497906001600160a01b031681565b61052461086f366004613fe6565b611b59565b34801561088057600080fd5b5061052460db5481565b34801561089657600080fd5b506104cf611d3b565b6104cf6108ad366004613ca6565b611d53565b3480156108be57600080fd5b5061046a611e63565b3480156108d357600080fd5b506108fb7f000000000000000000000000000000000000000000000000000000000000000a81565b60405163ffffffff909116815260200161044c565b34801561091c57600080fd5b506033546001600160a01b0316610497565b34801561093a57600080fd5b5061094461271081565b60405161ffff909116815260200161044c565b34801561096357600080fd5b506105247f0000000000000000000000000000000000000000000000000000000017d7840081565b34801561099757600080fd5b506105246109a6366004613d9d565b611e70565b3480156109b757600080fd5b5061046a611e8c565b3480156109cc57600080fd5b506104cf6109db366004613ca6565b611e9b565b6104cf6109ee366004613d05565b611ea8565b3480156109ff57600080fd5b506104cf610a0e366004614019565b612043565b348015610a1f57600080fd5b506104cf610a2e366004613d05565b61204e565b348015610a3f57600080fd5b506104cf610a4e366004614055565b6120ea565b348015610a5f57600080fd5b506104cf610a6e366004613e35565b61216f565b348015610a7f57600080fd5b506104cf610a8e3660046140df565b612181565b348015610a9f57600080fd5b5060da54610497906001600160a01b031681565b348015610abf57600080fd5b5061046a610ace366004613ca6565b6121b2565b348015610adf57600080fd5b5060df546109449061ffff1681565b348015610afa57600080fd5b506104cf610b093660046141ba565b6121e9565b348015610b1a57600080fd5b506105247f0000000000000000000000000000000000000000000000000000000011e1a30181565b348015610b4e57600080fd5b5061052460d75481565b348015610b6457600080fd5b50610524610b73366004613d05565b60e26020526000908152604090205481565b348015610b9157600080fd5b506104cf61220c565b348015610ba657600080fd5b506104977f000000000000000000000000d4c1905bb1d26bc93dac913e13cacc278cdcc80d81565b348015610bda57600080fd5b50606654610497906001600160a01b031681565b348015610bfa57600080fd5b50610944610c09366004613d05565b60e06020526000908152604090205461ffff1681565b348015610c2b57600080fd5b506104cf610c3a366004614219565b6123e8565b348015610c4b57600080fd5b50610440610c5a366004614278565b6001600160a01b03918216600090815260d06020908152604080832093909416825291909152205460ff1690565b348015610c9457600080fd5b506104cf610ca3366004613ca6565b612497565b348015610cb457600080fd5b506104cf610cc3366004613d9d565b6124a4565b348015610cd457600080fd5b50610524610ce3366004613d9d565b6124b5565b348015610cf457600080fd5b506104cf610d03366004613d05565b6124d0565b348015610d1457600080fd5b50610524610d23366004613d05565b60e36020526000908152604090205481565b60006001600160e01b0319821663780e9d6360e01b1480610d5a5750610d5a82612546565b92915050565b606060cb8054610d6f906142a2565b80601f0160208091040260200160405190810160405280929190818152602001828054610d9b906142a2565b8015610de85780601f10610dbd57610100808354040283529160200191610de8565b820191906000526020600020905b815481529060010190602001808311610dcb57829003601f168201915b5050505050905090565b6000610dfd82612596565b50600090815260cf60205260409020546001600160a01b031690565b6000610e2482611901565b9050806001600160a01b0316836001600160a01b031603610e965760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b0382161480610eb25750610eb28133610c5a565b610f245760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610e8d565b610f2e83836125f5565b505050565b60da546001600160a01b0316336001600160a01b03161480610f5f57506033546001600160a01b031633145b610fbf5760405162461bcd60e51b815260206004820152602b60248201527f5265737175653a204f6e6c792066656520636f6c6c6563746f72206f72206f7760448201526a1b995c88185b1b1bddd95960aa1b6064820152608401610e8d565b604051600090339047908381818185875af1925050503d8060008114611001576040519150601f19603f3d011682016040523d82523d6000602084013e611006565b606091505b50509050806110575760405162461bcd60e51b815260206004820152601d60248201527f5265737175653a20204661696c656420746f2073656e642045746865720000006044820152606401610e8d565b50565b806001600160a01b0381163b15158061107a57506001600160a01b038116155b6110965760405162461bcd60e51b8152600401610e8d906142dc565b61109e612663565b50606680546001600160a01b0319166001600160a01b0392909216919091179055565b6110c96126bd565b6110d1612716565b60dc5434146110f25760405162461bcd60e51b8152600401610e8d90614323565b60d7547f0000000000000000000000000000000000000000000000000000000017d784008111156111355760405162461bcd60e51b8152600401610e8d90614365565b60d760008154611144906143b2565b919050819055503460dd600082825461115d91906143cb565b9091555061116e9050335b8261275c565b60dc54604080519182526000602083018190529183913391600080516020614941833981519152910160405180910390a4506111aa600160d655565b565b6111b63382612776565b6111d25760405162461bcd60e51b8152600401610e8d906143de565b610f2e8383836127f4565b6111e5612663565b61271061ffff8216111561120b5760405162461bcd60e51b8152600401610e8d9061442b565b60df805461ffff191661ffff92909216919091179055565b60008061123a609763ffffffff8086169061296516565b949350505050565b600061124d8361297e565b82106112af5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610e8d565b506001600160a01b0391909116600090815260d160209081526040808320938352929052205490565b6112e0612663565b61271061ffff821611156113065760405162461bcd60e51b8152600401610e8d9061442b565b6001600160a01b0391909116600090815260e060205260409020805461ffff191661ffff909216919091179055565b60d88054611342906142a2565b80601f016020809104026020016040519081016040528092919081815260200182805461136e906142a2565b80156113bb5780601f10611390576101008083540402835291602001916113bb565b820191906000526020600020905b81548152906001019060200180831161139e57829003601f168201915b505050505081565b806001600160a01b0381163b1515806113e357506001600160a01b038116155b6113ff5760405162461bcd60e51b8152600401610e8d906142dc565b611407612663565b50606580546001600160a01b0319166001600160a01b0392909216919091179055565b611432612663565b61143a612a04565b6111aa612a4d565b610f2e83838360405180602001604052806000815250612181565b60606114696097612a9f565b905090565b611476612663565b63ffffffff91909116600090815260ca6020526040902055565b5050565b61149c612663565b61271061ffff821611156114c25760405162461bcd60e51b8152600401610e8d9061442b565b60005b82811015611538578160e060008686858181106114e4576114e4614475565b90506020020160208101906114f99190613d05565b6001600160a01b031681526020810191909152604001600020805461ffff191661ffff9290921691909117905580611530816143b2565b9150506114c5565b50505050565b6001600160a01b038216600090815260e0602052604081205461ffff168181156115685781611570565b60df5461ffff165b90508060000361158557600092505050610d5a565b6000612710611594838761448b565b61159e91906144a2565b9695505050505050565b60006115b360d35490565b82106116165760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610e8d565b60d3828154811061162957611629614475565b90600052602060002001549050919050565b336001600160a01b037f000000000000000000000000d4c1905bb1d26bc93dac913e13cacc278cdcc80d16146116bd5760405162461bcd60e51b815260206004820152602160248201527f4d61696c626f78436c69656e743a2073656e646572206e6f74206d61696c626f6044820152600f60fb1b6064820152608401610e8d565b60006116c885612b59565b90508381146117275760405162461bcd60e51b815260206004820152602560248201527f456e726f6c6c656420726f7574657220646f6573206e6f74206d61746368207360448201526432b73232b960d91b6064820152608401610e8d565b61173385858585612ba5565b5050505050565b6117426126bd565b61174a612716565b336001600160a01b0382161480159061176b57506001600160a01b03811615155b6117875760405162461bcd60e51b8152600401610e8d906144c4565b8160dc54611795919061448b565b34146117b35760405162461bcd60e51b8152600401610e8d90614323565b60005b828110156118f65760d7547f0000000000000000000000000000000000000000000000000000000017d784008111156118015760405162461bcd60e51b8152600401610e8d90614365565b60dc546000611810858361153e565b905060d760008154611821906143b2565b9091555061182f8183614509565b60dd600082825461184091906143cb565b90915550506001600160a01b038516600090815260e260205260408120805483929061186d9084906143cb565b90915550506001600160a01b038516600090815260e1602052604081208054909190611898906143b2565b909155506118a7335b8461275c565b60dc5460408051918252602082018390526001600160a01b0387169185913391600080516020614941833981519152910160405180910390a450505080806118ee906143b2565b9150506117b6565b50611490600160d655565b600081815260cd60205260408120546001600160a01b031680610d5a5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b6119696126bd565b33600090815260e26020526040902054806119b95760405162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b6044820152606401610e8d565b33600081815260e26020908152604080832083905560e3909152812080548492906119e59084906143cb565b90915550506040516000906001600160a01b0383169084908381818185875af1925050503d8060008114611a35576040519150601f19603f3d011682016040523d82523d6000602084013e611a3a565b606091505b5050905080611a975760405162461bcd60e51b8152602060048201526024808201527f526566657272616c53797374656d3a204661696c656420746f2073656e6420456044820152633a3432b960e11b6064820152608401610e8d565b816001600160a01b03167fa6183a81b1ce4e0d90156f6ec9b6f2d13c204d11884302b40b47bb456fb5915684604051611ad291815260200190565b60405180910390a25050506111aa600160d655565b6000610d5a8261297e565b611afa612663565b6111aa6000612c2f565b611b0c612663565b8060005b8181101561153857611b47848483818110611b2d57611b2d614475565b9050602002016020810190611b429190613d9d565b612c81565b611b526001826143cb565b9050611b10565b6000611b636126bd565b611b6b612716565b82611bb85760405162461bcd60e51b815260206004820152601d60248201527f576f6d65784e46543732313a20496e76616c69642072656365697665720000006044820152606401610e8d565b611bc3335b83612776565b611c2a5760405162461bcd60e51b815260206004820152603260248201527f576f6d65784e46543732313a2073656e642063616c6c6572206973206e6f74206044820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b6064820152608401610e8d565b6000611c3585611e70565b905060db5481611c4591906143cb565b341015611ca05760405162461bcd60e51b8152602060048201526024808201527f576f6d65784e46543732313a20496e636f7272656374206d6573736167652076604482015263616c756560e01b6064820152608401610e8d565b60db5460dd6000828254611cb491906143cb565b92505081905550611cd485858560db5434611ccf9190614509565b612cbc565b60db546040805186815260208101929092529193506001600160a01b0386169163ffffffff88169133917f8c76f9a0946e85f2e4c199f247a3436d1766156d4ce90144bf16dfb353878ade910160405180910390a450611d34600160d655565b9392505050565b611d43612663565b611d4b612716565b6111aa612d2b565b611d5b6126bd565b611d63612716565b8060dc54611d71919061448b565b3414611d8f5760405162461bcd60e51b8152600401610e8d90614323565b60005b81811015611e585760d7547f0000000000000000000000000000000000000000000000000000000017d78400811115611ddd5760405162461bcd60e51b8152600401610e8d90614365565b60d760008154611dec906143b2565b919050819055503460dd6000828254611e0591906143cb565b90915550611e14905033611168565b60dc54604080519182526000602083018190529183913391600080516020614941833981519152910160405180910390a45080611e50816143b2565b915050611d92565b50611057600160d655565b60d98054611342906142a2565b600080611d348360405180602001604052806000815250612d68565b606060cc8054610d6f906142a2565b611ea3612663565b60db55565b611eb06126bd565b611eb8612716565b336001600160a01b03821614801590611ed957506001600160a01b03811615155b611ef55760405162461bcd60e51b8152600401610e8d906144c4565b60dc543414611f165760405162461bcd60e51b8152600401610e8d90614323565b60d7547f0000000000000000000000000000000000000000000000000000000017d78400811115611f595760405162461bcd60e51b8152600401610e8d90614365565b60dc546000611f68848361153e565b905060d760008154611f79906143b2565b90915550611f878183614509565b60dd6000828254611f9891906143cb565b90915550506001600160a01b038416600090815260e2602052604081208054839290611fc59084906143cb565b90915550506001600160a01b038416600090815260e1602052604081208054909190611ff0906143b2565b90915550611ffd336118a1565b60dc5460408051918252602082018390526001600160a01b0386169185913391600080516020614941833981519152910160405180910390a4505050611057600160d655565b611490338383612d81565b612056612663565b6001600160a01b0381166120c85760405162461bcd60e51b815260206004820152603360248201527f576f6d65784e46543732313a2046656520636f6c6c6563746f72206d757374206044820152726265206e6f6e2d7a65726f206164647265737360681b6064820152608401610e8d565b60da80546001600160a01b0319166001600160a01b0392909216919091179055565b6120f2612663565b60005b81811015610f2e5761215d83838381811061211257612112614475565b6121289260206040909202019081019150613d9d565b84848481811061213a5761213a614475565b9050604002016020013563ffffffff909116600090815260ca6020526040902055565b6121686001826143cb565b90506120f5565b612177612663565b6114908282612e4f565b61218a33611bbd565b6121a65760405162461bcd60e51b8152600401610e8d906143de565b61153884848484612e65565b606060d86121bf83612e98565b60d96040516020016121d39392919061458f565b6040516020818303038152906040529050919050565b6121f1612663565b60d86121fe848683614608565b5060d9611733828483614608565b6122146126bd565b60da546001600160a01b0316336001600160a01b0316146122875760405162461bcd60e51b815260206004820152602760248201527f576f6d65784e46543732313a204f6e6c792066656520636f6c6c6563746f7220604482015266185b1b1bddd95960ca1b6064820152608401610e8d565b60dd5460008190036122db5760405162461bcd60e51b815260206004820152601d60248201527f576f6d65784e46543732313a204e6f7468696e6720746f20636c61696d0000006044820152606401610e8d565b600060dd819055508060de60008282546122f591906143cb565b909155505060da546040516000916001600160a01b03169083908381818185875af1925050503d8060008114612347576040519150601f19603f3d011682016040523d82523d6000602084013e61234c565b606091505b50509050806123a75760405162461bcd60e51b815260206004820152602160248201527f576f6d65784e46543732313a204661696c656420746f2073656e6420457468656044820152603960f91b6064820152608401610e8d565b60405182815233907f582c87414358df39212a275853c71633d2dc65d15ae92cc5718e7438766bea769060200160405180910390a250506111aa600160d655565b6123f0612663565b8281146124295760405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b6044820152606401610e8d565b8260005b8181101561248f5761247d86868381811061244a5761244a614475565b905060200201602081019061245f9190613d9d565b85858481811061247157612471614475565b90506020020135612e4f565b6124886001826143cb565b905061242d565b505050505050565b61249f612663565b60dc55565b6124ac612663565b61105781612c81565b6000610d5a8260405180602001604052806000815250612d68565b6124d8612663565b6001600160a01b03811661253d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e8d565b61105781612c2f565b60006001600160e01b031982166380ac58cd60e01b148061257757506001600160e01b03198216635b5e139f60e01b145b80610d5a57506301ffc9a760e01b6001600160e01b0319831614610d5a565b600081815260cd60205260409020546001600160a01b03166110575760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b600081815260cf6020526040902080546001600160a01b0319166001600160a01b038416908117909155819061262a82611901565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6033546001600160a01b031633146111aa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e8d565b600260d6540361270f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610e8d565b600260d655565b60d55460ff16156111aa5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610e8d565b611490828260405180602001604052806000815250612f2a565b60008061278283611901565b9050806001600160a01b0316846001600160a01b031614806127c957506001600160a01b03808216600090815260d0602090815260408083209388168352929052205460ff165b8061123a5750836001600160a01b03166127e284610df2565b6001600160a01b031614949350505050565b826001600160a01b031661280782611901565b6001600160a01b03161461282d5760405162461bcd60e51b8152600401610e8d906146c7565b6001600160a01b03821661288f5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610e8d565b61289c8383836001612f5d565b826001600160a01b03166128af82611901565b6001600160a01b0316146128d55760405162461bcd60e51b8152600401610e8d906146c7565b600081815260cf6020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260ce855283862080546000190190559087168086528386208054600101905586865260cd90945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600080612972848461308a565b915091505b9250929050565b60006001600160a01b0382166129e85760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610e8d565b506001600160a01b0316600090815260ce602052604090205490565b60d55460ff166111aa5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610e8d565b612a55612a04565b60d5805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60606000612aac836130c4565b905080516001600160401b03811115612ac757612ac76140c9565b604051908082528060200260200182016040528015612af0578160200160208202803683370190505b50915060005b8151811015612b5257818181518110612b1157612b11614475565b6020026020010151838281518110612b2b57612b2b614475565b63ffffffff9092166020928302919091019091015280612b4a816143b2565b915050612af6565b5050919050565b60008080612b71609763ffffffff8087169061296516565b9150915081612b7f8561315e565b90612b9d5760405162461bcd60e51b8152600401610e8d9190613c93565b509392505050565b6000612bb1838361317f565b90506000612bbf8484613197565b9050366000612bce86866131a7565b91509150612be4612bdc8590565b8484846131b7565b838863ffffffff167fba20947a325f450d232530e5f5fce293e7963499d5309a07cee84a269f2f15a685604051612c1d91815260200190565b60405180910390a35050505050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b612c95609763ffffffff808416906131c116565b612c9e8261315e565b906114905760405162461bcd60e51b8152600401610e8d9190613c93565b600080612cc8846131cd565b9050612cdf8684612cda888886613235565b613264565b9150848663ffffffff167fd229aacb94204188fe8042965fa6b269c62dc5818b21238779ab64bdd17efeec86604051612d1a91815260200190565b60405180910390a350949350505050565b612d33612716565b60d5805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612a823390565b600080612d7484612b59565b905061123a848285613287565b816001600160a01b0316836001600160a01b031603612de25760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610e8d565b6001600160a01b03838116600081815260d06020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b611490609763ffffffff80851690849061333616565b612e708484846127f4565b612e7c84848484613341565b6115385760405162461bcd60e51b8152600401610e8d9061470c565b60606000612ea583613442565b60010190506000816001600160401b03811115612ec457612ec46140c9565b6040519080825280601f01601f191660200182016040528015612eee576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612ef857509392505050565b612f34838361351a565b612f416000848484613341565b610f2e5760405162461bcd60e51b8152600401610e8d9061470c565b6001811115612fcc5760405162461bcd60e51b815260206004820152603560248201527f455243373231456e756d657261626c653a20636f6e7365637574697665207472604482015274185b9cd9995c9cc81b9bdd081cdd5c1c1bdc9d1959605a1b6064820152608401610e8d565b816001600160a01b038516613028576130238160d38054600083815260d460205260408120829055600182018355919091527f915c3eb987b20e1af620c1403197bf687fb7f18513b3a73fde6e78c7072c41a60155565b61304b565b836001600160a01b0316856001600160a01b03161461304b5761304b85826136b3565b6001600160a01b0384166130675761306281613750565b611733565b846001600160a01b0316846001600160a01b0316146117335761173384826137ff565b60008181526002830160205260408120548190806130b9576130ac8585613843565b9250600091506129779050565b600192509050612977565b606060006130d18361384f565b9050806001600160401b038111156130eb576130eb6140c9565b604051908082528060200260200182016040528015613114578160200160208202803683370190505b50915060005b81811015612b525761312c848261385a565b60001c83828151811061314157613141614475565b602090810291909101015280613156816143b2565b91505061311a565b606061316f8263ffffffff16612e98565b6040516020016121d3919061475e565b600061318e60208284866147a3565b611d34916147cd565b600061318e6040602084866147a3565b36600061297283604081876147a3565b611538848461275c565b6000611d348383613866565b6060336131d983611901565b6001600160a01b0316146132185760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610e8d565b61322182613883565b505060408051602081019091526000815290565b606083838360405160200161324c939291906147eb565b60405160208183030381529060405290509392505050565b60008061327085612b59565b905061327e85828686613926565b95945050505050565b60007f000000000000000000000000d4c1905bb1d26bc93dac913e13cacc278cdcc80d6001600160a01b03166381d2ea958585856132c4896139d8565b6065546040516001600160e01b031960e088901b1681526132f595949392916001600160a01b031690600401614818565b602060405180830381865afa158015613312573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123a919061486a565b6115388383836139fa565b60006001600160a01b0384163b1561343757604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290613385903390899088908890600401614883565b6020604051808303816000875af19250505080156133c0575060408051601f3d908101601f191682019092526133bd918101906148b6565b60015b61341d573d8080156133ee576040519150601f19603f3d011682016040523d82523d6000602084013e6133f3565b606091505b5080516000036134155760405162461bcd60e51b8152600401610e8d9061470c565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061123a565b506001949350505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106134815772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106134ad576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106134cb57662386f26fc10000830492506010015b6305f5e10083106134e3576305f5e100830492506008015b61271083106134f757612710830492506004015b60648310613509576064830492506002015b600a8310610d5a5760010192915050565b6001600160a01b0382166135705760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610e8d565b600081815260cd60205260409020546001600160a01b0316156135d55760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610e8d565b6135e3600083836001612f5d565b600081815260cd60205260409020546001600160a01b0316156136485760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610e8d565b6001600160a01b038216600081815260ce602090815260408083208054600101905584835260cd90915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600060016136c08461297e565b6136ca9190614509565b600083815260d2602052604090205490915080821461371d576001600160a01b038416600090815260d160209081526040808320858452825280832054848452818420819055835260d290915290208190555b50600091825260d2602090815260408084208490556001600160a01b03909416835260d181528383209183525290812055565b60d35460009061376290600190614509565b600083815260d4602052604081205460d3805493945090928490811061378a5761378a614475565b906000526020600020015490508060d383815481106137ab576137ab614475565b600091825260208083209091019290925582815260d4909152604080822084905585825281205560d38054806137e3576137e36148d3565b6001900381819060005260206000200160009055905550505050565b600061380a8361297e565b6001600160a01b03909316600090815260d160209081526040808320868452825280832085905593825260d29052919091209190915550565b6000611d348383613a17565b6000610d5a82613a2f565b6000611d348383613a39565b60008181526002830160205260408120819055611d348383613a63565b600061388e82611901565b905061389e816000846001612f5d565b6138a782611901565b600083815260cf6020908152604080832080546001600160a01b03199081169091556001600160a01b03851680855260ce8452828520805460001901905587855260cd909352818420805490911690555192935084927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b60007f000000000000000000000000d4c1905bb1d26bc93dac913e13cacc278cdcc80d6001600160a01b03166310b83dc0848787866139648b6139d8565b6065546040516001600160e01b031960e089901b16815261399595949392916001600160a01b031690600401614818565b60206040518083038185885af11580156139b3573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061327e919061486a565b63ffffffff8116600090815260ca6020526040902054606090610d5a90613a6f565b6000828152600284016020526040812082905561123a8484613a8d565b60008181526001830160205260408120541515611d34565b6000610d5a825490565b6000826000018281548110613a5057613a50614475565b9060005260206000200154905092915050565b6000611d348383613a99565b6060610d5a6000833360405180602001604052806000815250613b8c565b6000611d348383613bc1565b60008181526001830160205260408120548015613b82576000613abd600183614509565b8554909150600090613ad190600190614509565b9050818114613b36576000866000018281548110613af157613af1614475565b9060005260206000200154905080876000018481548110613b1457613b14614475565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613b4757613b476148d3565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610d5a565b6000915050610d5a565b6060600185858585604051602001613ba89594939291906148e9565b6040516020818303038152906040529050949350505050565b6000818152600183016020526040812054613c0857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d5a565b506000610d5a565b6001600160e01b03198116811461105757600080fd5b600060208284031215613c3857600080fd5b8135611d3481613c10565b60005b83811015613c5e578181015183820152602001613c46565b50506000910152565b60008151808452613c7f816020860160208601613c43565b601f01601f19169290920160200192915050565b602081526000611d346020830184613c67565b600060208284031215613cb857600080fd5b5035919050565b80356001600160a01b0381168114613cd657600080fd5b919050565b60008060408385031215613cee57600080fd5b613cf783613cbf565b946020939093013593505050565b600060208284031215613d1757600080fd5b611d3482613cbf565b600080600060608486031215613d3557600080fd5b613d3e84613cbf565b9250613d4c60208501613cbf565b9150604084013590509250925092565b803561ffff81168114613cd657600080fd5b600060208284031215613d8057600080fd5b611d3482613d5c565b803563ffffffff81168114613cd657600080fd5b600060208284031215613daf57600080fd5b611d3482613d89565b60008060408385031215613dcb57600080fd5b613dd483613cbf565b9150613de260208401613d5c565b90509250929050565b6020808252825182820181905260009190848201906040850190845b81811015613e2957835163ffffffff1683529284019291840191600101613e07565b50909695505050505050565b60008060408385031215613e4857600080fd5b613cf783613d89565b60008083601f840112613e6357600080fd5b5081356001600160401b03811115613e7a57600080fd5b6020830191508360208260051b850101111561297757600080fd5b600080600060408486031215613eaa57600080fd5b83356001600160401b03811115613ec057600080fd5b613ecc86828701613e51565b9094509250613edf905060208501613d5c565b90509250925092565b60008083601f840112613efa57600080fd5b5081356001600160401b03811115613f1157600080fd5b60208301915083602082850101111561297757600080fd5b60008060008060608587031215613f3f57600080fd5b613f4885613d89565b93506020850135925060408501356001600160401b03811115613f6a57600080fd5b613f7687828801613ee8565b95989497509550505050565b60008060408385031215613f9557600080fd5b82359150613de260208401613cbf565b60008060208385031215613fb857600080fd5b82356001600160401b03811115613fce57600080fd5b613fda85828601613e51565b90969095509350505050565b600080600060608486031215613ffb57600080fd5b61400484613d89565b95602085013595506040909401359392505050565b6000806040838503121561402c57600080fd5b61403583613cbf565b91506020830135801515811461404a57600080fd5b809150509250929050565b6000806020838503121561406857600080fd5b82356001600160401b038082111561407f57600080fd5b818501915085601f83011261409357600080fd5b8135818111156140a257600080fd5b8660208260061b85010111156140b757600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052604160045260246000fd5b600080600080608085870312156140f557600080fd5b6140fe85613cbf565b935061410c60208601613cbf565b92506040850135915060608501356001600160401b038082111561412f57600080fd5b818701915087601f83011261414357600080fd5b813581811115614155576141556140c9565b604051601f8201601f19908116603f0116810190838211818310171561417d5761417d6140c9565b816040528281528a602084870101111561419657600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600080600080604085870312156141d057600080fd5b84356001600160401b03808211156141e757600080fd5b6141f388838901613ee8565b9096509450602087013591508082111561420c57600080fd5b50613f7687828801613ee8565b6000806000806040858703121561422f57600080fd5b84356001600160401b038082111561424657600080fd5b61425288838901613e51565b9096509450602087013591508082111561426b57600080fd5b50613f7687828801613e51565b6000806040838503121561428b57600080fd5b61429483613cbf565b9150613de260208401613cbf565b600181811c908216806142b657607f821691505b6020821081036142d657634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526027908201527f4d61696c626f78436c69656e743a20696e76616c696420636f6e74726163742060408201526673657474696e6760c81b606082015260800190565b60208082526022908201527f576f6d65784e46543732313a20496e73756666696369656e74206d696e742066604082015261656560f01b606082015260800190565b6020808252601f908201527f576f6d65784e46543732313a204d696e742065786365656473206c696d697400604082015260600190565b634e487b7160e01b600052601160045260246000fd5b6000600182016143c4576143c461439c565b5060010190565b80820180821115610d5a57610d5a61439c565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b6020808252602a908201527f526566657272616c53797374656d3a20526566657272616c20626970732061726040820152690ca40e8dede40d0d2ced60b31b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417610d5a57610d5a61439c565b6000826144bf57634e487b7160e01b600052601260045260246000fd5b500490565b60208082526025908201527f576f6d65784e46543732313a20496e76616c6964207265666572726572206164604082015264647265737360d81b606082015260800190565b81810381811115610d5a57610d5a61439c565b60008154614529816142a2565b60018281168015614541576001811461455657614585565b60ff1984168752821515830287019450614585565b8560005260208060002060005b8581101561457c5781548a820152908401908201614563565b50505082870194505b5050505092915050565b600061459b828661451c565b84516145ab818360208901613c43565b6145b78183018661451c565b979650505050505050565b601f821115610f2e57600081815260208120601f850160051c810160208610156145e95750805b601f850160051c820191505b8181101561248f578281556001016145f5565b6001600160401b0383111561461f5761461f6140c9565b6146338361462d83546142a2565b836145c2565b6000601f841160018114614667576000851561464f5750838201355b600019600387901b1c1916600186901b178355611733565b600083815260209020601f19861690835b828110156146985786850135825560209485019460019092019101614678565b50868210156146b55760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b7f4e6f20726f7574657220656e726f6c6c656420666f7220646f6d61696e3a200081526000825161479681601f850160208701613c43565b91909101601f0192915050565b600080858511156147b357600080fd5b838611156147c057600080fd5b5050820193919092039150565b80356020831015610d5a57600019602084900360031b1b1692915050565b83815282602082015260008251614809816040850160208701613c43565b91909101604001949350505050565b63ffffffff8616815284602082015260a06040820152600061483d60a0830186613c67565b828103606084015261484f8186613c67565b91505060018060a01b03831660808301529695505050505050565b60006020828403121561487c57600080fd5b5051919050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061159e90830184613c67565b6000602082840312156148c857600080fd5b8151611d3481613c10565b634e487b7160e01b600052603160045260246000fd5b61ffff60f01b8660f01b1681528460028201528360228201526bffffffffffffffffffffffff198360601b1660428201526000825161492f816056850160208701613c43565b91909101605601969550505050505056fedc9e7f115f499a243fe74d676de78b20c5c147ba36ff1e3bfc8d9f1821d30385a264697066735822122081f2f8538eb61e6f15f384445725e8e2fceccd7afe6cf02bd4e43a3f53607c0664736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000d4c1905bb1d26bc93dac913e13cacc278cdcc80d000000000000000000000000149676d254f9c01f1011c580b8f3dfd702da333300000000000000000000000000000000000000000000000000003faa2522600000000000000000000000000000000000000000000000000000001fd5129130000000000000000000000000000000000000000000000000000000000005f5e1000000000000000000000000000000000000000000000000000000000000000003
-----Decoded View---------------
Arg [0] : _mailbox (address): 0xd4C1905BB1D26BC93DAC913e13CaCC278CdCC80D
Arg [1] : _feeCollector (address): 0x149676D254f9C01f1011C580B8F3DFD702DA3333
Arg [2] : _mintFee (uint256): 70000000000000
Arg [3] : _bridgeFee (uint256): 35000000000000
Arg [4] : _totalSupply (uint256): 100000000
Arg [5] : _idMultiplier (uint256): 3
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000d4c1905bb1d26bc93dac913e13cacc278cdcc80d
Arg [1] : 000000000000000000000000149676d254f9c01f1011c580b8f3dfd702da3333
Arg [2] : 00000000000000000000000000000000000000000000000000003faa25226000
Arg [3] : 00000000000000000000000000000000000000000000000000001fd512913000
Arg [4] : 0000000000000000000000000000000000000000000000000000000005f5e100
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000003
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.