Source Code
Overview
GLMR Balance
GLMR Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 2 internal transactions
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 5483295 | 716 days ago | Contract Creation | 0 GLMR | |||
| 5483295 | 716 days ago | Contract Creation | 0 GLMR |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
MarketplaceV3
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 20 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
// $$\ $$\ $$\ $$\ $$\
// $$ | $$ | \__| $$ | $$ |
// $$$$$$\ $$$$$$$\ $$\ $$$$$$\ $$$$$$$ |$$\ $$\ $$\ $$$$$$\ $$$$$$$\
// \_$$ _| $$ __$$\ $$ |$$ __$$\ $$ __$$ |$$ | $$ | $$ |$$ __$$\ $$ __$$\
// $$ | $$ | $$ |$$ |$$ | \__|$$ / $$ |$$ | $$ | $$ |$$$$$$$$ |$$ | $$ |
// $$ |$$\ $$ | $$ |$$ |$$ | $$ | $$ |$$ | $$ | $$ |$$ ____|$$ | $$ |
// \$$$$ |$$ | $$ |$$ |$$ | \$$$$$$$ |\$$$$$\$$$$ |\$$$$$$$\ $$$$$$$ |
// \____/ \__| \__|\__|\__| \_______| \_____\____/ \_______|\_______/
// ====== External imports ======
import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import { ERC721Holder } from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
import { ERC1155Holder, ERC1155Receiver } from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
// ========== Internal imports ==========
import { BaseRouter, IRouter, IRouterState } from "@thirdweb-dev/dynamic-contracts/src/presets/BaseRouter.sol";
import { ERC165 } from "../../../eip/ERC165.sol";
import "../../../extension/Multicall.sol";
import "../../../extension/upgradeable/Initializable.sol";
import "../../../extension/upgradeable/ContractMetadata.sol";
import "../../../extension/upgradeable/PlatformFee.sol";
import "../../../extension/upgradeable/PermissionsEnumerable.sol";
import "../../../extension/upgradeable/init/ReentrancyGuardInit.sol";
import "../../../extension/upgradeable/ERC2771ContextUpgradeable.sol";
import { RoyaltyPaymentsLogic } from "../../../extension/upgradeable/RoyaltyPayments.sol";
/**
* @author thirdweb.com
*/
contract MarketplaceV3 is
Initializable,
Multicall,
BaseRouter,
ContractMetadata,
PlatformFee,
PermissionsEnumerable,
ReentrancyGuardInit,
ERC2771ContextUpgradeable,
RoyaltyPaymentsLogic,
ERC721Holder,
ERC1155Holder,
ERC165
{
/// @dev Only EXTENSION_ROLE holders can perform upgrades.
bytes32 private constant EXTENSION_ROLE = keccak256("EXTENSION_ROLE");
bytes32 private constant MODULE_TYPE = bytes32("MarketplaceV3");
uint256 private constant VERSION = 3;
/// @dev The address of the native token wrapper contract.
address private immutable nativeTokenWrapper;
/*///////////////////////////////////////////////////////////////
Constructor + initializer logic
//////////////////////////////////////////////////////////////*/
/// @dev We accept constructor params as a struct to avoid `Stack too deep` errors.
struct MarketplaceConstructorParams {
Extension[] extensions;
address royaltyEngineAddress;
address nativeTokenWrapper;
}
constructor(
MarketplaceConstructorParams memory _marketplaceV3Params
) BaseRouter(_marketplaceV3Params.extensions) RoyaltyPaymentsLogic(_marketplaceV3Params.royaltyEngineAddress) {
nativeTokenWrapper = _marketplaceV3Params.nativeTokenWrapper;
_disableInitializers();
}
receive() external payable {
assert(msg.sender == nativeTokenWrapper); // only accept ETH via fallback from the native token wrapper contract
}
/// @dev Initializes the contract, like a constructor.
function initialize(
address _defaultAdmin,
string memory _contractURI,
address[] memory _trustedForwarders,
address _platformFeeRecipient,
uint16 _platformFeeBps
) external initializer {
// Initialize BaseRouter
__BaseRouter_init();
// Initialize inherited contracts, most base-like -> most derived.
__ReentrancyGuard_init();
__ERC2771Context_init(_trustedForwarders);
// Initialize this contract's state.
_setupContractURI(_contractURI);
_setupPlatformFeeInfo(_platformFeeRecipient, _platformFeeBps);
_setupRole(DEFAULT_ADMIN_ROLE, _defaultAdmin);
_setupRole(EXTENSION_ROLE, _defaultAdmin);
_setupRole(keccak256("LISTER_ROLE"), address(0));
_setupRole(keccak256("ASSET_ROLE"), address(0));
_setupRole(EXTENSION_ROLE, _defaultAdmin);
_setRoleAdmin(EXTENSION_ROLE, EXTENSION_ROLE);
}
/*///////////////////////////////////////////////////////////////
Generic contract logic
//////////////////////////////////////////////////////////////*/
/// @dev Returns the type of the contract.
function contractType() external pure returns (bytes32) {
return MODULE_TYPE;
}
/// @dev Returns the version of the contract.
function contractVersion() external pure returns (uint8) {
return uint8(VERSION);
}
/*///////////////////////////////////////////////////////////////
ERC 165 / 721 / 1155 logic
//////////////////////////////////////////////////////////////*/
function supportsInterface(
bytes4 interfaceId
) public view virtual override(ERC165, IERC165, ERC1155Receiver) returns (bool) {
return
interfaceId == type(IERC1155Receiver).interfaceId ||
interfaceId == type(IERC721Receiver).interfaceId ||
interfaceId == type(IRouter).interfaceId ||
interfaceId == type(IRouterState).interfaceId ||
super.supportsInterface(interfaceId);
}
/*///////////////////////////////////////////////////////////////
Overridable Permissions
//////////////////////////////////////////////////////////////*/
/// @dev Checks whether platform fee info can be set in the given execution context.
function _canSetPlatformFeeInfo() internal view override returns (bool) {
return _hasRole(DEFAULT_ADMIN_ROLE, _msgSender());
}
/// @dev Checks whether contract metadata can be set in the given execution context.
function _canSetContractURI() internal view override returns (bool) {
return _hasRole(DEFAULT_ADMIN_ROLE, _msgSender());
}
/// @dev Returns whether royalty engine address can be set in the given execution context.
function _canSetRoyaltyEngine() internal view override returns (bool) {
return _hasRole(DEFAULT_ADMIN_ROLE, _msgSender());
}
/// @dev Checks whether an account has a particular role.
function _hasRole(bytes32 _role, address _account) internal view returns (bool) {
PermissionsStorage.Data storage data = PermissionsStorage.data();
return data._hasRole[_role][_account];
}
/// @dev Returns whether all relevant permission and other checks are met before any upgrade.
function _isAuthorizedCallToUpgrade() internal view virtual override returns (bool) {
return _hasRole(EXTENSION_ROLE, msg.sender);
}
function _msgSender()
internal
view
override(ERC2771ContextUpgradeable, Permissions, Multicall)
returns (address sender)
{
return ERC2771ContextUpgradeable._msgSender();
}
function _msgData() internal view override(ERC2771ContextUpgradeable, Permissions) returns (bytes calldata) {
return ERC2771ContextUpgradeable._msgData();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./interface/IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// 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
* [EIP](https://eips.ethereum.org/EIPS/eip-165).
*
* 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
* [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Interface for the NFT Royalty Standard.
*
* A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
* support for royalty payments across all NFT marketplaces and ecosystem participants.
*
* _Available since v4.5._
*/
interface IERC2981 is IERC165 {
/**
* @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
* exchange. The royalty amount is denominated and should be payed in that same unit of exchange.
*/
function royaltyInfo(
uint256 tokenId,
uint256 salePrice
) external view returns (address receiver, uint256 royaltyAmount);
}// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;
/// @author thirdweb
import "../lib/Address.sol";
import "./interface/IMulticall.sol";
/**
* @dev Provides a function to batch together multiple calls in a single external call.
*
* _Available since v4.1._
*/
contract Multicall is IMulticall {
/**
* @notice Receives and executes a batch of function calls on this contract.
* @dev Receives and executes a batch of function calls on this contract.
*
* @param data The bytes data that makes up the batch of function calls to execute.
* @return results The bytes data that makes up the result of the batch of function calls executed.
*/
function multicall(bytes[] calldata data) external returns (bytes[] memory results) {
results = new bytes[](data.length);
address sender = _msgSender();
bool isForwarder = msg.sender != sender;
for (uint256 i = 0; i < data.length; i++) {
if (isForwarder) {
results[i] = Address.functionDelegateCall(address(this), abi.encodePacked(data[i], sender));
} else {
results[i] = Address.functionDelegateCall(address(this), data[i]);
}
}
return results;
}
/// @notice Returns the sender in the given execution context.
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
/**
* Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI
* for you contract.
*
* Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea.
*/
interface IContractMetadata {
/// @dev Returns the metadata URI of the contract.
function contractURI() external view returns (string memory);
/**
* @dev Sets contract URI for the storefront-level metadata of the contract.
* Only module admin can call this function.
*/
function setContractURI(string calldata _uri) external;
/// @dev Emitted when the contract URI is updated.
event ContractURIUpdated(string prevURI, string newURI);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
interface IERC2771Context {
function isTrustedForwarder(address forwarder) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author thirdweb
/**
* @dev Provides a function to batch together multiple calls in a single external call.
*
* _Available since v4.1._
*/
interface IMulticall {
/**
* @dev Receives and executes a batch of function calls on this contract.
*/
function multicall(bytes[] calldata data) external returns (bytes[] memory results);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IPermissions {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
import "./IPermissions.sol";
/**
* @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
*/
interface IPermissionsEnumerable is IPermissions {
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
*
* Role bearers are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
* you perform all queries on the same block. See the following
* [forum post](https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296)
* for more information.
*/
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
/**
* @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role.
*/
function getRoleMemberCount(bytes32 role) external view returns (uint256);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
/**
* Thirdweb's `PlatformFee` is a contract extension to be used with any base contract. It exposes functions for setting and reading
* the recipient of platform fee and the platform fee basis points, and lets the inheriting contract perform conditional logic
* that uses information about platform fees, if desired.
*/
interface IPlatformFee {
/// @dev Fee type variants: percentage fee and flat fee
enum PlatformFeeType {
Bps,
Flat
}
/// @dev Returns the platform fee bps and recipient.
function getPlatformFeeInfo() external view returns (address, uint16);
/// @dev Lets a module admin update the fees on primary sales.
function setPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) external;
/// @dev Emitted when fee on primary sales is updated.
event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps);
/// @dev Emitted when the flat platform fee is updated.
event FlatPlatformFeeUpdated(address platformFeeRecipient, uint256 flatFee);
/// @dev Emitted when the platform fee type is updated.
event PlatformFeeTypeUpdated(PlatformFeeType feeType);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @dev Lookup engine interface
*/
interface IRoyaltyEngineV1 is IERC165 {
/**
* Get the royalty for a given token (address, id) and value amount. Does not cache the bps/amounts. Caches the spec for a given token address
*
* @param tokenAddress - The address of the token
* @param tokenId - The id of the token
* @param value - The value you wish to get the royalty of
*
* returns Two arrays of equal length, royalty recipients and the corresponding amount each recipient should get
*/
function getRoyalty(
address tokenAddress,
uint256 tokenId,
uint256 value
) external returns (address payable[] memory recipients, uint256[] memory amounts);
/**
* View only version of getRoyalty
*
* @param tokenAddress - The address of the token
* @param tokenId - The id of the token
* @param value - The value you wish to get the royalty of
*
* returns Two arrays of equal length, royalty recipients and the corresponding amount each recipient should get
*/
function getRoyaltyView(
address tokenAddress,
uint256 tokenId,
uint256 value
) external view returns (address payable[] memory recipients, uint256[] memory amounts);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @dev Read royalty info for a token.
* Supports RoyaltyEngineV1 and RoyaltyRegistry by manifold.xyz.
*/
interface IRoyaltyPayments is IERC165 {
/// @dev Emitted when the address of RoyaltyEngine is set or updated.
event RoyaltyEngineUpdated(address indexed previousAddress, address indexed newAddress);
/**
* Get the royalty for a given token (address, id) and value amount.
*
* @param tokenAddress - The address of the token
* @param tokenId - The id of the token
* @param value - The value you wish to get the royalty of
*
* returns Two arrays of equal length, royalty recipients and the corresponding amount each recipient should get
*/
function getRoyalty(
address tokenAddress,
uint256 tokenId,
uint256 value
) external returns (address payable[] memory recipients, uint256[] memory amounts);
/**
* Set or override RoyaltyEngine address
*
* @param _royaltyEngineAddress - RoyaltyEngineV1 address
*/
function setRoyaltyEngine(address _royaltyEngineAddress) external;
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
import "../interface/IContractMetadata.sol";
/**
* @author thirdweb.com
*
* @title Contract Metadata
* @notice Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI
* for you contract.
* Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea.
*/
library ContractMetadataStorage {
/// @custom:storage-location erc7201:contract.metadata.storage
/// @dev keccak256(abi.encode(uint256(keccak256("contract.metadata.storage")) - 1)) & ~bytes32(uint256(0xff))
bytes32 public constant CONTRACT_METADATA_STORAGE_POSITION =
0x4bc804ba64359c0e35e5ed5d90ee596ecaa49a3a930ddcb1470ea0dd625da900;
struct Data {
/// @notice Returns the contract metadata URI.
string contractURI;
}
function data() internal pure returns (Data storage data_) {
bytes32 position = CONTRACT_METADATA_STORAGE_POSITION;
assembly {
data_.slot := position
}
}
}
abstract contract ContractMetadata is IContractMetadata {
/**
* @notice Lets a contract admin set the URI for contract-level metadata.
* @dev Caller should be authorized to setup contractURI, e.g. contract admin.
* See {_canSetContractURI}.
* Emits {ContractURIUpdated Event}.
*
* @param _uri keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
*/
function setContractURI(string memory _uri) external override {
if (!_canSetContractURI()) {
revert("Not authorized");
}
_setupContractURI(_uri);
}
/// @dev Lets a contract admin set the URI for contract-level metadata.
function _setupContractURI(string memory _uri) internal {
string memory prevURI = _contractMetadataStorage().contractURI;
_contractMetadataStorage().contractURI = _uri;
emit ContractURIUpdated(prevURI, _uri);
}
/// @notice Returns the contract metadata URI.
function contractURI() public view virtual override returns (string memory) {
return _contractMetadataStorage().contractURI;
}
/// @dev Returns the AccountPermissions storage.
function _contractMetadataStorage() internal pure returns (ContractMetadataStorage.Data storage data) {
data = ContractMetadataStorage.data();
}
/// @dev Returns whether contract metadata can be set in the given execution context.
function _canSetContractURI() internal view virtual returns (bool);
}// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;
import "../interface/IERC2771Context.sol";
import "./Initializable.sol";
/**
* @dev Context variant with ERC2771 support.
*/
library ERC2771ContextStorage {
/// @custom:storage-location erc7201:erc2771.context.storage
/// @dev keccak256(abi.encode(uint256(keccak256("erc2771.context.storage")) - 1)) & ~bytes32(uint256(0xff))
bytes32 public constant ERC2771_CONTEXT_STORAGE_POSITION =
0x82aadcdf5bea62fd30615b6c0754b644e71b6c1e8c55b71bb927ad005b504f00;
struct Data {
mapping(address => bool) trustedForwarder;
}
function data() internal pure returns (Data storage data_) {
bytes32 position = ERC2771_CONTEXT_STORAGE_POSITION;
assembly {
data_.slot := position
}
}
}
/**
* @dev Context variant with ERC2771 support.
*/
abstract contract ERC2771ContextUpgradeable is Initializable {
function __ERC2771Context_init(address[] memory trustedForwarder) internal onlyInitializing {
__ERC2771Context_init_unchained(trustedForwarder);
}
function __ERC2771Context_init_unchained(address[] memory trustedForwarder) internal onlyInitializing {
for (uint256 i = 0; i < trustedForwarder.length; i++) {
_erc2771ContextStorage().trustedForwarder[trustedForwarder[i]] = true;
}
}
function isTrustedForwarder(address forwarder) public view virtual returns (bool) {
return _erc2771ContextStorage().trustedForwarder[forwarder];
}
function _msgSender() internal view virtual returns (address sender) {
if (isTrustedForwarder(msg.sender)) {
// The assembly code is more direct than the Solidity version using `abi.decode`.
assembly {
sender := shr(96, calldataload(sub(calldatasize(), 20)))
}
} else {
return msg.sender;
}
}
function _msgData() internal view virtual returns (bytes calldata) {
if (isTrustedForwarder(msg.sender)) {
return msg.data[:msg.data.length - 20];
} else {
return msg.data;
}
}
/// @dev Returns the ERC2771ContextStorage storage.
function _erc2771ContextStorage() internal pure returns (ERC2771ContextStorage.Data storage data) {
data = ERC2771ContextStorage.data();
}
uint256[49] private __gap;
}// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;
import "../../lib/Address.sol";
library InitStorage {
/// @custom:storage-location erc7201:init.storage
/// @dev keccak256(abi.encode(uint256(keccak256("init.storage")) - 1)) & ~bytes32(uint256(0xff))
bytes32 constant INIT_STORAGE_POSITION = 0x322cf19c484104d3b1a9c2982ebae869ede3fa5f6c4703ca41b9a48c76ee0300;
/// @dev Layout of the entrypoint contract's storage.
struct Data {
uint8 initialized;
bool initializing;
}
/// @dev Returns the entrypoint contract's data at the relevant storage location.
function data() internal pure returns (Data storage data_) {
bytes32 position = INIT_STORAGE_POSITION;
assembly {
data_.slot := position
}
}
}
abstract contract Initializable {
/**
* @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. Equivalent to `reinitializer(1)`.
*/
modifier initializer() {
uint8 _initialized = _initStorage().initialized;
bool _initializing = _initStorage().initializing;
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initStorage().initialized = 1;
if (isTopLevelCall) {
_initStorage().initializing = true;
}
_;
if (isTopLevelCall) {
_initStorage().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.
*
* `initializer` is equivalent to `reinitializer(1)`, so 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.
*
* 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.
*/
modifier reinitializer(uint8 version) {
uint8 _initialized = _initStorage().initialized;
bool _initializing = _initStorage().initializing;
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initStorage().initialized = version;
_initStorage().initializing = true;
_;
_initStorage().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(_initStorage().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.
*/
function _disableInitializers() internal virtual {
uint8 _initialized = _initStorage().initialized;
bool _initializing = _initStorage().initializing;
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initStorage().initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/// @dev Returns the InitStorage storage.
function _initStorage() internal pure returns (InitStorage.Data storage data) {
data = InitStorage.data();
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
import "../interface/IPermissions.sol";
import "../../lib/Strings.sol";
/**
* @title Permissions
* @dev This contracts provides extending-contracts with role-based access control mechanisms
*/
library PermissionsStorage {
/// @custom:storage-location erc7201:permissions.storage
/// @dev keccak256(abi.encode(uint256(keccak256("permissions.storage")) - 1)) & ~bytes32(uint256(0xff))
bytes32 public constant PERMISSIONS_STORAGE_POSITION =
0x0a7b0f5c59907924802379ebe98cdc23e2ee7820f63d30126e10b3752010e500;
struct Data {
/// @dev Map from keccak256 hash of a role => a map from address => whether address has role.
mapping(bytes32 => mapping(address => bool)) _hasRole;
/// @dev Map from keccak256 hash of a role to role admin. See {getRoleAdmin}.
mapping(bytes32 => bytes32) _getRoleAdmin;
}
function data() internal pure returns (Data storage data_) {
bytes32 position = PERMISSIONS_STORAGE_POSITION;
assembly {
data_.slot := position
}
}
}
contract Permissions is IPermissions {
/// @dev Default admin role for all roles. Only accounts with this role can grant/revoke other roles.
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/// @dev Modifier that checks if an account has the specified role; reverts otherwise.
modifier onlyRole(bytes32 role) {
_checkRole(role, _msgSender());
_;
}
/**
* @notice Checks whether an account has a particular role.
* @dev Returns `true` if `account` has been granted `role`.
*
* @param role keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
* @param account Address of the account for which the role is being checked.
*/
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _permissionsStorage()._hasRole[role][account];
}
/**
* @notice Checks whether an account has a particular role;
* role restrictions can be swtiched on and off.
*
* @dev Returns `true` if `account` has been granted `role`.
* Role restrictions can be swtiched on and off:
* - If address(0) has ROLE, then the ROLE restrictions
* don't apply.
* - If address(0) does not have ROLE, then the ROLE
* restrictions will apply.
*
* @param role keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
* @param account Address of the account for which the role is being checked.
*/
function hasRoleWithSwitch(bytes32 role, address account) public view returns (bool) {
if (!_permissionsStorage()._hasRole[role][address(0)]) {
return _permissionsStorage()._hasRole[role][account];
}
return true;
}
/**
* @notice Returns the admin role that controls the specified role.
* @dev See {grantRole} and {revokeRole}.
* To change a role's admin, use {_setRoleAdmin}.
*
* @param role keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
*/
function getRoleAdmin(bytes32 role) external view override returns (bytes32) {
return _permissionsStorage()._getRoleAdmin[role];
}
/**
* @notice Grants a role to an account, if not previously granted.
* @dev Caller must have admin role for the `role`.
* Emits {RoleGranted Event}.
*
* @param role keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
* @param account Address of the account to which the role is being granted.
*/
function grantRole(bytes32 role, address account) public virtual override {
_checkRole(_permissionsStorage()._getRoleAdmin[role], _msgSender());
if (_permissionsStorage()._hasRole[role][account]) {
revert("Can only grant to non holders");
}
_setupRole(role, account);
}
/**
* @notice Revokes role from an account.
* @dev Caller must have admin role for the `role`.
* Emits {RoleRevoked Event}.
*
* @param role keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
* @param account Address of the account from which the role is being revoked.
*/
function revokeRole(bytes32 role, address account) public virtual override {
_checkRole(_permissionsStorage()._getRoleAdmin[role], _msgSender());
_revokeRole(role, account);
}
/**
* @notice Revokes role from the account.
* @dev Caller must have the `role`, with caller being the same as `account`.
* Emits {RoleRevoked Event}.
*
* @param role keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
* @param account Address of the account from which the role is being revoked.
*/
function renounceRole(bytes32 role, address account) public virtual override {
if (_msgSender() != account) {
revert("Can only renounce for self");
}
_revokeRole(role, account);
}
/// @dev Sets `adminRole` as `role`'s admin role.
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = _permissionsStorage()._getRoleAdmin[role];
_permissionsStorage()._getRoleAdmin[role] = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/// @dev Sets up `role` for `account`
function _setupRole(bytes32 role, address account) internal virtual {
_permissionsStorage()._hasRole[role][account] = true;
emit RoleGranted(role, account, _msgSender());
}
/// @dev Revokes `role` from `account`
function _revokeRole(bytes32 role, address account) internal virtual {
_checkRole(role, account);
delete _permissionsStorage()._hasRole[role][account];
emit RoleRevoked(role, account, _msgSender());
}
/// @dev Checks `role` for `account`. Reverts with a message including the required role.
function _checkRole(bytes32 role, address account) internal view virtual {
if (!_permissionsStorage()._hasRole[role][account]) {
revert(
string(
abi.encodePacked(
"Permissions: account ",
Strings.toHexString(uint160(account), 20),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/// @dev Checks `role` for `account`. Reverts with a message including the required role.
function _checkRoleWithSwitch(bytes32 role, address account) internal view virtual {
if (!hasRoleWithSwitch(role, account)) {
revert(
string(
abi.encodePacked(
"Permissions: account ",
Strings.toHexString(uint160(account), 20),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
function _msgSender() internal view virtual returns (address sender) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/// @dev Returns the Permissions storage.
function _permissionsStorage() internal pure returns (PermissionsStorage.Data storage data) {
data = PermissionsStorage.data();
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
import "../interface/IPermissionsEnumerable.sol";
import "./Permissions.sol";
/**
* @title PermissionsEnumerable
* @dev This contracts provides extending-contracts with role-based access control mechanisms.
* Also provides interfaces to view all members with a given role, and total count of members.
*/
library PermissionsEnumerableStorage {
/// @custom:storage-location erc7201:extension.manager.storage
bytes32 public constant PERMISSIONS_ENUMERABLE_STORAGE_POSITION =
keccak256(abi.encode(uint256(keccak256("permissions.enumerable.storage")) - 1)) & ~bytes32(uint256(0xff));
/**
* @notice A data structure to store data of members for a given role.
*
* @param index Current index in the list of accounts that have a role.
* @param members map from index => address of account that has a role
* @param indexOf map from address => index which the account has.
*/
struct RoleMembers {
uint256 index;
mapping(uint256 => address) members;
mapping(address => uint256) indexOf;
}
struct Data {
/// @dev map from keccak256 hash of a role to its members' data. See {RoleMembers}.
mapping(bytes32 => RoleMembers) roleMembers;
}
function data() internal pure returns (Data storage data_) {
bytes32 position = PERMISSIONS_ENUMERABLE_STORAGE_POSITION;
assembly {
data_.slot := position
}
}
}
contract PermissionsEnumerable is IPermissionsEnumerable, Permissions {
/**
* @notice Returns the role-member from a list of members for a role,
* at a given index.
* @dev Returns `member` who has `role`, at `index` of role-members list.
* See struct {RoleMembers}, and mapping {roleMembers}
*
* @param role keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
* @param index Index in list of current members for the role.
*
* @return member Address of account that has `role`
*/
function getRoleMember(bytes32 role, uint256 index) external view override returns (address member) {
uint256 currentIndex = _permissionsEnumerableStorage().roleMembers[role].index;
uint256 check;
for (uint256 i = 0; i < currentIndex; i += 1) {
if (_permissionsEnumerableStorage().roleMembers[role].members[i] != address(0)) {
if (check == index) {
member = _permissionsEnumerableStorage().roleMembers[role].members[i];
return member;
}
check += 1;
} else if (
hasRole(role, address(0)) && i == _permissionsEnumerableStorage().roleMembers[role].indexOf[address(0)]
) {
check += 1;
}
}
}
/**
* @notice Returns total number of accounts that have a role.
* @dev Returns `count` of accounts that have `role`.
* See struct {RoleMembers}, and mapping {roleMembers}
*
* @param role keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
*
* @return count Total number of accounts that have `role`
*/
function getRoleMemberCount(bytes32 role) external view override returns (uint256 count) {
uint256 currentIndex = _permissionsEnumerableStorage().roleMembers[role].index;
for (uint256 i = 0; i < currentIndex; i += 1) {
if (_permissionsEnumerableStorage().roleMembers[role].members[i] != address(0)) {
count += 1;
}
}
if (hasRole(role, address(0))) {
count += 1;
}
}
/// @dev Revokes `role` from `account`, and removes `account` from {roleMembers}
/// See {_removeMember}
function _revokeRole(bytes32 role, address account) internal virtual override {
super._revokeRole(role, account);
_removeMember(role, account);
}
/// @dev Grants `role` to `account`, and adds `account` to {roleMembers}
/// See {_addMember}
function _setupRole(bytes32 role, address account) internal virtual override {
super._setupRole(role, account);
_addMember(role, account);
}
/// @dev adds `account` to {roleMembers}, for `role`
function _addMember(bytes32 role, address account) internal {
uint256 idx = _permissionsEnumerableStorage().roleMembers[role].index;
_permissionsEnumerableStorage().roleMembers[role].index += 1;
_permissionsEnumerableStorage().roleMembers[role].members[idx] = account;
_permissionsEnumerableStorage().roleMembers[role].indexOf[account] = idx;
}
/// @dev removes `account` from {roleMembers}, for `role`
function _removeMember(bytes32 role, address account) internal {
uint256 idx = _permissionsEnumerableStorage().roleMembers[role].indexOf[account];
delete _permissionsEnumerableStorage().roleMembers[role].members[idx];
delete _permissionsEnumerableStorage().roleMembers[role].indexOf[account];
}
/// @dev Returns the PermissionsEnumerable storage.
function _permissionsEnumerableStorage() internal pure returns (PermissionsEnumerableStorage.Data storage data) {
data = PermissionsEnumerableStorage.data();
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
import "../interface/IPlatformFee.sol";
/**
* @author thirdweb.com
*/
library PlatformFeeStorage {
/// @custom:storage-location erc7201:platform.fee.storage
/// @dev keccak256(abi.encode(uint256(keccak256("platform.fee.storage")) - 1)) & ~bytes32(uint256(0xff))
bytes32 public constant PLATFORM_FEE_STORAGE_POSITION =
0xc0c34308b4a2f4c5ee9af8ba82541cfb3c33b076d1fd05c65f9ce7060c64c400;
struct Data {
/// @dev The address that receives all platform fees from all sales.
address platformFeeRecipient;
/// @dev The % of primary sales collected as platform fees.
uint16 platformFeeBps;
/// @dev Fee type variants: percentage fee and flat fee
IPlatformFee.PlatformFeeType platformFeeType;
/// @dev The flat amount collected by the contract as fees on primary sales.
uint256 flatPlatformFee;
}
function data() internal pure returns (Data storage data_) {
bytes32 position = PLATFORM_FEE_STORAGE_POSITION;
assembly {
data_.slot := position
}
}
}
/**
* @author thirdweb.com
*
* @title Platform Fee
* @notice Thirdweb's `PlatformFee` is a contract extension to be used with any base contract. It exposes functions for setting and reading
* the recipient of platform fee and the platform fee basis points, and lets the inheriting contract perform conditional logic
* that uses information about platform fees, if desired.
*/
abstract contract PlatformFee is IPlatformFee {
/// @dev Returns the platform fee recipient and bps.
function getPlatformFeeInfo() public view override returns (address, uint16) {
return (_platformFeeStorage().platformFeeRecipient, uint16(_platformFeeStorage().platformFeeBps));
}
/// @dev Returns the platform fee bps and recipient.
function getFlatPlatformFeeInfo() public view returns (address, uint256) {
return (_platformFeeStorage().platformFeeRecipient, _platformFeeStorage().flatPlatformFee);
}
/// @dev Returns the platform fee type.
function getPlatformFeeType() public view returns (PlatformFeeType) {
return _platformFeeStorage().platformFeeType;
}
/**
* @notice Updates the platform fee recipient and bps.
* @dev Caller should be authorized to set platform fee info.
* See {_canSetPlatformFeeInfo}.
* Emits {PlatformFeeInfoUpdated Event}; See {_setupPlatformFeeInfo}.
*
* @param _platformFeeRecipient Address to be set as new platformFeeRecipient.
* @param _platformFeeBps Updated platformFeeBps.
*/
function setPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) external override {
if (!_canSetPlatformFeeInfo()) {
revert("Not authorized");
}
_setupPlatformFeeInfo(_platformFeeRecipient, _platformFeeBps);
}
/// @dev Lets a contract admin update the platform fee recipient and bps
function _setupPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) internal {
if (_platformFeeBps > 10_000) {
revert("Exceeds max bps");
}
if (_platformFeeRecipient == address(0)) {
revert("Invalid recipient");
}
_platformFeeStorage().platformFeeBps = uint16(_platformFeeBps);
_platformFeeStorage().platformFeeRecipient = _platformFeeRecipient;
emit PlatformFeeInfoUpdated(_platformFeeRecipient, _platformFeeBps);
}
/// @notice Lets a module admin set a flat fee on primary sales.
function setFlatPlatformFeeInfo(address _platformFeeRecipient, uint256 _flatFee) external {
if (!_canSetPlatformFeeInfo()) {
revert("Not authorized");
}
_setupFlatPlatformFeeInfo(_platformFeeRecipient, _flatFee);
}
/// @dev Sets a flat fee on primary sales.
function _setupFlatPlatformFeeInfo(address _platformFeeRecipient, uint256 _flatFee) internal {
_platformFeeStorage().flatPlatformFee = _flatFee;
_platformFeeStorage().platformFeeRecipient = _platformFeeRecipient;
emit FlatPlatformFeeUpdated(_platformFeeRecipient, _flatFee);
}
/// @notice Lets a module admin set platform fee type.
function setPlatformFeeType(PlatformFeeType _feeType) external {
if (!_canSetPlatformFeeInfo()) {
revert("Not authorized");
}
_setupPlatformFeeType(_feeType);
}
/// @dev Sets platform fee type.
function _setupPlatformFeeType(PlatformFeeType _feeType) internal {
_platformFeeStorage().platformFeeType = _feeType;
emit PlatformFeeTypeUpdated(_feeType);
}
/// @dev Returns the PlatformFee storage.
function _platformFeeStorage() internal pure returns (PlatformFeeStorage.Data storage data) {
data = PlatformFeeStorage.data();
}
/// @dev Returns whether platform fee info can be set in the given execution context.
function _canSetPlatformFeeInfo() internal view virtual returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
library ReentrancyGuardStorage {
/// @custom:storage-location erc7201:reentrancy.guard.storage
/// @dev keccak256(abi.encode(uint256(keccak256("reentrancy.guard.storage")) - 1)) & ~bytes32(uint256(0xff))
bytes32 public constant REENTRANCY_GUARD_STORAGE_POSITION =
0x1d281c488dae143b6ea4122e80c65059929950b9c32f17fc57be22089d9c3b00;
struct Data {
uint256 _status;
}
function data() internal pure returns (Data storage data_) {
bytes32 position = REENTRANCY_GUARD_STORAGE_POSITION;
assembly {
data_.slot := position
}
}
}
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
constructor() {
_reentrancyGuardStorage()._status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_reentrancyGuardStorage()._status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_reentrancyGuardStorage()._status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_reentrancyGuardStorage()._status = _NOT_ENTERED;
}
/// @dev Returns the ReentrancyGuard storage.
function _reentrancyGuardStorage() internal pure returns (ReentrancyGuardStorage.Data storage data) {
data = ReentrancyGuardStorage.data();
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
import "../interface/IRoyaltyPayments.sol";
import "../interface/IRoyaltyEngineV1.sol";
import { IERC2981 } from "../../eip/interface/IERC2981.sol";
library RoyaltyPaymentsStorage {
/// @custom:storage-location erc7201:royalty.payments.storage
/// @dev keccak256(abi.encode(uint256(keccak256("royalty.payments.storage")) - 1)) & ~bytes32(uint256(0xff))
bytes32 public constant ROYALTY_PAYMENTS_STORAGE_POSITION =
0xc802b338f3fb784853cf3c808df5ff08335200e394ea2c687d12571a91045000;
struct Data {
/// @dev The address of RoyaltyEngineV1, replacing the one set during construction.
address royaltyEngineAddressOverride;
}
function royaltyPaymentsStorage() internal pure returns (Data storage royaltyPaymentsData) {
bytes32 position = ROYALTY_PAYMENTS_STORAGE_POSITION;
assembly {
royaltyPaymentsData.slot := position
}
}
}
/**
* @author thirdweb.com
*
* @title Royalty Payments
* @notice Thirdweb's `RoyaltyPayments` is a contract extension to be used with a marketplace contract.
* It exposes functions for fetching royalty settings for a token.
* It Supports RoyaltyEngineV1 and RoyaltyRegistry by manifold.xyz.
*/
abstract contract RoyaltyPaymentsLogic is IRoyaltyPayments {
// solhint-disable-next-line var-name-mixedcase
address immutable ROYALTY_ENGINE_ADDRESS;
constructor(address _royaltyEngineAddress) {
// allow address(0) in case RoyaltyEngineV1 not present on a network
require(
_royaltyEngineAddress == address(0) ||
IERC165(_royaltyEngineAddress).supportsInterface(type(IRoyaltyEngineV1).interfaceId),
"Doesn't support IRoyaltyEngineV1 interface"
);
ROYALTY_ENGINE_ADDRESS = _royaltyEngineAddress;
}
/**
* Get the royalty for a given token (address, id) and value amount. Does not cache the bps/amounts. Caches the spec for a given token address
*
* @param tokenAddress - The address of the token
* @param tokenId - The id of the token
* @param value - The value you wish to get the royalty of
*
* returns Two arrays of equal length, royalty recipients and the corresponding amount each recipient should get
*/
function getRoyalty(
address tokenAddress,
uint256 tokenId,
uint256 value
) external returns (address payable[] memory recipients, uint256[] memory amounts) {
address royaltyEngineAddress = getRoyaltyEngineAddress();
if (royaltyEngineAddress == address(0)) {
try IERC2981(tokenAddress).royaltyInfo(tokenId, value) returns (address recipient, uint256 amount) {
require(amount <= value, "Invalid royalty amount");
recipients = new address payable[](1);
amounts = new uint256[](1);
recipients[0] = payable(recipient);
amounts[0] = amount;
} catch {}
} else {
(recipients, amounts) = IRoyaltyEngineV1(royaltyEngineAddress).getRoyalty(tokenAddress, tokenId, value);
}
}
/**
* Set or override RoyaltyEngine address
*
* @param _royaltyEngineAddress - RoyaltyEngineV1 address
*/
function setRoyaltyEngine(address _royaltyEngineAddress) external {
if (!_canSetRoyaltyEngine()) {
revert("Not authorized");
}
require(
_royaltyEngineAddress != address(0) &&
IERC165(_royaltyEngineAddress).supportsInterface(type(IRoyaltyEngineV1).interfaceId),
"Doesn't support IRoyaltyEngineV1 interface"
);
_setupRoyaltyEngine(_royaltyEngineAddress);
}
/// @dev Returns original or overridden address for RoyaltyEngineV1
function getRoyaltyEngineAddress() public view returns (address royaltyEngineAddress) {
RoyaltyPaymentsStorage.Data storage data = RoyaltyPaymentsStorage.royaltyPaymentsStorage();
address royaltyEngineOverride = data.royaltyEngineAddressOverride;
royaltyEngineAddress = royaltyEngineOverride != address(0) ? royaltyEngineOverride : ROYALTY_ENGINE_ADDRESS;
}
/// @dev Lets a contract admin update the royalty engine address
function _setupRoyaltyEngine(address _royaltyEngineAddress) internal {
RoyaltyPaymentsStorage.Data storage data = RoyaltyPaymentsStorage.royaltyPaymentsStorage();
address currentAddress = data.royaltyEngineAddressOverride;
data.royaltyEngineAddressOverride = _royaltyEngineAddress;
emit RoyaltyEngineUpdated(currentAddress, _royaltyEngineAddress);
}
/// @dev Returns whether royalty engine address can be set in the given execution context.
function _canSetRoyaltyEngine() internal view virtual returns (bool);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import { ReentrancyGuardStorage } from "../ReentrancyGuard.sol";
import "../Initializable.sol";
contract ReentrancyGuardInit is Initializable {
uint256 private constant _NOT_ENTERED = 1;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
ReentrancyGuardStorage.Data storage data = ReentrancyGuardStorage.data();
data._status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.1;
/// @author thirdweb, OpenZeppelin Contracts (v4.9.0)
/**
* @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);
}
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @author thirdweb
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @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] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte,
/// and the alphabets are capitalized conditionally according to
/// https://eips.ethereum.org/EIPS/eip-55
function toHexStringChecksummed(address value) internal pure returns (string memory str) {
str = toHexString(value);
/// @solidity memory-safe-assembly
assembly {
let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...`
let o := add(str, 0x22)
let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... `
let t := shl(240, 136) // `0b10001000 << 240`
for {
let i := 0
} 1 {
} {
mstore(add(i, i), mul(t, byte(i, hashed)))
i := add(i, 1)
if eq(i, 20) {
break
}
}
mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask)))))
o := add(o, 0x20)
mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask)))))
}
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
function toHexString(address value) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value);
/// @solidity memory-safe-assembly
assembly {
let strLength := add(mload(str), 2) // Compute the length.
mstore(str, 0x3078) // Write the "0x" prefix.
str := sub(str, 2) // Move the pointer.
mstore(str, strLength) // Write the length.
}
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output is encoded using 2 hexadecimal digits per byte.
function toHexStringNoPrefix(address value) internal pure returns (string memory str) {
/// @solidity memory-safe-assembly
assembly {
str := mload(0x40)
// Allocate the memory.
// We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
// 0x02 bytes for the prefix, and 0x28 bytes for the digits.
// The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80.
mstore(0x40, add(str, 0x80))
// Store "0123456789abcdef" in scratch space.
mstore(0x0f, 0x30313233343536373839616263646566)
str := add(str, 2)
mstore(str, 40)
let o := add(str, 0x20)
mstore(add(o, 40), 0)
value := shl(96, value)
// We write the string from rightmost digit to leftmost digit.
// The following is essentially a do-while loop that also handles the zero case.
for {
let i := 0
} 1 {
} {
let p := add(o, add(i, i))
let temp := byte(i, value)
mstore8(add(p, 1), mload(and(temp, 15)))
mstore8(p, mload(shr(4, temp)))
i := add(i, 1)
if eq(i, 20) {
break
}
}
}
}
/// @dev Returns the hex encoded string from the raw bytes.
/// The output is encoded using 2 hexadecimal digits per byte.
function toHexString(bytes memory raw) internal pure returns (string memory str) {
str = toHexStringNoPrefix(raw);
/// @solidity memory-safe-assembly
assembly {
let strLength := add(mload(str), 2) // Compute the length.
mstore(str, 0x3078) // Write the "0x" prefix.
str := sub(str, 2) // Move the pointer.
mstore(str, strLength) // Write the length.
}
}
/// @dev Returns the hex encoded string from the raw bytes.
/// The output is encoded using 2 hexadecimal digits per byte.
function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) {
/// @solidity memory-safe-assembly
assembly {
let length := mload(raw)
str := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix.
mstore(str, add(length, length)) // Store the length of the output.
// Store "0123456789abcdef" in scratch space.
mstore(0x0f, 0x30313233343536373839616263646566)
let o := add(str, 0x20)
let end := add(raw, length)
for {
} iszero(eq(raw, end)) {
} {
raw := add(raw, 1)
mstore8(add(o, 1), mload(and(mload(raw), 15)))
mstore8(o, mload(and(shr(4, mload(raw)), 15)))
o := add(o, 2)
}
mstore(o, 0) // Zeroize the slot after the string.
mstore(0x40, add(o, 0x20)) // Allocate the memory.
}
}
}// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./utils/Bytecode.sol"; /** @title A key-value storage with auto-generated keys for storing chunks of data with a lower write & read cost. @author Agustin Aguilar <[email protected]> Readme: https://github.com/0xsequence/sstore2#readme */ library SSTORE2 { error WriteError(); /** @notice Stores `_data` and returns `pointer` as key for later retrieval @dev The pointer is a contract address with `_data` as code @param _data to be written @return pointer Pointer to the written `_data` */ function write(bytes memory _data) internal returns (address pointer) { // Append 00 to _data so contract can't be called // Build init code bytes memory code = Bytecode.creationCodeFor( abi.encodePacked( hex'00', _data ) ); // Deploy contract using create assembly { pointer := create(0, add(code, 32), mload(code)) } // Address MUST be non-zero if (pointer == address(0)) revert WriteError(); } /** @notice Reads the contents of the `_pointer` code as data, skips the first byte @dev The function is intended for reading pointers generated by `write` @param _pointer to be read @return data read from `_pointer` contract */ function read(address _pointer) internal view returns (bytes memory) { return Bytecode.codeAt(_pointer, 1, type(uint256).max); } /** @notice Reads the contents of the `_pointer` code as data, skips the first byte @dev The function is intended for reading pointers generated by `write` @param _pointer to be read @param _start number of bytes to skip @return data read from `_pointer` contract */ function read(address _pointer, uint256 _start) internal view returns (bytes memory) { return Bytecode.codeAt(_pointer, _start + 1, type(uint256).max); } /** @notice Reads the contents of the `_pointer` code as data, skips the first byte @dev The function is intended for reading pointers generated by `write` @param _pointer to be read @param _start number of bytes to skip @param _end index before which to end extraction @return data read from `_pointer` contract */ function read(address _pointer, uint256 _start, uint256 _end) internal view returns (bytes memory) { return Bytecode.codeAt(_pointer, _start + 1, _end + 1); } }
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library Bytecode {
error InvalidCodeAtRange(uint256 _size, uint256 _start, uint256 _end);
/**
@notice Generate a creation code that results on a contract with `_code` as bytecode
@param _code The returning value of the resulting `creationCode`
@return creationCode (constructor) for new contract
*/
function creationCodeFor(bytes memory _code) internal pure returns (bytes memory) {
/*
0x00 0x63 0x63XXXXXX PUSH4 _code.length size
0x01 0x80 0x80 DUP1 size size
0x02 0x60 0x600e PUSH1 14 14 size size
0x03 0x60 0x6000 PUSH1 00 0 14 size size
0x04 0x39 0x39 CODECOPY size
0x05 0x60 0x6000 PUSH1 00 0 size
0x06 0xf3 0xf3 RETURN
<CODE>
*/
return abi.encodePacked(
hex"63",
uint32(_code.length),
hex"80_60_0E_60_00_39_60_00_F3",
_code
);
}
/**
@notice Returns the size of the code on a given address
@param _addr Address that may or may not contain code
@return size of the code on the given `_addr`
*/
function codeSize(address _addr) internal view returns (uint256 size) {
assembly { size := extcodesize(_addr) }
}
/**
@notice Returns the code of a given address
@dev It will fail if `_end < _start`
@param _addr Address that may or may not contain code
@param _start number of bytes of code to skip on read
@param _end index before which to end extraction
@return oCode read from `_addr` deployed bytecode
Forked from: https://gist.github.com/KardanovIR/fe98661df9338c842b4a30306d507fbd
*/
function codeAt(address _addr, uint256 _start, uint256 _end) internal view returns (bytes memory oCode) {
uint256 csize = codeSize(_addr);
if (csize == 0) return bytes("");
if (_start > csize) return bytes("");
if (_end < _start) revert InvalidCodeAtRange(csize, _start, _end);
unchecked {
uint256 reqSize = _end - _start;
uint256 maxSize = csize - _start;
uint256 size = maxSize < reqSize ? maxSize : reqSize;
assembly {
// allocate output byte array - this could also be done without assembly
// by using o_code = new bytes(size)
oCode := mload(0x40)
// new "memory end" including padding
mstore(0x40, add(oCode, and(add(add(size, 0x20), 0x1f), not(0x1f))))
// store length in memory
mstore(oCode, size)
// actually retrieve the code, this needs assembly
extcodecopy(_addr, add(oCode, 0x20), _start, size)
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../interface/IRouter.sol";
/// @title ERC-7504 Dynamic Contracts: Router.
/// @author thirdweb (https://github.com/thirdweb-dev/dynamic-contracts)
/// @notice Routes an incoming call to an appropriate implementation address.
abstract contract Router is IRouter {
/**
* @notice delegateCalls the appropriate implementation address for the given incoming function call.
* @dev The implementation address to delegateCall MUST be retrieved from calling `getImplementationForFunction` with the
* incoming call's function selector.
*/
fallback() external payable virtual {
if(msg.data.length == 0) return;
address implementation = getImplementationForFunction(msg.sig);
require(implementation != address(0), "Router: function does not exist.");
_delegate(implementation);
}
/// @dev delegateCalls an `implementation` smart contract.
function _delegate(address implementation) internal virtual {
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
/**
* @notice Returns the implementation address to delegateCall for the given function selector.
* @param _functionSelector The function selector to get the implementation address for.
* @return implementation The implementation address to delegateCall for the given function selector.
*/
function getImplementationForFunction(bytes4 _functionSelector) public view virtual returns (address implementation);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title IExtension
/// @author thirdweb (https://github.com/thirdweb-dev/dynamic-contracts)
/// @notice Provides an `Extension` abstraction for a router's implementation contracts.
interface IExtension {
/*///////////////////////////////////////////////////////////////
Structs
//////////////////////////////////////////////////////////////*/
/**
* @notice An interface to describe an extension's metadata.
*
* @param name The unique name of the extension.
* @param metadataURI The URI where the metadata for the extension lives.
* @param implementation The implementation smart contract address of the extension.
*/
struct ExtensionMetadata {
string name;
string metadataURI;
address implementation;
}
/**
* @notice An interface to describe an extension's function.
*
* @param functionSelector The 4 byte selector of the function.
* @param functionSignature Function signature as a string. E.g. "transfer(address,address,uint256)"
*/
struct ExtensionFunction {
bytes4 functionSelector;
string functionSignature;
}
/**
* @notice An interface to describe an extension.
*
* @param metadata The extension's metadata; it's name, metadata URI and implementation contract address.
* @param functions The functions that belong to the extension.
*/
struct Extension {
ExtensionMetadata metadata;
ExtensionFunction[] functions;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IExtension.sol";
/// @title IExtensionManager
/// @author thirdweb (https://github.com/thirdweb-dev/dynamic-contracts)
/// @notice Defined storage and API for managing a router's extensions.
interface IExtensionManager is IExtension {
/*///////////////////////////////////////////////////////////////
Events
//////////////////////////////////////////////////////////////*/
/// @dev Emitted when a extension is added.
event ExtensionAdded(string indexed name, address indexed implementation, Extension extension);
/// @dev Emitted when a extension is replaced.
event ExtensionReplaced(string indexed name, address indexed implementation, Extension extension);
/// @dev Emitted when a extension is removed.
event ExtensionRemoved(string indexed name, Extension extension);
/// @dev Emitted when a function is enabled i.e. made callable.
event FunctionEnabled(string indexed name, bytes4 indexed functionSelector, ExtensionFunction extFunction, ExtensionMetadata extMetadata);
/// @dev Emitted when a function is disabled i.e. made un-callable.
event FunctionDisabled(string indexed name, bytes4 indexed functionSelector, ExtensionMetadata extMetadata);
/*///////////////////////////////////////////////////////////////
External functions
//////////////////////////////////////////////////////////////*/
/**
* @notice Add a new extension to the router.
* @param extension The extension to add.
*/
function addExtension(Extension memory extension) external;
/**
* @notice Fully replace an existing extension of the router.
* @dev The extension with name `extension.name` is the extension being replaced.
* @param extension The extension to replace or overwrite.
*/
function replaceExtension(Extension memory extension) external;
/**
* @notice Remove an existing extension from the router.
* @param extensionName The name of the extension to remove.
*/
function removeExtension(string memory extensionName) external;
/**
* @notice Enables a single function in an existing extension.
* @dev Makes the given function callable on the router.
*
* @param extensionName The name of the extension to which `extFunction` belongs.
* @param extFunction The function to enable.
*/
function enableFunctionInExtension(string memory extensionName, ExtensionFunction memory extFunction) external;
/**
* @notice Disables a single function in an Extension.
*
* @param extensionName The name of the extension to which the function of `functionSelector` belongs.
* @param functionSelector The function to disable.
*/
function disableFunctionInExtension(string memory extensionName, bytes4 functionSelector) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title ERC-7504 Dynamic Contracts: IRouter.
/// @author thirdweb (https://github.com/thirdweb-dev/dynamic-contracts)
/// @notice Routes an incoming call to an appropriate implementation address.
/// @dev Fallback function delegateCalls `getImplementationForFunction(msg.sig)` for a given incoming call.
/// NOTE: The ERC-165 identifier for this interface is 0xce0b6013.
interface IRouter {
/**
* @notice delegateCalls the appropriate implementation address for the given incoming function call.
* @dev The implementation address to delegateCall MUST be retrieved from calling `getImplementationForFunction` with the
* incoming call's function selector.
*/
fallback() external payable;
/*///////////////////////////////////////////////////////////////
View Functions
//////////////////////////////////////////////////////////////*/
/**
* @notice Returns the implementation address to delegateCall for the given function selector.
* @param _functionSelector The function selector to get the implementation address for.
* @return implementation The implementation address to delegateCall for the given function selector.
*/
function getImplementationForFunction(bytes4 _functionSelector) external view returns (address implementation);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IExtension.sol";
/// @title ERC-7504 Dynamic Contracts: IRouterState.
/// @author thirdweb (https://github.com/thirdweb-dev/dynamic-contracts)
/// @notice Defines an API to expose a router's extensions.
interface IRouterState is IExtension {
/*///////////////////////////////////////////////////////////////
View Functions
//////////////////////////////////////////////////////////////*/
/**
* @notice Returns all extensions of the Router.
* @return allExtensions An array of all extensions.
*/
function getAllExtensions() external view returns (Extension[] memory allExtensions);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IExtension.sol";
/// @title IRouterStateGetters.
/// @author thirdweb (https://github.com/thirdweb-dev/dynamic-contracts)
/// @notice Helper view functions to inspect a router's state.
interface IRouterStateGetters is IExtension {
/*///////////////////////////////////////////////////////////////
View functions
//////////////////////////////////////////////////////////////*/
/**
* @notice Returns the extension metadata for a given function.
* @param functionSelector The function selector to get the extension metadata for.
* @return metadata The extension metadata for a given function.
*/
function getMetadataForFunction(bytes4 functionSelector) external view returns (ExtensionMetadata memory metadata);
/**
* @notice Returns the extension metadata and functions for a given extension.
* @param extensionName The name of the extension to get the metadata and functions for.
* @return extension The extension metadata and functions for a given extension.
*/
function getExtension(string memory extensionName) external view returns (Extension memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title BaseRouterStorage
/// @author thirdweb (https://github.com/thirdweb-dev/dynamic-contracts)
/// @notice Defined storage for base router
library BaseRouterStorage {
/// @custom:storage-location erc7201:base.router.storage
bytes32 public constant BASE_ROUTER_STORAGE_POSITION = keccak256(abi.encode(uint256(keccak256("base.router.storage")) - 1));
struct Data {
/// @dev Mapping used only for checking default extension validity in constructor.
mapping(bytes4 => bool) functionMap;
/// @dev Mapping used only for checking default extension validity in constructor.
mapping(string => bool) extensionMap;
}
/// @dev Returns access to base router storage.
function data() internal pure returns (Data storage data_) {
bytes32 position = BASE_ROUTER_STORAGE_POSITION;
assembly {
data_.slot := position
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./StringSet.sol";
import "../interface/IExtension.sol";
/// @title IExtensionManagerStorage
/// @author thirdweb (https://github.com/thirdweb-dev/dynamic-contracts)
/// @notice Defined storage for managing a router's extensions.
library ExtensionManagerStorage {
/// @custom:storage-location erc7201:extension.manager.storage
bytes32 public constant EXTENSION_MANAGER_STORAGE_POSITION = keccak256(abi.encode(uint256(keccak256("extension.manager.storage")) - 1));
struct Data {
/// @dev Set of names of all extensions of the router.
StringSet.Set extensionNames;
/// @dev Mapping from extension name => `Extension` i.e. extension metadata and functions.
mapping(string => IExtension.Extension) extensions;
/// @dev Mapping from function selector => metadata of the extension the function belongs to.
mapping(bytes4 => IExtension.ExtensionMetadata) extensionMetadata;
}
/// @dev Returns access to the extension manager's storage.
function data() internal pure returns (Data storage data_) {
bytes32 position = EXTENSION_MANAGER_STORAGE_POSITION;
assembly {
data_.slot := position
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library StringSet {
struct Set {
// Storage of set values
string[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(string => 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, string memory 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, string memory 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) {
string memory 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, string memory 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 (string memory) {
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 (string[] memory) {
return set._values;
}
/**
* @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, string memory value) internal returns (bool) {
return _add(set, 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(Set storage set, string memory value) internal returns (bool) {
return _remove(set, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Set storage set, string memory value) internal view returns (bool) {
return _contains(set, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Set storage set) internal view returns (uint256) {
return _length(set);
}
/**
* @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) internal view returns (string memory) {
return _at(set, 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) internal view returns (string[] memory) {
return _values(set);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Router, IRouter } from "../core/Router.sol";
import { IRouterState } from "../interface/IRouterState.sol";
import { IRouterStateGetters } from "../interface/IRouterStateGetters.sol";
import { BaseRouterStorage } from "../lib/BaseRouterStorage.sol";
import { ExtensionManager } from "./ExtensionManager.sol";
import { StringSet } from "../lib/StringSet.sol";
import "lib/sstore2/contracts/SSTORE2.sol";
/// @title BaseRouter
/// @author thirdweb (https://github.com/thirdweb-dev/dynamic-contracts)
/// @notice A router with an API to manage its extensions.
abstract contract BaseRouter is Router, ExtensionManager {
using StringSet for StringSet.Set;
/// @notice The address where the router's default extension set is stored.
address public immutable defaultExtensions;
/// @notice Initialize the Router with a set of default extensions.
constructor(Extension[] memory _extensions) {
address pointer;
if(_extensions.length > 0) {
_validateExtensions(_extensions);
pointer = SSTORE2.write(abi.encode(_extensions));
}
defaultExtensions = pointer;
}
/// @notice Initialize the Router with a set of default extensions.
function __BaseRouter_init() internal {
if(defaultExtensions == address(0)) {
return;
}
bytes memory data = SSTORE2.read(defaultExtensions);
Extension[] memory defaults = abi.decode(data, (Extension[]));
// Unchecked since we already validated extensions in constructor.
__BaseRouter_init_unchecked(defaults);
}
/// @notice Initializes the Router with a set of extensions.
function __BaseRouter_init_checked(Extension[] memory _extensions) internal {
_validateExtensions(_extensions);
__BaseRouter_init_unchecked(_extensions);
}
/// @notice Initializes the Router with a set of extensions.
function __BaseRouter_init_unchecked(Extension[] memory _extensions) internal {
for(uint256 i = 0; i < _extensions.length; i += 1) {
Extension memory extension = _extensions[i];
// Store: new extension name.
_extensionManagerStorage().extensionNames.add(extension.metadata.name);
// 1. Store: metadata for extension.
_setMetadataForExtension(extension.metadata.name, extension.metadata);
uint256 len = extension.functions.length;
for (uint256 j = 0; j < len; j += 1) {
// 2. Store: name -> extension.functions map
_extensionManagerStorage().extensions[extension.metadata.name].functions.push(extension.functions[j]);
// 3. Store: metadata for function.
_setMetadataForFunction(extension.functions[j].functionSelector, extension.metadata);
}
emit ExtensionAdded(extension.metadata.name, extension.metadata.implementation, extension);
}
}
/// @notice Returns the implementation contract address for a given function signature.
function getImplementationForFunction(bytes4 _functionSelector) public view virtual override returns (address) {
return getMetadataForFunction(_functionSelector).implementation;
}
/// @dev Validates default extensions.
function _validateExtensions(Extension[] memory _extensions) internal {
uint256 len = _extensions.length;
bool isValid = true;
for (uint256 i = 0; i < len; i += 1) {
isValid = _isValidExtension(_extensions[i]);
if(!isValid) {
break;
}
}
require(isValid, "BaseRouter: invalid extension.");
}
function _isValidExtension(Extension memory _extension) internal returns (bool isValid) {
isValid = bytes(_extension.metadata.name).length > 0 // non-empty name
&& !BaseRouterStorage.data().extensionMap[_extension.metadata.name] // unused name
&& _extension.metadata.implementation != address(0); // non-empty implementation
BaseRouterStorage.data().extensionMap[_extension.metadata.name] = true;
if(!isValid) {
return false;
}
uint256 len = _extension.functions.length;
for(uint256 i = 0; i < len; i += 1) {
if(!isValid) {
break;
}
ExtensionFunction memory _extFunction = _extension.functions[i];
/**
* Note: `bytes4(0)` is the function selector for the `receive` function.
* So, we maintain a special fn selector-signature mismatch check for the `receive` function.
**/
bool mismatch = false;
if(_extFunction.functionSelector == bytes4(0)) {
mismatch = keccak256(abi.encode(_extFunction.functionSignature)) != keccak256(abi.encode("receive()"));
} else {
mismatch = _extFunction.functionSelector !=
bytes4(keccak256(abi.encodePacked(_extFunction.functionSignature)));
}
// No fn signature-selector mismatch and no duplicate function.
isValid = !mismatch && !BaseRouterStorage.data().functionMap[_extFunction.functionSelector];
BaseRouterStorage.data().functionMap[_extFunction.functionSelector] = true;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../interface/IExtensionManager.sol";
import "../interface/IRouterState.sol";
import "../interface/IRouterStateGetters.sol";
import "../lib/ExtensionManagerStorage.sol";
/// @title ExtensionManager
/// @author thirdweb (https://github.com/thirdweb-dev/dynamic-contracts)
/// @notice Defined storage and API for managing a router's extensions.
abstract contract ExtensionManager is IExtensionManager, IRouterState, IRouterStateGetters {
using StringSet for StringSet.Set;
/*///////////////////////////////////////////////////////////////
Modifier
//////////////////////////////////////////////////////////////*/
/// @notice Checks that a call to any external function is authorized.
modifier onlyAuthorizedCall() {
require(_isAuthorizedCallToUpgrade(), "ExtensionManager: unauthorized.");
_;
}
/*///////////////////////////////////////////////////////////////
View functions
//////////////////////////////////////////////////////////////*/
/**
* @notice Returns all extensions of the Router.
* @return allExtensions An array of all extensions.
*/
function getAllExtensions() external view virtual override returns (Extension[] memory allExtensions) {
string[] memory names = _extensionManagerStorage().extensionNames.values();
uint256 len = names.length;
allExtensions = new Extension[](len);
for (uint256 i = 0; i < len; i += 1) {
allExtensions[i] = _getExtension(names[i]);
}
}
/**
* @notice Returns the extension metadata for a given function.
* @param functionSelector The function selector to get the extension metadata for.
* @return metadata The extension metadata for a given function.
*/
function getMetadataForFunction(bytes4 functionSelector) public view virtual returns (ExtensionMetadata memory) {
return _extensionManagerStorage().extensionMetadata[functionSelector];
}
/**
* @notice Returns the extension metadata and functions for a given extension.
* @param extensionName The name of the extension to get the metadata and functions for.
* @return extension The extension metadata and functions for a given extension.
*/
function getExtension(string memory extensionName) public view virtual returns (Extension memory) {
return _getExtension(extensionName);
}
/*///////////////////////////////////////////////////////////////
External functions
//////////////////////////////////////////////////////////////*/
/**
* @notice Add a new extension to the router.
* @param _extension The extension to add.
*/
function addExtension(Extension memory _extension) public virtual onlyAuthorizedCall {
_addExtension(_extension);
}
/**
* @notice Fully replace an existing extension of the router.
* @dev The extension with name `extension.name` is the extension being replaced.
* @param _extension The extension to replace or overwrite.
*/
function replaceExtension(Extension memory _extension) public virtual onlyAuthorizedCall {
_replaceExtension(_extension);
}
/**
* @notice Remove an existing extension from the router.
* @param _extensionName The name of the extension to remove.
*/
function removeExtension(string memory _extensionName) public virtual onlyAuthorizedCall {
_removeExtension(_extensionName);
}
/**
* @notice Enables a single function in an existing extension.
* @dev Makes the given function callable on the router.
*
* @param _extensionName The name of the extension to which `extFunction` belongs.
* @param _function The function to enable.
*/
function enableFunctionInExtension(string memory _extensionName, ExtensionFunction memory _function) public virtual onlyAuthorizedCall {
_enableFunctionInExtension(_extensionName, _function);
}
/**
* @notice Disables a single function in an Extension.
*
* @param _extensionName The name of the extension to which the function of `functionSelector` belongs.
* @param _functionSelector The function to disable.
*/
function disableFunctionInExtension(string memory _extensionName, bytes4 _functionSelector) public virtual onlyAuthorizedCall {
_disableFunctionInExtension(_extensionName, _functionSelector);
}
/*///////////////////////////////////////////////////////////////
Internal functions
//////////////////////////////////////////////////////////////*/
/// @dev Add a new extension to the router.
function _addExtension(Extension memory _extension) internal virtual {
// Check: extension namespace must not already exist.
// Check: provided extension namespace must not be empty.
// Check: provided extension implementation must be non-zero.
// Store: new extension name.
require(_canAddExtension(_extension), "ExtensionManager: cannot add extension.");
// 1. Store: metadata for extension.
_setMetadataForExtension(_extension.metadata.name, _extension.metadata);
uint256 len = _extension.functions.length;
for (uint256 i = 0; i < len; i += 1) {
// 2. Store: function for extension.
_addToFunctionMap(_extension.metadata.name, _extension.functions[i]);
// 3. Store: metadata for function.
_setMetadataForFunction(_extension.functions[i].functionSelector, _extension.metadata);
}
emit ExtensionAdded(_extension.metadata.name, _extension.metadata.implementation, _extension);
}
/// @dev Fully replace an existing extension of the router.
function _replaceExtension(Extension memory _extension) internal virtual {
// Check: extension namespace must already exist.
// Check: provided extension implementation must be non-zero.
require(_canReplaceExtension(_extension), "ExtensionManager: cannot replace extension.");
// 1. Store: metadata for extension.
_setMetadataForExtension(_extension.metadata.name, _extension.metadata);
// 2. Delete: existing extension.functions and metadata for each function.
_removeAllFunctionsFromExtension(_extension.metadata.name);
uint256 len = _extension.functions.length;
for (uint256 i = 0; i < len; i += 1) {
// 2. Store: function for extension.
_addToFunctionMap(_extension.metadata.name, _extension.functions[i]);
// 3. Store: metadata for function.
_setMetadataForFunction(_extension.functions[i].functionSelector, _extension.metadata);
}
emit ExtensionReplaced(_extension.metadata.name, _extension.metadata.implementation, _extension);
}
/// @dev Remove an existing extension from the router.
function _removeExtension(string memory _extensionName) internal virtual {
// Check: extension namespace must already exist.
// Delete: extension namespace.
require(_canRemoveExtension(_extensionName), "ExtensionManager: cannot remove extension.");
Extension memory extension = _extensionManagerStorage().extensions[_extensionName];
// 1. Delete: metadata for extension.
_deleteMetadataForExtension(_extensionName);
// 2. Delete: existing extension.functions and metadata for each function.
_removeAllFunctionsFromExtension(_extensionName);
emit ExtensionRemoved(_extensionName, extension);
}
/// @dev Makes the given function callable on the router.
function _enableFunctionInExtension(string memory _extensionName, ExtensionFunction memory _function) internal virtual {
// Check: extension namespace must already exist.
require(_canEnableFunctionInExtension(_extensionName, _function), "ExtensionManager: cannot Store: function for extension.");
// 1. Store: function for extension.
_addToFunctionMap(_extensionName, _function);
ExtensionMetadata memory metadata = _extensionManagerStorage().extensions[_extensionName].metadata;
// 2. Store: metadata for function.
_setMetadataForFunction(_function.functionSelector, metadata);
emit FunctionEnabled(_extensionName, _function.functionSelector, _function, metadata);
}
/// @dev Disables a single function in an Extension.
function _disableFunctionInExtension(string memory _extensionName, bytes4 _functionSelector) public virtual onlyAuthorizedCall {
// Check: extension namespace must already exist.
// Check: function must be mapped to provided extension.
require(_canDisableFunctionInExtension(_extensionName, _functionSelector), "ExtensionManager: cannot remove function from extension.");
ExtensionMetadata memory extMetadata = _extensionManagerStorage().extensionMetadata[_functionSelector];
// 1. Delete: function from extension.
_deleteFromFunctionMap(_extensionName, _functionSelector);
// 2. Delete: metadata for function.
_deleteMetadataForFunction(_functionSelector);
emit FunctionDisabled(_extensionName, _functionSelector, extMetadata);
}
/// @dev Returns the Extension for a given name.
function _getExtension(string memory _extensionName) internal view returns (Extension memory) {
return _extensionManagerStorage().extensions[_extensionName];
}
/// @dev Sets the ExtensionMetadata for a given extension.
function _setMetadataForExtension(string memory _extensionName, ExtensionMetadata memory _metadata) internal {
_extensionManagerStorage().extensions[_extensionName].metadata = _metadata;
}
/// @dev Deletes the ExtensionMetadata for a given extension.
function _deleteMetadataForExtension(string memory _extensionName) internal {
delete _extensionManagerStorage().extensions[_extensionName].metadata;
}
/// @dev Sets the ExtensionMetadata for a given function.
function _setMetadataForFunction(bytes4 _functionSelector, ExtensionMetadata memory _metadata) internal {
_extensionManagerStorage().extensionMetadata[_functionSelector] = _metadata;
}
/// @dev Deletes the ExtensionMetadata for a given function.
function _deleteMetadataForFunction(bytes4 _functionSelector) internal {
delete _extensionManagerStorage().extensionMetadata[_functionSelector];
}
/// @dev Adds a function to the function map of an extension.
function _addToFunctionMap(string memory _extensionName, ExtensionFunction memory _extFunction) internal virtual {
/**
* Note: `bytes4(0)` is the function selector for the `receive` function.
* So, we maintain a special fn selector-signature mismatch check for the `receive` function.
**/
bool mismatch = false;
if(_extFunction.functionSelector == bytes4(0)) {
mismatch = keccak256(abi.encode(_extFunction.functionSignature)) != keccak256(abi.encode("receive()"));
} else {
mismatch = _extFunction.functionSelector !=
bytes4(keccak256(abi.encodePacked(_extFunction.functionSignature)));
}
// Check: function selector and signature must match.
require(
!mismatch,
"ExtensionManager: fn selector and signature mismatch."
);
// Check: function must not already be mapped to an implementation.
require(
_extensionManagerStorage().extensionMetadata[_extFunction.functionSelector].implementation == address(0),
"ExtensionManager: function impl already exists."
);
// Store: name -> extension.functions map
_extensionManagerStorage().extensions[_extensionName].functions.push(_extFunction);
}
/// @dev Deletes a function from an extension's function map.
function _deleteFromFunctionMap(string memory _extensionName, bytes4 _functionSelector) internal {
ExtensionFunction[] memory extensionFunctions = _extensionManagerStorage().extensions[_extensionName].functions;
uint256 len = extensionFunctions.length;
for (uint256 i = 0; i < len; i += 1) {
if(extensionFunctions[i].functionSelector == _functionSelector) {
// Delete: particular function from name -> extension.functions map
_extensionManagerStorage().extensions[_extensionName].functions[i] = _extensionManagerStorage().extensions[_extensionName].functions[len - 1];
_extensionManagerStorage().extensions[_extensionName].functions.pop();
break;
}
}
}
/// @dev Removes all functions from an Extension.
function _removeAllFunctionsFromExtension(string memory _extensionName) internal {
ExtensionFunction[] memory functions = _extensionManagerStorage().extensions[_extensionName].functions;
// Delete: existing name -> extension.functions map
delete _extensionManagerStorage().extensions[_extensionName].functions;
for(uint256 i = 0; i < functions.length; i += 1) {
// Delete: metadata for function.
_deleteMetadataForFunction(functions[i].functionSelector);
}
}
/// @dev Returns whether a new extension can be added in the given execution context.
function _canAddExtension(Extension memory _extension) internal virtual returns (bool) {
// Check: provided extension namespace must not be empty.
require(bytes(_extension.metadata.name).length > 0, "ExtensionManager: empty name.");
// Check: extension namespace must not already exist.
// Store: new extension name.
require(_extensionManagerStorage().extensionNames.add(_extension.metadata.name), "ExtensionManager: extension already exists.");
// Check: extension implementation must be non-zero.
require(_extension.metadata.implementation != address(0), "ExtensionManager: adding extension without implementation.");
return true;
}
/// @dev Returns whether an extension can be replaced in the given execution context.
function _canReplaceExtension(Extension memory _extension) internal virtual returns (bool) {
// Check: extension namespace must already exist.
require(_extensionManagerStorage().extensionNames.contains(_extension.metadata.name), "ExtensionManager: extension does not exist.");
// Check: extension implementation must be non-zero.
require(_extension.metadata.implementation != address(0), "ExtensionManager: adding extension without implementation.");
return true;
}
/// @dev Returns whether an extension can be removed in the given execution context.
function _canRemoveExtension(string memory _extensionName) internal virtual returns (bool) {
// Check: extension namespace must already exist.
// Delete: extension namespace.
require(_extensionManagerStorage().extensionNames.remove(_extensionName), "ExtensionManager: extension does not exist.");
return true;
}
/// @dev Returns whether a function can be enabled in an extension in the given execution context.
function _canEnableFunctionInExtension(string memory _extensionName, ExtensionFunction memory) internal view virtual returns (bool) {
// Check: extension namespace must already exist.
require(_extensionManagerStorage().extensionNames.contains(_extensionName), "ExtensionManager: extension does not exist.");
return true;
}
/// @dev Returns whether a function can be disabled in an extension in the given execution context.
function _canDisableFunctionInExtension(string memory _extensionName, bytes4 _functionSelector) internal view virtual returns (bool) {
// Check: extension namespace must already exist.
require(_extensionManagerStorage().extensionNames.contains(_extensionName), "ExtensionManager: extension does not exist.");
// Check: function must be mapped to provided extension.
require(keccak256(abi.encode(_extensionManagerStorage().extensionMetadata[_functionSelector].name)) == keccak256(abi.encode(_extensionName)), "ExtensionManager: incorrect extension.");
return true;
}
/// @dev Returns the ExtensionManager storage.
function _extensionManagerStorage() internal pure returns (ExtensionManagerStorage.Data storage data) {
data = ExtensionManagerStorage.data();
}
/// @dev To override; returns whether all relevant permission and other checks are met before any upgrade.
function _isAuthorizedCallToUpgrade() internal view virtual returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev _Available since v3.1._
*/
interface IERC1155Receiver is IERC165 {
/**
* @dev Handles the receipt of a single ERC1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol)
pragma solidity ^0.8.0;
import "./ERC1155Receiver.sol";
/**
* Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens.
*
* IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be
* stuck.
*
* @dev _Available since v3.1._
*/
contract ERC1155Holder is ERC1155Receiver {
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address,
address,
uint256[] memory,
uint256[] memory,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155BatchReceived.selector;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Receiver.sol)
pragma solidity ^0.8.0;
import "../IERC1155Receiver.sol";
import "../../../utils/introspection/ERC165.sol";
/**
* @dev _Available since v3.1._
*/
abstract contract ERC1155Receiver is ERC165, IERC1155Receiver {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
}
}// 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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/utils/ERC721Holder.sol)
pragma solidity ^0.8.0;
import "../IERC721Receiver.sol";
/**
* @dev Implementation of the {IERC721Receiver} interface.
*
* Accepts all token transfers.
* Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}.
*/
contract ERC721Holder is IERC721Receiver {
/**
* @dev See {IERC721Receiver-onERC721Received}.
*
* Always returns `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// 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);
}{
"optimizer": {
"enabled": true,
"runs": 20
},
"evmVersion": "london",
"remappings": [
":@chainlink/=lib/chainlink/",
":@ds-test/=lib/ds-test/src/",
":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
":@prb/test/=lib/prb-proxy/node_modules/@prb/test/",
":@std/=lib/forge-std/src/",
":@thirdweb-dev/dynamic-contracts/=lib/dynamic-contracts/",
":ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/",
":ERC721A/=lib/ERC721A/contracts/",
":chainlink/=lib/chainlink/contracts/",
":contracts/=contracts/",
":ds-test/=lib/ds-test/src/",
":dynamic-contracts/=lib/dynamic-contracts/src/",
":erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
":erc721a-upgradeable/=lib/ERC721A-Upgradeable/",
":erc721a/=lib/ERC721A/",
":forge-std/=lib/forge-std/src/",
":lib/sstore2/=lib/dynamic-contracts/lib/sstore2/",
":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/",
":prb-proxy/=lib/prb-proxy/src/",
":sstore2/=lib/dynamic-contracts/lib/sstore2/contracts/"
],
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"components":[{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"metadataURI","type":"string"},{"internalType":"address","name":"implementation","type":"address"}],"internalType":"struct IExtension.ExtensionMetadata","name":"metadata","type":"tuple"},{"components":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"string","name":"functionSignature","type":"string"}],"internalType":"struct IExtension.ExtensionFunction[]","name":"functions","type":"tuple[]"}],"internalType":"struct IExtension.Extension[]","name":"extensions","type":"tuple[]"},{"internalType":"address","name":"royaltyEngineAddress","type":"address"},{"internalType":"address","name":"nativeTokenWrapper","type":"address"}],"internalType":"struct MarketplaceV3.MarketplaceConstructorParams","name":"_marketplaceV3Params","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"_size","type":"uint256"},{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_end","type":"uint256"}],"name":"InvalidCodeAtRange","type":"error"},{"inputs":[],"name":"WriteError","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"prevURI","type":"string"},{"indexed":false,"internalType":"string","name":"newURI","type":"string"}],"name":"ContractURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"name","type":"string"},{"indexed":true,"internalType":"address","name":"implementation","type":"address"},{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"metadataURI","type":"string"},{"internalType":"address","name":"implementation","type":"address"}],"internalType":"struct IExtension.ExtensionMetadata","name":"metadata","type":"tuple"},{"components":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"string","name":"functionSignature","type":"string"}],"internalType":"struct IExtension.ExtensionFunction[]","name":"functions","type":"tuple[]"}],"indexed":false,"internalType":"struct IExtension.Extension","name":"extension","type":"tuple"}],"name":"ExtensionAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"name","type":"string"},{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"metadataURI","type":"string"},{"internalType":"address","name":"implementation","type":"address"}],"internalType":"struct IExtension.ExtensionMetadata","name":"metadata","type":"tuple"},{"components":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"string","name":"functionSignature","type":"string"}],"internalType":"struct IExtension.ExtensionFunction[]","name":"functions","type":"tuple[]"}],"indexed":false,"internalType":"struct IExtension.Extension","name":"extension","type":"tuple"}],"name":"ExtensionRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"name","type":"string"},{"indexed":true,"internalType":"address","name":"implementation","type":"address"},{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"metadataURI","type":"string"},{"internalType":"address","name":"implementation","type":"address"}],"internalType":"struct IExtension.ExtensionMetadata","name":"metadata","type":"tuple"},{"components":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"string","name":"functionSignature","type":"string"}],"internalType":"struct IExtension.ExtensionFunction[]","name":"functions","type":"tuple[]"}],"indexed":false,"internalType":"struct IExtension.Extension","name":"extension","type":"tuple"}],"name":"ExtensionReplaced","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"platformFeeRecipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"flatFee","type":"uint256"}],"name":"FlatPlatformFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"name","type":"string"},{"indexed":true,"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"metadataURI","type":"string"},{"internalType":"address","name":"implementation","type":"address"}],"indexed":false,"internalType":"struct IExtension.ExtensionMetadata","name":"extMetadata","type":"tuple"}],"name":"FunctionDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"name","type":"string"},{"indexed":true,"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"components":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"string","name":"functionSignature","type":"string"}],"indexed":false,"internalType":"struct IExtension.ExtensionFunction","name":"extFunction","type":"tuple"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"metadataURI","type":"string"},{"internalType":"address","name":"implementation","type":"address"}],"indexed":false,"internalType":"struct IExtension.ExtensionMetadata","name":"extMetadata","type":"tuple"}],"name":"FunctionEnabled","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":"platformFeeRecipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"platformFeeBps","type":"uint256"}],"name":"PlatformFeeInfoUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum IPlatformFee.PlatformFeeType","name":"feeType","type":"uint8"}],"name":"PlatformFeeTypeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousAddress","type":"address"},{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"RoyaltyEngineUpdated","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_extensionName","type":"string"},{"internalType":"bytes4","name":"_functionSelector","type":"bytes4"}],"name":"_disableFunctionInExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"metadataURI","type":"string"},{"internalType":"address","name":"implementation","type":"address"}],"internalType":"struct IExtension.ExtensionMetadata","name":"metadata","type":"tuple"},{"components":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"string","name":"functionSignature","type":"string"}],"internalType":"struct IExtension.ExtensionFunction[]","name":"functions","type":"tuple[]"}],"internalType":"struct IExtension.Extension","name":"_extension","type":"tuple"}],"name":"addExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractType","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"defaultExtensions","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_extensionName","type":"string"},{"internalType":"bytes4","name":"_functionSelector","type":"bytes4"}],"name":"disableFunctionInExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_extensionName","type":"string"},{"components":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"string","name":"functionSignature","type":"string"}],"internalType":"struct IExtension.ExtensionFunction","name":"_function","type":"tuple"}],"name":"enableFunctionInExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllExtensions","outputs":[{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"metadataURI","type":"string"},{"internalType":"address","name":"implementation","type":"address"}],"internalType":"struct IExtension.ExtensionMetadata","name":"metadata","type":"tuple"},{"components":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"string","name":"functionSignature","type":"string"}],"internalType":"struct IExtension.ExtensionFunction[]","name":"functions","type":"tuple[]"}],"internalType":"struct IExtension.Extension[]","name":"allExtensions","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"extensionName","type":"string"}],"name":"getExtension","outputs":[{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"metadataURI","type":"string"},{"internalType":"address","name":"implementation","type":"address"}],"internalType":"struct IExtension.ExtensionMetadata","name":"metadata","type":"tuple"},{"components":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"string","name":"functionSignature","type":"string"}],"internalType":"struct IExtension.ExtensionFunction[]","name":"functions","type":"tuple[]"}],"internalType":"struct IExtension.Extension","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFlatPlatformFeeInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_functionSelector","type":"bytes4"}],"name":"getImplementationForFunction","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"}],"name":"getMetadataForFunction","outputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"metadataURI","type":"string"},{"internalType":"address","name":"implementation","type":"address"}],"internalType":"struct IExtension.ExtensionMetadata","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPlatformFeeInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPlatformFeeType","outputs":[{"internalType":"enum IPlatformFee.PlatformFeeType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"member","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"getRoyalty","outputs":[{"internalType":"address payable[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRoyaltyEngineAddress","outputs":[{"internalType":"address","name":"royaltyEngineAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRoleWithSwitch","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_defaultAdmin","type":"address"},{"internalType":"string","name":"_contractURI","type":"string"},{"internalType":"address[]","name":"_trustedForwarders","type":"address[]"},{"internalType":"address","name":"_platformFeeRecipient","type":"address"},{"internalType":"uint16","name":"_platformFeeBps","type":"uint16"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_extensionName","type":"string"}],"name":"removeExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"metadataURI","type":"string"},{"internalType":"address","name":"implementation","type":"address"}],"internalType":"struct IExtension.ExtensionMetadata","name":"metadata","type":"tuple"},{"components":[{"internalType":"bytes4","name":"functionSelector","type":"bytes4"},{"internalType":"string","name":"functionSignature","type":"string"}],"internalType":"struct IExtension.ExtensionFunction[]","name":"functions","type":"tuple[]"}],"internalType":"struct IExtension.Extension","name":"_extension","type":"tuple"}],"name":"replaceExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_platformFeeRecipient","type":"address"},{"internalType":"uint256","name":"_flatFee","type":"uint256"}],"name":"setFlatPlatformFeeInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_platformFeeRecipient","type":"address"},{"internalType":"uint256","name":"_platformFeeBps","type":"uint256"}],"name":"setPlatformFeeInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IPlatformFee.PlatformFeeType","name":"_feeType","type":"uint8"}],"name":"setPlatformFeeType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_royaltyEngineAddress","type":"address"}],"name":"setRoyaltyEngine","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60e06040523480156200001157600080fd5b506040516200691238038062006912833981016040819052620000349162000914565b60208101518151805160009015620000815762000051826200019a565b6200007e8260405160200162000068919062000b88565b60408051601f198184030181529190526200024a565b90505b6001600160a01b039081166080528216159050806200010d57506040516301ffc9a760e01b8152636591fc0b60e11b60048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa158015620000e7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010d919062000cab565b620001725760405162461bcd60e51b815260206004820152602a60248201527f446f65736e277420737570706f72742049526f79616c7479456e67696e65563160448201526920696e7465726661636560b01b60648201526084015b60405180910390fd5b6001600160a01b0390811660a05260408201511660c05262000193620002b5565b5062000de2565b8051600160005b82811015620001f557620001d7848281518110620001c357620001c362000cd6565b6020026020010151620003b560201b60201c565b91508115620001f557620001ed60018262000d02565b9050620001a1565b5080620002455760405162461bcd60e51b815260206004820152601e60248201527f42617365526f757465723a20696e76616c696420657874656e73696f6e2e0000604482015260640162000169565b505050565b6000806200027a8360405160200162000264919062000d1e565b60408051601f1981840301815291905262000617565b90508051602082016000f091506001600160a01b038216620002af5760405163046a55db60e11b815260040160405180910390fd5b50919050565b7f322cf19c484104d3b1a9c2982ebae869ede3fa5f6c4703ca41b9a48c76ee03005460ff808216916101009004168015620003435760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840162000169565b60ff8281161015620003b1577f322cf19c484104d3b1a9c2982ebae869ede3fa5f6c4703ca41b9a48c76ee0300805460ff191660ff90811790915560408051918252517f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989181900360200190a15b5050565b8051515160009015801590620004005750620003d062000645565b600101826000015160000151604051620003eb919062000d46565b9081526040519081900360200190205460ff16155b80156200041a57508151604001516001600160a01b031615155b905060016200042862000645565b60010183600001516000015160405162000443919062000d46565b908152604051908190036020019020805491151560ff19909216919091179055806200047157506000919050565b60208201515160005b81811015620006105782156200061057600084602001518281518110620004a557620004a562000cd6565b602090810291909101015180519091506000906001600160e01b0319166200054257604051602001620004f59060208082526009908201526872656365697665282960b81b604082015260600190565b60405160208183030381529060405280519060200120826020015160405160200162000522919062000d64565b60405160208183030381529060405280519060200120141590506200058b565b60208083015160405162000557920162000d46565b604051602081830303815290604052805190602001206001600160e01b03191682600001516001600160e01b031916141590505b80158015620005c057506200059f62000645565b82516001600160e01b0319166000908152602091909152604090205460ff16155b94506001620005ce62000645565b92516001600160e01b03191660009081526020939093526040909220805460ff191692151592909217909155506200060860018262000d02565b90506200047a565b5050919050565b60608151826040516020016200062f92919062000d79565b6040516020818303038152906040529050919050565b6000806200067560017f11c19c8d567686e9e4073585fe511ac02fcfc0ce76ceba4592185bf5bec3cd1f62000dcc565b6040516020016200068891815260200190565b60408051601f19818403018152919052805160209091012092915050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715620006e157620006e1620006a6565b60405290565b604051606081016001600160401b0381118282101715620006e157620006e1620006a6565b604051601f8201601f191681016001600160401b0381118282101715620007375762000737620006a6565b604052919050565b60006001600160401b038211156200075b576200075b620006a6565b5060051b60200190565b60005b838110156200078257818101518382015260200162000768565b50506000910152565b600082601f8301126200079d57600080fd5b81516001600160401b03811115620007b957620007b9620006a6565b620007ce601f8201601f19166020016200070c565b818152846020838601011115620007e457600080fd5b620007f782602083016020870162000765565b949350505050565b80516001600160a01b03811681146200081757600080fd5b919050565b600082601f8301126200082e57600080fd5b815160206200084762000841836200073f565b6200070c565b82815260059290921b840181019181810190868411156200086757600080fd5b8286015b84811015620009095780516001600160401b03808211156200088d5760008081fd5b908801906040828b03601f1901811315620008a85760008081fd5b620008b2620006bc565b838801516001600160e01b031981168114620008ce5760008081fd5b8152908301519082821115620008e45760008081fd5b620008f48c89848701016200078b565b8189015286525050509183019183016200086b565b509695505050505050565b6000602082840312156200092757600080fd5b81516001600160401b038111156200093e57600080fd5b6060818401850312156200095157600080fd5b6200095b620006e7565b838201516001600160401b038111156200097457600080fd5b85601f828588010101126200098857600080fd5b8083860101516200099d62000841826200073f565b808282526020820191508860208460051b86898c010101011115620009c157600080fd5b602084878a0101015b60208460051b86898c0101010181101562000b215780516001600160401b03811115620009f657600080fd5b8988018601016040818c03601f1901121562000a1157600080fd5b62000a1b620006bc565b60208201516001600160401b0381111562000a3557600080fd5b60608382018e03601f1901121562000a4c57600080fd5b62000a56620006e7565b838201602001516001600160401b0381111562000a7257600080fd5b62000a858f60208386890101016200078b565b825250838201604001516001600160401b0381111562000aa457600080fd5b62000ab78f60208386890101016200078b565b60208301525062000acd606083860101620007ff565b60408281019190915290835283015190506001600160401b0381111562000af357600080fd5b62000b048d6020838601016200081c565b6020830152508085525050602083019250602081019050620009ca565b5084525062000b38915050848301602001620007ff565b602082015262000b4d604083860101620007ff565b6040820152949350505050565b6000815180845262000b7481602086016020860162000765565b601f01601f19169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b8481101562000c9c57603f19808b86030187528351805189875280516060808c8a015262000be260a08a018362000b5a565b91508c830151858a840301828b015262000bfd838262000b5a565b938d01516001600160a01b031660808b0152505050908a01518682038b88015280518083529192508a01908a830190600581901b84018c01865b8281101562000c8457858203601f19018452845180516001600160e01b03191683528e01518e83018e905262000c708e84018262000b5a565b958f0195948f019492505060010162000c37565b50998c01999750505093890193505060010162000bb0565b50919998505050505050505050565b60006020828403121562000cbe57600080fd5b8151801515811462000ccf57600080fd5b9392505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111562000d185762000d1862000cec565b92915050565b600081526000825162000d3981600185016020870162000765565b9190910160010192915050565b6000825162000d5a81846020870162000765565b9190910192915050565b60208152600062000ccf602083018462000b5a565b606360f81b815260e083901b6001600160e01b03191660018201526880600e6000396000f360b81b6005820152815160009062000dbe81600e85016020870162000765565b91909101600e019392505050565b8181038181111562000d185762000d1862000cec565b60805160a05160c051615af262000e2060003960006101ef01526000610f700152600081816103e7015281816128a601526128db0152615af26000f3fe6080604052600436106101df5760003560e01c8063a217fddf116100fe578063a217fddf14610581578063a32fa5b314610596578063aaae5633146105b6578063ac9650d8146105d6578063b6f10c7914610603578063bc197c8114610623578063c0562f6d1461064f578063c22707ee1461066f578063ca15c8731461069c578063cb2ef6f7146106bc578063ce0b6013146106df578063d45573f6146106ff578063d547741f14610736578063e05688fe14610756578063e57553da14610776578063e8a3d48514610799578063ee7d2adf146107bb578063f23a6e61146107db578063f28083c314610807578063f533b802146108295761021e565b806301ffc9a7146102a5578063150b7a02146102da5780631e7ac4881461030757806321ede03214610327578063248a9ca3146103475780632f2ff15d1461037557806336568abe14610395578063429eed80146103b5578063463c4864146103d55780634a00cc4814610421578063512cf91414610443578063572b6c05146104635780635a9ad231146104835780637e54523c146104985780638856a113146104b85780639010d07c146104d857806391d14854146104f8578063938e3d7b14610518578063a0a8e46014610538578063a0dbaefd146105545761021e565b3661021e57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461021c5761021c61451d565b005b3660000361022857005b600061023f6000356001600160e01b031916610857565b90506001600160a01b03811661029c5760405162461bcd60e51b815260206004820181905260248201527f526f757465723a2066756e6374696f6e20646f6573206e6f742065786973742e60448201526064015b60405180910390fd5b61021c8161086c565b3480156102b157600080fd5b506102c56102c0366004614549565b610895565b60405190151581526020015b60405180910390f35b3480156102e657600080fd5b506102fa6102f5366004614698565b61091d565b6040516102d19190614703565b34801561031357600080fd5b5061021c610322366004614718565b61092e565b34801561033357600080fd5b5061021c610342366004614744565b610960565b34801561035357600080fd5b50610367610362366004614761565b610a76565b6040519081526020016102d1565b34801561038157600080fd5b5061021c61039036600461477a565b610a94565b3480156103a157600080fd5b5061021c6103b036600461477a565b610b41565b3480156103c157600080fd5b5061021c6103d03660046147aa565b610bb0565b3480156103e157600080fd5b506104097f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102d1565b34801561042d57600080fd5b50610436610e27565b6040516102d1919061492f565b34801561044f57600080fd5b5061021c61045e3660046147aa565b610ef6565b34801561046f57600080fd5b506102c561047e366004614744565b610f24565b34801561048f57600080fd5b50610409610f50565b3480156104a457600080fd5b5061021c6104b3366004614718565b610f9d565b3480156104c457600080fd5b5061021c6104d33660046149ed565b610fcb565b3480156104e457600080fd5b506104096104f3366004614a50565b610ff9565b34801561050457600080fd5b506102c561051336600461477a565b611107565b34801561052457600080fd5b5061021c610533366004614a72565b61113b565b34801561054457600080fd5b50604051600381526020016102d1565b34801561056057600080fd5b5061057461056f366004614549565b611168565b6040516102d19190614aa6565b34801561058d57600080fd5b50610367600081565b3480156105a257600080fd5b506102c56105b136600461477a565b6112de565b3480156105c257600080fd5b5061021c6105d1366004614aee565b611341565b3480156105e257600080fd5b506105f66105f1366004614be4565b61157b565b6040516102d19190614c58565b34801561060f57600080fd5b5061021c61061e366004614caf565b6116ee565b34801561062f57600080fd5b506102fa61063e366004614d3a565b63bc197c8160e01b95945050505050565b34801561065b57600080fd5b5061021c61066a366004614e66565b61171b565b34801561067b57600080fd5b5061068f61068a366004614a72565b611748565b6040516102d19190614f5d565b3480156106a857600080fd5b506103676106b7366004614761565b611759565b3480156106c857600080fd5b506c4d61726b6574706c616365563360981b610367565b3480156106eb57600080fd5b506104096106fa366004614549565b610857565b34801561070b57600080fd5b506107146117f6565b604080516001600160a01b03909316835261ffff9091166020830152016102d1565b34801561074257600080fd5b5061021c61075136600461477a565b611828565b34801561076257600080fd5b5061021c610771366004614e66565b611833565b34801561078257600080fd5b5061078b611860565b6040516102d1929190614f70565b3480156107a557600080fd5b506107ae611889565b6040516102d19190614f89565b3480156107c757600080fd5b5061021c6107d6366004614a72565b611921565b3480156107e757600080fd5b506102fa6107f6366004614f9c565b63f23a6e6160e01b95945050505050565b34801561081357600080fd5b5061081c61194e565b6040516102d1919061501a565b34801561083557600080fd5b50610849610844366004615042565b611968565b6040516102d1929190615077565b600061086282611168565b6040015192915050565b3660008037600080366000845af43d6000803e80801561088b573d6000f35b3d6000fd5b505050565b60006001600160e01b03198216630271189760e51b14806108c657506001600160e01b03198216630a85bd0160e11b145b806108e157506001600160e01b0319821663ce0b601360e01b145b806108fc57506001600160e01b03198216630940198960e31b145b8061091757506301ffc9a760e01b6001600160e01b03198316145b92915050565b630a85bd0160e11b5b949350505050565b610936611b62565b6109525760405162461bcd60e51b8152600401610293906150fb565b61095c8282611b7a565b5050565b610968611b62565b6109845760405162461bcd60e51b8152600401610293906150fb565b6001600160a01b03811615801590610a0b57506040516301ffc9a760e01b81526001600160a01b038216906301ffc9a7906109ca90636591fc0b60e11b90600401614703565b602060405180830381865afa1580156109e7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0b9190615123565b610a6a5760405162461bcd60e51b815260206004820152602a60248201527f446f65736e277420737570706f72742049526f79616c7479456e67696e65563160448201526920696e7465726661636560b01b6064820152608401610293565b610a7381611c8f565b50565b6000610a80611ceb565b600092835260010160205250604090205490565b610abf610a9f611ceb565b60008481526001919091016020526040902054610aba611cf5565b611cff565b610ac7611ceb565b6000838152602091825260408082206001600160a01b0385168352909252205460ff1615610b375760405162461bcd60e51b815260206004820152601d60248201527f43616e206f6e6c79206772616e7420746f206e6f6e20686f6c646572730000006044820152606401610293565b61095c8282611d84565b806001600160a01b0316610b53611cf5565b6001600160a01b031614610ba65760405162461bcd60e51b815260206004820152601a60248201527921b0b71037b7363c903932b737bab731b2903337b91039b2b63360311b6044820152606401610293565b61095c8282611d98565b610bb8611dac565b610bd45760405162461bcd60e51b815260040161029390615145565b610bde8282611dc6565b610c4b5760405162461bcd60e51b815260206004820152603860248201527f457874656e73696f6e4d616e616765723a2063616e6e6f742072656d6f766520604482015277333ab731ba34b7b710333937b69032bc3a32b739b4b7b71760411b6064820152608401610293565b6000610c55611ec5565b6001600160e01b031983166000908152600391909101602052604090819020815160608101909252805482908290610c8c9061517c565b80601f0160208091040260200160405190810160405280929190818152602001828054610cb89061517c565b8015610d055780601f10610cda57610100808354040283529160200191610d05565b820191906000526020600020905b815481529060010190602001808311610ce857829003601f168201915b50505050508152602001600182018054610d1e9061517c565b80601f0160208091040260200160405190810160405280929190818152602001828054610d4a9061517c565b8015610d975780601f10610d6c57610100808354040283529160200191610d97565b820191906000526020600020905b815481529060010190602001808311610d7a57829003601f168201915b5050509183525050600291909101546001600160a01b03166020909101529050610dc18383611ecf565b610dca8261219c565b816001600160e01b03191683604051610de391906151b0565b60405180910390207fbb931a9651175c9c82f86afbf6ad37a9141aa8d1d42bf798739be245a12e4e8883604051610e1a9190614aa6565b60405180910390a3505050565b60606000610e3b610e36611ec5565b6121ef565b8051909150806001600160401b03811115610e5857610e5861458b565b604051908082528060200260200182016040528015610e9157816020015b610e7e614434565b815260200190600190039081610e765790505b50925060005b81811015610ef057610ec1838281518110610eb457610eb46151cc565b60200260200101516121fa565b848281518110610ed357610ed36151cc565b6020908102919091010152610ee96001826151f8565b9050610e97565b50505090565b610efe611dac565b610f1a5760405162461bcd60e51b815260040161029390615145565b61095c8282610bb0565b6000610f2e612483565b6001600160a01b03909216600090815260209290925250604090205460ff1690565b600080610f5b6124a7565b80549091506001600160a01b031680610f94577f0000000000000000000000000000000000000000000000000000000000000000610f96565b805b9250505090565b610fa5611b62565b610fc15760405162461bcd60e51b8152600401610293906150fb565b61095c82826124cb565b610fd3611dac565b610fef5760405162461bcd60e51b815260040161029390615145565b61095c828261253d565b60008061100461278c565b600085815260209190915260408120549150805b828110156110fe57600061102a61278c565b60008881526020918252604080822085835260010190925220546001600160a01b0316146110a2578482036110905761106161278c565b600087815260209182526040808220938252600190930190915220546001600160a01b03169250610917915050565b61109b6001836151f8565b91506110ec565b6110ad866000611107565b80156110d957506110bc61278c565b600087815260209182526040808220828052600201909252205481145b156110ec576110e96001836151f8565b91505b6110f76001826151f8565b9050611018565b50505092915050565b6000611111611ceb565b6000938452602090815260408085206001600160a01b039490941685529290525090205460ff1690565b611143611b62565b61115f5760405162461bcd60e51b8152600401610293906150fb565b610a7381612796565b611170614454565b611178611ec5565b6001600160e01b0319831660009081526003919091016020526040908190208151606081019092528054829082906111af9061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546111db9061517c565b80156112285780601f106111fd57610100808354040283529160200191611228565b820191906000526020600020905b81548152906001019060200180831161120b57829003601f168201915b505050505081526020016001820180546112419061517c565b80601f016020809104026020016040519081016040528092919081815260200182805461126d9061517c565b80156112ba5780601f1061128f576101008083540402835291602001916112ba565b820191906000526020600020905b81548152906001019060200180831161129d57829003601f168201915b5050509183525050600291909101546001600160a01b031660209091015292915050565b60006112e8611ceb565b600084815260209182526040808220828052909252205460ff166113385761130e611ceb565b6000848152602091825260408082206001600160a01b0386168352909252205460ff169050610917565b50600192915050565b600061134b612871565b5460ff169050600061135b612871565b54610100900460ff1690508015808015611378575060018360ff16105b80611397575061138730612895565b15801561139757508260ff166001145b6113fa5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610293565b6001611404612871565b805460ff191660ff92909216919091179055801561143d576001611426612871565b80549115156101000261ff00199092169190911790555b6114456128a4565b61144d612922565b61145686612959565b61145f87612796565b61146d858561ffff16611b7a565b611478600089611d84565b611490600080516020615a9d83398151915289611d84565b6114bb7ff94103142c1baabe9ac2b5d1487bf783de9e69cfeea9a72f5c9c94afd7877b8c6000611d84565b6114e67f86d5cf0a6bdc8d859ba3bdc97043337c82a0e609035f378e419298b6a3e00ae66000611d84565b6114fe600080516020615a9d83398151915289611d84565b611516600080516020615a9d8339815191528061298f565b8015611571576000611526612871565b80549115156101000261ff0019909216919091179055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6060816001600160401b038111156115955761159561458b565b6040519080825280602002602001820160405280156115c857816020015b60608152602001906001900390816115b35790505b50905060006115d5611cf5565b9050336001600160a01b038216141560005b848110156110fe578115611666576116443087878481811061160b5761160b6151cc565b905060200281019061161d919061520b565b8660405160200161163093929190615258565b6040516020818303038152906040526129fe565b848281518110611656576116566151cc565b60200260200101819052506116e6565b6116c83087878481811061167c5761167c6151cc565b905060200281019061168e919061520b565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506129fe92505050565b8482815181106116da576116da6151cc565b60200260200101819052505b6001016115e7565b6116f6611b62565b6117125760405162461bcd60e51b8152600401610293906150fb565b610a7381612a2a565b611723611dac565b61173f5760405162461bcd60e51b815260040161029390615145565b610a7381612a92565b611750614434565b610917826121fa565b60008061176461278c565b6000848152602091909152604081205491505b818110156117d157600061178961278c565b60008681526020918252604080822085835260010190925220546001600160a01b0316146117bf576117bc6001846151f8565b92505b6117ca6001826151f8565b9050611777565b506117dd836000611107565b156117f0576117ed6001836151f8565b91505b50919050565b600080611801612bfb565b546001600160a01b0316611813612bfb565b549093600160a01b90910461ffff1692509050565b610ba6610a9f611ceb565b61183b611dac565b6118575760405162461bcd60e51b815260040161029390615145565b610a7381612c1f565b60008061186b612bfb565b546001600160a01b031661187d612bfb565b60010154915091509091565b6060611893612d49565b805461189e9061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546118ca9061517c565b80156119175780601f106118ec57610100808354040283529160200191611917565b820191906000526020600020905b8154815290600101906020018083116118fa57829003601f168201915b5050505050905090565b611929611dac565b6119455760405162461bcd60e51b815260040161029390615145565b610a7381612d6d565b6000611958612bfb565b54600160b01b900460ff16919050565b6060806000611975610f50565b90506001600160a01b038116611ad55760405163152a902d60e11b815260048101869052602481018590526001600160a01b03871690632a55205a906044016040805180830381865afa9250505080156119ec575060408051601f3d908101601f191682019092526119e991810190615279565b60015b15611b595785811115611a3a5760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081c9bde585b1d1e48185b5bdd5b9d60521b6044820152606401610293565b604080516001808252818301909252906020808301908036833750506040805160018082528183019092529297509050602080830190803683370190505093508185600081518110611a8e57611a8e6151cc565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600081518110611ac257611ac26151cc565b6020026020010181815250505050611b59565b604051637a99dc0160e11b81526001600160a01b038781166004830152602482018790526044820186905282169063f533b802906064016000604051808303816000875af1158015611b2b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b539190810190615306565b90935091505b50935093915050565b6000611b7581611b70611cf5565b6130ab565b905090565b612710811115611bbe5760405162461bcd60e51b815260206004820152600f60248201526e45786365656473206d61782062707360881b6044820152606401610293565b6001600160a01b038216611c085760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606401610293565b80611c11612bfb565b805461ffff92909216600160a01b0261ffff60a01b1990921691909117905581611c39612bfb565b80546001600160a01b0319166001600160a01b03928316179055604051828152908316907fe2497bd806ec41a6e0dd992c29a72efc0ef8fec9092d1978fd4a1e00b2f18304906020015b60405180910390a25050565b6000611c996124a7565b80546001600160a01b038481166001600160a01b031983168117845560405193945091169182907fdb773077c54b973d26a2973b12d9e7e458768cbf218f12160d3ea5f015820ef990600090a3505050565b6000611b756130e1565b6000611b75613105565b611d07611ceb565b6000838152602091825260408082206001600160a01b0385168352909252205460ff1661095c57611d42816001600160a01b03166014613127565b611d4d836020613127565b604051602001611d5e9291906153c0565b60408051601f198184030181529082905262461bcd60e51b825261029391600401614f89565b611d8e82826132c2565b61095c8282613346565b611da28282613405565b61095c828261348a565b6000611b75600080516020615a9d833981519152336130ab565b6000611dda83611dd4611ec5565b90613519565b611df65760405162461bcd60e51b81526004016102939061542d565b82604051602001611e079190614f89565b60405160208183030381529060405280519060200120611e25611ec5565b6001600160e01b03198416600090815260039190910160209081526040918290209151611e53929101615478565b60405160208183030381529060405280519060200120146113385760405162461bcd60e51b815260206004820152602660248201527f457874656e73696f6e4d616e616765723a20696e636f727265637420657874656044820152653739b4b7b71760d11b6064820152608401610293565b6000611b75613525565b6000611ed9611ec5565b60020183604051611eea91906151b0565b9081526020016040518091039020600301805480602002602001604051908101604052809291908181526020016000905b82821015611ff85760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b03191682526001810180549293919291840191611f679061517c565b80601f0160208091040260200160405190810160405280929190818152602001828054611f939061517c565b8015611fe05780601f10611fb557610100808354040283529160200191611fe0565b820191906000526020600020905b815481529060010190602001808311611fc357829003601f168201915b50505050508152505081526020019060010190611f1b565b5050825192935060009150505b8181101561219557836001600160e01b03191683828151811061202a5761202a6151cc565b6020026020010151600001516001600160e01b031916036121835761204d611ec5565b6002018560405161205e91906151b0565b90815260405190819003602001902060030161207b600184615508565b8154811061208b5761208b6151cc565b90600052602060002090600202016120a1611ec5565b600201866040516120b291906151b0565b908152602001604051809103902060030182815481106120d4576120d46151cc565b600091825260209091208254600290920201805463ffffffff191663ffffffff90921691909117815560018082019061210f90840182615578565b5090505061211b611ec5565b6002018560405161212c91906151b0565b908152602001604051809103902060030180548061214c5761214c61564e565b600082815260208120600260001990930192830201805463ffffffff191681559061217a600183018261447e565b50509055612195565b61218e6001826151f8565b9050612005565b5050505050565b6121a4611ec5565b6001600160e01b03198216600090815260039190910160205260408120906121cc828261447e565b6121da60018301600061447e565b5060020180546001600160a01b031916905550565b606061091782613583565b612202614434565b61220a611ec5565b6002018260405161221b91906151b0565b9081526040805191829003602001822060a0830182528054909183919082019083908290829061224a9061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546122769061517c565b80156122c35780601f10612298576101008083540402835291602001916122c3565b820191906000526020600020905b8154815290600101906020018083116122a657829003601f168201915b505050505081526020016001820180546122dc9061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546123089061517c565b80156123555780601f1061232a57610100808354040283529160200191612355565b820191906000526020600020905b81548152906001019060200180831161233857829003601f168201915b5050509183525050600291909101546001600160a01b03166020918201529082526003830180546040805182850281018501909152818152938301939260009084015b828210156124755760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b031916825260018101805492939192918401916123e49061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546124109061517c565b801561245d5780601f106124325761010080835404028352916020019161245d565b820191906000526020600020905b81548152906001019060200180831161244057829003601f168201915b50505050508152505081526020019060010190612398565b505050915250909392505050565b7f82aadcdf5bea62fd30615b6c0754b644e71b6c1e8c55b71bb927ad005b504f0090565b7fc802b338f3fb784853cf3c808df5ff08335200e394ea2c687d12571a9104500090565b806124d4612bfb565b60010155816124e1612bfb565b80546001600160a01b0319166001600160a01b03929092169190911790556040517ff8086cee80709bd44c82f89dbca54115ebd05e840a88ab81df9cf5be9754eb63906125319084908490614f70565b60405180910390a15050565b6125478282613660565b6125b35760405162461bcd60e51b815260206004820152603760248201527f457874656e73696f6e4d616e616765723a2063616e6e6f742053746f72653a20604482015276333ab731ba34b7b7103337b91032bc3a32b739b4b7b71760491b6064820152608401610293565b6125bd828261368a565b60006125c7611ec5565b600201836040516125d891906151b0565b90815260408051918290036020018220606083019091528054829082906125fe9061517c565b80601f016020809104026020016040519081016040528092919081815260200182805461262a9061517c565b80156126775780601f1061264c57610100808354040283529160200191612677565b820191906000526020600020905b81548152906001019060200180831161265a57829003601f168201915b505050505081526020016001820180546126909061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546126bc9061517c565b80156127095780601f106126de57610100808354040283529160200191612709565b820191906000526020600020905b8154815290600101906020018083116126ec57829003601f168201915b5050509183525050600291909101546001600160a01b0316602090910152825190915061273690826138d8565b81600001516001600160e01b0319168360405161275391906151b0565b60405180910390207f681115194e519bda23de4da5218f3bc38f5585eab7c6b7d5fa66caa4602f574d8484604051610e1a929190615664565b6000611b7561394f565b60006127a0612d49565b80546127ab9061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546127d79061517c565b80156128245780601f106127f957610100808354040283529160200191612824565b820191906000526020600020905b81548152906001019060200180831161280757829003601f168201915b5050505050905081612834612d49565b9061283f9082615692565b507fc9c7c3fe08b88b4df9d4d47ef47d2c43d55c025a0ba88ca442580ed9e7348a168183604051612531929190615743565b7f322cf19c484104d3b1a9c2982ebae869ede3fa5f6c4703ca41b9a48c76ee030090565b6001600160a01b03163b151590565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166128d457565b60006128ff7f00000000000000000000000000000000000000000000000000000000000000006139b1565b90506000818060200190518101906129179190615877565b905061095c816139c1565b61292a612871565b54610100900460ff1661294f5760405162461bcd60e51b8152600401610293906159fc565b612957613b5f565b565b612961612871565b54610100900460ff166129865760405162461bcd60e51b8152600401610293906159fc565b610a7381613bb2565b6000612999611ceb565b600084815260019190910160205260409020549050816129b7611ceb565b600085815260019190910160205260408082209290925590518391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff91a4505050565b6060612a238383604051806060016040528060278152602001615a7660279139613c46565b9392505050565b80612a33612bfb565b805460ff60b01b1916600160b01b836001811115612a5357612a53615004565b02179055507fd246da9440709ce0dd3f4fd669abc85ada012ab9774b8ecdcc5059ba1486b9c181604051612a87919061501a565b60405180910390a150565b612a9b81613cbe565b612afb5760405162461bcd60e51b815260206004820152602b60248201527f457874656e73696f6e4d616e616765723a2063616e6e6f74207265706c61636560448201526a1032bc3a32b739b4b7b71760a91b6064820152608401610293565b80518051612b0891613d72565b805151612b1490613da9565b60208101515160005b81811015612b9557612b5483600001516000015184602001518381518110612b4757612b476151cc565b602002602001015161368a565b612b8383602001518281518110612b6d57612b6d6151cc565b60200260200101516000015184600001516138d8565b612b8e6001826151f8565b9050612b1d565b508151604080820151915190516001600160a01b0390921691612bb891906151b0565b60405180910390207f5f1ef2b136db521971a88818ce904a8e310082338afdc100212a31270664215884604051612bef9190614f5d565b60405180910390a35050565b7fc0c34308b4a2f4c5ee9af8ba82541cfb3c33b076d1fd05c65f9ce7060c64c40090565b612c2881613f52565b612c845760405162461bcd60e51b815260206004820152602760248201527f457874656e73696f6e4d616e616765723a2063616e6e6f74206164642065787460448201526632b739b4b7b71760c91b6064820152608401610293565b80518051612c9191613d72565b60208101515160005b81811015612cef57612cc483600001516000015184602001518381518110612b4757612b476151cc565b612cdd83602001518281518110612b6d57612b6d6151cc565b612ce86001826151f8565b9050612c9a565b508151604080820151915190516001600160a01b0390921691612d1291906151b0565b60405180910390207fbb37a605de78ba6bc667aeaf438d0aae8247e6f48a8fad23730e4fbbb480abf384604051612bef9190614f5d565b7f4bc804ba64359c0e35e5ed5d90ee596ecaa49a3a930ddcb1470ea0dd625da90090565b612d7681614014565b612dd55760405162461bcd60e51b815260206004820152602a60248201527f457874656e73696f6e4d616e616765723a2063616e6e6f742072656d6f76652060448201526932bc3a32b739b4b7b71760b11b6064820152608401610293565b6000612ddf611ec5565b60020182604051612df091906151b0565b9081526040805191829003602001822060a08301825280549091839190820190839082908290612e1f9061517c565b80601f0160208091040260200160405190810160405280929190818152602001828054612e4b9061517c565b8015612e985780601f10612e6d57610100808354040283529160200191612e98565b820191906000526020600020905b815481529060010190602001808311612e7b57829003601f168201915b50505050508152602001600182018054612eb19061517c565b80601f0160208091040260200160405190810160405280929190818152602001828054612edd9061517c565b8015612f2a5780601f10612eff57610100808354040283529160200191612f2a565b820191906000526020600020905b815481529060010190602001808311612f0d57829003601f168201915b5050509183525050600291909101546001600160a01b03166020918201529082526003830180546040805182850281018501909152818152938301939260009084015b8282101561304a5760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b03191682526001810180549293919291840191612fb99061517c565b80601f0160208091040260200160405190810160405280929190818152602001828054612fe59061517c565b80156130325780601f1061300757610100808354040283529160200191613032565b820191906000526020600020905b81548152906001019060200180831161301557829003601f168201915b50505050508152505081526020019060010190612f6d565b5050505081525050905061305d82614044565b61306682613da9565b8160405161307491906151b0565b60405180910390207f3169a23cec9ad1a25ab59bbe00ecf8973dd840c745775ea8877041ef5ce65bcc82604051611c839190614f5d565b6000806130b66130e1565b6000948552602090815260408086206001600160a01b03959095168652939052505090205460ff1690565b7f0a7b0f5c59907924802379ebe98cdc23e2ee7820f63d30126e10b3752010e50090565b600061311033610f24565b15613122575060131936013560601c90565b503390565b60606000613136836002615a47565b6131419060026151f8565b6001600160401b038111156131585761315861458b565b6040519080825280601f01601f191660200182016040528015613182576020820181803683370190505b509050600360fc1b8160008151811061319d5761319d6151cc565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106131cc576131cc6151cc565b60200101906001600160f81b031916908160001a90535060006131f0846002615a47565b6131fb9060016151f8565b90505b6001811115613273576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061322f5761322f6151cc565b1a60f81b828281518110613245576132456151cc565b60200101906001600160f81b031916908160001a90535060049490941c9361326c81615a5e565b90506131fe565b508315612a235760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610293565b60016132cc611ceb565b6000848152602091825260408082206001600160a01b038616835290925220805460ff1916911515919091179055613302611cf5565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600061335061278c565b600084815260209190915260409020549050600161336c61278c565b600085815260209190915260408120805490919061338b9084906151f8565b9091555082905061339a61278c565b6000858152602091825260408082208583526001019092522080546001600160a01b0319166001600160a01b0392909216919091179055806133da61278c565b6000948552602090815260408086206001600160a01b03909516865260029094019052919092205550565b61340f8282611cff565b613417611ceb565b6000838152602091825260408082206001600160a01b038516835290925220805460ff19169055613446611cf5565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600061349461278c565b6000848152602091825260408082206001600160a01b0386168352600201909252205490506134c161278c565b6000848152602091825260408082208483526001019092522080546001600160a01b03191690556134f061278c565b6000938452602090815260408085206001600160a01b0390941685526002909301905250812055565b6000612a238383614078565b60008061355360017f775b9fab5634a62bb2a682c067408edbed43efd726183d2e2af744334d47acb7615508565b60405160200161356591815260200190565b60408051601f19818403018152919052805160209091012092915050565b606081600001805480602002602001604051908101604052809291908181526020016000905b828210156136555783829060005260206000200180546135c89061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546135f49061517c565b80156136415780601f1061361657610100808354040283529160200191613641565b820191906000526020600020905b81548152906001019060200180831161362457829003601f168201915b5050505050815260200190600101906135a9565b505050509050919050565b600061366e83611dd4611ec5565b6113385760405162461bcd60e51b81526004016102939061542d565b80516000906001600160e01b031916613714576040516020016136ca9060208082526009908201526872656365697665282960b81b604082015260600190565b6040516020818303038152906040528051906020012082602001516040516020016136f59190614f89565b604051602081830303815290604052805190602001201415905061375b565b60208083015160405161372792016151b0565b604051602081830303815290604052805190602001206001600160e01b03191682600001516001600160e01b031916141590505b80156137c75760405162461bcd60e51b815260206004820152603560248201527f457874656e73696f6e4d616e616765723a20666e2073656c6563746f7220616e604482015274321039b4b3b730ba3ab9329036b4b9b6b0ba31b41760591b6064820152608401610293565b60006137d1611ec5565b83516001600160e01b031916600090815260039190910160205260409020600201546001600160a01b0316146138615760405162461bcd60e51b815260206004820152602f60248201527f457874656e73696f6e4d616e616765723a2066756e6374696f6e20696d706c2060448201526e30b63932b0b23c9032bc34b9ba399760891b6064820152608401610293565b613869611ec5565b6002018360405161387a91906151b0565b908152604051602091819003820190206003018054600180820183556000928352918390208551600290920201805463ffffffff191660e09290921c919091178155918401518492918201906138d09082615692565b505050505050565b806138e1611ec5565b6001600160e01b031984166000908152600391909101602052604090208151819061390c9082615692565b50602082015160018201906139219082615692565b5060409190910151600290910180546001600160a01b0319166001600160a01b039092169190911790555050565b60008060ff1961398060017f0c4ba382c0009cf238e4c1ca1a52f51c61e6248a70bdfb34e5ed49d5578a5c0c615508565b60405160200161399291815260200190565b60408051601f1981840301815291905280516020909101201692915050565b60606109178260016000196140a5565b60005b815181101561095c5760008282815181106139e1576139e16151cc565b60200260200101519050613a058160000151600001516139ff611ec5565b9061415a565b5080518051613a1391613d72565b60208101515160005b81811015613ae857613a2c611ec5565b600201836000015160000151604051613a4591906151b0565b908152602001604051809103902060030183602001518281518110613a6c57613a6c6151cc565b6020908102919091018101518254600180820185556000948552938390208251600290920201805463ffffffff191660e09290921c919091178155918101519092820190613aba9082615692565b505050613ad683602001518281518110612b6d57612b6d6151cc565b613ae16001826151f8565b9050613a1c565b508151604080820151915190516001600160a01b0390921691613b0b91906151b0565b60405180910390207fbb37a605de78ba6bc667aeaf438d0aae8247e6f48a8fad23730e4fbbb480abf384604051613b429190614f5d565b60405180910390a350613b5890506001826151f8565b90506139c4565b613b67612871565b54610100900460ff16613b8c5760405162461bcd60e51b8152600401610293906159fc565b60017f1d281c488dae143b6ea4122e80c65059929950b9c32f17fc57be22089d9c3b0055565b613bba612871565b54610100900460ff16613bdf5760405162461bcd60e51b8152600401610293906159fc565b60005b815181101561095c576001613bf5612483565b6000016000848481518110613c0c57613c0c6151cc565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff1916911515919091179055600101613be2565b6060600080856001600160a01b031685604051613c6391906151b0565b600060405180830381855af49150503d8060008114613c9e576040519150601f19603f3d011682016040523d82523d6000602084013e613ca3565b606091505b5091509150613cb486838387614166565b9695505050505050565b805151600090613cd090611dd4611ec5565b613cec5760405162461bcd60e51b81526004016102939061542d565b8151604001516001600160a01b0316613d6a5760405162461bcd60e51b815260206004820152603a60248201527f457874656e73696f6e4d616e616765723a20616464696e6720657874656e736960448201527937b7103bb4ba3437baba1034b6b83632b6b2b73a30ba34b7b71760311b6064820152608401610293565b506001919050565b80613d7b611ec5565b60020183604051613d8c91906151b0565b9081526040519081900360200190208151819061390c9082615692565b6000613db3611ec5565b60020182604051613dc491906151b0565b9081526020016040518091039020600301805480602002602001604051908101604052809291908181526020016000905b82821015613ed25760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b03191682526001810180549293919291840191613e419061517c565b80601f0160208091040260200160405190810160405280929190818152602001828054613e6d9061517c565b8015613eba5780601f10613e8f57610100808354040283529160200191613eba565b820191906000526020600020905b815481529060010190602001808311613e9d57829003601f168201915b50505050508152505081526020019060010190613df5565b505050509050613ee0611ec5565b60020182604051613ef191906151b0565b90815260200160405180910390206003016000613f0e91906144b8565b60005b815181101561089057613f40828281518110613f2f57613f2f6151cc565b60200260200101516000015161219c565b613f4b6001826151f8565b9050613f11565b80515151600090613fa55760405162461bcd60e51b815260206004820152601d60248201527f457874656e73696f6e4d616e616765723a20656d707479206e616d652e0000006044820152606401610293565b815151613fb4906139ff611ec5565b613cec5760405162461bcd60e51b815260206004820152602b60248201527f457874656e73696f6e4d616e616765723a20657874656e73696f6e20616c726560448201526a30b23c9032bc34b9ba399760a91b6064820152608401610293565b600061402882614022611ec5565b906141dd565b613d6a5760405162461bcd60e51b81526004016102939061542d565b61404c611ec5565b6002018160405161405d91906151b0565b90815260405190819003602001902060006121cc828261447e565b6000826001018260405161408c91906151b0565b9081526040519081900360200190205415159392505050565b6060833b60008190036140c8575050604080516020810190915260008152612a23565b808411156140e6575050604080516020810190915260008152612a23565b838310156141185760405163162544fd60e11b8152600481018290526024810185905260448101849052606401610293565b838303848203600082821061412d578261412f565b815b60408051603f8301601f19168101909152818152955090508087602087018a3c505050509392505050565b6000612a2383836141e9565b606083156141d35782516000036141cc5761418085612895565b6141cc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610293565b5081610926565b610926838361424b565b6000612a238383614275565b60006141f58383614078565b614243578254600181018455600084815260209020016142158382615692565b508254604051600185019061422b9085906151b0565b90815260405190819003602001902055506001610917565b506000610917565b81511561425b5781518083602001fd5b8060405162461bcd60e51b81526004016102939190614f89565b600080836001018360405161428a91906151b0565b90815260200160405180910390205490508060001461442a5760006142b0600183615508565b85549091506000906142c490600190615508565b90508181146143cb5760008660000182815481106142e4576142e46151cc565b9060005260206000200180546142f99061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546143259061517c565b80156143725780601f1061434757610100808354040283529160200191614372565b820191906000526020600020905b81548152906001019060200180831161435557829003601f168201915b505050505090508087600001848154811061438f5761438f6151cc565b9060005260206000200190816143a59190615692565b508387600101826040516143b991906151b0565b90815260405190819003602001902055505b85548690806143dc576143dc61564e565b6001900381819060005260206000200160006143f8919061447e565b9055856001018560405161440c91906151b0565b90815260200160405180910390206000905560019350505050610917565b6000915050610917565b6040518060400160405280614447614454565b8152602001606081525090565b6040518060600160405280606081526020016060815260200160006001600160a01b031681525090565b50805461448a9061517c565b6000825580601f1061449a575050565b601f016020900490600052602060002090810190610a7391906144d9565b5080546000825560020290600052602060002090810190610a7391906144f2565b5b808211156144ee57600081556001016144da565b5090565b808211156144ee57805463ffffffff191681556000614514600183018261447e565b506002016144f2565b634e487b7160e01b600052600160045260246000fd5b6001600160e01b031981168114610a7357600080fd5b60006020828403121561455b57600080fd5b8135612a2381614533565b6001600160a01b0381168114610a7357600080fd5b803561458681614566565b919050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156145c3576145c361458b565b60405290565b604051606081016001600160401b03811182821017156145c3576145c361458b565b604051601f8201601f191681016001600160401b03811182821017156146135761461361458b565b604052919050565b60006001600160401b038211156146345761463461458b565b50601f01601f191660200190565b600082601f83011261465357600080fd5b81356146666146618261461b565b6145eb565b81815284602083860101111561467b57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156146ae57600080fd5b84356146b981614566565b935060208501356146c981614566565b92506040850135915060608501356001600160401b038111156146eb57600080fd5b6146f787828801614642565b91505092959194509250565b6001600160e01b031991909116815260200190565b6000806040838503121561472b57600080fd5b823561473681614566565b946020939093013593505050565b60006020828403121561475657600080fd5b8135612a2381614566565b60006020828403121561477357600080fd5b5035919050565b6000806040838503121561478d57600080fd5b82359150602083013561479f81614566565b809150509250929050565b600080604083850312156147bd57600080fd5b82356001600160401b038111156147d357600080fd5b6147df85828601614642565b925050602083013561479f81614533565b60005b8381101561480b5781810151838201526020016147f3565b50506000910152565b6000815180845261482c8160208601602086016147f0565b601f01601f19169290920160200192915050565b60008151606084526148556060850182614814565b90506020830151848203602086015261486e8282614814565b6040948501516001600160a01b03169590940194909452509092915050565b63ffffffff60e01b815116825260006020820151604060208501526109266040850182614814565b60008151604084526148ca6040850182614840565b9050602080840151858303828701528281518085528385019150838160051b860101848401935060005b8281101561492257601f1987830301845261491082865161488d565b948601949386019391506001016148f4565b5098975050505050505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561498657603f198886030184526149748583516148b5565b94509285019290850190600101614958565b5092979650505050505050565b6000604082840312156149a557600080fd5b6149ad6145a1565b905081356149ba81614533565b815260208201356001600160401b038111156149d557600080fd5b6149e184828501614642565b60208301525092915050565b60008060408385031215614a0057600080fd5b82356001600160401b0380821115614a1757600080fd5b614a2386838701614642565b93506020850135915080821115614a3957600080fd5b50614a4685828601614993565b9150509250929050565b60008060408385031215614a6357600080fd5b50508035926020909101359150565b600060208284031215614a8457600080fd5b81356001600160401b03811115614a9a57600080fd5b61092684828501614642565b602081526000612a236020830184614840565b60006001600160401b03821115614ad257614ad261458b565b5060051b60200190565b803561ffff8116811461458657600080fd5b600080600080600060a08688031215614b0657600080fd5b8535614b1181614566565b94506020868101356001600160401b0380821115614b2e57600080fd5b614b3a8a838b01614642565b96506040890135915080821115614b5057600080fd5b508701601f81018913614b6257600080fd5b8035614b7061466182614ab9565b81815260059190911b8201830190838101908b831115614b8f57600080fd5b928401925b82841015614bb6578335614ba781614566565b82529284019290840190614b94565b8097505050505050614bca6060870161457b565b9150614bd860808701614adc565b90509295509295909350565b60008060208385031215614bf757600080fd5b82356001600160401b0380821115614c0e57600080fd5b818501915085601f830112614c2257600080fd5b813581811115614c3157600080fd5b8660208260051b8501011115614c4657600080fd5b60209290920196919550909350505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561498657603f19888603018452614c9d858351614814565b94509285019290850190600101614c81565b600060208284031215614cc157600080fd5b813560028110612a2357600080fd5b600082601f830112614ce157600080fd5b81356020614cf161466183614ab9565b8083825260208201915060208460051b870101935086841115614d1357600080fd5b602086015b84811015614d2f5780358352918301918301614d18565b509695505050505050565b600080600080600060a08688031215614d5257600080fd5b8535614d5d81614566565b94506020860135614d6d81614566565b935060408601356001600160401b0380821115614d8957600080fd5b614d9589838a01614cd0565b94506060880135915080821115614dab57600080fd5b614db789838a01614cd0565b93506080880135915080821115614dcd57600080fd5b50614dda88828901614642565b9150509295509295909350565b600082601f830112614df857600080fd5b81356020614e0861466183614ab9565b82815260059290921b84018101918181019086841115614e2757600080fd5b8286015b84811015614d2f5780356001600160401b03811115614e4a5760008081fd5b614e588986838b0101614993565b845250918301918301614e2b565b600060208284031215614e7857600080fd5b81356001600160401b0380821115614e8f57600080fd5b9083019060408286031215614ea357600080fd5b614eab6145a1565b823582811115614eba57600080fd5b830160608188031215614ecc57600080fd5b614ed46145c9565b813584811115614ee357600080fd5b614eef89828501614642565b825250602082013584811115614f0457600080fd5b614f1089828501614642565b60208301525060408201359150614f2682614566565b60408101919091528152602083013582811115614f4257600080fd5b614f4e87828601614de7565b60208301525095945050505050565b602081526000612a2360208301846148b5565b6001600160a01b03929092168252602082015260400190565b602081526000612a236020830184614814565b600080600080600060a08688031215614fb457600080fd5b8535614fbf81614566565b94506020860135614fcf81614566565b9350604086013592506060860135915060808601356001600160401b03811115614ff857600080fd5b614dda88828901614642565b634e487b7160e01b600052602160045260246000fd5b602081016002831061503c57634e487b7160e01b600052602160045260246000fd5b91905290565b60008060006060848603121561505757600080fd5b833561506281614566565b95602085013595506040909401359392505050565b604080825283519082018190526000906020906060840190828701845b828110156150b95781516001600160a01b031684529284019290840190600101615094565b5050508381038285015284518082528583019183019060005b818110156150ee578351835292840192918401916001016150d2565b5090979650505050505050565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b60006020828403121561513557600080fd5b81518015158114612a2357600080fd5b6020808252601f908201527f457874656e73696f6e4d616e616765723a20756e617574686f72697a65642e00604082015260600190565b600181811c9082168061519057607f821691505b6020821081036117f057634e487b7160e01b600052602260045260246000fd5b600082516151c28184602087016147f0565b9190910192915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610917576109176151e2565b6000808335601e1984360301811261522257600080fd5b8301803591506001600160401b0382111561523c57600080fd5b60200191503681900382131561525157600080fd5b9250929050565b8284823760609190911b6001600160601b0319169101908152601401919050565b6000806040838503121561528c57600080fd5b825161529781614566565b6020939093015192949293505050565b600082601f8301126152b857600080fd5b815160206152c861466183614ab9565b8083825260208201915060208460051b8701019350868411156152ea57600080fd5b602086015b84811015614d2f57805183529183019183016152ef565b6000806040838503121561531957600080fd5b82516001600160401b038082111561533057600080fd5b818501915085601f83011261534457600080fd5b8151602061535461466183614ab9565b82815260059290921b8401810191818101908984111561537357600080fd5b948201945b8386101561539a57855161538b81614566565b82529482019490820190615378565b918801519196509093505050808211156153b357600080fd5b50614a46858286016152a7565b7402832b936b4b9b9b4b7b7399d1030b1b1b7bab73a1605d1b8152600083516153f08160158501602088016147f0565b7001034b99036b4b9b9b4b733903937b6329607d1b60159184019182015283516154218160268401602088016147f0565b01602601949350505050565b6020808252602b908201527f457874656e73696f6e4d616e616765723a20657874656e73696f6e20646f657360408201526a103737ba1032bc34b9ba1760a91b606082015260800190565b600060208083526000845461548c8161517c565b80602087015260406001808416600081146154ae57600181146154ca576154fa565b60ff19851660408a0152604084151560051b8a010195506154fa565b89600052602060002060005b858110156154f15781548b82018601529083019088016154d6565b8a016040019650505b509398975050505050505050565b81810381811115610917576109176151e2565b601f821115610890576000816000526020600020601f850160051c810160208610156155445750805b601f850160051c820191505b818110156138d057828155600101615550565b600019600383901b1c191660019190911b1790565b818103615583575050565b61558d825461517c565b6001600160401b038111156155a4576155a461458b565b6155b8816155b2845461517c565b8461551b565b6000601f8211600181146155e657600083156155d45750848201545b6155de8482615563565b855550612195565b600085815260209020601f19841690600086815260209020845b838110156156205782860154825560019586019590910190602001615600565b508583101561563e5781850154600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603160045260246000fd5b604081526000615677604083018561488d565b82810360208401526156898185614840565b95945050505050565b81516001600160401b038111156156ab576156ab61458b565b6156b9816155b2845461517c565b602080601f8311600181146156e857600084156156d65750858301515b6156e08582615563565b8655506138d0565b600085815260208120601f198616915b82811015615717578886015182559484019460019091019084016156f8565b508582101561563e57939096015160001960f8600387901b161c19169092555050600190811b01905550565b6040815260006157566040830185614814565b82810360208401526156898185614814565b600082601f83011261577957600080fd5b81516157876146618261461b565b81815284602083860101111561579c57600080fd5b6109268260208301602087016147f0565b600082601f8301126157be57600080fd5b815160206157ce61466183614ab9565b82815260059290921b840181019181810190868411156157ed57600080fd5b8286015b84811015614d2f5780516001600160401b03808211156158115760008081fd5b908801906040828b03601f190181131561582b5760008081fd5b6158336145a1565b8784015161584081614533565b81529083015190828211156158555760008081fd5b6158638c8984870101615768565b8189015286525050509183019183016157f1565b60006020828403121561588957600080fd5b81516001600160401b03808211156158a057600080fd5b818401915084601f8301126158b457600080fd5b81516158c261466182614ab9565b8082825260208201915060208360051b8601019250878311156158e457600080fd5b602085015b838110156159f05780518581111561590057600080fd5b8601601f196040828c038201121561591757600080fd5b61591f6145a1565b60208301518881111561593157600080fd5b83016060818e038401121561594557600080fd5b61594d6145c9565b925060208101518981111561596157600080fd5b6159708e602083850101615768565b84525060408101518981111561598557600080fd5b6159948e602083850101615768565b602085015250606001516159a781614566565b8060408401525081815260408301519150878211156159c557600080fd5b6159d48c6020848601016157ad565b60208201528086525050506020830192506020810190506158e9565b50979650505050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b8082028115828204841417610917576109176151e2565b600081615a6d57615a6d6151e2565b50600019019056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c656455add213c41f3851b4506717b8af695a4256979dff496dcaae7789f6121331aaa2646970667358221220d0d665cd7a3a5f895033502db80e03093ab43e012c8e8bbb137fdef824939b9264736f6c63430008170033000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d23e77b7e1726577006799b7194b6ae31958a839000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000269c83b25c7b062ad0f3dbff966e444a55c72c1000000000000000000000000000000000000000000000000000000000000000134469726563744c697374696e67734c6f676963000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008c048dd77df000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002c617070726f76654275796572466f724c697374696e672875696e743235362c616464726573732c626f6f6c290000000000000000000000000000000000000000ea8f9a3c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000032617070726f766543757272656e6379466f724c697374696e672875696e743235362c616464726573732c75696e74323536290000000000000000000000000000704232dc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003762757946726f6d4c697374696e672875696e743235362c616464726573732c75696e743235362c616464726573732c75696e7432353629000000000000000000305a67a8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001663616e63656c4c697374696e672875696e743235362900000000000000000000746415b5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004d6372656174654c697374696e672828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743132382c75696e743132382c626f6f6c292900000000000000000000000000000000000000fb14079d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002863757272656e63795072696365466f724c697374696e672875696e743235362c6164647265737329000000000000000000000000000000000000000000000000c5275fb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001f676574416c6c4c697374696e67732875696e743235362c75696e74323536290031654b4d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024676574416c6c56616c69644c697374696e67732875696e743235362c75696e743235362900000000000000000000000000000000000000000000000000000000107a274a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000136765744c697374696e672875696e7432353629000000000000000000000000009cfbe2a6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002a69734275796572417070726f766564466f724c697374696e672875696e743235362c616464726573732900000000000000000000000000000000000000000000a8519047000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002d697343757272656e6379417070726f766564466f724c697374696e672875696e743235362c616464726573732900000000000000000000000000000000000000c78b616c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000f746f74616c4c697374696e67732829000000000000000000000000000000000007b6775800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000557570646174654c697374696e672875696e743235362c28616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743132382c75696e743132382c626f6f6c2929000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000076cc26705d81f5a3198a5eaf2bd370c23c67b7a40000000000000000000000000000000000000000000000000000000000000014456e676c69736841756374696f6e734c6f6769630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005e0000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000007600858e5ad000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d626964496e41756374696f6e2875696e743235362c75696e743235362900000096b5a755000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001663616e63656c41756374696f6e2875696e743235362900000000000000000000ebf05a62000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d636f6c6c65637441756374696f6e5061796f75742875696e743235362900000003a54fe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d636f6c6c65637441756374696f6e546f6b656e732875696e743235362900000016654d40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005c63726561746541756374696f6e2828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743235362c75696e7436342c75696e7436342c75696e7436342c75696e743634292900000000c291537c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001f676574416c6c41756374696f6e732875696e743235362c75696e7432353629007b0638010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024676574416c6c56616c696441756374696f6e732875696e743235362c75696e74323536290000000000000000000000000000000000000000000000000000000078bd7935000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001367657441756374696f6e2875696e7432353629000000000000000000000000006891939d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001667657457696e6e696e674269642875696e7432353629000000000000000000001389b1170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000019697341756374696f6e457870697265642875696e7432353629000000000000002eb566bd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002069734e657757696e6e696e674269642875696e743235362c75696e743235362916002f4a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000f746f74616c41756374696f6e732829000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000081b851fb4e850c5aadc00f12f147a6a27aaa66ee000000000000000000000000000000000000000000000000000000000000000b4f66666572734c6f6769630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000420c815729d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000146163636570744f666665722875696e7432353629000000000000000000000000ef706adf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001463616e63656c4f666665722875696e7432353629000000000000000000000000c1edcfbe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d676574416c6c4f66666572732875696e743235362c75696e743235362900000091940b3e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000022676574416c6c56616c69644f66666572732875696e743235362c75696e74323536290000000000000000000000000000000000000000000000000000000000004579268a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000116765744f666665722875696e7432353629000000000000000000000000000000016767fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003c6d616b654f666665722828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e74323536292900000000a9fd8ed1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000d746f74616c4f6666657273282900000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106101df5760003560e01c8063a217fddf116100fe578063a217fddf14610581578063a32fa5b314610596578063aaae5633146105b6578063ac9650d8146105d6578063b6f10c7914610603578063bc197c8114610623578063c0562f6d1461064f578063c22707ee1461066f578063ca15c8731461069c578063cb2ef6f7146106bc578063ce0b6013146106df578063d45573f6146106ff578063d547741f14610736578063e05688fe14610756578063e57553da14610776578063e8a3d48514610799578063ee7d2adf146107bb578063f23a6e61146107db578063f28083c314610807578063f533b802146108295761021e565b806301ffc9a7146102a5578063150b7a02146102da5780631e7ac4881461030757806321ede03214610327578063248a9ca3146103475780632f2ff15d1461037557806336568abe14610395578063429eed80146103b5578063463c4864146103d55780634a00cc4814610421578063512cf91414610443578063572b6c05146104635780635a9ad231146104835780637e54523c146104985780638856a113146104b85780639010d07c146104d857806391d14854146104f8578063938e3d7b14610518578063a0a8e46014610538578063a0dbaefd146105545761021e565b3661021e57336001600160a01b037f000000000000000000000000d23e77b7e1726577006799b7194b6ae31958a839161461021c5761021c61451d565b005b3660000361022857005b600061023f6000356001600160e01b031916610857565b90506001600160a01b03811661029c5760405162461bcd60e51b815260206004820181905260248201527f526f757465723a2066756e6374696f6e20646f6573206e6f742065786973742e60448201526064015b60405180910390fd5b61021c8161086c565b3480156102b157600080fd5b506102c56102c0366004614549565b610895565b60405190151581526020015b60405180910390f35b3480156102e657600080fd5b506102fa6102f5366004614698565b61091d565b6040516102d19190614703565b34801561031357600080fd5b5061021c610322366004614718565b61092e565b34801561033357600080fd5b5061021c610342366004614744565b610960565b34801561035357600080fd5b50610367610362366004614761565b610a76565b6040519081526020016102d1565b34801561038157600080fd5b5061021c61039036600461477a565b610a94565b3480156103a157600080fd5b5061021c6103b036600461477a565b610b41565b3480156103c157600080fd5b5061021c6103d03660046147aa565b610bb0565b3480156103e157600080fd5b506104097f0000000000000000000000000e3869050e7353061aff8239d24eefb0dc4d99d381565b6040516001600160a01b0390911681526020016102d1565b34801561042d57600080fd5b50610436610e27565b6040516102d1919061492f565b34801561044f57600080fd5b5061021c61045e3660046147aa565b610ef6565b34801561046f57600080fd5b506102c561047e366004614744565b610f24565b34801561048f57600080fd5b50610409610f50565b3480156104a457600080fd5b5061021c6104b3366004614718565b610f9d565b3480156104c457600080fd5b5061021c6104d33660046149ed565b610fcb565b3480156104e457600080fd5b506104096104f3366004614a50565b610ff9565b34801561050457600080fd5b506102c561051336600461477a565b611107565b34801561052457600080fd5b5061021c610533366004614a72565b61113b565b34801561054457600080fd5b50604051600381526020016102d1565b34801561056057600080fd5b5061057461056f366004614549565b611168565b6040516102d19190614aa6565b34801561058d57600080fd5b50610367600081565b3480156105a257600080fd5b506102c56105b136600461477a565b6112de565b3480156105c257600080fd5b5061021c6105d1366004614aee565b611341565b3480156105e257600080fd5b506105f66105f1366004614be4565b61157b565b6040516102d19190614c58565b34801561060f57600080fd5b5061021c61061e366004614caf565b6116ee565b34801561062f57600080fd5b506102fa61063e366004614d3a565b63bc197c8160e01b95945050505050565b34801561065b57600080fd5b5061021c61066a366004614e66565b61171b565b34801561067b57600080fd5b5061068f61068a366004614a72565b611748565b6040516102d19190614f5d565b3480156106a857600080fd5b506103676106b7366004614761565b611759565b3480156106c857600080fd5b506c4d61726b6574706c616365563360981b610367565b3480156106eb57600080fd5b506104096106fa366004614549565b610857565b34801561070b57600080fd5b506107146117f6565b604080516001600160a01b03909316835261ffff9091166020830152016102d1565b34801561074257600080fd5b5061021c61075136600461477a565b611828565b34801561076257600080fd5b5061021c610771366004614e66565b611833565b34801561078257600080fd5b5061078b611860565b6040516102d1929190614f70565b3480156107a557600080fd5b506107ae611889565b6040516102d19190614f89565b3480156107c757600080fd5b5061021c6107d6366004614a72565b611921565b3480156107e757600080fd5b506102fa6107f6366004614f9c565b63f23a6e6160e01b95945050505050565b34801561081357600080fd5b5061081c61194e565b6040516102d1919061501a565b34801561083557600080fd5b50610849610844366004615042565b611968565b6040516102d1929190615077565b600061086282611168565b6040015192915050565b3660008037600080366000845af43d6000803e80801561088b573d6000f35b3d6000fd5b505050565b60006001600160e01b03198216630271189760e51b14806108c657506001600160e01b03198216630a85bd0160e11b145b806108e157506001600160e01b0319821663ce0b601360e01b145b806108fc57506001600160e01b03198216630940198960e31b145b8061091757506301ffc9a760e01b6001600160e01b03198316145b92915050565b630a85bd0160e11b5b949350505050565b610936611b62565b6109525760405162461bcd60e51b8152600401610293906150fb565b61095c8282611b7a565b5050565b610968611b62565b6109845760405162461bcd60e51b8152600401610293906150fb565b6001600160a01b03811615801590610a0b57506040516301ffc9a760e01b81526001600160a01b038216906301ffc9a7906109ca90636591fc0b60e11b90600401614703565b602060405180830381865afa1580156109e7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0b9190615123565b610a6a5760405162461bcd60e51b815260206004820152602a60248201527f446f65736e277420737570706f72742049526f79616c7479456e67696e65563160448201526920696e7465726661636560b01b6064820152608401610293565b610a7381611c8f565b50565b6000610a80611ceb565b600092835260010160205250604090205490565b610abf610a9f611ceb565b60008481526001919091016020526040902054610aba611cf5565b611cff565b610ac7611ceb565b6000838152602091825260408082206001600160a01b0385168352909252205460ff1615610b375760405162461bcd60e51b815260206004820152601d60248201527f43616e206f6e6c79206772616e7420746f206e6f6e20686f6c646572730000006044820152606401610293565b61095c8282611d84565b806001600160a01b0316610b53611cf5565b6001600160a01b031614610ba65760405162461bcd60e51b815260206004820152601a60248201527921b0b71037b7363c903932b737bab731b2903337b91039b2b63360311b6044820152606401610293565b61095c8282611d98565b610bb8611dac565b610bd45760405162461bcd60e51b815260040161029390615145565b610bde8282611dc6565b610c4b5760405162461bcd60e51b815260206004820152603860248201527f457874656e73696f6e4d616e616765723a2063616e6e6f742072656d6f766520604482015277333ab731ba34b7b710333937b69032bc3a32b739b4b7b71760411b6064820152608401610293565b6000610c55611ec5565b6001600160e01b031983166000908152600391909101602052604090819020815160608101909252805482908290610c8c9061517c565b80601f0160208091040260200160405190810160405280929190818152602001828054610cb89061517c565b8015610d055780601f10610cda57610100808354040283529160200191610d05565b820191906000526020600020905b815481529060010190602001808311610ce857829003601f168201915b50505050508152602001600182018054610d1e9061517c565b80601f0160208091040260200160405190810160405280929190818152602001828054610d4a9061517c565b8015610d975780601f10610d6c57610100808354040283529160200191610d97565b820191906000526020600020905b815481529060010190602001808311610d7a57829003601f168201915b5050509183525050600291909101546001600160a01b03166020909101529050610dc18383611ecf565b610dca8261219c565b816001600160e01b03191683604051610de391906151b0565b60405180910390207fbb931a9651175c9c82f86afbf6ad37a9141aa8d1d42bf798739be245a12e4e8883604051610e1a9190614aa6565b60405180910390a3505050565b60606000610e3b610e36611ec5565b6121ef565b8051909150806001600160401b03811115610e5857610e5861458b565b604051908082528060200260200182016040528015610e9157816020015b610e7e614434565b815260200190600190039081610e765790505b50925060005b81811015610ef057610ec1838281518110610eb457610eb46151cc565b60200260200101516121fa565b848281518110610ed357610ed36151cc565b6020908102919091010152610ee96001826151f8565b9050610e97565b50505090565b610efe611dac565b610f1a5760405162461bcd60e51b815260040161029390615145565b61095c8282610bb0565b6000610f2e612483565b6001600160a01b03909216600090815260209290925250604090205460ff1690565b600080610f5b6124a7565b80549091506001600160a01b031680610f94577f0000000000000000000000000000000000000000000000000000000000000000610f96565b805b9250505090565b610fa5611b62565b610fc15760405162461bcd60e51b8152600401610293906150fb565b61095c82826124cb565b610fd3611dac565b610fef5760405162461bcd60e51b815260040161029390615145565b61095c828261253d565b60008061100461278c565b600085815260209190915260408120549150805b828110156110fe57600061102a61278c565b60008881526020918252604080822085835260010190925220546001600160a01b0316146110a2578482036110905761106161278c565b600087815260209182526040808220938252600190930190915220546001600160a01b03169250610917915050565b61109b6001836151f8565b91506110ec565b6110ad866000611107565b80156110d957506110bc61278c565b600087815260209182526040808220828052600201909252205481145b156110ec576110e96001836151f8565b91505b6110f76001826151f8565b9050611018565b50505092915050565b6000611111611ceb565b6000938452602090815260408085206001600160a01b039490941685529290525090205460ff1690565b611143611b62565b61115f5760405162461bcd60e51b8152600401610293906150fb565b610a7381612796565b611170614454565b611178611ec5565b6001600160e01b0319831660009081526003919091016020526040908190208151606081019092528054829082906111af9061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546111db9061517c565b80156112285780601f106111fd57610100808354040283529160200191611228565b820191906000526020600020905b81548152906001019060200180831161120b57829003601f168201915b505050505081526020016001820180546112419061517c565b80601f016020809104026020016040519081016040528092919081815260200182805461126d9061517c565b80156112ba5780601f1061128f576101008083540402835291602001916112ba565b820191906000526020600020905b81548152906001019060200180831161129d57829003601f168201915b5050509183525050600291909101546001600160a01b031660209091015292915050565b60006112e8611ceb565b600084815260209182526040808220828052909252205460ff166113385761130e611ceb565b6000848152602091825260408082206001600160a01b0386168352909252205460ff169050610917565b50600192915050565b600061134b612871565b5460ff169050600061135b612871565b54610100900460ff1690508015808015611378575060018360ff16105b80611397575061138730612895565b15801561139757508260ff166001145b6113fa5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610293565b6001611404612871565b805460ff191660ff92909216919091179055801561143d576001611426612871565b80549115156101000261ff00199092169190911790555b6114456128a4565b61144d612922565b61145686612959565b61145f87612796565b61146d858561ffff16611b7a565b611478600089611d84565b611490600080516020615a9d83398151915289611d84565b6114bb7ff94103142c1baabe9ac2b5d1487bf783de9e69cfeea9a72f5c9c94afd7877b8c6000611d84565b6114e67f86d5cf0a6bdc8d859ba3bdc97043337c82a0e609035f378e419298b6a3e00ae66000611d84565b6114fe600080516020615a9d83398151915289611d84565b611516600080516020615a9d8339815191528061298f565b8015611571576000611526612871565b80549115156101000261ff0019909216919091179055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6060816001600160401b038111156115955761159561458b565b6040519080825280602002602001820160405280156115c857816020015b60608152602001906001900390816115b35790505b50905060006115d5611cf5565b9050336001600160a01b038216141560005b848110156110fe578115611666576116443087878481811061160b5761160b6151cc565b905060200281019061161d919061520b565b8660405160200161163093929190615258565b6040516020818303038152906040526129fe565b848281518110611656576116566151cc565b60200260200101819052506116e6565b6116c83087878481811061167c5761167c6151cc565b905060200281019061168e919061520b565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506129fe92505050565b8482815181106116da576116da6151cc565b60200260200101819052505b6001016115e7565b6116f6611b62565b6117125760405162461bcd60e51b8152600401610293906150fb565b610a7381612a2a565b611723611dac565b61173f5760405162461bcd60e51b815260040161029390615145565b610a7381612a92565b611750614434565b610917826121fa565b60008061176461278c565b6000848152602091909152604081205491505b818110156117d157600061178961278c565b60008681526020918252604080822085835260010190925220546001600160a01b0316146117bf576117bc6001846151f8565b92505b6117ca6001826151f8565b9050611777565b506117dd836000611107565b156117f0576117ed6001836151f8565b91505b50919050565b600080611801612bfb565b546001600160a01b0316611813612bfb565b549093600160a01b90910461ffff1692509050565b610ba6610a9f611ceb565b61183b611dac565b6118575760405162461bcd60e51b815260040161029390615145565b610a7381612c1f565b60008061186b612bfb565b546001600160a01b031661187d612bfb565b60010154915091509091565b6060611893612d49565b805461189e9061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546118ca9061517c565b80156119175780601f106118ec57610100808354040283529160200191611917565b820191906000526020600020905b8154815290600101906020018083116118fa57829003601f168201915b5050505050905090565b611929611dac565b6119455760405162461bcd60e51b815260040161029390615145565b610a7381612d6d565b6000611958612bfb565b54600160b01b900460ff16919050565b6060806000611975610f50565b90506001600160a01b038116611ad55760405163152a902d60e11b815260048101869052602481018590526001600160a01b03871690632a55205a906044016040805180830381865afa9250505080156119ec575060408051601f3d908101601f191682019092526119e991810190615279565b60015b15611b595785811115611a3a5760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081c9bde585b1d1e48185b5bdd5b9d60521b6044820152606401610293565b604080516001808252818301909252906020808301908036833750506040805160018082528183019092529297509050602080830190803683370190505093508185600081518110611a8e57611a8e6151cc565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600081518110611ac257611ac26151cc565b6020026020010181815250505050611b59565b604051637a99dc0160e11b81526001600160a01b038781166004830152602482018790526044820186905282169063f533b802906064016000604051808303816000875af1158015611b2b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b539190810190615306565b90935091505b50935093915050565b6000611b7581611b70611cf5565b6130ab565b905090565b612710811115611bbe5760405162461bcd60e51b815260206004820152600f60248201526e45786365656473206d61782062707360881b6044820152606401610293565b6001600160a01b038216611c085760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606401610293565b80611c11612bfb565b805461ffff92909216600160a01b0261ffff60a01b1990921691909117905581611c39612bfb565b80546001600160a01b0319166001600160a01b03928316179055604051828152908316907fe2497bd806ec41a6e0dd992c29a72efc0ef8fec9092d1978fd4a1e00b2f18304906020015b60405180910390a25050565b6000611c996124a7565b80546001600160a01b038481166001600160a01b031983168117845560405193945091169182907fdb773077c54b973d26a2973b12d9e7e458768cbf218f12160d3ea5f015820ef990600090a3505050565b6000611b756130e1565b6000611b75613105565b611d07611ceb565b6000838152602091825260408082206001600160a01b0385168352909252205460ff1661095c57611d42816001600160a01b03166014613127565b611d4d836020613127565b604051602001611d5e9291906153c0565b60408051601f198184030181529082905262461bcd60e51b825261029391600401614f89565b611d8e82826132c2565b61095c8282613346565b611da28282613405565b61095c828261348a565b6000611b75600080516020615a9d833981519152336130ab565b6000611dda83611dd4611ec5565b90613519565b611df65760405162461bcd60e51b81526004016102939061542d565b82604051602001611e079190614f89565b60405160208183030381529060405280519060200120611e25611ec5565b6001600160e01b03198416600090815260039190910160209081526040918290209151611e53929101615478565b60405160208183030381529060405280519060200120146113385760405162461bcd60e51b815260206004820152602660248201527f457874656e73696f6e4d616e616765723a20696e636f727265637420657874656044820152653739b4b7b71760d11b6064820152608401610293565b6000611b75613525565b6000611ed9611ec5565b60020183604051611eea91906151b0565b9081526020016040518091039020600301805480602002602001604051908101604052809291908181526020016000905b82821015611ff85760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b03191682526001810180549293919291840191611f679061517c565b80601f0160208091040260200160405190810160405280929190818152602001828054611f939061517c565b8015611fe05780601f10611fb557610100808354040283529160200191611fe0565b820191906000526020600020905b815481529060010190602001808311611fc357829003601f168201915b50505050508152505081526020019060010190611f1b565b5050825192935060009150505b8181101561219557836001600160e01b03191683828151811061202a5761202a6151cc565b6020026020010151600001516001600160e01b031916036121835761204d611ec5565b6002018560405161205e91906151b0565b90815260405190819003602001902060030161207b600184615508565b8154811061208b5761208b6151cc565b90600052602060002090600202016120a1611ec5565b600201866040516120b291906151b0565b908152602001604051809103902060030182815481106120d4576120d46151cc565b600091825260209091208254600290920201805463ffffffff191663ffffffff90921691909117815560018082019061210f90840182615578565b5090505061211b611ec5565b6002018560405161212c91906151b0565b908152602001604051809103902060030180548061214c5761214c61564e565b600082815260208120600260001990930192830201805463ffffffff191681559061217a600183018261447e565b50509055612195565b61218e6001826151f8565b9050612005565b5050505050565b6121a4611ec5565b6001600160e01b03198216600090815260039190910160205260408120906121cc828261447e565b6121da60018301600061447e565b5060020180546001600160a01b031916905550565b606061091782613583565b612202614434565b61220a611ec5565b6002018260405161221b91906151b0565b9081526040805191829003602001822060a0830182528054909183919082019083908290829061224a9061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546122769061517c565b80156122c35780601f10612298576101008083540402835291602001916122c3565b820191906000526020600020905b8154815290600101906020018083116122a657829003601f168201915b505050505081526020016001820180546122dc9061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546123089061517c565b80156123555780601f1061232a57610100808354040283529160200191612355565b820191906000526020600020905b81548152906001019060200180831161233857829003601f168201915b5050509183525050600291909101546001600160a01b03166020918201529082526003830180546040805182850281018501909152818152938301939260009084015b828210156124755760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b031916825260018101805492939192918401916123e49061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546124109061517c565b801561245d5780601f106124325761010080835404028352916020019161245d565b820191906000526020600020905b81548152906001019060200180831161244057829003601f168201915b50505050508152505081526020019060010190612398565b505050915250909392505050565b7f82aadcdf5bea62fd30615b6c0754b644e71b6c1e8c55b71bb927ad005b504f0090565b7fc802b338f3fb784853cf3c808df5ff08335200e394ea2c687d12571a9104500090565b806124d4612bfb565b60010155816124e1612bfb565b80546001600160a01b0319166001600160a01b03929092169190911790556040517ff8086cee80709bd44c82f89dbca54115ebd05e840a88ab81df9cf5be9754eb63906125319084908490614f70565b60405180910390a15050565b6125478282613660565b6125b35760405162461bcd60e51b815260206004820152603760248201527f457874656e73696f6e4d616e616765723a2063616e6e6f742053746f72653a20604482015276333ab731ba34b7b7103337b91032bc3a32b739b4b7b71760491b6064820152608401610293565b6125bd828261368a565b60006125c7611ec5565b600201836040516125d891906151b0565b90815260408051918290036020018220606083019091528054829082906125fe9061517c565b80601f016020809104026020016040519081016040528092919081815260200182805461262a9061517c565b80156126775780601f1061264c57610100808354040283529160200191612677565b820191906000526020600020905b81548152906001019060200180831161265a57829003601f168201915b505050505081526020016001820180546126909061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546126bc9061517c565b80156127095780601f106126de57610100808354040283529160200191612709565b820191906000526020600020905b8154815290600101906020018083116126ec57829003601f168201915b5050509183525050600291909101546001600160a01b0316602090910152825190915061273690826138d8565b81600001516001600160e01b0319168360405161275391906151b0565b60405180910390207f681115194e519bda23de4da5218f3bc38f5585eab7c6b7d5fa66caa4602f574d8484604051610e1a929190615664565b6000611b7561394f565b60006127a0612d49565b80546127ab9061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546127d79061517c565b80156128245780601f106127f957610100808354040283529160200191612824565b820191906000526020600020905b81548152906001019060200180831161280757829003601f168201915b5050505050905081612834612d49565b9061283f9082615692565b507fc9c7c3fe08b88b4df9d4d47ef47d2c43d55c025a0ba88ca442580ed9e7348a168183604051612531929190615743565b7f322cf19c484104d3b1a9c2982ebae869ede3fa5f6c4703ca41b9a48c76ee030090565b6001600160a01b03163b151590565b7f0000000000000000000000000e3869050e7353061aff8239d24eefb0dc4d99d36001600160a01b03166128d457565b60006128ff7f0000000000000000000000000e3869050e7353061aff8239d24eefb0dc4d99d36139b1565b90506000818060200190518101906129179190615877565b905061095c816139c1565b61292a612871565b54610100900460ff1661294f5760405162461bcd60e51b8152600401610293906159fc565b612957613b5f565b565b612961612871565b54610100900460ff166129865760405162461bcd60e51b8152600401610293906159fc565b610a7381613bb2565b6000612999611ceb565b600084815260019190910160205260409020549050816129b7611ceb565b600085815260019190910160205260408082209290925590518391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff91a4505050565b6060612a238383604051806060016040528060278152602001615a7660279139613c46565b9392505050565b80612a33612bfb565b805460ff60b01b1916600160b01b836001811115612a5357612a53615004565b02179055507fd246da9440709ce0dd3f4fd669abc85ada012ab9774b8ecdcc5059ba1486b9c181604051612a87919061501a565b60405180910390a150565b612a9b81613cbe565b612afb5760405162461bcd60e51b815260206004820152602b60248201527f457874656e73696f6e4d616e616765723a2063616e6e6f74207265706c61636560448201526a1032bc3a32b739b4b7b71760a91b6064820152608401610293565b80518051612b0891613d72565b805151612b1490613da9565b60208101515160005b81811015612b9557612b5483600001516000015184602001518381518110612b4757612b476151cc565b602002602001015161368a565b612b8383602001518281518110612b6d57612b6d6151cc565b60200260200101516000015184600001516138d8565b612b8e6001826151f8565b9050612b1d565b508151604080820151915190516001600160a01b0390921691612bb891906151b0565b60405180910390207f5f1ef2b136db521971a88818ce904a8e310082338afdc100212a31270664215884604051612bef9190614f5d565b60405180910390a35050565b7fc0c34308b4a2f4c5ee9af8ba82541cfb3c33b076d1fd05c65f9ce7060c64c40090565b612c2881613f52565b612c845760405162461bcd60e51b815260206004820152602760248201527f457874656e73696f6e4d616e616765723a2063616e6e6f74206164642065787460448201526632b739b4b7b71760c91b6064820152608401610293565b80518051612c9191613d72565b60208101515160005b81811015612cef57612cc483600001516000015184602001518381518110612b4757612b476151cc565b612cdd83602001518281518110612b6d57612b6d6151cc565b612ce86001826151f8565b9050612c9a565b508151604080820151915190516001600160a01b0390921691612d1291906151b0565b60405180910390207fbb37a605de78ba6bc667aeaf438d0aae8247e6f48a8fad23730e4fbbb480abf384604051612bef9190614f5d565b7f4bc804ba64359c0e35e5ed5d90ee596ecaa49a3a930ddcb1470ea0dd625da90090565b612d7681614014565b612dd55760405162461bcd60e51b815260206004820152602a60248201527f457874656e73696f6e4d616e616765723a2063616e6e6f742072656d6f76652060448201526932bc3a32b739b4b7b71760b11b6064820152608401610293565b6000612ddf611ec5565b60020182604051612df091906151b0565b9081526040805191829003602001822060a08301825280549091839190820190839082908290612e1f9061517c565b80601f0160208091040260200160405190810160405280929190818152602001828054612e4b9061517c565b8015612e985780601f10612e6d57610100808354040283529160200191612e98565b820191906000526020600020905b815481529060010190602001808311612e7b57829003601f168201915b50505050508152602001600182018054612eb19061517c565b80601f0160208091040260200160405190810160405280929190818152602001828054612edd9061517c565b8015612f2a5780601f10612eff57610100808354040283529160200191612f2a565b820191906000526020600020905b815481529060010190602001808311612f0d57829003601f168201915b5050509183525050600291909101546001600160a01b03166020918201529082526003830180546040805182850281018501909152818152938301939260009084015b8282101561304a5760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b03191682526001810180549293919291840191612fb99061517c565b80601f0160208091040260200160405190810160405280929190818152602001828054612fe59061517c565b80156130325780601f1061300757610100808354040283529160200191613032565b820191906000526020600020905b81548152906001019060200180831161301557829003601f168201915b50505050508152505081526020019060010190612f6d565b5050505081525050905061305d82614044565b61306682613da9565b8160405161307491906151b0565b60405180910390207f3169a23cec9ad1a25ab59bbe00ecf8973dd840c745775ea8877041ef5ce65bcc82604051611c839190614f5d565b6000806130b66130e1565b6000948552602090815260408086206001600160a01b03959095168652939052505090205460ff1690565b7f0a7b0f5c59907924802379ebe98cdc23e2ee7820f63d30126e10b3752010e50090565b600061311033610f24565b15613122575060131936013560601c90565b503390565b60606000613136836002615a47565b6131419060026151f8565b6001600160401b038111156131585761315861458b565b6040519080825280601f01601f191660200182016040528015613182576020820181803683370190505b509050600360fc1b8160008151811061319d5761319d6151cc565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106131cc576131cc6151cc565b60200101906001600160f81b031916908160001a90535060006131f0846002615a47565b6131fb9060016151f8565b90505b6001811115613273576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061322f5761322f6151cc565b1a60f81b828281518110613245576132456151cc565b60200101906001600160f81b031916908160001a90535060049490941c9361326c81615a5e565b90506131fe565b508315612a235760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610293565b60016132cc611ceb565b6000848152602091825260408082206001600160a01b038616835290925220805460ff1916911515919091179055613302611cf5565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600061335061278c565b600084815260209190915260409020549050600161336c61278c565b600085815260209190915260408120805490919061338b9084906151f8565b9091555082905061339a61278c565b6000858152602091825260408082208583526001019092522080546001600160a01b0319166001600160a01b0392909216919091179055806133da61278c565b6000948552602090815260408086206001600160a01b03909516865260029094019052919092205550565b61340f8282611cff565b613417611ceb565b6000838152602091825260408082206001600160a01b038516835290925220805460ff19169055613446611cf5565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600061349461278c565b6000848152602091825260408082206001600160a01b0386168352600201909252205490506134c161278c565b6000848152602091825260408082208483526001019092522080546001600160a01b03191690556134f061278c565b6000938452602090815260408085206001600160a01b0390941685526002909301905250812055565b6000612a238383614078565b60008061355360017f775b9fab5634a62bb2a682c067408edbed43efd726183d2e2af744334d47acb7615508565b60405160200161356591815260200190565b60408051601f19818403018152919052805160209091012092915050565b606081600001805480602002602001604051908101604052809291908181526020016000905b828210156136555783829060005260206000200180546135c89061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546135f49061517c565b80156136415780601f1061361657610100808354040283529160200191613641565b820191906000526020600020905b81548152906001019060200180831161362457829003601f168201915b5050505050815260200190600101906135a9565b505050509050919050565b600061366e83611dd4611ec5565b6113385760405162461bcd60e51b81526004016102939061542d565b80516000906001600160e01b031916613714576040516020016136ca9060208082526009908201526872656365697665282960b81b604082015260600190565b6040516020818303038152906040528051906020012082602001516040516020016136f59190614f89565b604051602081830303815290604052805190602001201415905061375b565b60208083015160405161372792016151b0565b604051602081830303815290604052805190602001206001600160e01b03191682600001516001600160e01b031916141590505b80156137c75760405162461bcd60e51b815260206004820152603560248201527f457874656e73696f6e4d616e616765723a20666e2073656c6563746f7220616e604482015274321039b4b3b730ba3ab9329036b4b9b6b0ba31b41760591b6064820152608401610293565b60006137d1611ec5565b83516001600160e01b031916600090815260039190910160205260409020600201546001600160a01b0316146138615760405162461bcd60e51b815260206004820152602f60248201527f457874656e73696f6e4d616e616765723a2066756e6374696f6e20696d706c2060448201526e30b63932b0b23c9032bc34b9ba399760891b6064820152608401610293565b613869611ec5565b6002018360405161387a91906151b0565b908152604051602091819003820190206003018054600180820183556000928352918390208551600290920201805463ffffffff191660e09290921c919091178155918401518492918201906138d09082615692565b505050505050565b806138e1611ec5565b6001600160e01b031984166000908152600391909101602052604090208151819061390c9082615692565b50602082015160018201906139219082615692565b5060409190910151600290910180546001600160a01b0319166001600160a01b039092169190911790555050565b60008060ff1961398060017f0c4ba382c0009cf238e4c1ca1a52f51c61e6248a70bdfb34e5ed49d5578a5c0c615508565b60405160200161399291815260200190565b60408051601f1981840301815291905280516020909101201692915050565b60606109178260016000196140a5565b60005b815181101561095c5760008282815181106139e1576139e16151cc565b60200260200101519050613a058160000151600001516139ff611ec5565b9061415a565b5080518051613a1391613d72565b60208101515160005b81811015613ae857613a2c611ec5565b600201836000015160000151604051613a4591906151b0565b908152602001604051809103902060030183602001518281518110613a6c57613a6c6151cc565b6020908102919091018101518254600180820185556000948552938390208251600290920201805463ffffffff191660e09290921c919091178155918101519092820190613aba9082615692565b505050613ad683602001518281518110612b6d57612b6d6151cc565b613ae16001826151f8565b9050613a1c565b508151604080820151915190516001600160a01b0390921691613b0b91906151b0565b60405180910390207fbb37a605de78ba6bc667aeaf438d0aae8247e6f48a8fad23730e4fbbb480abf384604051613b429190614f5d565b60405180910390a350613b5890506001826151f8565b90506139c4565b613b67612871565b54610100900460ff16613b8c5760405162461bcd60e51b8152600401610293906159fc565b60017f1d281c488dae143b6ea4122e80c65059929950b9c32f17fc57be22089d9c3b0055565b613bba612871565b54610100900460ff16613bdf5760405162461bcd60e51b8152600401610293906159fc565b60005b815181101561095c576001613bf5612483565b6000016000848481518110613c0c57613c0c6151cc565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff1916911515919091179055600101613be2565b6060600080856001600160a01b031685604051613c6391906151b0565b600060405180830381855af49150503d8060008114613c9e576040519150601f19603f3d011682016040523d82523d6000602084013e613ca3565b606091505b5091509150613cb486838387614166565b9695505050505050565b805151600090613cd090611dd4611ec5565b613cec5760405162461bcd60e51b81526004016102939061542d565b8151604001516001600160a01b0316613d6a5760405162461bcd60e51b815260206004820152603a60248201527f457874656e73696f6e4d616e616765723a20616464696e6720657874656e736960448201527937b7103bb4ba3437baba1034b6b83632b6b2b73a30ba34b7b71760311b6064820152608401610293565b506001919050565b80613d7b611ec5565b60020183604051613d8c91906151b0565b9081526040519081900360200190208151819061390c9082615692565b6000613db3611ec5565b60020182604051613dc491906151b0565b9081526020016040518091039020600301805480602002602001604051908101604052809291908181526020016000905b82821015613ed25760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b03191682526001810180549293919291840191613e419061517c565b80601f0160208091040260200160405190810160405280929190818152602001828054613e6d9061517c565b8015613eba5780601f10613e8f57610100808354040283529160200191613eba565b820191906000526020600020905b815481529060010190602001808311613e9d57829003601f168201915b50505050508152505081526020019060010190613df5565b505050509050613ee0611ec5565b60020182604051613ef191906151b0565b90815260200160405180910390206003016000613f0e91906144b8565b60005b815181101561089057613f40828281518110613f2f57613f2f6151cc565b60200260200101516000015161219c565b613f4b6001826151f8565b9050613f11565b80515151600090613fa55760405162461bcd60e51b815260206004820152601d60248201527f457874656e73696f6e4d616e616765723a20656d707479206e616d652e0000006044820152606401610293565b815151613fb4906139ff611ec5565b613cec5760405162461bcd60e51b815260206004820152602b60248201527f457874656e73696f6e4d616e616765723a20657874656e73696f6e20616c726560448201526a30b23c9032bc34b9ba399760a91b6064820152608401610293565b600061402882614022611ec5565b906141dd565b613d6a5760405162461bcd60e51b81526004016102939061542d565b61404c611ec5565b6002018160405161405d91906151b0565b90815260405190819003602001902060006121cc828261447e565b6000826001018260405161408c91906151b0565b9081526040519081900360200190205415159392505050565b6060833b60008190036140c8575050604080516020810190915260008152612a23565b808411156140e6575050604080516020810190915260008152612a23565b838310156141185760405163162544fd60e11b8152600481018290526024810185905260448101849052606401610293565b838303848203600082821061412d578261412f565b815b60408051603f8301601f19168101909152818152955090508087602087018a3c505050509392505050565b6000612a2383836141e9565b606083156141d35782516000036141cc5761418085612895565b6141cc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610293565b5081610926565b610926838361424b565b6000612a238383614275565b60006141f58383614078565b614243578254600181018455600084815260209020016142158382615692565b508254604051600185019061422b9085906151b0565b90815260405190819003602001902055506001610917565b506000610917565b81511561425b5781518083602001fd5b8060405162461bcd60e51b81526004016102939190614f89565b600080836001018360405161428a91906151b0565b90815260200160405180910390205490508060001461442a5760006142b0600183615508565b85549091506000906142c490600190615508565b90508181146143cb5760008660000182815481106142e4576142e46151cc565b9060005260206000200180546142f99061517c565b80601f01602080910402602001604051908101604052809291908181526020018280546143259061517c565b80156143725780601f1061434757610100808354040283529160200191614372565b820191906000526020600020905b81548152906001019060200180831161435557829003601f168201915b505050505090508087600001848154811061438f5761438f6151cc565b9060005260206000200190816143a59190615692565b508387600101826040516143b991906151b0565b90815260405190819003602001902055505b85548690806143dc576143dc61564e565b6001900381819060005260206000200160006143f8919061447e565b9055856001018560405161440c91906151b0565b90815260200160405180910390206000905560019350505050610917565b6000915050610917565b6040518060400160405280614447614454565b8152602001606081525090565b6040518060600160405280606081526020016060815260200160006001600160a01b031681525090565b50805461448a9061517c565b6000825580601f1061449a575050565b601f016020900490600052602060002090810190610a7391906144d9565b5080546000825560020290600052602060002090810190610a7391906144f2565b5b808211156144ee57600081556001016144da565b5090565b808211156144ee57805463ffffffff191681556000614514600183018261447e565b506002016144f2565b634e487b7160e01b600052600160045260246000fd5b6001600160e01b031981168114610a7357600080fd5b60006020828403121561455b57600080fd5b8135612a2381614533565b6001600160a01b0381168114610a7357600080fd5b803561458681614566565b919050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156145c3576145c361458b565b60405290565b604051606081016001600160401b03811182821017156145c3576145c361458b565b604051601f8201601f191681016001600160401b03811182821017156146135761461361458b565b604052919050565b60006001600160401b038211156146345761463461458b565b50601f01601f191660200190565b600082601f83011261465357600080fd5b81356146666146618261461b565b6145eb565b81815284602083860101111561467b57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156146ae57600080fd5b84356146b981614566565b935060208501356146c981614566565b92506040850135915060608501356001600160401b038111156146eb57600080fd5b6146f787828801614642565b91505092959194509250565b6001600160e01b031991909116815260200190565b6000806040838503121561472b57600080fd5b823561473681614566565b946020939093013593505050565b60006020828403121561475657600080fd5b8135612a2381614566565b60006020828403121561477357600080fd5b5035919050565b6000806040838503121561478d57600080fd5b82359150602083013561479f81614566565b809150509250929050565b600080604083850312156147bd57600080fd5b82356001600160401b038111156147d357600080fd5b6147df85828601614642565b925050602083013561479f81614533565b60005b8381101561480b5781810151838201526020016147f3565b50506000910152565b6000815180845261482c8160208601602086016147f0565b601f01601f19169290920160200192915050565b60008151606084526148556060850182614814565b90506020830151848203602086015261486e8282614814565b6040948501516001600160a01b03169590940194909452509092915050565b63ffffffff60e01b815116825260006020820151604060208501526109266040850182614814565b60008151604084526148ca6040850182614840565b9050602080840151858303828701528281518085528385019150838160051b860101848401935060005b8281101561492257601f1987830301845261491082865161488d565b948601949386019391506001016148f4565b5098975050505050505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561498657603f198886030184526149748583516148b5565b94509285019290850190600101614958565b5092979650505050505050565b6000604082840312156149a557600080fd5b6149ad6145a1565b905081356149ba81614533565b815260208201356001600160401b038111156149d557600080fd5b6149e184828501614642565b60208301525092915050565b60008060408385031215614a0057600080fd5b82356001600160401b0380821115614a1757600080fd5b614a2386838701614642565b93506020850135915080821115614a3957600080fd5b50614a4685828601614993565b9150509250929050565b60008060408385031215614a6357600080fd5b50508035926020909101359150565b600060208284031215614a8457600080fd5b81356001600160401b03811115614a9a57600080fd5b61092684828501614642565b602081526000612a236020830184614840565b60006001600160401b03821115614ad257614ad261458b565b5060051b60200190565b803561ffff8116811461458657600080fd5b600080600080600060a08688031215614b0657600080fd5b8535614b1181614566565b94506020868101356001600160401b0380821115614b2e57600080fd5b614b3a8a838b01614642565b96506040890135915080821115614b5057600080fd5b508701601f81018913614b6257600080fd5b8035614b7061466182614ab9565b81815260059190911b8201830190838101908b831115614b8f57600080fd5b928401925b82841015614bb6578335614ba781614566565b82529284019290840190614b94565b8097505050505050614bca6060870161457b565b9150614bd860808701614adc565b90509295509295909350565b60008060208385031215614bf757600080fd5b82356001600160401b0380821115614c0e57600080fd5b818501915085601f830112614c2257600080fd5b813581811115614c3157600080fd5b8660208260051b8501011115614c4657600080fd5b60209290920196919550909350505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561498657603f19888603018452614c9d858351614814565b94509285019290850190600101614c81565b600060208284031215614cc157600080fd5b813560028110612a2357600080fd5b600082601f830112614ce157600080fd5b81356020614cf161466183614ab9565b8083825260208201915060208460051b870101935086841115614d1357600080fd5b602086015b84811015614d2f5780358352918301918301614d18565b509695505050505050565b600080600080600060a08688031215614d5257600080fd5b8535614d5d81614566565b94506020860135614d6d81614566565b935060408601356001600160401b0380821115614d8957600080fd5b614d9589838a01614cd0565b94506060880135915080821115614dab57600080fd5b614db789838a01614cd0565b93506080880135915080821115614dcd57600080fd5b50614dda88828901614642565b9150509295509295909350565b600082601f830112614df857600080fd5b81356020614e0861466183614ab9565b82815260059290921b84018101918181019086841115614e2757600080fd5b8286015b84811015614d2f5780356001600160401b03811115614e4a5760008081fd5b614e588986838b0101614993565b845250918301918301614e2b565b600060208284031215614e7857600080fd5b81356001600160401b0380821115614e8f57600080fd5b9083019060408286031215614ea357600080fd5b614eab6145a1565b823582811115614eba57600080fd5b830160608188031215614ecc57600080fd5b614ed46145c9565b813584811115614ee357600080fd5b614eef89828501614642565b825250602082013584811115614f0457600080fd5b614f1089828501614642565b60208301525060408201359150614f2682614566565b60408101919091528152602083013582811115614f4257600080fd5b614f4e87828601614de7565b60208301525095945050505050565b602081526000612a2360208301846148b5565b6001600160a01b03929092168252602082015260400190565b602081526000612a236020830184614814565b600080600080600060a08688031215614fb457600080fd5b8535614fbf81614566565b94506020860135614fcf81614566565b9350604086013592506060860135915060808601356001600160401b03811115614ff857600080fd5b614dda88828901614642565b634e487b7160e01b600052602160045260246000fd5b602081016002831061503c57634e487b7160e01b600052602160045260246000fd5b91905290565b60008060006060848603121561505757600080fd5b833561506281614566565b95602085013595506040909401359392505050565b604080825283519082018190526000906020906060840190828701845b828110156150b95781516001600160a01b031684529284019290840190600101615094565b5050508381038285015284518082528583019183019060005b818110156150ee578351835292840192918401916001016150d2565b5090979650505050505050565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b60006020828403121561513557600080fd5b81518015158114612a2357600080fd5b6020808252601f908201527f457874656e73696f6e4d616e616765723a20756e617574686f72697a65642e00604082015260600190565b600181811c9082168061519057607f821691505b6020821081036117f057634e487b7160e01b600052602260045260246000fd5b600082516151c28184602087016147f0565b9190910192915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610917576109176151e2565b6000808335601e1984360301811261522257600080fd5b8301803591506001600160401b0382111561523c57600080fd5b60200191503681900382131561525157600080fd5b9250929050565b8284823760609190911b6001600160601b0319169101908152601401919050565b6000806040838503121561528c57600080fd5b825161529781614566565b6020939093015192949293505050565b600082601f8301126152b857600080fd5b815160206152c861466183614ab9565b8083825260208201915060208460051b8701019350868411156152ea57600080fd5b602086015b84811015614d2f57805183529183019183016152ef565b6000806040838503121561531957600080fd5b82516001600160401b038082111561533057600080fd5b818501915085601f83011261534457600080fd5b8151602061535461466183614ab9565b82815260059290921b8401810191818101908984111561537357600080fd5b948201945b8386101561539a57855161538b81614566565b82529482019490820190615378565b918801519196509093505050808211156153b357600080fd5b50614a46858286016152a7565b7402832b936b4b9b9b4b7b7399d1030b1b1b7bab73a1605d1b8152600083516153f08160158501602088016147f0565b7001034b99036b4b9b9b4b733903937b6329607d1b60159184019182015283516154218160268401602088016147f0565b01602601949350505050565b6020808252602b908201527f457874656e73696f6e4d616e616765723a20657874656e73696f6e20646f657360408201526a103737ba1032bc34b9ba1760a91b606082015260800190565b600060208083526000845461548c8161517c565b80602087015260406001808416600081146154ae57600181146154ca576154fa565b60ff19851660408a0152604084151560051b8a010195506154fa565b89600052602060002060005b858110156154f15781548b82018601529083019088016154d6565b8a016040019650505b509398975050505050505050565b81810381811115610917576109176151e2565b601f821115610890576000816000526020600020601f850160051c810160208610156155445750805b601f850160051c820191505b818110156138d057828155600101615550565b600019600383901b1c191660019190911b1790565b818103615583575050565b61558d825461517c565b6001600160401b038111156155a4576155a461458b565b6155b8816155b2845461517c565b8461551b565b6000601f8211600181146155e657600083156155d45750848201545b6155de8482615563565b855550612195565b600085815260209020601f19841690600086815260209020845b838110156156205782860154825560019586019590910190602001615600565b508583101561563e5781850154600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603160045260246000fd5b604081526000615677604083018561488d565b82810360208401526156898185614840565b95945050505050565b81516001600160401b038111156156ab576156ab61458b565b6156b9816155b2845461517c565b602080601f8311600181146156e857600084156156d65750858301515b6156e08582615563565b8655506138d0565b600085815260208120601f198616915b82811015615717578886015182559484019460019091019084016156f8565b508582101561563e57939096015160001960f8600387901b161c19169092555050600190811b01905550565b6040815260006157566040830185614814565b82810360208401526156898185614814565b600082601f83011261577957600080fd5b81516157876146618261461b565b81815284602083860101111561579c57600080fd5b6109268260208301602087016147f0565b600082601f8301126157be57600080fd5b815160206157ce61466183614ab9565b82815260059290921b840181019181810190868411156157ed57600080fd5b8286015b84811015614d2f5780516001600160401b03808211156158115760008081fd5b908801906040828b03601f190181131561582b5760008081fd5b6158336145a1565b8784015161584081614533565b81529083015190828211156158555760008081fd5b6158638c8984870101615768565b8189015286525050509183019183016157f1565b60006020828403121561588957600080fd5b81516001600160401b03808211156158a057600080fd5b818401915084601f8301126158b457600080fd5b81516158c261466182614ab9565b8082825260208201915060208360051b8601019250878311156158e457600080fd5b602085015b838110156159f05780518581111561590057600080fd5b8601601f196040828c038201121561591757600080fd5b61591f6145a1565b60208301518881111561593157600080fd5b83016060818e038401121561594557600080fd5b61594d6145c9565b925060208101518981111561596157600080fd5b6159708e602083850101615768565b84525060408101518981111561598557600080fd5b6159948e602083850101615768565b602085015250606001516159a781614566565b8060408401525081815260408301519150878211156159c557600080fd5b6159d48c6020848601016157ad565b60208201528086525050506020830192506020810190506158e9565b50979650505050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b8082028115828204841417610917576109176151e2565b600081615a6d57615a6d6151e2565b50600019019056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c656455add213c41f3851b4506717b8af695a4256979dff496dcaae7789f6121331aaa2646970667358221220d0d665cd7a3a5f895033502db80e03093ab43e012c8e8bbb137fdef824939b9264736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d23e77b7e1726577006799b7194b6ae31958a839000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000269c83b25c7b062ad0f3dbff966e444a55c72c1000000000000000000000000000000000000000000000000000000000000000134469726563744c697374696e67734c6f676963000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008c048dd77df000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002c617070726f76654275796572466f724c697374696e672875696e743235362c616464726573732c626f6f6c290000000000000000000000000000000000000000ea8f9a3c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000032617070726f766543757272656e6379466f724c697374696e672875696e743235362c616464726573732c75696e74323536290000000000000000000000000000704232dc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003762757946726f6d4c697374696e672875696e743235362c616464726573732c75696e743235362c616464726573732c75696e7432353629000000000000000000305a67a8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001663616e63656c4c697374696e672875696e743235362900000000000000000000746415b5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004d6372656174654c697374696e672828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743132382c75696e743132382c626f6f6c292900000000000000000000000000000000000000fb14079d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002863757272656e63795072696365466f724c697374696e672875696e743235362c6164647265737329000000000000000000000000000000000000000000000000c5275fb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001f676574416c6c4c697374696e67732875696e743235362c75696e74323536290031654b4d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024676574416c6c56616c69644c697374696e67732875696e743235362c75696e743235362900000000000000000000000000000000000000000000000000000000107a274a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000136765744c697374696e672875696e7432353629000000000000000000000000009cfbe2a6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002a69734275796572417070726f766564466f724c697374696e672875696e743235362c616464726573732900000000000000000000000000000000000000000000a8519047000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002d697343757272656e6379417070726f766564466f724c697374696e672875696e743235362c616464726573732900000000000000000000000000000000000000c78b616c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000f746f74616c4c697374696e67732829000000000000000000000000000000000007b6775800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000557570646174654c697374696e672875696e743235362c28616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743132382c75696e743132382c626f6f6c2929000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000076cc26705d81f5a3198a5eaf2bd370c23c67b7a40000000000000000000000000000000000000000000000000000000000000014456e676c69736841756374696f6e734c6f6769630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005e0000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000007600858e5ad000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d626964496e41756374696f6e2875696e743235362c75696e743235362900000096b5a755000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001663616e63656c41756374696f6e2875696e743235362900000000000000000000ebf05a62000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d636f6c6c65637441756374696f6e5061796f75742875696e743235362900000003a54fe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d636f6c6c65637441756374696f6e546f6b656e732875696e743235362900000016654d40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005c63726561746541756374696f6e2828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743235362c75696e7436342c75696e7436342c75696e7436342c75696e743634292900000000c291537c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001f676574416c6c41756374696f6e732875696e743235362c75696e7432353629007b0638010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024676574416c6c56616c696441756374696f6e732875696e743235362c75696e74323536290000000000000000000000000000000000000000000000000000000078bd7935000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001367657441756374696f6e2875696e7432353629000000000000000000000000006891939d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001667657457696e6e696e674269642875696e7432353629000000000000000000001389b1170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000019697341756374696f6e457870697265642875696e7432353629000000000000002eb566bd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002069734e657757696e6e696e674269642875696e743235362c75696e743235362916002f4a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000f746f74616c41756374696f6e732829000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000081b851fb4e850c5aadc00f12f147a6a27aaa66ee000000000000000000000000000000000000000000000000000000000000000b4f66666572734c6f6769630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000420c815729d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000146163636570744f666665722875696e7432353629000000000000000000000000ef706adf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001463616e63656c4f666665722875696e7432353629000000000000000000000000c1edcfbe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d676574416c6c4f66666572732875696e743235362c75696e743235362900000091940b3e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000022676574416c6c56616c69644f66666572732875696e743235362c75696e74323536290000000000000000000000000000000000000000000000000000000000004579268a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000116765744f666665722875696e7432353629000000000000000000000000000000016767fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003c6d616b654f666665722828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e74323536292900000000a9fd8ed1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000d746f74616c4f6666657273282900000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _marketplaceV3Params (tuple):
Arg [1] : extensions (tuple[]):
Arg [1] : metadata (tuple):
Arg [1] : name (string): DirectListingsLogic
Arg [2] : metadataURI (string):
Arg [3] : implementation (address): 0x269c83B25C7B062ad0f3dbFF966E444a55c72c10
Arg [2] : functions (tuple[]):
Arg [1] : functionSelector (bytes4): 0x48dd77df
Arg [2] : functionSignature (string): approveBuyerForListing(uint256,address,bool)
,
Arg [1] : functionSelector (bytes4): 0xea8f9a3c
Arg [2] : functionSignature (string): approveCurrencyForListing(uint256,address,uint256)
,
Arg [1] : functionSelector (bytes4): 0x704232dc
Arg [2] : functionSignature (string): buyFromListing(uint256,address,uint256,address,uint256)
,
Arg [1] : functionSelector (bytes4): 0x305a67a8
Arg [2] : functionSignature (string): cancelListing(uint256)
,
Arg [1] : functionSelector (bytes4): 0x746415b5
Arg [2] : functionSignature (string): createListing((address,uint256,uint256,address,uint256,uint128,uint128,bool))
,
Arg [1] : functionSelector (bytes4): 0xfb14079d
Arg [2] : functionSignature (string): currencyPriceForListing(uint256,address)
,
Arg [1] : functionSelector (bytes4): 0xc5275fb0
Arg [2] : functionSignature (string): getAllListings(uint256,uint256)
,
Arg [1] : functionSelector (bytes4): 0x31654b4d
Arg [2] : functionSignature (string): getAllValidListings(uint256,uint256)
,
Arg [1] : functionSelector (bytes4): 0x107a274a
Arg [2] : functionSignature (string): getListing(uint256)
,
Arg [1] : functionSelector (bytes4): 0x9cfbe2a6
Arg [2] : functionSignature (string): isBuyerApprovedForListing(uint256,address)
,
Arg [1] : functionSelector (bytes4): 0xa8519047
Arg [2] : functionSignature (string): isCurrencyApprovedForListing(uint256,address)
,
Arg [1] : functionSelector (bytes4): 0xc78b616c
Arg [2] : functionSignature (string): totalListings()
,
Arg [1] : functionSelector (bytes4): 0x07b67758
Arg [2] : functionSignature (string): updateListing(uint256,(address,uint256,uint256,address,uint256,uint128,uint128,bool))
,
Arg [1] : metadata (tuple):
Arg [1] : name (string): EnglishAuctionsLogic
Arg [2] : metadataURI (string):
Arg [3] : implementation (address): 0x76cc26705d81F5A3198a5EaF2bD370C23c67B7a4
Arg [2] : functions (tuple[]):
Arg [1] : functionSelector (bytes4): 0x0858e5ad
Arg [2] : functionSignature (string): bidInAuction(uint256,uint256)
,
Arg [1] : functionSelector (bytes4): 0x96b5a755
Arg [2] : functionSignature (string): cancelAuction(uint256)
,
Arg [1] : functionSelector (bytes4): 0xebf05a62
Arg [2] : functionSignature (string): collectAuctionPayout(uint256)
,
Arg [1] : functionSelector (bytes4): 0x03a54fe0
Arg [2] : functionSignature (string): collectAuctionTokens(uint256)
,
Arg [1] : functionSelector (bytes4): 0x16654d40
Arg [2] : functionSignature (string): createAuction((address,uint256,uint256,address,uint256,uint256,uint64,uint64,uint64,uint64))
,
Arg [1] : functionSelector (bytes4): 0xc291537c
Arg [2] : functionSignature (string): getAllAuctions(uint256,uint256)
,
Arg [1] : functionSelector (bytes4): 0x7b063801
Arg [2] : functionSignature (string): getAllValidAuctions(uint256,uint256)
,
Arg [1] : functionSelector (bytes4): 0x78bd7935
Arg [2] : functionSignature (string): getAuction(uint256)
,
Arg [1] : functionSelector (bytes4): 0x6891939d
Arg [2] : functionSignature (string): getWinningBid(uint256)
,
Arg [1] : functionSelector (bytes4): 0x1389b117
Arg [2] : functionSignature (string): isAuctionExpired(uint256)
,
Arg [1] : functionSelector (bytes4): 0x2eb566bd
Arg [2] : functionSignature (string): isNewWinningBid(uint256,uint256)
,
Arg [1] : functionSelector (bytes4): 0x16002f4a
Arg [2] : functionSignature (string): totalAuctions()
,
Arg [1] : metadata (tuple):
Arg [1] : name (string): OffersLogic
Arg [2] : metadataURI (string):
Arg [3] : implementation (address): 0x81b851fb4E850c5AadC00F12f147a6a27aaA66EE
Arg [2] : functions (tuple[]):
Arg [1] : functionSelector (bytes4): 0xc815729d
Arg [2] : functionSignature (string): acceptOffer(uint256)
,
Arg [1] : functionSelector (bytes4): 0xef706adf
Arg [2] : functionSignature (string): cancelOffer(uint256)
,
Arg [1] : functionSelector (bytes4): 0xc1edcfbe
Arg [2] : functionSignature (string): getAllOffers(uint256,uint256)
,
Arg [1] : functionSelector (bytes4): 0x91940b3e
Arg [2] : functionSignature (string): getAllValidOffers(uint256,uint256)
,
Arg [1] : functionSelector (bytes4): 0x4579268a
Arg [2] : functionSignature (string): getOffer(uint256)
,
Arg [1] : functionSelector (bytes4): 0x016767fa
Arg [2] : functionSignature (string): makeOffer((address,uint256,uint256,address,uint256,uint256))
,
Arg [1] : functionSelector (bytes4): 0xa9fd8ed1
Arg [2] : functionSignature (string): totalOffers()
Arg [2] : royaltyEngineAddress (address): 0x0000000000000000000000000000000000000000
Arg [3] : nativeTokenWrapper (address): 0xD23e77b7e1726577006799B7194b6Ae31958a839
-----Encoded View---------------
211 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [3] : 000000000000000000000000d23e77b7e1726577006799b7194b6ae31958a839
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000b00
Arg [7] : 0000000000000000000000000000000000000000000000000000000000001400
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [11] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [12] : 000000000000000000000000269c83b25c7b062ad0f3dbff966e444a55c72c10
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000013
Arg [14] : 4469726563744c697374696e67734c6f67696300000000000000000000000000
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [16] : 000000000000000000000000000000000000000000000000000000000000000d
Arg [17] : 00000000000000000000000000000000000000000000000000000000000001a0
Arg [18] : 0000000000000000000000000000000000000000000000000000000000000240
Arg [19] : 00000000000000000000000000000000000000000000000000000000000002e0
Arg [20] : 0000000000000000000000000000000000000000000000000000000000000380
Arg [21] : 0000000000000000000000000000000000000000000000000000000000000400
Arg [22] : 00000000000000000000000000000000000000000000000000000000000004c0
Arg [23] : 0000000000000000000000000000000000000000000000000000000000000560
Arg [24] : 00000000000000000000000000000000000000000000000000000000000005e0
Arg [25] : 0000000000000000000000000000000000000000000000000000000000000680
Arg [26] : 0000000000000000000000000000000000000000000000000000000000000700
Arg [27] : 00000000000000000000000000000000000000000000000000000000000007a0
Arg [28] : 0000000000000000000000000000000000000000000000000000000000000840
Arg [29] : 00000000000000000000000000000000000000000000000000000000000008c0
Arg [30] : 48dd77df00000000000000000000000000000000000000000000000000000000
Arg [31] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [32] : 000000000000000000000000000000000000000000000000000000000000002c
Arg [33] : 617070726f76654275796572466f724c697374696e672875696e743235362c61
Arg [34] : 6464726573732c626f6f6c290000000000000000000000000000000000000000
Arg [35] : ea8f9a3c00000000000000000000000000000000000000000000000000000000
Arg [36] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [37] : 0000000000000000000000000000000000000000000000000000000000000032
Arg [38] : 617070726f766543757272656e6379466f724c697374696e672875696e743235
Arg [39] : 362c616464726573732c75696e74323536290000000000000000000000000000
Arg [40] : 704232dc00000000000000000000000000000000000000000000000000000000
Arg [41] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [42] : 0000000000000000000000000000000000000000000000000000000000000037
Arg [43] : 62757946726f6d4c697374696e672875696e743235362c616464726573732c75
Arg [44] : 696e743235362c616464726573732c75696e7432353629000000000000000000
Arg [45] : 305a67a800000000000000000000000000000000000000000000000000000000
Arg [46] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [47] : 0000000000000000000000000000000000000000000000000000000000000016
Arg [48] : 63616e63656c4c697374696e672875696e743235362900000000000000000000
Arg [49] : 746415b500000000000000000000000000000000000000000000000000000000
Arg [50] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [51] : 000000000000000000000000000000000000000000000000000000000000004d
Arg [52] : 6372656174654c697374696e672828616464726573732c75696e743235362c75
Arg [53] : 696e743235362c616464726573732c75696e743235362c75696e743132382c75
Arg [54] : 696e743132382c626f6f6c292900000000000000000000000000000000000000
Arg [55] : fb14079d00000000000000000000000000000000000000000000000000000000
Arg [56] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [57] : 0000000000000000000000000000000000000000000000000000000000000028
Arg [58] : 63757272656e63795072696365466f724c697374696e672875696e743235362c
Arg [59] : 6164647265737329000000000000000000000000000000000000000000000000
Arg [60] : c5275fb000000000000000000000000000000000000000000000000000000000
Arg [61] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [62] : 000000000000000000000000000000000000000000000000000000000000001f
Arg [63] : 676574416c6c4c697374696e67732875696e743235362c75696e743235362900
Arg [64] : 31654b4d00000000000000000000000000000000000000000000000000000000
Arg [65] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [66] : 0000000000000000000000000000000000000000000000000000000000000024
Arg [67] : 676574416c6c56616c69644c697374696e67732875696e743235362c75696e74
Arg [68] : 3235362900000000000000000000000000000000000000000000000000000000
Arg [69] : 107a274a00000000000000000000000000000000000000000000000000000000
Arg [70] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [71] : 0000000000000000000000000000000000000000000000000000000000000013
Arg [72] : 6765744c697374696e672875696e743235362900000000000000000000000000
Arg [73] : 9cfbe2a600000000000000000000000000000000000000000000000000000000
Arg [74] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [75] : 000000000000000000000000000000000000000000000000000000000000002a
Arg [76] : 69734275796572417070726f766564466f724c697374696e672875696e743235
Arg [77] : 362c616464726573732900000000000000000000000000000000000000000000
Arg [78] : a851904700000000000000000000000000000000000000000000000000000000
Arg [79] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [80] : 000000000000000000000000000000000000000000000000000000000000002d
Arg [81] : 697343757272656e6379417070726f766564466f724c697374696e672875696e
Arg [82] : 743235362c616464726573732900000000000000000000000000000000000000
Arg [83] : c78b616c00000000000000000000000000000000000000000000000000000000
Arg [84] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [85] : 000000000000000000000000000000000000000000000000000000000000000f
Arg [86] : 746f74616c4c697374696e677328290000000000000000000000000000000000
Arg [87] : 07b6775800000000000000000000000000000000000000000000000000000000
Arg [88] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [89] : 0000000000000000000000000000000000000000000000000000000000000055
Arg [90] : 7570646174654c697374696e672875696e743235362c28616464726573732c75
Arg [91] : 696e743235362c75696e743235362c616464726573732c75696e743235362c75
Arg [92] : 696e743132382c75696e743132382c626f6f6c29290000000000000000000000
Arg [93] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [94] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [95] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [96] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [97] : 00000000000000000000000076cc26705d81f5a3198a5eaf2bd370c23c67b7a4
Arg [98] : 0000000000000000000000000000000000000000000000000000000000000014
Arg [99] : 456e676c69736841756374696f6e734c6f676963000000000000000000000000
Arg [100] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [101] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [102] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [103] : 0000000000000000000000000000000000000000000000000000000000000200
Arg [104] : 0000000000000000000000000000000000000000000000000000000000000280
Arg [105] : 0000000000000000000000000000000000000000000000000000000000000300
Arg [106] : 0000000000000000000000000000000000000000000000000000000000000380
Arg [107] : 0000000000000000000000000000000000000000000000000000000000000440
Arg [108] : 00000000000000000000000000000000000000000000000000000000000004c0
Arg [109] : 0000000000000000000000000000000000000000000000000000000000000560
Arg [110] : 00000000000000000000000000000000000000000000000000000000000005e0
Arg [111] : 0000000000000000000000000000000000000000000000000000000000000660
Arg [112] : 00000000000000000000000000000000000000000000000000000000000006e0
Arg [113] : 0000000000000000000000000000000000000000000000000000000000000760
Arg [114] : 0858e5ad00000000000000000000000000000000000000000000000000000000
Arg [115] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [116] : 000000000000000000000000000000000000000000000000000000000000001d
Arg [117] : 626964496e41756374696f6e2875696e743235362c75696e7432353629000000
Arg [118] : 96b5a75500000000000000000000000000000000000000000000000000000000
Arg [119] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [120] : 0000000000000000000000000000000000000000000000000000000000000016
Arg [121] : 63616e63656c41756374696f6e2875696e743235362900000000000000000000
Arg [122] : ebf05a6200000000000000000000000000000000000000000000000000000000
Arg [123] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [124] : 000000000000000000000000000000000000000000000000000000000000001d
Arg [125] : 636f6c6c65637441756374696f6e5061796f75742875696e7432353629000000
Arg [126] : 03a54fe000000000000000000000000000000000000000000000000000000000
Arg [127] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [128] : 000000000000000000000000000000000000000000000000000000000000001d
Arg [129] : 636f6c6c65637441756374696f6e546f6b656e732875696e7432353629000000
Arg [130] : 16654d4000000000000000000000000000000000000000000000000000000000
Arg [131] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [132] : 000000000000000000000000000000000000000000000000000000000000005c
Arg [133] : 63726561746541756374696f6e2828616464726573732c75696e743235362c75
Arg [134] : 696e743235362c616464726573732c75696e743235362c75696e743235362c75
Arg [135] : 696e7436342c75696e7436342c75696e7436342c75696e743634292900000000
Arg [136] : c291537c00000000000000000000000000000000000000000000000000000000
Arg [137] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [138] : 000000000000000000000000000000000000000000000000000000000000001f
Arg [139] : 676574416c6c41756374696f6e732875696e743235362c75696e743235362900
Arg [140] : 7b06380100000000000000000000000000000000000000000000000000000000
Arg [141] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [142] : 0000000000000000000000000000000000000000000000000000000000000024
Arg [143] : 676574416c6c56616c696441756374696f6e732875696e743235362c75696e74
Arg [144] : 3235362900000000000000000000000000000000000000000000000000000000
Arg [145] : 78bd793500000000000000000000000000000000000000000000000000000000
Arg [146] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [147] : 0000000000000000000000000000000000000000000000000000000000000013
Arg [148] : 67657441756374696f6e2875696e743235362900000000000000000000000000
Arg [149] : 6891939d00000000000000000000000000000000000000000000000000000000
Arg [150] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [151] : 0000000000000000000000000000000000000000000000000000000000000016
Arg [152] : 67657457696e6e696e674269642875696e743235362900000000000000000000
Arg [153] : 1389b11700000000000000000000000000000000000000000000000000000000
Arg [154] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [155] : 0000000000000000000000000000000000000000000000000000000000000019
Arg [156] : 697341756374696f6e457870697265642875696e743235362900000000000000
Arg [157] : 2eb566bd00000000000000000000000000000000000000000000000000000000
Arg [158] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [159] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [160] : 69734e657757696e6e696e674269642875696e743235362c75696e7432353629
Arg [161] : 16002f4a00000000000000000000000000000000000000000000000000000000
Arg [162] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [163] : 000000000000000000000000000000000000000000000000000000000000000f
Arg [164] : 746f74616c41756374696f6e7328290000000000000000000000000000000000
Arg [165] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [166] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [167] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [168] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [169] : 00000000000000000000000081b851fb4e850c5aadc00f12f147a6a27aaa66ee
Arg [170] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [171] : 4f66666572734c6f676963000000000000000000000000000000000000000000
Arg [172] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [173] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [174] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [175] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [176] : 00000000000000000000000000000000000000000000000000000000000001e0
Arg [177] : 0000000000000000000000000000000000000000000000000000000000000260
Arg [178] : 0000000000000000000000000000000000000000000000000000000000000300
Arg [179] : 0000000000000000000000000000000000000000000000000000000000000380
Arg [180] : 0000000000000000000000000000000000000000000000000000000000000420
Arg [181] : c815729d00000000000000000000000000000000000000000000000000000000
Arg [182] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [183] : 0000000000000000000000000000000000000000000000000000000000000014
Arg [184] : 6163636570744f666665722875696e7432353629000000000000000000000000
Arg [185] : ef706adf00000000000000000000000000000000000000000000000000000000
Arg [186] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [187] : 0000000000000000000000000000000000000000000000000000000000000014
Arg [188] : 63616e63656c4f666665722875696e7432353629000000000000000000000000
Arg [189] : c1edcfbe00000000000000000000000000000000000000000000000000000000
Arg [190] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [191] : 000000000000000000000000000000000000000000000000000000000000001d
Arg [192] : 676574416c6c4f66666572732875696e743235362c75696e7432353629000000
Arg [193] : 91940b3e00000000000000000000000000000000000000000000000000000000
Arg [194] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [195] : 0000000000000000000000000000000000000000000000000000000000000022
Arg [196] : 676574416c6c56616c69644f66666572732875696e743235362c75696e743235
Arg [197] : 3629000000000000000000000000000000000000000000000000000000000000
Arg [198] : 4579268a00000000000000000000000000000000000000000000000000000000
Arg [199] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [200] : 0000000000000000000000000000000000000000000000000000000000000011
Arg [201] : 6765744f666665722875696e7432353629000000000000000000000000000000
Arg [202] : 016767fa00000000000000000000000000000000000000000000000000000000
Arg [203] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [204] : 000000000000000000000000000000000000000000000000000000000000003c
Arg [205] : 6d616b654f666665722828616464726573732c75696e743235362c75696e7432
Arg [206] : 35362c616464726573732c75696e743235362c75696e74323536292900000000
Arg [207] : a9fd8ed100000000000000000000000000000000000000000000000000000000
Arg [208] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [209] : 000000000000000000000000000000000000000000000000000000000000000d
Arg [210] : 746f74616c4f6666657273282900000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in GLMR
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.