Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 2 internal transactions
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 10294839 | 328 days ago | Contract Creation | 0 ETH | |||
| 10294839 | 328 days ago | Contract Creation | 0 ETH |
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:
london 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;
address public constant DEFAULT_FEE_RECIPIENT = 0x1Af20C6B23373350aD464700B5965CE4B0D2aD94;
/*///////////////////////////////////////////////////////////////
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/",
":@rari-capital/solmate/=lib/seaport/lib/solmate/",
":@seaport/=lib/seaport/contracts/",
":@std/=lib/forge-std/src/",
":@thirdweb-dev/dynamic-contracts/=lib/dynamic-contracts/",
":@uniswap/swap-router-contracts/contracts/=lib/swap-router-contracts/contracts/",
":@uniswap/v3-core/contracts/=lib/v3-core/contracts/",
":@uniswap/v3-periphery/contracts/=lib/v3-periphery/contracts/",
":ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/",
":ERC721A/=lib/ERC721A/contracts/",
":chainlink/=lib/chainlink/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/",
":murky/=lib/murky/src/",
":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/",
":seaport-core/=lib/seaport/lib/seaport-core/",
":seaport-sol/=lib/seaport-sol/src/",
":seaport-types/=lib/seaport/lib/seaport-types/",
":seaport/=lib/seaport/",
":solady/=lib/solady/",
":solarray/=lib/seaport/lib/solarray/src/",
":solmate/=lib/seaport/lib/solmate/src/",
":sstore2/=lib/dynamic-contracts/lib/sstore2/contracts/",
":swap-router-contracts/=lib/swap-router-contracts/contracts/",
":v3-core/=lib/v3-core/",
":v3-periphery/=lib/v3-periphery/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":[],"name":"DEFAULT_FEE_RECIPIENT","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":[{"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
60e06040523480156200001157600080fd5b506040516200694538038062006945833981016040819052620000349162000914565b60208101518151805160009015620000815762000051826200019a565b6200007e8260405160200162000068919062000b88565b60408051601f198184030181529190526200024a565b90505b6001600160a01b039081166080528216159050806200010d57506040516301ffc9a760e01b8152636591fc0b60e11b60048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa158015620000e7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010d919062000cab565b620001725760405162461bcd60e51b815260206004820152602a60248201527f446f65736e277420737570706f72742049526f79616c7479456e67696e65563160448201526920696e7465726661636560b01b60648201526084015b60405180910390fd5b6001600160a01b0390811660a05260408201511660c05262000193620002b5565b5062000de2565b8051600160005b82811015620001f557620001d7848281518110620001c357620001c362000cd6565b6020026020010151620003b560201b60201c565b91508115620001f557620001ed60018262000d02565b9050620001a1565b5080620002455760405162461bcd60e51b815260206004820152601e60248201527f42617365526f757465723a20696e76616c696420657874656e73696f6e2e0000604482015260640162000169565b505050565b6000806200027a8360405160200162000264919062000d1e565b60408051601f1981840301815291905262000617565b90508051602082016000f091506001600160a01b038216620002af5760405163046a55db60e11b815260040160405180910390fd5b50919050565b7f322cf19c484104d3b1a9c2982ebae869ede3fa5f6c4703ca41b9a48c76ee03005460ff808216916101009004168015620003435760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840162000169565b60ff8281161015620003b1577f322cf19c484104d3b1a9c2982ebae869ede3fa5f6c4703ca41b9a48c76ee0300805460ff191660ff90811790915560408051918252517f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989181900360200190a15b5050565b8051515160009015801590620004005750620003d062000645565b600101826000015160000151604051620003eb919062000d46565b9081526040519081900360200190205460ff16155b80156200041a57508151604001516001600160a01b031615155b905060016200042862000645565b60010183600001516000015160405162000443919062000d46565b908152604051908190036020019020805491151560ff19909216919091179055806200047157506000919050565b60208201515160005b81811015620006105782156200061057600084602001518281518110620004a557620004a562000cd6565b602090810291909101015180519091506000906001600160e01b0319166200054257604051602001620004f59060208082526009908201526872656365697665282960b81b604082015260600190565b60405160208183030381529060405280519060200120826020015160405160200162000522919062000d64565b60405160208183030381529060405280519060200120141590506200058b565b60208083015160405162000557920162000d46565b604051602081830303815290604052805190602001206001600160e01b03191682600001516001600160e01b031916141590505b80158015620005c057506200059f62000645565b82516001600160e01b0319166000908152602091909152604090205460ff16155b94506001620005ce62000645565b92516001600160e01b03191660009081526020939093526040909220805460ff191692151592909217909155506200060860018262000d02565b90506200047a565b5050919050565b60608151826040516020016200062f92919062000d79565b6040516020818303038152906040529050919050565b6000806200067560017f11c19c8d567686e9e4073585fe511ac02fcfc0ce76ceba4592185bf5bec3cd1f62000dcc565b6040516020016200068891815260200190565b60408051601f19818403018152919052805160209091012092915050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715620006e157620006e1620006a6565b60405290565b604051606081016001600160401b0381118282101715620006e157620006e1620006a6565b604051601f8201601f191681016001600160401b0381118282101715620007375762000737620006a6565b604052919050565b60006001600160401b038211156200075b576200075b620006a6565b5060051b60200190565b60005b838110156200078257818101518382015260200162000768565b50506000910152565b600082601f8301126200079d57600080fd5b81516001600160401b03811115620007b957620007b9620006a6565b620007ce601f8201601f19166020016200070c565b818152846020838601011115620007e457600080fd5b620007f782602083016020870162000765565b949350505050565b80516001600160a01b03811681146200081757600080fd5b919050565b600082601f8301126200082e57600080fd5b815160206200084762000841836200073f565b6200070c565b82815260059290921b840181019181810190868411156200086757600080fd5b8286015b84811015620009095780516001600160401b03808211156200088d5760008081fd5b908801906040828b03601f1901811315620008a85760008081fd5b620008b2620006bc565b838801516001600160e01b031981168114620008ce5760008081fd5b8152908301519082821115620008e45760008081fd5b620008f48c89848701016200078b565b8189015286525050509183019183016200086b565b509695505050505050565b6000602082840312156200092757600080fd5b81516001600160401b038111156200093e57600080fd5b6060818401850312156200095157600080fd5b6200095b620006e7565b838201516001600160401b038111156200097457600080fd5b85601f828588010101126200098857600080fd5b8083860101516200099d62000841826200073f565b808282526020820191508860208460051b86898c010101011115620009c157600080fd5b602084878a0101015b60208460051b86898c0101010181101562000b215780516001600160401b03811115620009f657600080fd5b8988018601016040818c03601f1901121562000a1157600080fd5b62000a1b620006bc565b60208201516001600160401b0381111562000a3557600080fd5b60608382018e03601f1901121562000a4c57600080fd5b62000a56620006e7565b838201602001516001600160401b0381111562000a7257600080fd5b62000a858f60208386890101016200078b565b825250838201604001516001600160401b0381111562000aa457600080fd5b62000ab78f60208386890101016200078b565b60208301525062000acd606083860101620007ff565b60408281019190915290835283015190506001600160401b0381111562000af357600080fd5b62000b048d6020838601016200081c565b6020830152508085525050602083019250602081019050620009ca565b5084525062000b38915050848301602001620007ff565b602082015262000b4d604083860101620007ff565b6040820152949350505050565b6000815180845262000b7481602086016020860162000765565b601f01601f19169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b8481101562000c9c57603f19808b86030187528351805189875280516060808c8a015262000be260a08a018362000b5a565b91508c830151858a840301828b015262000bfd838262000b5a565b938d01516001600160a01b031660808b0152505050908a01518682038b88015280518083529192508a01908a830190600581901b84018c01865b8281101562000c8457858203601f19018452845180516001600160e01b03191683528e01518e83018e905262000c708e84018262000b5a565b958f0195948f019492505060010162000c37565b50998c01999750505093890193505060010162000bb0565b50919998505050505050505050565b60006020828403121562000cbe57600080fd5b8151801515811462000ccf57600080fd5b9392505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111562000d185762000d1862000cec565b92915050565b600081526000825162000d3981600185016020870162000765565b9190910160010192915050565b6000825162000d5a81846020870162000765565b9190910192915050565b60208152600062000ccf602083018462000b5a565b606360f81b815260e083901b6001600160e01b03191660018201526880600e6000396000f360b81b6005820152815160009062000dbe81600e85016020870162000765565b91909101600e019392505050565b8181038181111562000d185762000d1862000cec565b60805160a05160c051615b2562000e2060003960006101fa01526000610fa30152600081816103f2015281816128d9015261290e0152615b256000f3fe6080604052600436106101ea5760003560e01c8063a0dbaefd11610109578063a0dbaefd14610587578063a217fddf146105b4578063a32fa5b3146105c9578063aaae5633146105e9578063ac9650d814610609578063b6f10c7914610636578063bc197c8114610656578063c0562f6d14610682578063c22707ee146106a2578063ca15c873146106cf578063cb2ef6f7146106ef578063ce0b601314610712578063d45573f614610732578063d547741f14610769578063e05688fe14610789578063e57553da146107a9578063e8a3d485146107cc578063ee7d2adf146107ee578063f23a6e611461080e578063f28083c31461083a578063f533b8021461085c57610229565b806301ffc9a7146102b0578063150b7a02146102e55780631e7ac4881461031257806321ede03214610332578063248a9ca3146103525780632f2ff15d1461038057806336568abe146103a0578063429eed80146103c0578063463c4864146103e05780634a00cc481461042c578063512cf9141461044e578063572b6c051461046e5780635a9ad2311461048e578063637102df146104a35780637e54523c146104cb5780638856a113146104eb5780639010d07c1461050b57806391d148541461052b578063938e3d7b1461054b578063a0a8e4601461056b57610229565b3661022957336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461022757610227614550565b005b3660000361023357005b600061024a6000356001600160e01b03191661088a565b90506001600160a01b0381166102a75760405162461bcd60e51b815260206004820181905260248201527f526f757465723a2066756e6374696f6e20646f6573206e6f742065786973742e60448201526064015b60405180910390fd5b6102278161089f565b3480156102bc57600080fd5b506102d06102cb36600461457c565b6108c8565b60405190151581526020015b60405180910390f35b3480156102f157600080fd5b506103056103003660046146cb565b610950565b6040516102dc9190614736565b34801561031e57600080fd5b5061022761032d36600461474b565b610961565b34801561033e57600080fd5b5061022761034d366004614777565b610993565b34801561035e57600080fd5b5061037261036d366004614794565b610aa9565b6040519081526020016102dc565b34801561038c57600080fd5b5061022761039b3660046147ad565b610ac7565b3480156103ac57600080fd5b506102276103bb3660046147ad565b610b74565b3480156103cc57600080fd5b506102276103db3660046147dd565b610be3565b3480156103ec57600080fd5b506104147f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102dc565b34801561043857600080fd5b50610441610e5a565b6040516102dc9190614962565b34801561045a57600080fd5b506102276104693660046147dd565b610f29565b34801561047a57600080fd5b506102d0610489366004614777565b610f57565b34801561049a57600080fd5b50610414610f83565b3480156104af57600080fd5b50610414731af20c6b23373350ad464700b5965ce4b0d2ad9481565b3480156104d757600080fd5b506102276104e636600461474b565b610fd0565b3480156104f757600080fd5b50610227610506366004614a20565b610ffe565b34801561051757600080fd5b50610414610526366004614a83565b61102c565b34801561053757600080fd5b506102d06105463660046147ad565b61113a565b34801561055757600080fd5b50610227610566366004614aa5565b61116e565b34801561057757600080fd5b50604051600381526020016102dc565b34801561059357600080fd5b506105a76105a236600461457c565b61119b565b6040516102dc9190614ad9565b3480156105c057600080fd5b50610372600081565b3480156105d557600080fd5b506102d06105e43660046147ad565b611311565b3480156105f557600080fd5b50610227610604366004614b21565b611374565b34801561061557600080fd5b50610629610624366004614c17565b6115ae565b6040516102dc9190614c8b565b34801561064257600080fd5b50610227610651366004614ce2565b611721565b34801561066257600080fd5b50610305610671366004614d6d565b63bc197c8160e01b95945050505050565b34801561068e57600080fd5b5061022761069d366004614e99565b61174e565b3480156106ae57600080fd5b506106c26106bd366004614aa5565b61177b565b6040516102dc9190614f90565b3480156106db57600080fd5b506103726106ea366004614794565b61178c565b3480156106fb57600080fd5b506c4d61726b6574706c616365563360981b610372565b34801561071e57600080fd5b5061041461072d36600461457c565b61088a565b34801561073e57600080fd5b50610747611829565b604080516001600160a01b03909316835261ffff9091166020830152016102dc565b34801561077557600080fd5b506102276107843660046147ad565b61185b565b34801561079557600080fd5b506102276107a4366004614e99565b611866565b3480156107b557600080fd5b506107be611893565b6040516102dc929190614fa3565b3480156107d857600080fd5b506107e16118bc565b6040516102dc9190614fbc565b3480156107fa57600080fd5b50610227610809366004614aa5565b611954565b34801561081a57600080fd5b50610305610829366004614fcf565b63f23a6e6160e01b95945050505050565b34801561084657600080fd5b5061084f611981565b6040516102dc919061504d565b34801561086857600080fd5b5061087c610877366004615075565b61199b565b6040516102dc9291906150aa565b60006108958261119b565b6040015192915050565b3660008037600080366000845af43d6000803e8080156108be573d6000f35b3d6000fd5b505050565b60006001600160e01b03198216630271189760e51b14806108f957506001600160e01b03198216630a85bd0160e11b145b8061091457506001600160e01b0319821663ce0b601360e01b145b8061092f57506001600160e01b03198216630940198960e31b145b8061094a57506301ffc9a760e01b6001600160e01b03198316145b92915050565b630a85bd0160e11b5b949350505050565b610969611b95565b6109855760405162461bcd60e51b815260040161029e9061512e565b61098f8282611bad565b5050565b61099b611b95565b6109b75760405162461bcd60e51b815260040161029e9061512e565b6001600160a01b03811615801590610a3e57506040516301ffc9a760e01b81526001600160a01b038216906301ffc9a7906109fd90636591fc0b60e11b90600401614736565b602060405180830381865afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e9190615156565b610a9d5760405162461bcd60e51b815260206004820152602a60248201527f446f65736e277420737570706f72742049526f79616c7479456e67696e65563160448201526920696e7465726661636560b01b606482015260840161029e565b610aa681611cc2565b50565b6000610ab3611d1e565b600092835260010160205250604090205490565b610af2610ad2611d1e565b60008481526001919091016020526040902054610aed611d28565b611d32565b610afa611d1e565b6000838152602091825260408082206001600160a01b0385168352909252205460ff1615610b6a5760405162461bcd60e51b815260206004820152601d60248201527f43616e206f6e6c79206772616e7420746f206e6f6e20686f6c64657273000000604482015260640161029e565b61098f8282611db7565b806001600160a01b0316610b86611d28565b6001600160a01b031614610bd95760405162461bcd60e51b815260206004820152601a60248201527921b0b71037b7363c903932b737bab731b2903337b91039b2b63360311b604482015260640161029e565b61098f8282611dcb565b610beb611ddf565b610c075760405162461bcd60e51b815260040161029e90615178565b610c118282611df9565b610c7e5760405162461bcd60e51b815260206004820152603860248201527f457874656e73696f6e4d616e616765723a2063616e6e6f742072656d6f766520604482015277333ab731ba34b7b710333937b69032bc3a32b739b4b7b71760411b606482015260840161029e565b6000610c88611ef8565b6001600160e01b031983166000908152600391909101602052604090819020815160608101909252805482908290610cbf906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054610ceb906151af565b8015610d385780601f10610d0d57610100808354040283529160200191610d38565b820191906000526020600020905b815481529060010190602001808311610d1b57829003601f168201915b50505050508152602001600182018054610d51906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7d906151af565b8015610dca5780601f10610d9f57610100808354040283529160200191610dca565b820191906000526020600020905b815481529060010190602001808311610dad57829003601f168201915b5050509183525050600291909101546001600160a01b03166020909101529050610df48383611f02565b610dfd826121cf565b816001600160e01b03191683604051610e1691906151e3565b60405180910390207fbb931a9651175c9c82f86afbf6ad37a9141aa8d1d42bf798739be245a12e4e8883604051610e4d9190614ad9565b60405180910390a3505050565b60606000610e6e610e69611ef8565b612222565b8051909150806001600160401b03811115610e8b57610e8b6145be565b604051908082528060200260200182016040528015610ec457816020015b610eb1614467565b815260200190600190039081610ea95790505b50925060005b81811015610f2357610ef4838281518110610ee757610ee76151ff565b602002602001015161222d565b848281518110610f0657610f066151ff565b6020908102919091010152610f1c60018261522b565b9050610eca565b50505090565b610f31611ddf565b610f4d5760405162461bcd60e51b815260040161029e90615178565b61098f8282610be3565b6000610f616124b6565b6001600160a01b03909216600090815260209290925250604090205460ff1690565b600080610f8e6124da565b80549091506001600160a01b031680610fc7577f0000000000000000000000000000000000000000000000000000000000000000610fc9565b805b9250505090565b610fd8611b95565b610ff45760405162461bcd60e51b815260040161029e9061512e565b61098f82826124fe565b611006611ddf565b6110225760405162461bcd60e51b815260040161029e90615178565b61098f8282612570565b6000806110376127bf565b600085815260209190915260408120549150805b8281101561113157600061105d6127bf565b60008881526020918252604080822085835260010190925220546001600160a01b0316146110d5578482036110c3576110946127bf565b600087815260209182526040808220938252600190930190915220546001600160a01b0316925061094a915050565b6110ce60018361522b565b915061111f565b6110e086600061113a565b801561110c57506110ef6127bf565b600087815260209182526040808220828052600201909252205481145b1561111f5761111c60018361522b565b91505b61112a60018261522b565b905061104b565b50505092915050565b6000611144611d1e565b6000938452602090815260408085206001600160a01b039490941685529290525090205460ff1690565b611176611b95565b6111925760405162461bcd60e51b815260040161029e9061512e565b610aa6816127c9565b6111a3614487565b6111ab611ef8565b6001600160e01b0319831660009081526003919091016020526040908190208151606081019092528054829082906111e2906151af565b80601f016020809104026020016040519081016040528092919081815260200182805461120e906151af565b801561125b5780601f106112305761010080835404028352916020019161125b565b820191906000526020600020905b81548152906001019060200180831161123e57829003601f168201915b50505050508152602001600182018054611274906151af565b80601f01602080910402602001604051908101604052809291908181526020018280546112a0906151af565b80156112ed5780601f106112c2576101008083540402835291602001916112ed565b820191906000526020600020905b8154815290600101906020018083116112d057829003601f168201915b5050509183525050600291909101546001600160a01b031660209091015292915050565b600061131b611d1e565b600084815260209182526040808220828052909252205460ff1661136b57611341611d1e565b6000848152602091825260408082206001600160a01b0386168352909252205460ff16905061094a565b50600192915050565b600061137e6128a4565b5460ff169050600061138e6128a4565b54610100900460ff16905080158080156113ab575060018360ff16105b806113ca57506113ba306128c8565b1580156113ca57508260ff166001145b61142d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161029e565b60016114376128a4565b805460ff191660ff9290921691909117905580156114705760016114596128a4565b80549115156101000261ff00199092169190911790555b6114786128d7565b611480612955565b6114898661298c565b611492876127c9565b6114a0858561ffff16611bad565b6114ab600089611db7565b6114c3600080516020615ad083398151915289611db7565b6114ee7ff94103142c1baabe9ac2b5d1487bf783de9e69cfeea9a72f5c9c94afd7877b8c6000611db7565b6115197f86d5cf0a6bdc8d859ba3bdc97043337c82a0e609035f378e419298b6a3e00ae66000611db7565b611531600080516020615ad083398151915289611db7565b611549600080516020615ad0833981519152806129c2565b80156115a45760006115596128a4565b80549115156101000261ff0019909216919091179055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6060816001600160401b038111156115c8576115c86145be565b6040519080825280602002602001820160405280156115fb57816020015b60608152602001906001900390816115e65790505b5090506000611608611d28565b9050336001600160a01b038216141560005b84811015611131578115611699576116773087878481811061163e5761163e6151ff565b9050602002810190611650919061523e565b866040516020016116639392919061528b565b604051602081830303815290604052612a31565b848281518110611689576116896151ff565b6020026020010181905250611719565b6116fb308787848181106116af576116af6151ff565b90506020028101906116c1919061523e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612a3192505050565b84828151811061170d5761170d6151ff565b60200260200101819052505b60010161161a565b611729611b95565b6117455760405162461bcd60e51b815260040161029e9061512e565b610aa681612a5d565b611756611ddf565b6117725760405162461bcd60e51b815260040161029e90615178565b610aa681612ac5565b611783614467565b61094a8261222d565b6000806117976127bf565b6000848152602091909152604081205491505b818110156118045760006117bc6127bf565b60008681526020918252604080822085835260010190925220546001600160a01b0316146117f2576117ef60018461522b565b92505b6117fd60018261522b565b90506117aa565b5061181083600061113a565b156118235761182060018361522b565b91505b50919050565b600080611834612c2e565b546001600160a01b0316611846612c2e565b549093600160a01b90910461ffff1692509050565b610bd9610ad2611d1e565b61186e611ddf565b61188a5760405162461bcd60e51b815260040161029e90615178565b610aa681612c52565b60008061189e612c2e565b546001600160a01b03166118b0612c2e565b60010154915091509091565b60606118c6612d7c565b80546118d1906151af565b80601f01602080910402602001604051908101604052809291908181526020018280546118fd906151af565b801561194a5780601f1061191f5761010080835404028352916020019161194a565b820191906000526020600020905b81548152906001019060200180831161192d57829003601f168201915b5050505050905090565b61195c611ddf565b6119785760405162461bcd60e51b815260040161029e90615178565b610aa681612da0565b600061198b612c2e565b54600160b01b900460ff16919050565b60608060006119a8610f83565b90506001600160a01b038116611b085760405163152a902d60e11b815260048101869052602481018590526001600160a01b03871690632a55205a906044016040805180830381865afa925050508015611a1f575060408051601f3d908101601f19168201909252611a1c918101906152ac565b60015b15611b8c5785811115611a6d5760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081c9bde585b1d1e48185b5bdd5b9d60521b604482015260640161029e565b604080516001808252818301909252906020808301908036833750506040805160018082528183019092529297509050602080830190803683370190505093508185600081518110611ac157611ac16151ff565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600081518110611af557611af56151ff565b6020026020010181815250505050611b8c565b604051637a99dc0160e11b81526001600160a01b038781166004830152602482018790526044820186905282169063f533b802906064016000604051808303816000875af1158015611b5e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b869190810190615339565b90935091505b50935093915050565b6000611ba881611ba3611d28565b6130de565b905090565b612710811115611bf15760405162461bcd60e51b815260206004820152600f60248201526e45786365656473206d61782062707360881b604482015260640161029e565b6001600160a01b038216611c3b5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b604482015260640161029e565b80611c44612c2e565b805461ffff92909216600160a01b0261ffff60a01b1990921691909117905581611c6c612c2e565b80546001600160a01b0319166001600160a01b03928316179055604051828152908316907fe2497bd806ec41a6e0dd992c29a72efc0ef8fec9092d1978fd4a1e00b2f18304906020015b60405180910390a25050565b6000611ccc6124da565b80546001600160a01b038481166001600160a01b031983168117845560405193945091169182907fdb773077c54b973d26a2973b12d9e7e458768cbf218f12160d3ea5f015820ef990600090a3505050565b6000611ba8613114565b6000611ba8613138565b611d3a611d1e565b6000838152602091825260408082206001600160a01b0385168352909252205460ff1661098f57611d75816001600160a01b0316601461315a565b611d8083602061315a565b604051602001611d919291906153f3565b60408051601f198184030181529082905262461bcd60e51b825261029e91600401614fbc565b611dc182826132f5565b61098f8282613379565b611dd58282613438565b61098f82826134bd565b6000611ba8600080516020615ad0833981519152336130de565b6000611e0d83611e07611ef8565b9061354c565b611e295760405162461bcd60e51b815260040161029e90615460565b82604051602001611e3a9190614fbc565b60405160208183030381529060405280519060200120611e58611ef8565b6001600160e01b03198416600090815260039190910160209081526040918290209151611e869291016154ab565b604051602081830303815290604052805190602001201461136b5760405162461bcd60e51b815260206004820152602660248201527f457874656e73696f6e4d616e616765723a20696e636f727265637420657874656044820152653739b4b7b71760d11b606482015260840161029e565b6000611ba8613558565b6000611f0c611ef8565b60020183604051611f1d91906151e3565b9081526020016040518091039020600301805480602002602001604051908101604052809291908181526020016000905b8282101561202b5760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b03191682526001810180549293919291840191611f9a906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054611fc6906151af565b80156120135780601f10611fe857610100808354040283529160200191612013565b820191906000526020600020905b815481529060010190602001808311611ff657829003601f168201915b50505050508152505081526020019060010190611f4e565b5050825192935060009150505b818110156121c857836001600160e01b03191683828151811061205d5761205d6151ff565b6020026020010151600001516001600160e01b031916036121b657612080611ef8565b6002018560405161209191906151e3565b9081526040519081900360200190206003016120ae60018461553b565b815481106120be576120be6151ff565b90600052602060002090600202016120d4611ef8565b600201866040516120e591906151e3565b90815260200160405180910390206003018281548110612107576121076151ff565b600091825260209091208254600290920201805463ffffffff191663ffffffff909216919091178155600180820190612142908401826155ab565b5090505061214e611ef8565b6002018560405161215f91906151e3565b908152602001604051809103902060030180548061217f5761217f615681565b600082815260208120600260001990930192830201805463ffffffff19168155906121ad60018301826144b1565b505090556121c8565b6121c160018261522b565b9050612038565b5050505050565b6121d7611ef8565b6001600160e01b03198216600090815260039190910160205260408120906121ff82826144b1565b61220d6001830160006144b1565b5060020180546001600160a01b031916905550565b606061094a826135b6565b612235614467565b61223d611ef8565b6002018260405161224e91906151e3565b9081526040805191829003602001822060a0830182528054909183919082019083908290829061227d906151af565b80601f01602080910402602001604051908101604052809291908181526020018280546122a9906151af565b80156122f65780601f106122cb576101008083540402835291602001916122f6565b820191906000526020600020905b8154815290600101906020018083116122d957829003601f168201915b5050505050815260200160018201805461230f906151af565b80601f016020809104026020016040519081016040528092919081815260200182805461233b906151af565b80156123885780601f1061235d57610100808354040283529160200191612388565b820191906000526020600020905b81548152906001019060200180831161236b57829003601f168201915b5050509183525050600291909101546001600160a01b03166020918201529082526003830180546040805182850281018501909152818152938301939260009084015b828210156124a85760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b03191682526001810180549293919291840191612417906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054612443906151af565b80156124905780601f1061246557610100808354040283529160200191612490565b820191906000526020600020905b81548152906001019060200180831161247357829003601f168201915b505050505081525050815260200190600101906123cb565b505050915250909392505050565b7f82aadcdf5bea62fd30615b6c0754b644e71b6c1e8c55b71bb927ad005b504f0090565b7fc802b338f3fb784853cf3c808df5ff08335200e394ea2c687d12571a9104500090565b80612507612c2e565b6001015581612514612c2e565b80546001600160a01b0319166001600160a01b03929092169190911790556040517ff8086cee80709bd44c82f89dbca54115ebd05e840a88ab81df9cf5be9754eb63906125649084908490614fa3565b60405180910390a15050565b61257a8282613693565b6125e65760405162461bcd60e51b815260206004820152603760248201527f457874656e73696f6e4d616e616765723a2063616e6e6f742053746f72653a20604482015276333ab731ba34b7b7103337b91032bc3a32b739b4b7b71760491b606482015260840161029e565b6125f082826136bd565b60006125fa611ef8565b6002018360405161260b91906151e3565b9081526040805191829003602001822060608301909152805482908290612631906151af565b80601f016020809104026020016040519081016040528092919081815260200182805461265d906151af565b80156126aa5780601f1061267f576101008083540402835291602001916126aa565b820191906000526020600020905b81548152906001019060200180831161268d57829003601f168201915b505050505081526020016001820180546126c3906151af565b80601f01602080910402602001604051908101604052809291908181526020018280546126ef906151af565b801561273c5780601f106127115761010080835404028352916020019161273c565b820191906000526020600020905b81548152906001019060200180831161271f57829003601f168201915b5050509183525050600291909101546001600160a01b03166020909101528251909150612769908261390b565b81600001516001600160e01b0319168360405161278691906151e3565b60405180910390207f681115194e519bda23de4da5218f3bc38f5585eab7c6b7d5fa66caa4602f574d8484604051610e4d929190615697565b6000611ba8613982565b60006127d3612d7c565b80546127de906151af565b80601f016020809104026020016040519081016040528092919081815260200182805461280a906151af565b80156128575780601f1061282c57610100808354040283529160200191612857565b820191906000526020600020905b81548152906001019060200180831161283a57829003601f168201915b5050505050905081612867612d7c565b9061287290826156c5565b507fc9c7c3fe08b88b4df9d4d47ef47d2c43d55c025a0ba88ca442580ed9e7348a168183604051612564929190615776565b7f322cf19c484104d3b1a9c2982ebae869ede3fa5f6c4703ca41b9a48c76ee030090565b6001600160a01b03163b151590565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661290757565b60006129327f00000000000000000000000000000000000000000000000000000000000000006139e4565b905060008180602001905181019061294a91906158aa565b905061098f816139f4565b61295d6128a4565b54610100900460ff166129825760405162461bcd60e51b815260040161029e90615a2f565b61298a613b92565b565b6129946128a4565b54610100900460ff166129b95760405162461bcd60e51b815260040161029e90615a2f565b610aa681613be5565b60006129cc611d1e565b600084815260019190910160205260409020549050816129ea611d1e565b600085815260019190910160205260408082209290925590518391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff91a4505050565b6060612a568383604051806060016040528060278152602001615aa960279139613c79565b9392505050565b80612a66612c2e565b805460ff60b01b1916600160b01b836001811115612a8657612a86615037565b02179055507fd246da9440709ce0dd3f4fd669abc85ada012ab9774b8ecdcc5059ba1486b9c181604051612aba919061504d565b60405180910390a150565b612ace81613cf1565b612b2e5760405162461bcd60e51b815260206004820152602b60248201527f457874656e73696f6e4d616e616765723a2063616e6e6f74207265706c61636560448201526a1032bc3a32b739b4b7b71760a91b606482015260840161029e565b80518051612b3b91613da5565b805151612b4790613ddc565b60208101515160005b81811015612bc857612b8783600001516000015184602001518381518110612b7a57612b7a6151ff565b60200260200101516136bd565b612bb683602001518281518110612ba057612ba06151ff565b602002602001015160000151846000015161390b565b612bc160018261522b565b9050612b50565b508151604080820151915190516001600160a01b0390921691612beb91906151e3565b60405180910390207f5f1ef2b136db521971a88818ce904a8e310082338afdc100212a31270664215884604051612c229190614f90565b60405180910390a35050565b7fc0c34308b4a2f4c5ee9af8ba82541cfb3c33b076d1fd05c65f9ce7060c64c40090565b612c5b81613f85565b612cb75760405162461bcd60e51b815260206004820152602760248201527f457874656e73696f6e4d616e616765723a2063616e6e6f74206164642065787460448201526632b739b4b7b71760c91b606482015260840161029e565b80518051612cc491613da5565b60208101515160005b81811015612d2257612cf783600001516000015184602001518381518110612b7a57612b7a6151ff565b612d1083602001518281518110612ba057612ba06151ff565b612d1b60018261522b565b9050612ccd565b508151604080820151915190516001600160a01b0390921691612d4591906151e3565b60405180910390207fbb37a605de78ba6bc667aeaf438d0aae8247e6f48a8fad23730e4fbbb480abf384604051612c229190614f90565b7f4bc804ba64359c0e35e5ed5d90ee596ecaa49a3a930ddcb1470ea0dd625da90090565b612da981614047565b612e085760405162461bcd60e51b815260206004820152602a60248201527f457874656e73696f6e4d616e616765723a2063616e6e6f742072656d6f76652060448201526932bc3a32b739b4b7b71760b11b606482015260840161029e565b6000612e12611ef8565b60020182604051612e2391906151e3565b9081526040805191829003602001822060a08301825280549091839190820190839082908290612e52906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054612e7e906151af565b8015612ecb5780601f10612ea057610100808354040283529160200191612ecb565b820191906000526020600020905b815481529060010190602001808311612eae57829003601f168201915b50505050508152602001600182018054612ee4906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054612f10906151af565b8015612f5d5780601f10612f3257610100808354040283529160200191612f5d565b820191906000526020600020905b815481529060010190602001808311612f4057829003601f168201915b5050509183525050600291909101546001600160a01b03166020918201529082526003830180546040805182850281018501909152818152938301939260009084015b8282101561307d5760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b03191682526001810180549293919291840191612fec906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054613018906151af565b80156130655780601f1061303a57610100808354040283529160200191613065565b820191906000526020600020905b81548152906001019060200180831161304857829003601f168201915b50505050508152505081526020019060010190612fa0565b5050505081525050905061309082614077565b61309982613ddc565b816040516130a791906151e3565b60405180910390207f3169a23cec9ad1a25ab59bbe00ecf8973dd840c745775ea8877041ef5ce65bcc82604051611cb69190614f90565b6000806130e9613114565b6000948552602090815260408086206001600160a01b03959095168652939052505090205460ff1690565b7f0a7b0f5c59907924802379ebe98cdc23e2ee7820f63d30126e10b3752010e50090565b600061314333610f57565b15613155575060131936013560601c90565b503390565b60606000613169836002615a7a565b61317490600261522b565b6001600160401b0381111561318b5761318b6145be565b6040519080825280601f01601f1916602001820160405280156131b5576020820181803683370190505b509050600360fc1b816000815181106131d0576131d06151ff565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106131ff576131ff6151ff565b60200101906001600160f81b031916908160001a9053506000613223846002615a7a565b61322e90600161522b565b90505b60018111156132a6576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110613262576132626151ff565b1a60f81b828281518110613278576132786151ff565b60200101906001600160f81b031916908160001a90535060049490941c9361329f81615a91565b9050613231565b508315612a565760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161029e565b60016132ff611d1e565b6000848152602091825260408082206001600160a01b038616835290925220805460ff1916911515919091179055613335611d28565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006133836127bf565b600084815260209190915260409020549050600161339f6127bf565b60008581526020919091526040812080549091906133be90849061522b565b909155508290506133cd6127bf565b6000858152602091825260408082208583526001019092522080546001600160a01b0319166001600160a01b03929092169190911790558061340d6127bf565b6000948552602090815260408086206001600160a01b03909516865260029094019052919092205550565b6134428282611d32565b61344a611d1e565b6000838152602091825260408082206001600160a01b038516835290925220805460ff19169055613479611d28565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b60006134c76127bf565b6000848152602091825260408082206001600160a01b0386168352600201909252205490506134f46127bf565b6000848152602091825260408082208483526001019092522080546001600160a01b03191690556135236127bf565b6000938452602090815260408085206001600160a01b0390941685526002909301905250812055565b6000612a5683836140ab565b60008061358660017f775b9fab5634a62bb2a682c067408edbed43efd726183d2e2af744334d47acb761553b565b60405160200161359891815260200190565b60408051601f19818403018152919052805160209091012092915050565b606081600001805480602002602001604051908101604052809291908181526020016000905b828210156136885783829060005260206000200180546135fb906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054613627906151af565b80156136745780601f1061364957610100808354040283529160200191613674565b820191906000526020600020905b81548152906001019060200180831161365757829003601f168201915b5050505050815260200190600101906135dc565b505050509050919050565b60006136a183611e07611ef8565b61136b5760405162461bcd60e51b815260040161029e90615460565b80516000906001600160e01b031916613747576040516020016136fd9060208082526009908201526872656365697665282960b81b604082015260600190565b6040516020818303038152906040528051906020012082602001516040516020016137289190614fbc565b604051602081830303815290604052805190602001201415905061378e565b60208083015160405161375a92016151e3565b604051602081830303815290604052805190602001206001600160e01b03191682600001516001600160e01b031916141590505b80156137fa5760405162461bcd60e51b815260206004820152603560248201527f457874656e73696f6e4d616e616765723a20666e2073656c6563746f7220616e604482015274321039b4b3b730ba3ab9329036b4b9b6b0ba31b41760591b606482015260840161029e565b6000613804611ef8565b83516001600160e01b031916600090815260039190910160205260409020600201546001600160a01b0316146138945760405162461bcd60e51b815260206004820152602f60248201527f457874656e73696f6e4d616e616765723a2066756e6374696f6e20696d706c2060448201526e30b63932b0b23c9032bc34b9ba399760891b606482015260840161029e565b61389c611ef8565b600201836040516138ad91906151e3565b908152604051602091819003820190206003018054600180820183556000928352918390208551600290920201805463ffffffff191660e09290921c9190911781559184015184929182019061390390826156c5565b505050505050565b80613914611ef8565b6001600160e01b031984166000908152600391909101602052604090208151819061393f90826156c5565b506020820151600182019061395490826156c5565b5060409190910151600290910180546001600160a01b0319166001600160a01b039092169190911790555050565b60008060ff196139b360017f0c4ba382c0009cf238e4c1ca1a52f51c61e6248a70bdfb34e5ed49d5578a5c0c61553b565b6040516020016139c591815260200190565b60408051601f1981840301815291905280516020909101201692915050565b606061094a8260016000196140d8565b60005b815181101561098f576000828281518110613a1457613a146151ff565b60200260200101519050613a38816000015160000151613a32611ef8565b9061418d565b5080518051613a4691613da5565b60208101515160005b81811015613b1b57613a5f611ef8565b600201836000015160000151604051613a7891906151e3565b908152602001604051809103902060030183602001518281518110613a9f57613a9f6151ff565b6020908102919091018101518254600180820185556000948552938390208251600290920201805463ffffffff191660e09290921c919091178155918101519092820190613aed90826156c5565b505050613b0983602001518281518110612ba057612ba06151ff565b613b1460018261522b565b9050613a4f565b508151604080820151915190516001600160a01b0390921691613b3e91906151e3565b60405180910390207fbb37a605de78ba6bc667aeaf438d0aae8247e6f48a8fad23730e4fbbb480abf384604051613b759190614f90565b60405180910390a350613b8b905060018261522b565b90506139f7565b613b9a6128a4565b54610100900460ff16613bbf5760405162461bcd60e51b815260040161029e90615a2f565b60017f1d281c488dae143b6ea4122e80c65059929950b9c32f17fc57be22089d9c3b0055565b613bed6128a4565b54610100900460ff16613c125760405162461bcd60e51b815260040161029e90615a2f565b60005b815181101561098f576001613c286124b6565b6000016000848481518110613c3f57613c3f6151ff565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff1916911515919091179055600101613c15565b6060600080856001600160a01b031685604051613c9691906151e3565b600060405180830381855af49150503d8060008114613cd1576040519150601f19603f3d011682016040523d82523d6000602084013e613cd6565b606091505b5091509150613ce786838387614199565b9695505050505050565b805151600090613d0390611e07611ef8565b613d1f5760405162461bcd60e51b815260040161029e90615460565b8151604001516001600160a01b0316613d9d5760405162461bcd60e51b815260206004820152603a60248201527f457874656e73696f6e4d616e616765723a20616464696e6720657874656e736960448201527937b7103bb4ba3437baba1034b6b83632b6b2b73a30ba34b7b71760311b606482015260840161029e565b506001919050565b80613dae611ef8565b60020183604051613dbf91906151e3565b9081526040519081900360200190208151819061393f90826156c5565b6000613de6611ef8565b60020182604051613df791906151e3565b9081526020016040518091039020600301805480602002602001604051908101604052809291908181526020016000905b82821015613f055760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b03191682526001810180549293919291840191613e74906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054613ea0906151af565b8015613eed5780601f10613ec257610100808354040283529160200191613eed565b820191906000526020600020905b815481529060010190602001808311613ed057829003601f168201915b50505050508152505081526020019060010190613e28565b505050509050613f13611ef8565b60020182604051613f2491906151e3565b90815260200160405180910390206003016000613f4191906144eb565b60005b81518110156108c357613f73828281518110613f6257613f626151ff565b6020026020010151600001516121cf565b613f7e60018261522b565b9050613f44565b80515151600090613fd85760405162461bcd60e51b815260206004820152601d60248201527f457874656e73696f6e4d616e616765723a20656d707479206e616d652e000000604482015260640161029e565b815151613fe790613a32611ef8565b613d1f5760405162461bcd60e51b815260206004820152602b60248201527f457874656e73696f6e4d616e616765723a20657874656e73696f6e20616c726560448201526a30b23c9032bc34b9ba399760a91b606482015260840161029e565b600061405b82614055611ef8565b90614210565b613d9d5760405162461bcd60e51b815260040161029e90615460565b61407f611ef8565b6002018160405161409091906151e3565b90815260405190819003602001902060006121ff82826144b1565b600082600101826040516140bf91906151e3565b9081526040519081900360200190205415159392505050565b6060833b60008190036140fb575050604080516020810190915260008152612a56565b80841115614119575050604080516020810190915260008152612a56565b8383101561414b5760405163162544fd60e11b815260048101829052602481018590526044810184905260640161029e565b83830384820360008282106141605782614162565b815b60408051603f8301601f19168101909152818152955090508087602087018a3c505050509392505050565b6000612a56838361421c565b606083156142065782516000036141ff576141b3856128c8565b6141ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161029e565b5081610959565b610959838361427e565b6000612a5683836142a8565b600061422883836140ab565b6142765782546001810184556000848152602090200161424883826156c5565b508254604051600185019061425e9085906151e3565b9081526040519081900360200190205550600161094a565b50600061094a565b81511561428e5781518083602001fd5b8060405162461bcd60e51b815260040161029e9190614fbc565b60008083600101836040516142bd91906151e3565b90815260200160405180910390205490508060001461445d5760006142e360018361553b565b85549091506000906142f79060019061553b565b90508181146143fe576000866000018281548110614317576143176151ff565b90600052602060002001805461432c906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054614358906151af565b80156143a55780601f1061437a576101008083540402835291602001916143a5565b820191906000526020600020905b81548152906001019060200180831161438857829003601f168201915b50505050509050808760000184815481106143c2576143c26151ff565b9060005260206000200190816143d891906156c5565b508387600101826040516143ec91906151e3565b90815260405190819003602001902055505b855486908061440f5761440f615681565b60019003818190600052602060002001600061442b91906144b1565b9055856001018560405161443f91906151e3565b9081526020016040518091039020600090556001935050505061094a565b600091505061094a565b604051806040016040528061447a614487565b8152602001606081525090565b6040518060600160405280606081526020016060815260200160006001600160a01b031681525090565b5080546144bd906151af565b6000825580601f106144cd575050565b601f016020900490600052602060002090810190610aa6919061450c565b5080546000825560020290600052602060002090810190610aa69190614525565b5b80821115614521576000815560010161450d565b5090565b8082111561452157805463ffffffff19168155600061454760018301826144b1565b50600201614525565b634e487b7160e01b600052600160045260246000fd5b6001600160e01b031981168114610aa657600080fd5b60006020828403121561458e57600080fd5b8135612a5681614566565b6001600160a01b0381168114610aa657600080fd5b80356145b981614599565b919050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156145f6576145f66145be565b60405290565b604051606081016001600160401b03811182821017156145f6576145f66145be565b604051601f8201601f191681016001600160401b0381118282101715614646576146466145be565b604052919050565b60006001600160401b03821115614667576146676145be565b50601f01601f191660200190565b600082601f83011261468657600080fd5b81356146996146948261464e565b61461e565b8181528460208386010111156146ae57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156146e157600080fd5b84356146ec81614599565b935060208501356146fc81614599565b92506040850135915060608501356001600160401b0381111561471e57600080fd5b61472a87828801614675565b91505092959194509250565b6001600160e01b031991909116815260200190565b6000806040838503121561475e57600080fd5b823561476981614599565b946020939093013593505050565b60006020828403121561478957600080fd5b8135612a5681614599565b6000602082840312156147a657600080fd5b5035919050565b600080604083850312156147c057600080fd5b8235915060208301356147d281614599565b809150509250929050565b600080604083850312156147f057600080fd5b82356001600160401b0381111561480657600080fd5b61481285828601614675565b92505060208301356147d281614566565b60005b8381101561483e578181015183820152602001614826565b50506000910152565b6000815180845261485f816020860160208601614823565b601f01601f19169290920160200192915050565b60008151606084526148886060850182614847565b9050602083015184820360208601526148a18282614847565b6040948501516001600160a01b03169590940194909452509092915050565b63ffffffff60e01b815116825260006020820151604060208501526109596040850182614847565b60008151604084526148fd6040850182614873565b9050602080840151858303828701528281518085528385019150838160051b860101848401935060005b8281101561495557601f198783030184526149438286516148c0565b94860194938601939150600101614927565b5098975050505050505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156149b957603f198886030184526149a78583516148e8565b9450928501929085019060010161498b565b5092979650505050505050565b6000604082840312156149d857600080fd5b6149e06145d4565b905081356149ed81614566565b815260208201356001600160401b03811115614a0857600080fd5b614a1484828501614675565b60208301525092915050565b60008060408385031215614a3357600080fd5b82356001600160401b0380821115614a4a57600080fd5b614a5686838701614675565b93506020850135915080821115614a6c57600080fd5b50614a79858286016149c6565b9150509250929050565b60008060408385031215614a9657600080fd5b50508035926020909101359150565b600060208284031215614ab757600080fd5b81356001600160401b03811115614acd57600080fd5b61095984828501614675565b602081526000612a566020830184614873565b60006001600160401b03821115614b0557614b056145be565b5060051b60200190565b803561ffff811681146145b957600080fd5b600080600080600060a08688031215614b3957600080fd5b8535614b4481614599565b94506020868101356001600160401b0380821115614b6157600080fd5b614b6d8a838b01614675565b96506040890135915080821115614b8357600080fd5b508701601f81018913614b9557600080fd5b8035614ba361469482614aec565b81815260059190911b8201830190838101908b831115614bc257600080fd5b928401925b82841015614be9578335614bda81614599565b82529284019290840190614bc7565b8097505050505050614bfd606087016145ae565b9150614c0b60808701614b0f565b90509295509295909350565b60008060208385031215614c2a57600080fd5b82356001600160401b0380821115614c4157600080fd5b818501915085601f830112614c5557600080fd5b813581811115614c6457600080fd5b8660208260051b8501011115614c7957600080fd5b60209290920196919550909350505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156149b957603f19888603018452614cd0858351614847565b94509285019290850190600101614cb4565b600060208284031215614cf457600080fd5b813560028110612a5657600080fd5b600082601f830112614d1457600080fd5b81356020614d2461469483614aec565b8083825260208201915060208460051b870101935086841115614d4657600080fd5b602086015b84811015614d625780358352918301918301614d4b565b509695505050505050565b600080600080600060a08688031215614d8557600080fd5b8535614d9081614599565b94506020860135614da081614599565b935060408601356001600160401b0380821115614dbc57600080fd5b614dc889838a01614d03565b94506060880135915080821115614dde57600080fd5b614dea89838a01614d03565b93506080880135915080821115614e0057600080fd5b50614e0d88828901614675565b9150509295509295909350565b600082601f830112614e2b57600080fd5b81356020614e3b61469483614aec565b82815260059290921b84018101918181019086841115614e5a57600080fd5b8286015b84811015614d625780356001600160401b03811115614e7d5760008081fd5b614e8b8986838b01016149c6565b845250918301918301614e5e565b600060208284031215614eab57600080fd5b81356001600160401b0380821115614ec257600080fd5b9083019060408286031215614ed657600080fd5b614ede6145d4565b823582811115614eed57600080fd5b830160608188031215614eff57600080fd5b614f076145fc565b813584811115614f1657600080fd5b614f2289828501614675565b825250602082013584811115614f3757600080fd5b614f4389828501614675565b60208301525060408201359150614f5982614599565b60408101919091528152602083013582811115614f7557600080fd5b614f8187828601614e1a565b60208301525095945050505050565b602081526000612a5660208301846148e8565b6001600160a01b03929092168252602082015260400190565b602081526000612a566020830184614847565b600080600080600060a08688031215614fe757600080fd5b8535614ff281614599565b9450602086013561500281614599565b9350604086013592506060860135915060808601356001600160401b0381111561502b57600080fd5b614e0d88828901614675565b634e487b7160e01b600052602160045260246000fd5b602081016002831061506f57634e487b7160e01b600052602160045260246000fd5b91905290565b60008060006060848603121561508a57600080fd5b833561509581614599565b95602085013595506040909401359392505050565b604080825283519082018190526000906020906060840190828701845b828110156150ec5781516001600160a01b0316845292840192908401906001016150c7565b5050508381038285015284518082528583019183019060005b8181101561512157835183529284019291840191600101615105565b5090979650505050505050565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b60006020828403121561516857600080fd5b81518015158114612a5657600080fd5b6020808252601f908201527f457874656e73696f6e4d616e616765723a20756e617574686f72697a65642e00604082015260600190565b600181811c908216806151c357607f821691505b60208210810361182357634e487b7160e01b600052602260045260246000fd5b600082516151f5818460208701614823565b9190910192915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561094a5761094a615215565b6000808335601e1984360301811261525557600080fd5b8301803591506001600160401b0382111561526f57600080fd5b60200191503681900382131561528457600080fd5b9250929050565b8284823760609190911b6001600160601b0319169101908152601401919050565b600080604083850312156152bf57600080fd5b82516152ca81614599565b6020939093015192949293505050565b600082601f8301126152eb57600080fd5b815160206152fb61469483614aec565b8083825260208201915060208460051b87010193508684111561531d57600080fd5b602086015b84811015614d625780518352918301918301615322565b6000806040838503121561534c57600080fd5b82516001600160401b038082111561536357600080fd5b818501915085601f83011261537757600080fd5b8151602061538761469483614aec565b82815260059290921b840181019181810190898411156153a657600080fd5b948201945b838610156153cd5785516153be81614599565b825294820194908201906153ab565b918801519196509093505050808211156153e657600080fd5b50614a79858286016152da565b7402832b936b4b9b9b4b7b7399d1030b1b1b7bab73a1605d1b815260008351615423816015850160208801614823565b7001034b99036b4b9b9b4b733903937b6329607d1b6015918401918201528351615454816026840160208801614823565b01602601949350505050565b6020808252602b908201527f457874656e73696f6e4d616e616765723a20657874656e73696f6e20646f657360408201526a103737ba1032bc34b9ba1760a91b606082015260800190565b60006020808352600084546154bf816151af565b80602087015260406001808416600081146154e157600181146154fd5761552d565b60ff19851660408a0152604084151560051b8a0101955061552d565b89600052602060002060005b858110156155245781548b8201860152908301908801615509565b8a016040019650505b509398975050505050505050565b8181038181111561094a5761094a615215565b601f8211156108c3576000816000526020600020601f850160051c810160208610156155775750805b601f850160051c820191505b8181101561390357828155600101615583565b600019600383901b1c191660019190911b1790565b8181036155b6575050565b6155c082546151af565b6001600160401b038111156155d7576155d76145be565b6155eb816155e584546151af565b8461554e565b6000601f82116001811461561957600083156156075750848201545b6156118482615596565b8555506121c8565b600085815260209020601f19841690600086815260209020845b838110156156535782860154825560019586019590910190602001615633565b50858310156156715781850154600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603160045260246000fd5b6040815260006156aa60408301856148c0565b82810360208401526156bc8185614873565b95945050505050565b81516001600160401b038111156156de576156de6145be565b6156ec816155e584546151af565b602080601f83116001811461571b57600084156157095750858301515b6157138582615596565b865550613903565b600085815260208120601f198616915b8281101561574a5788860151825594840194600190910190840161572b565b508582101561567157939096015160001960f8600387901b161c19169092555050600190811b01905550565b6040815260006157896040830185614847565b82810360208401526156bc8185614847565b600082601f8301126157ac57600080fd5b81516157ba6146948261464e565b8181528460208386010111156157cf57600080fd5b610959826020830160208701614823565b600082601f8301126157f157600080fd5b8151602061580161469483614aec565b82815260059290921b8401810191818101908684111561582057600080fd5b8286015b84811015614d625780516001600160401b03808211156158445760008081fd5b908801906040828b03601f190181131561585e5760008081fd5b6158666145d4565b8784015161587381614566565b81529083015190828211156158885760008081fd5b6158968c898487010161579b565b818901528652505050918301918301615824565b6000602082840312156158bc57600080fd5b81516001600160401b03808211156158d357600080fd5b818401915084601f8301126158e757600080fd5b81516158f561469482614aec565b8082825260208201915060208360051b86010192508783111561591757600080fd5b602085015b83811015615a235780518581111561593357600080fd5b8601601f196040828c038201121561594a57600080fd5b6159526145d4565b60208301518881111561596457600080fd5b83016060818e038401121561597857600080fd5b6159806145fc565b925060208101518981111561599457600080fd5b6159a38e60208385010161579b565b8452506040810151898111156159b857600080fd5b6159c78e60208385010161579b565b602085015250606001516159da81614599565b8060408401525081815260408301519150878211156159f857600080fd5b615a078c6020848601016157e0565b602082015280865250505060208301925060208101905061591c565b50979650505050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b808202811582820484141761094a5761094a615215565b600081615aa057615aa0615215565b50600019019056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c656455add213c41f3851b4506717b8af695a4256979dff496dcaae7789f6121331aaa2646970667358221220a30be0d08718f1cc1a8a45338f5b52458867958531b0f70821d038daaacf43b664736f6c6343000817003300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081e609b897393731a3d23c1d311330340cebb9e9000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000905338301564226227b641ef13a9585f03c7b134000000000000000000000000000000000000000000000000000000000000000f446972656374204c697374696e677300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008c048dd77df000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002c617070726f76654275796572466f724c697374696e672875696e743235362c616464726573732c626f6f6c290000000000000000000000000000000000000000ea8f9a3c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000032617070726f766543757272656e6379466f724c697374696e672875696e743235362c616464726573732c75696e74323536290000000000000000000000000000704232dc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003762757946726f6d4c697374696e672875696e743235362c616464726573732c75696e743235362c616464726573732c75696e7432353629000000000000000000305a67a8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001663616e63656c4c697374696e672875696e743235362900000000000000000000746415b5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004d6372656174654c697374696e672828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743132382c75696e743132382c626f6f6c292900000000000000000000000000000000000000fb14079d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002863757272656e63795072696365466f724c697374696e672875696e743235362c6164647265737329000000000000000000000000000000000000000000000000c5275fb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001f676574416c6c4c697374696e67732875696e743235362c75696e74323536290031654b4d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024676574416c6c56616c69644c697374696e67732875696e743235362c75696e743235362900000000000000000000000000000000000000000000000000000000107a274a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000136765744c697374696e672875696e7432353629000000000000000000000000009cfbe2a6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002a69734275796572417070726f766564466f724c697374696e672875696e743235362c616464726573732900000000000000000000000000000000000000000000a8519047000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002d697343757272656e6379417070726f766564466f724c697374696e672875696e743235362c616464726573732900000000000000000000000000000000000000c78b616c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000f746f74616c4c697374696e67732829000000000000000000000000000000000007b6775800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000557570646174654c697374696e672875696e743235362c28616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743132382c75696e743132382c626f6f6c2929000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000bac8f4b67a77da77b788b391b94027330cb3193c0000000000000000000000000000000000000000000000000000000000000010456e676c6973682041756374696f6e73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005e0000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000007600858e5ad000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d626964496e41756374696f6e2875696e743235362c75696e743235362900000096b5a755000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001663616e63656c41756374696f6e2875696e743235362900000000000000000000ebf05a62000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d636f6c6c65637441756374696f6e5061796f75742875696e743235362900000003a54fe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d636f6c6c65637441756374696f6e546f6b656e732875696e743235362900000016654d40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005c63726561746541756374696f6e2828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743235362c75696e7436342c75696e7436342c75696e7436342c75696e743634292900000000c291537c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001f676574416c6c41756374696f6e732875696e743235362c75696e7432353629007b0638010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024676574416c6c56616c696441756374696f6e732875696e743235362c75696e74323536290000000000000000000000000000000000000000000000000000000078bd7935000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001367657441756374696f6e2875696e7432353629000000000000000000000000006891939d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001667657457696e6e696e674269642875696e7432353629000000000000000000001389b1170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000019697341756374696f6e457870697265642875696e7432353629000000000000002eb566bd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002069734e657757696e6e696e674269642875696e743235362c75696e743235362916002f4a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000f746f74616c41756374696f6e732829000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000fcdc4640a590d9cfdd7e15eec024aa1f578f757900000000000000000000000000000000000000000000000000000000000000064f666665727300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000420c815729d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000146163636570744f666665722875696e7432353629000000000000000000000000ef706adf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001463616e63656c4f666665722875696e7432353629000000000000000000000000c1edcfbe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d676574416c6c4f66666572732875696e743235362c75696e743235362900000091940b3e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000022676574416c6c56616c69644f66666572732875696e743235362c75696e74323536290000000000000000000000000000000000000000000000000000000000004579268a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000116765744f666665722875696e7432353629000000000000000000000000000000016767fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003c6d616b654f666665722828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e74323536292900000000a9fd8ed1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000d746f74616c4f6666657273282900000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106101ea5760003560e01c8063a0dbaefd11610109578063a0dbaefd14610587578063a217fddf146105b4578063a32fa5b3146105c9578063aaae5633146105e9578063ac9650d814610609578063b6f10c7914610636578063bc197c8114610656578063c0562f6d14610682578063c22707ee146106a2578063ca15c873146106cf578063cb2ef6f7146106ef578063ce0b601314610712578063d45573f614610732578063d547741f14610769578063e05688fe14610789578063e57553da146107a9578063e8a3d485146107cc578063ee7d2adf146107ee578063f23a6e611461080e578063f28083c31461083a578063f533b8021461085c57610229565b806301ffc9a7146102b0578063150b7a02146102e55780631e7ac4881461031257806321ede03214610332578063248a9ca3146103525780632f2ff15d1461038057806336568abe146103a0578063429eed80146103c0578063463c4864146103e05780634a00cc481461042c578063512cf9141461044e578063572b6c051461046e5780635a9ad2311461048e578063637102df146104a35780637e54523c146104cb5780638856a113146104eb5780639010d07c1461050b57806391d148541461052b578063938e3d7b1461054b578063a0a8e4601461056b57610229565b3661022957336001600160a01b037f00000000000000000000000081e609b897393731a3d23c1d311330340cebb9e9161461022757610227614550565b005b3660000361023357005b600061024a6000356001600160e01b03191661088a565b90506001600160a01b0381166102a75760405162461bcd60e51b815260206004820181905260248201527f526f757465723a2066756e6374696f6e20646f6573206e6f742065786973742e60448201526064015b60405180910390fd5b6102278161089f565b3480156102bc57600080fd5b506102d06102cb36600461457c565b6108c8565b60405190151581526020015b60405180910390f35b3480156102f157600080fd5b506103056103003660046146cb565b610950565b6040516102dc9190614736565b34801561031e57600080fd5b5061022761032d36600461474b565b610961565b34801561033e57600080fd5b5061022761034d366004614777565b610993565b34801561035e57600080fd5b5061037261036d366004614794565b610aa9565b6040519081526020016102dc565b34801561038c57600080fd5b5061022761039b3660046147ad565b610ac7565b3480156103ac57600080fd5b506102276103bb3660046147ad565b610b74565b3480156103cc57600080fd5b506102276103db3660046147dd565b610be3565b3480156103ec57600080fd5b506104147f00000000000000000000000014d4e67fb1edccbeba826830dec92c9b85ab05cb81565b6040516001600160a01b0390911681526020016102dc565b34801561043857600080fd5b50610441610e5a565b6040516102dc9190614962565b34801561045a57600080fd5b506102276104693660046147dd565b610f29565b34801561047a57600080fd5b506102d0610489366004614777565b610f57565b34801561049a57600080fd5b50610414610f83565b3480156104af57600080fd5b50610414731af20c6b23373350ad464700b5965ce4b0d2ad9481565b3480156104d757600080fd5b506102276104e636600461474b565b610fd0565b3480156104f757600080fd5b50610227610506366004614a20565b610ffe565b34801561051757600080fd5b50610414610526366004614a83565b61102c565b34801561053757600080fd5b506102d06105463660046147ad565b61113a565b34801561055757600080fd5b50610227610566366004614aa5565b61116e565b34801561057757600080fd5b50604051600381526020016102dc565b34801561059357600080fd5b506105a76105a236600461457c565b61119b565b6040516102dc9190614ad9565b3480156105c057600080fd5b50610372600081565b3480156105d557600080fd5b506102d06105e43660046147ad565b611311565b3480156105f557600080fd5b50610227610604366004614b21565b611374565b34801561061557600080fd5b50610629610624366004614c17565b6115ae565b6040516102dc9190614c8b565b34801561064257600080fd5b50610227610651366004614ce2565b611721565b34801561066257600080fd5b50610305610671366004614d6d565b63bc197c8160e01b95945050505050565b34801561068e57600080fd5b5061022761069d366004614e99565b61174e565b3480156106ae57600080fd5b506106c26106bd366004614aa5565b61177b565b6040516102dc9190614f90565b3480156106db57600080fd5b506103726106ea366004614794565b61178c565b3480156106fb57600080fd5b506c4d61726b6574706c616365563360981b610372565b34801561071e57600080fd5b5061041461072d36600461457c565b61088a565b34801561073e57600080fd5b50610747611829565b604080516001600160a01b03909316835261ffff9091166020830152016102dc565b34801561077557600080fd5b506102276107843660046147ad565b61185b565b34801561079557600080fd5b506102276107a4366004614e99565b611866565b3480156107b557600080fd5b506107be611893565b6040516102dc929190614fa3565b3480156107d857600080fd5b506107e16118bc565b6040516102dc9190614fbc565b3480156107fa57600080fd5b50610227610809366004614aa5565b611954565b34801561081a57600080fd5b50610305610829366004614fcf565b63f23a6e6160e01b95945050505050565b34801561084657600080fd5b5061084f611981565b6040516102dc919061504d565b34801561086857600080fd5b5061087c610877366004615075565b61199b565b6040516102dc9291906150aa565b60006108958261119b565b6040015192915050565b3660008037600080366000845af43d6000803e8080156108be573d6000f35b3d6000fd5b505050565b60006001600160e01b03198216630271189760e51b14806108f957506001600160e01b03198216630a85bd0160e11b145b8061091457506001600160e01b0319821663ce0b601360e01b145b8061092f57506001600160e01b03198216630940198960e31b145b8061094a57506301ffc9a760e01b6001600160e01b03198316145b92915050565b630a85bd0160e11b5b949350505050565b610969611b95565b6109855760405162461bcd60e51b815260040161029e9061512e565b61098f8282611bad565b5050565b61099b611b95565b6109b75760405162461bcd60e51b815260040161029e9061512e565b6001600160a01b03811615801590610a3e57506040516301ffc9a760e01b81526001600160a01b038216906301ffc9a7906109fd90636591fc0b60e11b90600401614736565b602060405180830381865afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e9190615156565b610a9d5760405162461bcd60e51b815260206004820152602a60248201527f446f65736e277420737570706f72742049526f79616c7479456e67696e65563160448201526920696e7465726661636560b01b606482015260840161029e565b610aa681611cc2565b50565b6000610ab3611d1e565b600092835260010160205250604090205490565b610af2610ad2611d1e565b60008481526001919091016020526040902054610aed611d28565b611d32565b610afa611d1e565b6000838152602091825260408082206001600160a01b0385168352909252205460ff1615610b6a5760405162461bcd60e51b815260206004820152601d60248201527f43616e206f6e6c79206772616e7420746f206e6f6e20686f6c64657273000000604482015260640161029e565b61098f8282611db7565b806001600160a01b0316610b86611d28565b6001600160a01b031614610bd95760405162461bcd60e51b815260206004820152601a60248201527921b0b71037b7363c903932b737bab731b2903337b91039b2b63360311b604482015260640161029e565b61098f8282611dcb565b610beb611ddf565b610c075760405162461bcd60e51b815260040161029e90615178565b610c118282611df9565b610c7e5760405162461bcd60e51b815260206004820152603860248201527f457874656e73696f6e4d616e616765723a2063616e6e6f742072656d6f766520604482015277333ab731ba34b7b710333937b69032bc3a32b739b4b7b71760411b606482015260840161029e565b6000610c88611ef8565b6001600160e01b031983166000908152600391909101602052604090819020815160608101909252805482908290610cbf906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054610ceb906151af565b8015610d385780601f10610d0d57610100808354040283529160200191610d38565b820191906000526020600020905b815481529060010190602001808311610d1b57829003601f168201915b50505050508152602001600182018054610d51906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7d906151af565b8015610dca5780601f10610d9f57610100808354040283529160200191610dca565b820191906000526020600020905b815481529060010190602001808311610dad57829003601f168201915b5050509183525050600291909101546001600160a01b03166020909101529050610df48383611f02565b610dfd826121cf565b816001600160e01b03191683604051610e1691906151e3565b60405180910390207fbb931a9651175c9c82f86afbf6ad37a9141aa8d1d42bf798739be245a12e4e8883604051610e4d9190614ad9565b60405180910390a3505050565b60606000610e6e610e69611ef8565b612222565b8051909150806001600160401b03811115610e8b57610e8b6145be565b604051908082528060200260200182016040528015610ec457816020015b610eb1614467565b815260200190600190039081610ea95790505b50925060005b81811015610f2357610ef4838281518110610ee757610ee76151ff565b602002602001015161222d565b848281518110610f0657610f066151ff565b6020908102919091010152610f1c60018261522b565b9050610eca565b50505090565b610f31611ddf565b610f4d5760405162461bcd60e51b815260040161029e90615178565b61098f8282610be3565b6000610f616124b6565b6001600160a01b03909216600090815260209290925250604090205460ff1690565b600080610f8e6124da565b80549091506001600160a01b031680610fc7577f0000000000000000000000000000000000000000000000000000000000000000610fc9565b805b9250505090565b610fd8611b95565b610ff45760405162461bcd60e51b815260040161029e9061512e565b61098f82826124fe565b611006611ddf565b6110225760405162461bcd60e51b815260040161029e90615178565b61098f8282612570565b6000806110376127bf565b600085815260209190915260408120549150805b8281101561113157600061105d6127bf565b60008881526020918252604080822085835260010190925220546001600160a01b0316146110d5578482036110c3576110946127bf565b600087815260209182526040808220938252600190930190915220546001600160a01b0316925061094a915050565b6110ce60018361522b565b915061111f565b6110e086600061113a565b801561110c57506110ef6127bf565b600087815260209182526040808220828052600201909252205481145b1561111f5761111c60018361522b565b91505b61112a60018261522b565b905061104b565b50505092915050565b6000611144611d1e565b6000938452602090815260408085206001600160a01b039490941685529290525090205460ff1690565b611176611b95565b6111925760405162461bcd60e51b815260040161029e9061512e565b610aa6816127c9565b6111a3614487565b6111ab611ef8565b6001600160e01b0319831660009081526003919091016020526040908190208151606081019092528054829082906111e2906151af565b80601f016020809104026020016040519081016040528092919081815260200182805461120e906151af565b801561125b5780601f106112305761010080835404028352916020019161125b565b820191906000526020600020905b81548152906001019060200180831161123e57829003601f168201915b50505050508152602001600182018054611274906151af565b80601f01602080910402602001604051908101604052809291908181526020018280546112a0906151af565b80156112ed5780601f106112c2576101008083540402835291602001916112ed565b820191906000526020600020905b8154815290600101906020018083116112d057829003601f168201915b5050509183525050600291909101546001600160a01b031660209091015292915050565b600061131b611d1e565b600084815260209182526040808220828052909252205460ff1661136b57611341611d1e565b6000848152602091825260408082206001600160a01b0386168352909252205460ff16905061094a565b50600192915050565b600061137e6128a4565b5460ff169050600061138e6128a4565b54610100900460ff16905080158080156113ab575060018360ff16105b806113ca57506113ba306128c8565b1580156113ca57508260ff166001145b61142d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161029e565b60016114376128a4565b805460ff191660ff9290921691909117905580156114705760016114596128a4565b80549115156101000261ff00199092169190911790555b6114786128d7565b611480612955565b6114898661298c565b611492876127c9565b6114a0858561ffff16611bad565b6114ab600089611db7565b6114c3600080516020615ad083398151915289611db7565b6114ee7ff94103142c1baabe9ac2b5d1487bf783de9e69cfeea9a72f5c9c94afd7877b8c6000611db7565b6115197f86d5cf0a6bdc8d859ba3bdc97043337c82a0e609035f378e419298b6a3e00ae66000611db7565b611531600080516020615ad083398151915289611db7565b611549600080516020615ad0833981519152806129c2565b80156115a45760006115596128a4565b80549115156101000261ff0019909216919091179055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6060816001600160401b038111156115c8576115c86145be565b6040519080825280602002602001820160405280156115fb57816020015b60608152602001906001900390816115e65790505b5090506000611608611d28565b9050336001600160a01b038216141560005b84811015611131578115611699576116773087878481811061163e5761163e6151ff565b9050602002810190611650919061523e565b866040516020016116639392919061528b565b604051602081830303815290604052612a31565b848281518110611689576116896151ff565b6020026020010181905250611719565b6116fb308787848181106116af576116af6151ff565b90506020028101906116c1919061523e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612a3192505050565b84828151811061170d5761170d6151ff565b60200260200101819052505b60010161161a565b611729611b95565b6117455760405162461bcd60e51b815260040161029e9061512e565b610aa681612a5d565b611756611ddf565b6117725760405162461bcd60e51b815260040161029e90615178565b610aa681612ac5565b611783614467565b61094a8261222d565b6000806117976127bf565b6000848152602091909152604081205491505b818110156118045760006117bc6127bf565b60008681526020918252604080822085835260010190925220546001600160a01b0316146117f2576117ef60018461522b565b92505b6117fd60018261522b565b90506117aa565b5061181083600061113a565b156118235761182060018361522b565b91505b50919050565b600080611834612c2e565b546001600160a01b0316611846612c2e565b549093600160a01b90910461ffff1692509050565b610bd9610ad2611d1e565b61186e611ddf565b61188a5760405162461bcd60e51b815260040161029e90615178565b610aa681612c52565b60008061189e612c2e565b546001600160a01b03166118b0612c2e565b60010154915091509091565b60606118c6612d7c565b80546118d1906151af565b80601f01602080910402602001604051908101604052809291908181526020018280546118fd906151af565b801561194a5780601f1061191f5761010080835404028352916020019161194a565b820191906000526020600020905b81548152906001019060200180831161192d57829003601f168201915b5050505050905090565b61195c611ddf565b6119785760405162461bcd60e51b815260040161029e90615178565b610aa681612da0565b600061198b612c2e565b54600160b01b900460ff16919050565b60608060006119a8610f83565b90506001600160a01b038116611b085760405163152a902d60e11b815260048101869052602481018590526001600160a01b03871690632a55205a906044016040805180830381865afa925050508015611a1f575060408051601f3d908101601f19168201909252611a1c918101906152ac565b60015b15611b8c5785811115611a6d5760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081c9bde585b1d1e48185b5bdd5b9d60521b604482015260640161029e565b604080516001808252818301909252906020808301908036833750506040805160018082528183019092529297509050602080830190803683370190505093508185600081518110611ac157611ac16151ff565b60200260200101906001600160a01b031690816001600160a01b0316815250508084600081518110611af557611af56151ff565b6020026020010181815250505050611b8c565b604051637a99dc0160e11b81526001600160a01b038781166004830152602482018790526044820186905282169063f533b802906064016000604051808303816000875af1158015611b5e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b869190810190615339565b90935091505b50935093915050565b6000611ba881611ba3611d28565b6130de565b905090565b612710811115611bf15760405162461bcd60e51b815260206004820152600f60248201526e45786365656473206d61782062707360881b604482015260640161029e565b6001600160a01b038216611c3b5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b604482015260640161029e565b80611c44612c2e565b805461ffff92909216600160a01b0261ffff60a01b1990921691909117905581611c6c612c2e565b80546001600160a01b0319166001600160a01b03928316179055604051828152908316907fe2497bd806ec41a6e0dd992c29a72efc0ef8fec9092d1978fd4a1e00b2f18304906020015b60405180910390a25050565b6000611ccc6124da565b80546001600160a01b038481166001600160a01b031983168117845560405193945091169182907fdb773077c54b973d26a2973b12d9e7e458768cbf218f12160d3ea5f015820ef990600090a3505050565b6000611ba8613114565b6000611ba8613138565b611d3a611d1e565b6000838152602091825260408082206001600160a01b0385168352909252205460ff1661098f57611d75816001600160a01b0316601461315a565b611d8083602061315a565b604051602001611d919291906153f3565b60408051601f198184030181529082905262461bcd60e51b825261029e91600401614fbc565b611dc182826132f5565b61098f8282613379565b611dd58282613438565b61098f82826134bd565b6000611ba8600080516020615ad0833981519152336130de565b6000611e0d83611e07611ef8565b9061354c565b611e295760405162461bcd60e51b815260040161029e90615460565b82604051602001611e3a9190614fbc565b60405160208183030381529060405280519060200120611e58611ef8565b6001600160e01b03198416600090815260039190910160209081526040918290209151611e869291016154ab565b604051602081830303815290604052805190602001201461136b5760405162461bcd60e51b815260206004820152602660248201527f457874656e73696f6e4d616e616765723a20696e636f727265637420657874656044820152653739b4b7b71760d11b606482015260840161029e565b6000611ba8613558565b6000611f0c611ef8565b60020183604051611f1d91906151e3565b9081526020016040518091039020600301805480602002602001604051908101604052809291908181526020016000905b8282101561202b5760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b03191682526001810180549293919291840191611f9a906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054611fc6906151af565b80156120135780601f10611fe857610100808354040283529160200191612013565b820191906000526020600020905b815481529060010190602001808311611ff657829003601f168201915b50505050508152505081526020019060010190611f4e565b5050825192935060009150505b818110156121c857836001600160e01b03191683828151811061205d5761205d6151ff565b6020026020010151600001516001600160e01b031916036121b657612080611ef8565b6002018560405161209191906151e3565b9081526040519081900360200190206003016120ae60018461553b565b815481106120be576120be6151ff565b90600052602060002090600202016120d4611ef8565b600201866040516120e591906151e3565b90815260200160405180910390206003018281548110612107576121076151ff565b600091825260209091208254600290920201805463ffffffff191663ffffffff909216919091178155600180820190612142908401826155ab565b5090505061214e611ef8565b6002018560405161215f91906151e3565b908152602001604051809103902060030180548061217f5761217f615681565b600082815260208120600260001990930192830201805463ffffffff19168155906121ad60018301826144b1565b505090556121c8565b6121c160018261522b565b9050612038565b5050505050565b6121d7611ef8565b6001600160e01b03198216600090815260039190910160205260408120906121ff82826144b1565b61220d6001830160006144b1565b5060020180546001600160a01b031916905550565b606061094a826135b6565b612235614467565b61223d611ef8565b6002018260405161224e91906151e3565b9081526040805191829003602001822060a0830182528054909183919082019083908290829061227d906151af565b80601f01602080910402602001604051908101604052809291908181526020018280546122a9906151af565b80156122f65780601f106122cb576101008083540402835291602001916122f6565b820191906000526020600020905b8154815290600101906020018083116122d957829003601f168201915b5050505050815260200160018201805461230f906151af565b80601f016020809104026020016040519081016040528092919081815260200182805461233b906151af565b80156123885780601f1061235d57610100808354040283529160200191612388565b820191906000526020600020905b81548152906001019060200180831161236b57829003601f168201915b5050509183525050600291909101546001600160a01b03166020918201529082526003830180546040805182850281018501909152818152938301939260009084015b828210156124a85760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b03191682526001810180549293919291840191612417906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054612443906151af565b80156124905780601f1061246557610100808354040283529160200191612490565b820191906000526020600020905b81548152906001019060200180831161247357829003601f168201915b505050505081525050815260200190600101906123cb565b505050915250909392505050565b7f82aadcdf5bea62fd30615b6c0754b644e71b6c1e8c55b71bb927ad005b504f0090565b7fc802b338f3fb784853cf3c808df5ff08335200e394ea2c687d12571a9104500090565b80612507612c2e565b6001015581612514612c2e565b80546001600160a01b0319166001600160a01b03929092169190911790556040517ff8086cee80709bd44c82f89dbca54115ebd05e840a88ab81df9cf5be9754eb63906125649084908490614fa3565b60405180910390a15050565b61257a8282613693565b6125e65760405162461bcd60e51b815260206004820152603760248201527f457874656e73696f6e4d616e616765723a2063616e6e6f742053746f72653a20604482015276333ab731ba34b7b7103337b91032bc3a32b739b4b7b71760491b606482015260840161029e565b6125f082826136bd565b60006125fa611ef8565b6002018360405161260b91906151e3565b9081526040805191829003602001822060608301909152805482908290612631906151af565b80601f016020809104026020016040519081016040528092919081815260200182805461265d906151af565b80156126aa5780601f1061267f576101008083540402835291602001916126aa565b820191906000526020600020905b81548152906001019060200180831161268d57829003601f168201915b505050505081526020016001820180546126c3906151af565b80601f01602080910402602001604051908101604052809291908181526020018280546126ef906151af565b801561273c5780601f106127115761010080835404028352916020019161273c565b820191906000526020600020905b81548152906001019060200180831161271f57829003601f168201915b5050509183525050600291909101546001600160a01b03166020909101528251909150612769908261390b565b81600001516001600160e01b0319168360405161278691906151e3565b60405180910390207f681115194e519bda23de4da5218f3bc38f5585eab7c6b7d5fa66caa4602f574d8484604051610e4d929190615697565b6000611ba8613982565b60006127d3612d7c565b80546127de906151af565b80601f016020809104026020016040519081016040528092919081815260200182805461280a906151af565b80156128575780601f1061282c57610100808354040283529160200191612857565b820191906000526020600020905b81548152906001019060200180831161283a57829003601f168201915b5050505050905081612867612d7c565b9061287290826156c5565b507fc9c7c3fe08b88b4df9d4d47ef47d2c43d55c025a0ba88ca442580ed9e7348a168183604051612564929190615776565b7f322cf19c484104d3b1a9c2982ebae869ede3fa5f6c4703ca41b9a48c76ee030090565b6001600160a01b03163b151590565b7f00000000000000000000000014d4e67fb1edccbeba826830dec92c9b85ab05cb6001600160a01b031661290757565b60006129327f00000000000000000000000014d4e67fb1edccbeba826830dec92c9b85ab05cb6139e4565b905060008180602001905181019061294a91906158aa565b905061098f816139f4565b61295d6128a4565b54610100900460ff166129825760405162461bcd60e51b815260040161029e90615a2f565b61298a613b92565b565b6129946128a4565b54610100900460ff166129b95760405162461bcd60e51b815260040161029e90615a2f565b610aa681613be5565b60006129cc611d1e565b600084815260019190910160205260409020549050816129ea611d1e565b600085815260019190910160205260408082209290925590518391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff91a4505050565b6060612a568383604051806060016040528060278152602001615aa960279139613c79565b9392505050565b80612a66612c2e565b805460ff60b01b1916600160b01b836001811115612a8657612a86615037565b02179055507fd246da9440709ce0dd3f4fd669abc85ada012ab9774b8ecdcc5059ba1486b9c181604051612aba919061504d565b60405180910390a150565b612ace81613cf1565b612b2e5760405162461bcd60e51b815260206004820152602b60248201527f457874656e73696f6e4d616e616765723a2063616e6e6f74207265706c61636560448201526a1032bc3a32b739b4b7b71760a91b606482015260840161029e565b80518051612b3b91613da5565b805151612b4790613ddc565b60208101515160005b81811015612bc857612b8783600001516000015184602001518381518110612b7a57612b7a6151ff565b60200260200101516136bd565b612bb683602001518281518110612ba057612ba06151ff565b602002602001015160000151846000015161390b565b612bc160018261522b565b9050612b50565b508151604080820151915190516001600160a01b0390921691612beb91906151e3565b60405180910390207f5f1ef2b136db521971a88818ce904a8e310082338afdc100212a31270664215884604051612c229190614f90565b60405180910390a35050565b7fc0c34308b4a2f4c5ee9af8ba82541cfb3c33b076d1fd05c65f9ce7060c64c40090565b612c5b81613f85565b612cb75760405162461bcd60e51b815260206004820152602760248201527f457874656e73696f6e4d616e616765723a2063616e6e6f74206164642065787460448201526632b739b4b7b71760c91b606482015260840161029e565b80518051612cc491613da5565b60208101515160005b81811015612d2257612cf783600001516000015184602001518381518110612b7a57612b7a6151ff565b612d1083602001518281518110612ba057612ba06151ff565b612d1b60018261522b565b9050612ccd565b508151604080820151915190516001600160a01b0390921691612d4591906151e3565b60405180910390207fbb37a605de78ba6bc667aeaf438d0aae8247e6f48a8fad23730e4fbbb480abf384604051612c229190614f90565b7f4bc804ba64359c0e35e5ed5d90ee596ecaa49a3a930ddcb1470ea0dd625da90090565b612da981614047565b612e085760405162461bcd60e51b815260206004820152602a60248201527f457874656e73696f6e4d616e616765723a2063616e6e6f742072656d6f76652060448201526932bc3a32b739b4b7b71760b11b606482015260840161029e565b6000612e12611ef8565b60020182604051612e2391906151e3565b9081526040805191829003602001822060a08301825280549091839190820190839082908290612e52906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054612e7e906151af565b8015612ecb5780601f10612ea057610100808354040283529160200191612ecb565b820191906000526020600020905b815481529060010190602001808311612eae57829003601f168201915b50505050508152602001600182018054612ee4906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054612f10906151af565b8015612f5d5780601f10612f3257610100808354040283529160200191612f5d565b820191906000526020600020905b815481529060010190602001808311612f4057829003601f168201915b5050509183525050600291909101546001600160a01b03166020918201529082526003830180546040805182850281018501909152818152938301939260009084015b8282101561307d5760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b03191682526001810180549293919291840191612fec906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054613018906151af565b80156130655780601f1061303a57610100808354040283529160200191613065565b820191906000526020600020905b81548152906001019060200180831161304857829003601f168201915b50505050508152505081526020019060010190612fa0565b5050505081525050905061309082614077565b61309982613ddc565b816040516130a791906151e3565b60405180910390207f3169a23cec9ad1a25ab59bbe00ecf8973dd840c745775ea8877041ef5ce65bcc82604051611cb69190614f90565b6000806130e9613114565b6000948552602090815260408086206001600160a01b03959095168652939052505090205460ff1690565b7f0a7b0f5c59907924802379ebe98cdc23e2ee7820f63d30126e10b3752010e50090565b600061314333610f57565b15613155575060131936013560601c90565b503390565b60606000613169836002615a7a565b61317490600261522b565b6001600160401b0381111561318b5761318b6145be565b6040519080825280601f01601f1916602001820160405280156131b5576020820181803683370190505b509050600360fc1b816000815181106131d0576131d06151ff565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106131ff576131ff6151ff565b60200101906001600160f81b031916908160001a9053506000613223846002615a7a565b61322e90600161522b565b90505b60018111156132a6576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110613262576132626151ff565b1a60f81b828281518110613278576132786151ff565b60200101906001600160f81b031916908160001a90535060049490941c9361329f81615a91565b9050613231565b508315612a565760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161029e565b60016132ff611d1e565b6000848152602091825260408082206001600160a01b038616835290925220805460ff1916911515919091179055613335611d28565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006133836127bf565b600084815260209190915260409020549050600161339f6127bf565b60008581526020919091526040812080549091906133be90849061522b565b909155508290506133cd6127bf565b6000858152602091825260408082208583526001019092522080546001600160a01b0319166001600160a01b03929092169190911790558061340d6127bf565b6000948552602090815260408086206001600160a01b03909516865260029094019052919092205550565b6134428282611d32565b61344a611d1e565b6000838152602091825260408082206001600160a01b038516835290925220805460ff19169055613479611d28565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b60006134c76127bf565b6000848152602091825260408082206001600160a01b0386168352600201909252205490506134f46127bf565b6000848152602091825260408082208483526001019092522080546001600160a01b03191690556135236127bf565b6000938452602090815260408085206001600160a01b0390941685526002909301905250812055565b6000612a5683836140ab565b60008061358660017f775b9fab5634a62bb2a682c067408edbed43efd726183d2e2af744334d47acb761553b565b60405160200161359891815260200190565b60408051601f19818403018152919052805160209091012092915050565b606081600001805480602002602001604051908101604052809291908181526020016000905b828210156136885783829060005260206000200180546135fb906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054613627906151af565b80156136745780601f1061364957610100808354040283529160200191613674565b820191906000526020600020905b81548152906001019060200180831161365757829003601f168201915b5050505050815260200190600101906135dc565b505050509050919050565b60006136a183611e07611ef8565b61136b5760405162461bcd60e51b815260040161029e90615460565b80516000906001600160e01b031916613747576040516020016136fd9060208082526009908201526872656365697665282960b81b604082015260600190565b6040516020818303038152906040528051906020012082602001516040516020016137289190614fbc565b604051602081830303815290604052805190602001201415905061378e565b60208083015160405161375a92016151e3565b604051602081830303815290604052805190602001206001600160e01b03191682600001516001600160e01b031916141590505b80156137fa5760405162461bcd60e51b815260206004820152603560248201527f457874656e73696f6e4d616e616765723a20666e2073656c6563746f7220616e604482015274321039b4b3b730ba3ab9329036b4b9b6b0ba31b41760591b606482015260840161029e565b6000613804611ef8565b83516001600160e01b031916600090815260039190910160205260409020600201546001600160a01b0316146138945760405162461bcd60e51b815260206004820152602f60248201527f457874656e73696f6e4d616e616765723a2066756e6374696f6e20696d706c2060448201526e30b63932b0b23c9032bc34b9ba399760891b606482015260840161029e565b61389c611ef8565b600201836040516138ad91906151e3565b908152604051602091819003820190206003018054600180820183556000928352918390208551600290920201805463ffffffff191660e09290921c9190911781559184015184929182019061390390826156c5565b505050505050565b80613914611ef8565b6001600160e01b031984166000908152600391909101602052604090208151819061393f90826156c5565b506020820151600182019061395490826156c5565b5060409190910151600290910180546001600160a01b0319166001600160a01b039092169190911790555050565b60008060ff196139b360017f0c4ba382c0009cf238e4c1ca1a52f51c61e6248a70bdfb34e5ed49d5578a5c0c61553b565b6040516020016139c591815260200190565b60408051601f1981840301815291905280516020909101201692915050565b606061094a8260016000196140d8565b60005b815181101561098f576000828281518110613a1457613a146151ff565b60200260200101519050613a38816000015160000151613a32611ef8565b9061418d565b5080518051613a4691613da5565b60208101515160005b81811015613b1b57613a5f611ef8565b600201836000015160000151604051613a7891906151e3565b908152602001604051809103902060030183602001518281518110613a9f57613a9f6151ff565b6020908102919091018101518254600180820185556000948552938390208251600290920201805463ffffffff191660e09290921c919091178155918101519092820190613aed90826156c5565b505050613b0983602001518281518110612ba057612ba06151ff565b613b1460018261522b565b9050613a4f565b508151604080820151915190516001600160a01b0390921691613b3e91906151e3565b60405180910390207fbb37a605de78ba6bc667aeaf438d0aae8247e6f48a8fad23730e4fbbb480abf384604051613b759190614f90565b60405180910390a350613b8b905060018261522b565b90506139f7565b613b9a6128a4565b54610100900460ff16613bbf5760405162461bcd60e51b815260040161029e90615a2f565b60017f1d281c488dae143b6ea4122e80c65059929950b9c32f17fc57be22089d9c3b0055565b613bed6128a4565b54610100900460ff16613c125760405162461bcd60e51b815260040161029e90615a2f565b60005b815181101561098f576001613c286124b6565b6000016000848481518110613c3f57613c3f6151ff565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff1916911515919091179055600101613c15565b6060600080856001600160a01b031685604051613c9691906151e3565b600060405180830381855af49150503d8060008114613cd1576040519150601f19603f3d011682016040523d82523d6000602084013e613cd6565b606091505b5091509150613ce786838387614199565b9695505050505050565b805151600090613d0390611e07611ef8565b613d1f5760405162461bcd60e51b815260040161029e90615460565b8151604001516001600160a01b0316613d9d5760405162461bcd60e51b815260206004820152603a60248201527f457874656e73696f6e4d616e616765723a20616464696e6720657874656e736960448201527937b7103bb4ba3437baba1034b6b83632b6b2b73a30ba34b7b71760311b606482015260840161029e565b506001919050565b80613dae611ef8565b60020183604051613dbf91906151e3565b9081526040519081900360200190208151819061393f90826156c5565b6000613de6611ef8565b60020182604051613df791906151e3565b9081526020016040518091039020600301805480602002602001604051908101604052809291908181526020016000905b82821015613f055760008481526020908190206040805180820190915260028502909101805460e01b6001600160e01b03191682526001810180549293919291840191613e74906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054613ea0906151af565b8015613eed5780601f10613ec257610100808354040283529160200191613eed565b820191906000526020600020905b815481529060010190602001808311613ed057829003601f168201915b50505050508152505081526020019060010190613e28565b505050509050613f13611ef8565b60020182604051613f2491906151e3565b90815260200160405180910390206003016000613f4191906144eb565b60005b81518110156108c357613f73828281518110613f6257613f626151ff565b6020026020010151600001516121cf565b613f7e60018261522b565b9050613f44565b80515151600090613fd85760405162461bcd60e51b815260206004820152601d60248201527f457874656e73696f6e4d616e616765723a20656d707479206e616d652e000000604482015260640161029e565b815151613fe790613a32611ef8565b613d1f5760405162461bcd60e51b815260206004820152602b60248201527f457874656e73696f6e4d616e616765723a20657874656e73696f6e20616c726560448201526a30b23c9032bc34b9ba399760a91b606482015260840161029e565b600061405b82614055611ef8565b90614210565b613d9d5760405162461bcd60e51b815260040161029e90615460565b61407f611ef8565b6002018160405161409091906151e3565b90815260405190819003602001902060006121ff82826144b1565b600082600101826040516140bf91906151e3565b9081526040519081900360200190205415159392505050565b6060833b60008190036140fb575050604080516020810190915260008152612a56565b80841115614119575050604080516020810190915260008152612a56565b8383101561414b5760405163162544fd60e11b815260048101829052602481018590526044810184905260640161029e565b83830384820360008282106141605782614162565b815b60408051603f8301601f19168101909152818152955090508087602087018a3c505050509392505050565b6000612a56838361421c565b606083156142065782516000036141ff576141b3856128c8565b6141ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161029e565b5081610959565b610959838361427e565b6000612a5683836142a8565b600061422883836140ab565b6142765782546001810184556000848152602090200161424883826156c5565b508254604051600185019061425e9085906151e3565b9081526040519081900360200190205550600161094a565b50600061094a565b81511561428e5781518083602001fd5b8060405162461bcd60e51b815260040161029e9190614fbc565b60008083600101836040516142bd91906151e3565b90815260200160405180910390205490508060001461445d5760006142e360018361553b565b85549091506000906142f79060019061553b565b90508181146143fe576000866000018281548110614317576143176151ff565b90600052602060002001805461432c906151af565b80601f0160208091040260200160405190810160405280929190818152602001828054614358906151af565b80156143a55780601f1061437a576101008083540402835291602001916143a5565b820191906000526020600020905b81548152906001019060200180831161438857829003601f168201915b50505050509050808760000184815481106143c2576143c26151ff565b9060005260206000200190816143d891906156c5565b508387600101826040516143ec91906151e3565b90815260405190819003602001902055505b855486908061440f5761440f615681565b60019003818190600052602060002001600061442b91906144b1565b9055856001018560405161443f91906151e3565b9081526020016040518091039020600090556001935050505061094a565b600091505061094a565b604051806040016040528061447a614487565b8152602001606081525090565b6040518060600160405280606081526020016060815260200160006001600160a01b031681525090565b5080546144bd906151af565b6000825580601f106144cd575050565b601f016020900490600052602060002090810190610aa6919061450c565b5080546000825560020290600052602060002090810190610aa69190614525565b5b80821115614521576000815560010161450d565b5090565b8082111561452157805463ffffffff19168155600061454760018301826144b1565b50600201614525565b634e487b7160e01b600052600160045260246000fd5b6001600160e01b031981168114610aa657600080fd5b60006020828403121561458e57600080fd5b8135612a5681614566565b6001600160a01b0381168114610aa657600080fd5b80356145b981614599565b919050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156145f6576145f66145be565b60405290565b604051606081016001600160401b03811182821017156145f6576145f66145be565b604051601f8201601f191681016001600160401b0381118282101715614646576146466145be565b604052919050565b60006001600160401b03821115614667576146676145be565b50601f01601f191660200190565b600082601f83011261468657600080fd5b81356146996146948261464e565b61461e565b8181528460208386010111156146ae57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156146e157600080fd5b84356146ec81614599565b935060208501356146fc81614599565b92506040850135915060608501356001600160401b0381111561471e57600080fd5b61472a87828801614675565b91505092959194509250565b6001600160e01b031991909116815260200190565b6000806040838503121561475e57600080fd5b823561476981614599565b946020939093013593505050565b60006020828403121561478957600080fd5b8135612a5681614599565b6000602082840312156147a657600080fd5b5035919050565b600080604083850312156147c057600080fd5b8235915060208301356147d281614599565b809150509250929050565b600080604083850312156147f057600080fd5b82356001600160401b0381111561480657600080fd5b61481285828601614675565b92505060208301356147d281614566565b60005b8381101561483e578181015183820152602001614826565b50506000910152565b6000815180845261485f816020860160208601614823565b601f01601f19169290920160200192915050565b60008151606084526148886060850182614847565b9050602083015184820360208601526148a18282614847565b6040948501516001600160a01b03169590940194909452509092915050565b63ffffffff60e01b815116825260006020820151604060208501526109596040850182614847565b60008151604084526148fd6040850182614873565b9050602080840151858303828701528281518085528385019150838160051b860101848401935060005b8281101561495557601f198783030184526149438286516148c0565b94860194938601939150600101614927565b5098975050505050505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156149b957603f198886030184526149a78583516148e8565b9450928501929085019060010161498b565b5092979650505050505050565b6000604082840312156149d857600080fd5b6149e06145d4565b905081356149ed81614566565b815260208201356001600160401b03811115614a0857600080fd5b614a1484828501614675565b60208301525092915050565b60008060408385031215614a3357600080fd5b82356001600160401b0380821115614a4a57600080fd5b614a5686838701614675565b93506020850135915080821115614a6c57600080fd5b50614a79858286016149c6565b9150509250929050565b60008060408385031215614a9657600080fd5b50508035926020909101359150565b600060208284031215614ab757600080fd5b81356001600160401b03811115614acd57600080fd5b61095984828501614675565b602081526000612a566020830184614873565b60006001600160401b03821115614b0557614b056145be565b5060051b60200190565b803561ffff811681146145b957600080fd5b600080600080600060a08688031215614b3957600080fd5b8535614b4481614599565b94506020868101356001600160401b0380821115614b6157600080fd5b614b6d8a838b01614675565b96506040890135915080821115614b8357600080fd5b508701601f81018913614b9557600080fd5b8035614ba361469482614aec565b81815260059190911b8201830190838101908b831115614bc257600080fd5b928401925b82841015614be9578335614bda81614599565b82529284019290840190614bc7565b8097505050505050614bfd606087016145ae565b9150614c0b60808701614b0f565b90509295509295909350565b60008060208385031215614c2a57600080fd5b82356001600160401b0380821115614c4157600080fd5b818501915085601f830112614c5557600080fd5b813581811115614c6457600080fd5b8660208260051b8501011115614c7957600080fd5b60209290920196919550909350505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156149b957603f19888603018452614cd0858351614847565b94509285019290850190600101614cb4565b600060208284031215614cf457600080fd5b813560028110612a5657600080fd5b600082601f830112614d1457600080fd5b81356020614d2461469483614aec565b8083825260208201915060208460051b870101935086841115614d4657600080fd5b602086015b84811015614d625780358352918301918301614d4b565b509695505050505050565b600080600080600060a08688031215614d8557600080fd5b8535614d9081614599565b94506020860135614da081614599565b935060408601356001600160401b0380821115614dbc57600080fd5b614dc889838a01614d03565b94506060880135915080821115614dde57600080fd5b614dea89838a01614d03565b93506080880135915080821115614e0057600080fd5b50614e0d88828901614675565b9150509295509295909350565b600082601f830112614e2b57600080fd5b81356020614e3b61469483614aec565b82815260059290921b84018101918181019086841115614e5a57600080fd5b8286015b84811015614d625780356001600160401b03811115614e7d5760008081fd5b614e8b8986838b01016149c6565b845250918301918301614e5e565b600060208284031215614eab57600080fd5b81356001600160401b0380821115614ec257600080fd5b9083019060408286031215614ed657600080fd5b614ede6145d4565b823582811115614eed57600080fd5b830160608188031215614eff57600080fd5b614f076145fc565b813584811115614f1657600080fd5b614f2289828501614675565b825250602082013584811115614f3757600080fd5b614f4389828501614675565b60208301525060408201359150614f5982614599565b60408101919091528152602083013582811115614f7557600080fd5b614f8187828601614e1a565b60208301525095945050505050565b602081526000612a5660208301846148e8565b6001600160a01b03929092168252602082015260400190565b602081526000612a566020830184614847565b600080600080600060a08688031215614fe757600080fd5b8535614ff281614599565b9450602086013561500281614599565b9350604086013592506060860135915060808601356001600160401b0381111561502b57600080fd5b614e0d88828901614675565b634e487b7160e01b600052602160045260246000fd5b602081016002831061506f57634e487b7160e01b600052602160045260246000fd5b91905290565b60008060006060848603121561508a57600080fd5b833561509581614599565b95602085013595506040909401359392505050565b604080825283519082018190526000906020906060840190828701845b828110156150ec5781516001600160a01b0316845292840192908401906001016150c7565b5050508381038285015284518082528583019183019060005b8181101561512157835183529284019291840191600101615105565b5090979650505050505050565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b60006020828403121561516857600080fd5b81518015158114612a5657600080fd5b6020808252601f908201527f457874656e73696f6e4d616e616765723a20756e617574686f72697a65642e00604082015260600190565b600181811c908216806151c357607f821691505b60208210810361182357634e487b7160e01b600052602260045260246000fd5b600082516151f5818460208701614823565b9190910192915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561094a5761094a615215565b6000808335601e1984360301811261525557600080fd5b8301803591506001600160401b0382111561526f57600080fd5b60200191503681900382131561528457600080fd5b9250929050565b8284823760609190911b6001600160601b0319169101908152601401919050565b600080604083850312156152bf57600080fd5b82516152ca81614599565b6020939093015192949293505050565b600082601f8301126152eb57600080fd5b815160206152fb61469483614aec565b8083825260208201915060208460051b87010193508684111561531d57600080fd5b602086015b84811015614d625780518352918301918301615322565b6000806040838503121561534c57600080fd5b82516001600160401b038082111561536357600080fd5b818501915085601f83011261537757600080fd5b8151602061538761469483614aec565b82815260059290921b840181019181810190898411156153a657600080fd5b948201945b838610156153cd5785516153be81614599565b825294820194908201906153ab565b918801519196509093505050808211156153e657600080fd5b50614a79858286016152da565b7402832b936b4b9b9b4b7b7399d1030b1b1b7bab73a1605d1b815260008351615423816015850160208801614823565b7001034b99036b4b9b9b4b733903937b6329607d1b6015918401918201528351615454816026840160208801614823565b01602601949350505050565b6020808252602b908201527f457874656e73696f6e4d616e616765723a20657874656e73696f6e20646f657360408201526a103737ba1032bc34b9ba1760a91b606082015260800190565b60006020808352600084546154bf816151af565b80602087015260406001808416600081146154e157600181146154fd5761552d565b60ff19851660408a0152604084151560051b8a0101955061552d565b89600052602060002060005b858110156155245781548b8201860152908301908801615509565b8a016040019650505b509398975050505050505050565b8181038181111561094a5761094a615215565b601f8211156108c3576000816000526020600020601f850160051c810160208610156155775750805b601f850160051c820191505b8181101561390357828155600101615583565b600019600383901b1c191660019190911b1790565b8181036155b6575050565b6155c082546151af565b6001600160401b038111156155d7576155d76145be565b6155eb816155e584546151af565b8461554e565b6000601f82116001811461561957600083156156075750848201545b6156118482615596565b8555506121c8565b600085815260209020601f19841690600086815260209020845b838110156156535782860154825560019586019590910190602001615633565b50858310156156715781850154600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603160045260246000fd5b6040815260006156aa60408301856148c0565b82810360208401526156bc8185614873565b95945050505050565b81516001600160401b038111156156de576156de6145be565b6156ec816155e584546151af565b602080601f83116001811461571b57600084156157095750858301515b6157138582615596565b865550613903565b600085815260208120601f198616915b8281101561574a5788860151825594840194600190910190840161572b565b508582101561567157939096015160001960f8600387901b161c19169092555050600190811b01905550565b6040815260006157896040830185614847565b82810360208401526156bc8185614847565b600082601f8301126157ac57600080fd5b81516157ba6146948261464e565b8181528460208386010111156157cf57600080fd5b610959826020830160208701614823565b600082601f8301126157f157600080fd5b8151602061580161469483614aec565b82815260059290921b8401810191818101908684111561582057600080fd5b8286015b84811015614d625780516001600160401b03808211156158445760008081fd5b908801906040828b03601f190181131561585e5760008081fd5b6158666145d4565b8784015161587381614566565b81529083015190828211156158885760008081fd5b6158968c898487010161579b565b818901528652505050918301918301615824565b6000602082840312156158bc57600080fd5b81516001600160401b03808211156158d357600080fd5b818401915084601f8301126158e757600080fd5b81516158f561469482614aec565b8082825260208201915060208360051b86010192508783111561591757600080fd5b602085015b83811015615a235780518581111561593357600080fd5b8601601f196040828c038201121561594a57600080fd5b6159526145d4565b60208301518881111561596457600080fd5b83016060818e038401121561597857600080fd5b6159806145fc565b925060208101518981111561599457600080fd5b6159a38e60208385010161579b565b8452506040810151898111156159b857600080fd5b6159c78e60208385010161579b565b602085015250606001516159da81614599565b8060408401525081815260408301519150878211156159f857600080fd5b615a078c6020848601016157e0565b602082015280865250505060208301925060208101905061591c565b50979650505050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b808202811582820484141761094a5761094a615215565b600081615aa057615aa0615215565b50600019019056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c656455add213c41f3851b4506717b8af695a4256979dff496dcaae7789f6121331aaa2646970667358221220a30be0d08718f1cc1a8a45338f5b52458867958531b0f70821d038daaacf43b664736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081e609b897393731a3d23c1d311330340cebb9e9000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000905338301564226227b641ef13a9585f03c7b134000000000000000000000000000000000000000000000000000000000000000f446972656374204c697374696e677300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008c048dd77df000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002c617070726f76654275796572466f724c697374696e672875696e743235362c616464726573732c626f6f6c290000000000000000000000000000000000000000ea8f9a3c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000032617070726f766543757272656e6379466f724c697374696e672875696e743235362c616464726573732c75696e74323536290000000000000000000000000000704232dc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003762757946726f6d4c697374696e672875696e743235362c616464726573732c75696e743235362c616464726573732c75696e7432353629000000000000000000305a67a8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001663616e63656c4c697374696e672875696e743235362900000000000000000000746415b5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004d6372656174654c697374696e672828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743132382c75696e743132382c626f6f6c292900000000000000000000000000000000000000fb14079d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002863757272656e63795072696365466f724c697374696e672875696e743235362c6164647265737329000000000000000000000000000000000000000000000000c5275fb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001f676574416c6c4c697374696e67732875696e743235362c75696e74323536290031654b4d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024676574416c6c56616c69644c697374696e67732875696e743235362c75696e743235362900000000000000000000000000000000000000000000000000000000107a274a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000136765744c697374696e672875696e7432353629000000000000000000000000009cfbe2a6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002a69734275796572417070726f766564466f724c697374696e672875696e743235362c616464726573732900000000000000000000000000000000000000000000a8519047000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002d697343757272656e6379417070726f766564466f724c697374696e672875696e743235362c616464726573732900000000000000000000000000000000000000c78b616c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000f746f74616c4c697374696e67732829000000000000000000000000000000000007b6775800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000557570646174654c697374696e672875696e743235362c28616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743132382c75696e743132382c626f6f6c2929000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000bac8f4b67a77da77b788b391b94027330cb3193c0000000000000000000000000000000000000000000000000000000000000010456e676c6973682041756374696f6e73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005e0000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000007600858e5ad000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d626964496e41756374696f6e2875696e743235362c75696e743235362900000096b5a755000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001663616e63656c41756374696f6e2875696e743235362900000000000000000000ebf05a62000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d636f6c6c65637441756374696f6e5061796f75742875696e743235362900000003a54fe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d636f6c6c65637441756374696f6e546f6b656e732875696e743235362900000016654d40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005c63726561746541756374696f6e2828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e743235362c75696e7436342c75696e7436342c75696e7436342c75696e743634292900000000c291537c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001f676574416c6c41756374696f6e732875696e743235362c75696e7432353629007b0638010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024676574416c6c56616c696441756374696f6e732875696e743235362c75696e74323536290000000000000000000000000000000000000000000000000000000078bd7935000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001367657441756374696f6e2875696e7432353629000000000000000000000000006891939d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001667657457696e6e696e674269642875696e7432353629000000000000000000001389b1170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000019697341756374696f6e457870697265642875696e7432353629000000000000002eb566bd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002069734e657757696e6e696e674269642875696e743235362c75696e743235362916002f4a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000f746f74616c41756374696f6e732829000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000fcdc4640a590d9cfdd7e15eec024aa1f578f757900000000000000000000000000000000000000000000000000000000000000064f666665727300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000420c815729d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000146163636570744f666665722875696e7432353629000000000000000000000000ef706adf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001463616e63656c4f666665722875696e7432353629000000000000000000000000c1edcfbe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001d676574416c6c4f66666572732875696e743235362c75696e743235362900000091940b3e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000022676574416c6c56616c69644f66666572732875696e743235362c75696e74323536290000000000000000000000000000000000000000000000000000000000004579268a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000116765744f666665722875696e7432353629000000000000000000000000000000016767fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003c6d616b654f666665722828616464726573732c75696e743235362c75696e743235362c616464726573732c75696e743235362c75696e74323536292900000000a9fd8ed1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000d746f74616c4f6666657273282900000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _marketplaceV3Params (tuple):
Arg [1] : extensions (tuple[]):
Arg [1] : metadata (tuple):
Arg [1] : name (string): Direct Listings
Arg [2] : metadataURI (string):
Arg [3] : implementation (address): 0x905338301564226227B641ef13A9585F03C7B134
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): English Auctions
Arg [2] : metadataURI (string):
Arg [3] : implementation (address): 0xbaC8f4B67A77da77B788B391B94027330cb3193c
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): Offers
Arg [2] : metadataURI (string):
Arg [3] : implementation (address): 0xfcDc4640A590d9CFdd7e15eEc024aa1F578f7579
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): 0x81e609b897393731A3D23c1d311330340cEbB9e9
-----Encoded View---------------
211 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [3] : 00000000000000000000000081e609b897393731a3d23c1d311330340cebb9e9
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] : 000000000000000000000000905338301564226227b641ef13a9585f03c7b134
Arg [13] : 000000000000000000000000000000000000000000000000000000000000000f
Arg [14] : 446972656374204c697374696e67730000000000000000000000000000000000
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] : 000000000000000000000000bac8f4b67a77da77b788b391b94027330cb3193c
Arg [98] : 0000000000000000000000000000000000000000000000000000000000000010
Arg [99] : 456e676c6973682041756374696f6e7300000000000000000000000000000000
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] : 000000000000000000000000fcdc4640a590d9cfdd7e15eec024aa1f578f7579
Arg [170] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [171] : 4f66666572730000000000000000000000000000000000000000000000000000
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 ETH
0
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.