Polygon Sponsored slots available. Book your slot here!
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 6,077 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Safe Transfer Fr... | 70623063 | 14 hrs ago | IN | 0 POL | 0.00155662 | ||||
Safe Transfer Fr... | 70380164 | 6 days ago | IN | 0 POL | 0.025913 | ||||
Set Approval For... | 69529416 | 27 days ago | IN | 0 POL | 0.00213749 | ||||
Set Approval For... | 68069568 | 63 days ago | IN | 0 POL | 0.00163557 | ||||
Set Approval For... | 67561485 | 76 days ago | IN | 0 POL | 0.00068284 | ||||
Set Approval For... | 67410500 | 80 days ago | IN | 0 POL | 0.00070261 | ||||
Set Approval For... | 67346491 | 82 days ago | IN | 0 POL | 0.00163557 | ||||
Safe Transfer Fr... | 66802551 | 95 days ago | IN | 0 POL | 0.00110845 | ||||
Set Approval For... | 66773666 | 96 days ago | IN | 0 POL | 0.00482114 | ||||
Set Approval For... | 66766877 | 96 days ago | IN | 0 POL | 0.00069992 | ||||
Safe Transfer Fr... | 66017228 | 115 days ago | IN | 0 POL | 0.00194564 | ||||
Set Approval For... | 65984943 | 116 days ago | IN | 0 POL | 0.00945465 | ||||
Set Approval For... | 65745135 | 122 days ago | IN | 0 POL | 0.00830894 | ||||
Set Approval For... | 65674450 | 124 days ago | IN | 0 POL | 0.00697462 | ||||
Set Approval For... | 64846398 | 145 days ago | IN | 0 POL | 0.00163809 | ||||
Set Approval For... | 64487800 | 154 days ago | IN | 0 POL | 0.0016393 | ||||
Safe Transfer Fr... | 64389744 | 156 days ago | IN | 0 POL | 0.00175463 | ||||
Set Approval For... | 64307166 | 158 days ago | IN | 0 POL | 0.00238982 | ||||
Set Approval For... | 63946971 | 167 days ago | IN | 0 POL | 0.0108535 | ||||
Set Approval For... | 63326206 | 183 days ago | IN | 0 POL | 0.00190816 | ||||
Safe Transfer Fr... | 62692703 | 199 days ago | IN | 0 POL | 0.0015567 | ||||
Set Approval For... | 62525667 | 203 days ago | IN | 0 POL | 0.00163809 | ||||
Set Approval For... | 62490496 | 204 days ago | IN | 0 POL | 0.00179912 | ||||
Set Approval For... | 62447034 | 205 days ago | IN | 0 POL | 0.00163644 | ||||
Safe Transfer Fr... | 62317229 | 208 days ago | IN | 0 POL | 0.0015567 |
Loading...
Loading
Contract Name:
ERC1155FullBurn
Compiler Version
v0.8.22+commit.4fc1097e
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; import {IForwarderRegistry} from "./../../../metatx/interfaces/IForwarderRegistry.sol"; import {ITokenMetadataResolver} from "./../../metadata/interfaces/ITokenMetadataResolver.sol"; import {IOperatorFilterRegistry} from "./../../royalty/interfaces/IOperatorFilterRegistry.sol"; import {ERC1155WithOperatorFilterer} from "./../ERC1155WithOperatorFilterer.sol"; import {ERC1155Metadata} from "./../ERC1155Metadata.sol"; import {ERC1155Mintable} from "./../ERC1155Mintable.sol"; import {ERC1155Deliverable} from "./../ERC1155Deliverable.sol"; import {ERC1155Burnable} from "./../ERC1155Burnable.sol"; import {ERC2981} from "./../../royalty/ERC2981.sol"; import {ContractOwnership} from "./../../../access/ContractOwnership.sol"; import {TokenRecovery} from "./../../../security/TokenRecovery.sol"; import {Context} from "@openzeppelin/contracts/utils/Context.sol"; import {ForwarderRegistryContextBase} from "./../../../metatx/base/ForwarderRegistryContextBase.sol"; import {ForwarderRegistryContext} from "./../../../metatx/ForwarderRegistryContext.sol"; contract ERC1155FullBurn is ERC1155WithOperatorFilterer, ERC1155Metadata, ERC1155Mintable, ERC1155Deliverable, ERC1155Burnable, ERC2981, TokenRecovery, ForwarderRegistryContext { constructor( string memory tokenName, string memory tokenSymbol, ITokenMetadataResolver metadataResolver, IOperatorFilterRegistry filterRegistry, IForwarderRegistry forwarderRegistry ) ContractOwnership(msg.sender) ERC1155Metadata(tokenName, tokenSymbol, metadataResolver) ERC1155WithOperatorFilterer(filterRegistry) ForwarderRegistryContext(forwarderRegistry) {} /// @inheritdoc ForwarderRegistryContextBase function _msgSender() internal view virtual override(Context, ForwarderRegistryContextBase) returns (address) { return ForwarderRegistryContextBase._msgSender(); } /// @inheritdoc ForwarderRegistryContextBase function _msgData() internal view virtual override(Context, ForwarderRegistryContextBase) returns (bytes calldata) { return ForwarderRegistryContextBase._msgData(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @notice Thrown when trying to transfer tokens without calldata to the contract. error EtherReceptionDisabled(); /// @notice Thrown when the multiple related arrays have different lengths. error InconsistentArrayLengths(); /// @notice Thrown when an ETH transfer has failed. error TransferFailed();
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {AccessControlBase} from "./base/AccessControlBase.sol"; import {ContractOwnership} from "./ContractOwnership.sol"; /// @title Access control via roles management (immutable version). /// @dev This contract is to be used via inheritance in an immutable (non-proxied) implementation. abstract contract AccessControl is AccessControlBase, ContractOwnership { }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {ContractOwnershipStorage} from "./libraries/ContractOwnershipStorage.sol"; import {ContractOwnershipBase} from "./base/ContractOwnershipBase.sol"; import {InterfaceDetection} from "./../introspection/InterfaceDetection.sol"; /// @title ERC173 Contract Ownership Standard (immutable version). /// @dev See https://eips.ethereum.org/EIPS/eip-173 /// @dev This contract is to be used via inheritance in an immutable (non-proxied) implementation. abstract contract ContractOwnership is ContractOwnershipBase, InterfaceDetection { using ContractOwnershipStorage for ContractOwnershipStorage.Layout; /// @notice Initializes the storage with an initial contract owner. /// @notice Marks the following ERC165 interface(s) as supported: ERC173. /// @dev Emits an {OwnershipTransferred} if `initialOwner` is not the zero address. /// @param initialOwner the initial contract owner. constructor(address initialOwner) { ContractOwnershipStorage.layout().constructorInit(initialOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {IAccessControl} from "./../../access/interfaces/IAccessControl.sol"; import {AccessControlStorage} from "./../libraries/AccessControlStorage.sol"; import {ContractOwnershipStorage} from "./../libraries/ContractOwnershipStorage.sol"; import {Context} from "@openzeppelin/contracts/utils/Context.sol"; /// @title Access control via roles management (proxiable version). /// @dev This contract is to be used via inheritance in a proxied implementation. /// @dev Note: This contract requires ERC173 (Contract Ownership standard). abstract contract AccessControlBase is IAccessControl, Context { using AccessControlStorage for AccessControlStorage.Layout; using ContractOwnershipStorage for ContractOwnershipStorage.Layout; /// @notice Grants a role to an account. /// @dev Reverts with {NotContractOwner} if the sender is not the contract owner. /// @dev Emits a {RoleGranted} event if the account did not previously have the role. /// @param role The role to grant. /// @param account The account to grant the role to. function grantRole(bytes32 role, address account) external { address operator = _msgSender(); ContractOwnershipStorage.layout().enforceIsContractOwner(operator); AccessControlStorage.layout().grantRole(role, account, operator); } /// @notice Revokes a role from an account. /// @dev Reverts with {NotContractOwner} if the sender is not the contract owner. /// @dev Emits a {RoleRevoked} event if the account previously had the role. /// @param role The role to revoke. /// @param account The account to revoke the role from. function revokeRole(bytes32 role, address account) external { address operator = _msgSender(); ContractOwnershipStorage.layout().enforceIsContractOwner(operator); AccessControlStorage.layout().revokeRole(role, account, operator); } /// @inheritdoc IAccessControl function renounceRole(bytes32 role) external { AccessControlStorage.layout().renounceRole(_msgSender(), role); } /// @inheritdoc IAccessControl function hasRole(bytes32 role, address account) external view returns (bool hasRole_) { return AccessControlStorage.layout().hasRole(role, account); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {IERC173} from "./../interfaces/IERC173.sol"; import {ContractOwnershipStorage} from "./../libraries/ContractOwnershipStorage.sol"; import {Context} from "@openzeppelin/contracts/utils/Context.sol"; /// @title ERC173 Contract Ownership Standard (proxiable version). /// @dev See https://eips.ethereum.org/EIPS/eip-173 /// @dev This contract is to be used via inheritance in a proxied implementation. /// @dev Note: This contract requires ERC165 (Interface Detection Standard). abstract contract ContractOwnershipBase is IERC173, Context { using ContractOwnershipStorage for ContractOwnershipStorage.Layout; /// @inheritdoc IERC173 function owner() public view virtual returns (address) { return ContractOwnershipStorage.layout().owner(); } /// @inheritdoc IERC173 function transferOwnership(address newOwner) public virtual { ContractOwnershipStorage.layout().transferOwnership(_msgSender(), newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @notice Thrown when an account does not have the required role. /// @param role The role the caller is missing. /// @param account The account that was checked. error NotRoleHolder(bytes32 role, address account); /// @notice Thrown when an account does not have the required role on a target contract. /// @param targetContract The contract that was checked. /// @param role The role that was checked. /// @param account The account that was checked. error NotTargetContractRoleHolder(address targetContract, bytes32 role, address account);
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @notice Thrown when the target contract is actually not a contract. /// @param targetContract The contract that was checked error TargetIsNotAContract(address targetContract);
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @notice Thrown when an account is not the contract owner but is required to. /// @param account The account that was checked. error NotContractOwner(address account); /// @notice Thrown when an account is not the target contract owner but is required to. /// @param targetContract The contract that was checked. /// @param account The account that was checked. error NotTargetContractOwner(address targetContract, address account);
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @notice Emitted when `role` is granted to `account`. /// @param role The role that has been granted. /// @param account The account that has been granted the role. /// @param operator The account that granted the role. event RoleGranted(bytes32 role, address account, address operator); /// @notice Emitted when `role` is revoked from `account`. /// @param role The role that has been revoked. /// @param account The account that has been revoked the role. /// @param operator The account that revoked the role. event RoleRevoked(bytes32 role, address account, address operator);
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @notice Emitted when the contract ownership changes. /// @param previousOwner the previous contract owner. /// @param newOwner the new contract owner. event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @title Access control via roles management (functions) interface IAccessControl { /// @notice Renounces a role by the sender. /// @dev Reverts if `sender` does not have `role`. /// @dev Emits a {RoleRevoked} event. /// @param role The role to renounce. function renounceRole(bytes32 role) external; /// @notice Retrieves whether an account has a role. /// @param role The role. /// @param account The account. /// @return hasRole_ Whether `account` has `role`. function hasRole(bytes32 role, address account) external view returns (bool hasRole_); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @title ERC-173 Contract Ownership Standard (functions) /// @dev See https://eips.ethereum.org/EIPS/eip-173 /// @dev Note: the ERC-165 identifier for this interface is 0x7f5828d0 interface IERC173 { /// @notice Sets the address of the new contract owner. /// @dev Reverts if the sender is not the contract owner. /// @dev Emits an {OwnershipTransferred} event if `newOwner` is different from the current contract owner. /// @param newOwner The address of the new contract owner. Using the zero address means renouncing ownership. function transferOwnership(address newOwner) external; /// @notice Gets the address of the contract owner. /// @return contractOwner The address of the contract owner. function owner() external view returns (address contractOwner); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {NotRoleHolder, NotTargetContractRoleHolder} from "./../errors/AccessControlErrors.sol"; import {TargetIsNotAContract} from "./../errors/Common.sol"; import {RoleGranted, RoleRevoked} from "./../events/AccessControlEvents.sol"; import {IAccessControl} from "./../interfaces/IAccessControl.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; library AccessControlStorage { using Address for address; using AccessControlStorage for AccessControlStorage.Layout; struct Layout { mapping(bytes32 => mapping(address => bool)) roles; } bytes32 internal constant LAYOUT_STORAGE_SLOT = bytes32(uint256(keccak256("animoca.core.access.AccessControl.storage")) - 1); /// @notice Grants a role to an account. /// @dev Note: Call to this function should be properly access controlled. /// @dev Emits a {RoleGranted} event if the account did not previously have the role. /// @param role The role to grant. /// @param account The account to grant the role to. /// @param operator The account requesting the role change. function grantRole(Layout storage s, bytes32 role, address account, address operator) internal { if (!s.hasRole(role, account)) { s.roles[role][account] = true; emit RoleGranted(role, account, operator); } } /// @notice Revokes a role from an account. /// @dev Note: Call to this function should be properly access controlled. /// @dev Emits a {RoleRevoked} event if the account previously had the role. /// @param role The role to revoke. /// @param account The account to revoke the role from. /// @param operator The account requesting the role change. function revokeRole(Layout storage s, bytes32 role, address account, address operator) internal { if (s.hasRole(role, account)) { s.roles[role][account] = false; emit RoleRevoked(role, account, operator); } } /// @notice Renounces a role by the sender. /// @dev Reverts with {NotRoleHolder} if `sender` does not have `role`. /// @dev Emits a {RoleRevoked} event. /// @param sender The message sender. /// @param role The role to renounce. function renounceRole(Layout storage s, address sender, bytes32 role) internal { s.enforceHasRole(role, sender); s.roles[role][sender] = false; emit RoleRevoked(role, sender, sender); } /// @notice Retrieves whether an account has a role. /// @param role The role. /// @param account The account. /// @return hasRole_ Whether `account` has `role`. function hasRole(Layout storage s, bytes32 role, address account) internal view returns (bool hasRole_) { return s.roles[role][account]; } /// @notice Checks whether an account has a role in a target contract. /// @param targetContract The contract to check. /// @param role The role to check. /// @param account The account to check. /// @return hasTargetContractRole_ Whether `account` has `role` in `targetContract`. function hasTargetContractRole(address targetContract, bytes32 role, address account) internal view returns (bool hasTargetContractRole_) { if (!targetContract.isContract()) revert TargetIsNotAContract(targetContract); return IAccessControl(targetContract).hasRole(role, account); } /// @notice Ensures that an account has a role. /// @dev Reverts with {NotRoleHolder} if `account` does not have `role`. /// @param role The role. /// @param account The account. function enforceHasRole(Layout storage s, bytes32 role, address account) internal view { if (!s.hasRole(role, account)) revert NotRoleHolder(role, account); } /// @notice Enforces that an account has a role in a target contract. /// @dev Reverts with {NotTargetContractRoleHolder} if the account does not have the role. /// @param targetContract The contract to check. /// @param role The role to check. /// @param account The account to check. function enforceHasTargetContractRole(address targetContract, bytes32 role, address account) internal view { if (!hasTargetContractRole(targetContract, role, account)) revert NotTargetContractRoleHolder(targetContract, role, account); } function layout() internal pure returns (Layout storage s) { bytes32 position = LAYOUT_STORAGE_SLOT; assembly { s.slot := position } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {NotContractOwner, NotTargetContractOwner} from "./../errors/ContractOwnershipErrors.sol"; import {TargetIsNotAContract} from "./../errors/Common.sol"; import {OwnershipTransferred} from "./../events/ERC173Events.sol"; import {IERC173} from "./../interfaces/IERC173.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {ProxyInitialization} from "./../../proxy/libraries/ProxyInitialization.sol"; import {InterfaceDetectionStorage} from "./../../introspection/libraries/InterfaceDetectionStorage.sol"; library ContractOwnershipStorage { using Address for address; using ContractOwnershipStorage for ContractOwnershipStorage.Layout; using InterfaceDetectionStorage for InterfaceDetectionStorage.Layout; struct Layout { address contractOwner; } bytes32 internal constant LAYOUT_STORAGE_SLOT = bytes32(uint256(keccak256("animoca.core.access.ContractOwnership.storage")) - 1); bytes32 internal constant PROXY_INIT_PHASE_SLOT = bytes32(uint256(keccak256("animoca.core.access.ContractOwnership.phase")) - 1); /// @notice Initializes the storage with an initial contract owner (immutable version). /// @notice Marks the following ERC165 interface(s) as supported: ERC173. /// @dev Note: This function should be called ONLY in the constructor of an immutable (non-proxied) contract. /// @dev Emits an {OwnershipTransferred} if `initialOwner` is not the zero address. /// @param initialOwner The initial contract owner. function constructorInit(Layout storage s, address initialOwner) internal { if (initialOwner != address(0)) { s.contractOwner = initialOwner; emit OwnershipTransferred(address(0), initialOwner); } InterfaceDetectionStorage.layout().setSupportedInterface(type(IERC173).interfaceId, true); } /// @notice Initializes the storage with an initial contract owner (proxied version). /// @notice Sets the proxy initialization phase to `1`. /// @notice Marks the following ERC165 interface(s) as supported: ERC173. /// @dev Note: This function should be called ONLY in the init function of a proxied contract. /// @dev Reverts with {InitializationPhaseAlreadyReached} if the proxy initialization phase is set to `1` or above. /// @dev Emits an {OwnershipTransferred} if `initialOwner` is not the zero address. /// @param initialOwner The initial contract owner. function proxyInit(Layout storage s, address initialOwner) internal { ProxyInitialization.setPhase(PROXY_INIT_PHASE_SLOT, 1); s.constructorInit(initialOwner); } /// @notice Sets the address of the new contract owner. /// @dev Reverts with {NotContractOwner} if `sender` is not the contract owner. /// @dev Emits an {OwnershipTransferred} event if `newOwner` is different from the current contract owner. /// @param newOwner The address of the new contract owner. Using the zero address means renouncing ownership. function transferOwnership(Layout storage s, address sender, address newOwner) internal { address previousOwner = s.contractOwner; if (sender != previousOwner) revert NotContractOwner(sender); if (previousOwner != newOwner) { s.contractOwner = newOwner; emit OwnershipTransferred(previousOwner, newOwner); } } /// @notice Gets the address of the contract owner. /// @return contractOwner The address of the contract owner. function owner(Layout storage s) internal view returns (address contractOwner) { return s.contractOwner; } /// @notice Checks whether an account is the owner of a target contract. /// @param targetContract The contract to check. /// @param account The account to check. /// @return isTargetContractOwner_ Whether `account` is the owner of `targetContract`. function isTargetContractOwner(address targetContract, address account) internal view returns (bool isTargetContractOwner_) { if (!targetContract.isContract()) revert TargetIsNotAContract(targetContract); return IERC173(targetContract).owner() == account; } /// @notice Ensures that an account is the contract owner. /// @dev Reverts with {NotContractOwner} if `account` is not the contract owner. /// @param account The account. function enforceIsContractOwner(Layout storage s, address account) internal view { if (account != s.contractOwner) revert NotContractOwner(account); } /// @notice Enforces that an account is the owner of a target contract. /// @dev Reverts with {NotTheTargetContractOwner} if the account is not the owner. /// @param targetContract The contract to check. /// @param account The account to check. function enforceIsTargetContractOwner(address targetContract, address account) internal view { if (!isTargetContractOwner(targetContract, account)) revert NotTargetContractOwner(targetContract, account); } function layout() internal pure returns (Layout storage s) { bytes32 position = LAYOUT_STORAGE_SLOT; assembly { s.slot := position } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {IERC165} from "./interfaces/IERC165.sol"; import {InterfaceDetectionStorage} from "./libraries/InterfaceDetectionStorage.sol"; /// @title ERC165 Interface Detection Standard (immutable or proxiable version). /// @dev This contract is to be used via inheritance in an immutable (non-proxied) or proxied implementation. abstract contract InterfaceDetection is IERC165 { using InterfaceDetectionStorage for InterfaceDetectionStorage.Layout; /// @inheritdoc IERC165 function supportsInterface(bytes4 interfaceId) external view returns (bool) { return InterfaceDetectionStorage.layout().supportsInterface(interfaceId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @notice Thrown when setting the illegal interfaceId 0xffffffff. error IllegalInterfaceId();
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @title ERC165 Interface Detection Standard. /// @dev See https://eips.ethereum.org/EIPS/eip-165. /// @dev Note: The ERC-165 identifier for this interface is 0x01ffc9a7. interface IERC165 { /// @notice Returns whether this contract implements a given interface. /// @dev Note: This function call must use less than 30 000 gas. /// @param interfaceId the interface identifier to test. /// @return supported True if the interface is supported, false if `interfaceId` is `0xffffffff` or if the interface is not supported. function supportsInterface(bytes4 interfaceId) external view returns (bool supported); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {IllegalInterfaceId} from "./../errors/InterfaceDetectionErrors.sol"; import {IERC165} from "./../interfaces/IERC165.sol"; library InterfaceDetectionStorage { struct Layout { mapping(bytes4 => bool) supportedInterfaces; } bytes32 internal constant LAYOUT_STORAGE_SLOT = bytes32(uint256(keccak256("animoca.core.introspection.InterfaceDetection.storage")) - 1); bytes4 internal constant ILLEGAL_INTERFACE_ID = 0xffffffff; /// @notice Sets or unsets an ERC165 interface. /// @dev Revertswith {IllegalInterfaceId} if `interfaceId` is `0xffffffff`. /// @param interfaceId the interface identifier. /// @param supported True to set the interface, false to unset it. function setSupportedInterface(Layout storage s, bytes4 interfaceId, bool supported) internal { if (interfaceId == ILLEGAL_INTERFACE_ID) revert IllegalInterfaceId(); s.supportedInterfaces[interfaceId] = supported; } /// @notice Returns whether this contract implements a given interface. /// @dev Note: This function call must use less than 30 000 gas. /// @param interfaceId The interface identifier to test. /// @return supported True if the interface is supported, false if `interfaceId` is `0xffffffff` or if the interface is not supported. function supportsInterface(Layout storage s, bytes4 interfaceId) internal view returns (bool supported) { if (interfaceId == ILLEGAL_INTERFACE_ID) { return false; } if (interfaceId == type(IERC165).interfaceId) { return true; } return s.supportedInterfaces[interfaceId]; } function layout() internal pure returns (Layout storage s) { bytes32 position = LAYOUT_STORAGE_SLOT; assembly { s.slot := position } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {IForwarderRegistry} from "./interfaces/IForwarderRegistry.sol"; import {IERC2771} from "./interfaces/IERC2771.sol"; import {ForwarderRegistryContextBase} from "./base/ForwarderRegistryContextBase.sol"; /// @title Meta-Transactions Forwarder Registry Context (immutable version). /// @dev This contract is to be used via inheritance in an immutable (non-proxied) implementation. /// @dev Derived from https://github.com/wighawag/universal-forwarder (MIT licence) abstract contract ForwarderRegistryContext is ForwarderRegistryContextBase, IERC2771 { constructor(IForwarderRegistry forwarderRegistry_) ForwarderRegistryContextBase(forwarderRegistry_) {} function forwarderRegistry() external view returns (IForwarderRegistry) { return _FORWARDER_REGISTRY; } /// @inheritdoc IERC2771 function isTrustedForwarder(address forwarder) external view virtual returns (bool) { return forwarder == address(_FORWARDER_REGISTRY); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {IForwarderRegistry} from "./../interfaces/IForwarderRegistry.sol"; import {ERC2771Calldata} from "./../libraries/ERC2771Calldata.sol"; /// @title Meta-Transactions Forwarder Registry Context (proxiable version). /// @dev This contract is to be used via inheritance in a proxied implementation. /// @dev Derived from https://github.com/wighawag/universal-forwarder (MIT licence) abstract contract ForwarderRegistryContextBase { IForwarderRegistry internal immutable _FORWARDER_REGISTRY; constructor(IForwarderRegistry forwarderRegistry) { _FORWARDER_REGISTRY = forwarderRegistry; } /// @notice Returns the message sender depending on the ForwarderRegistry-based meta-transaction context. function _msgSender() internal view virtual returns (address) { // Optimised path in case of an EOA-initiated direct tx to the contract or a call from a contract not complying with EIP-2771 // solhint-disable-next-line avoid-tx-origin if (msg.sender == tx.origin || msg.data.length < 24) { return msg.sender; } address sender = ERC2771Calldata.msgSender(); // Return the EIP-2771 calldata-appended sender address if the message was forwarded by the ForwarderRegistry or an approved forwarder if (msg.sender == address(_FORWARDER_REGISTRY) || _FORWARDER_REGISTRY.isApprovedForwarder(sender, msg.sender)) { return sender; } return msg.sender; } /// @notice Returns the message data depending on the ForwarderRegistry-based meta-transaction context. function _msgData() internal view virtual returns (bytes calldata) { // Optimised path in case of an EOA-initiated direct tx to the contract or a call from a contract not complying with EIP-2771 // solhint-disable-next-line avoid-tx-origin if (msg.sender == tx.origin || msg.data.length < 24) { return msg.data; } // Return the EIP-2771 calldata (minus the appended sender) if the message was forwarded by the ForwarderRegistry or an approved forwarder if (msg.sender == address(_FORWARDER_REGISTRY) || _FORWARDER_REGISTRY.isApprovedForwarder(ERC2771Calldata.msgSender(), msg.sender)) { return ERC2771Calldata.msgData(); } return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @title Secure Protocol for Native Meta Transactions. /// @dev See https://eips.ethereum.org/EIPS/eip-2771 interface IERC2771 { /// @notice Checks whether a forwarder is trusted. /// @param forwarder The forwarder to check. /// @return isTrusted True if `forwarder` is trusted, false if not. function isTrustedForwarder(address forwarder) external view returns (bool isTrusted); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @title Universal Meta-Transactions Forwarder Registry. /// @dev Derived from https://github.com/wighawag/universal-forwarder (MIT licence) interface IForwarderRegistry { /// @notice Checks whether an account is as an approved meta-transaction forwarder for a sender account. /// @param sender The sender account. /// @param forwarder The forwarder account. /// @return isApproved True if `forwarder` is an approved meta-transaction forwarder for `sender`, false otherwise. function isApprovedForwarder(address sender, address forwarder) external view returns (bool isApproved); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @dev Derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT licence) /// @dev See https://eips.ethereum.org/EIPS/eip-2771 library ERC2771Calldata { /// @notice Returns the sender address appended at the end of the calldata, as specified in EIP-2771. function msgSender() internal pure returns (address sender) { assembly { sender := shr(96, calldataload(sub(calldatasize(), 20))) } } /// @notice Returns the calldata while omitting the appended sender address, as specified in EIP-2771. function msgData() internal pure returns (bytes calldata data) { unchecked { return msg.data[:msg.data.length - 20]; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @notice Emitted when trying to set a phase value that has already been reached. /// @param currentPhase The current phase. /// @param newPhase The new phase trying to be set. error InitializationPhaseAlreadyReached(uint256 currentPhase, uint256 newPhase);
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {InitializationPhaseAlreadyReached} from "./../errors/ProxyInitializationErrors.sol"; import {StorageSlot} from "@openzeppelin/contracts/utils/StorageSlot.sol"; /// @notice Multiple calls protection for storage-modifying proxy initialization functions. library ProxyInitialization { /// @notice Sets the initialization phase during a storage-modifying proxy initialization function. /// @dev Reverts with {InitializationPhaseAlreadyReached} if `phase` has been reached already. /// @param storageSlot the storage slot where `phase` is stored. /// @param phase the initialization phase. function setPhase(bytes32 storageSlot, uint256 phase) internal { StorageSlot.Uint256Slot storage currentVersion = StorageSlot.getUint256Slot(storageSlot); uint256 currentPhase = currentVersion.value; if (currentPhase >= phase) revert InitializationPhaseAlreadyReached(currentPhase, phase); currentVersion.value = phase; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {TokenRecoveryBase} from "./base/TokenRecoveryBase.sol"; import {ContractOwnership} from "./../access/ContractOwnership.sol"; /// @title Recovery mechanism for ETH/ERC20/ERC721 tokens accidentally sent to this contract (immutable version). /// @dev This contract is to be used via inheritance in an immutable (non-proxied) implementation. abstract contract TokenRecovery is TokenRecoveryBase, ContractOwnership { }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {InconsistentArrayLengths} from "./../../CommonErrors.sol"; import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; import {IERC721} from "./../../token/ERC721/interfaces/IERC721.sol"; import {ContractOwnershipStorage} from "./../../access/libraries/ContractOwnershipStorage.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {Context} from "@openzeppelin/contracts/utils/Context.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; /// @title Recovery mechanism for ETH/ERC20/ERC721 tokens accidentally sent to this contract (proxiable version). /// @dev This contract is to be used via inheritance in a proxied implementation. /// @dev Note: This contract requires ERC173 (Contract Ownership standard). abstract contract TokenRecoveryBase is Context { using ContractOwnershipStorage for ContractOwnershipStorage.Layout; using SafeERC20 for IERC20; using Address for address payable; /// @notice Extract ETH tokens which were accidentally sent to the contract to a list of accounts. /// @dev Note: While contracts can generally prevent accidental ETH transfer by implementating a reverting /// `receive()` function, this can still be bypassed in a `selfdestruct(address)` scenario. /// @dev Warning: this function should be overriden for contracts which are supposed to hold ETH tokens /// so that the extraction is limited to only amounts sent accidentally. /// @dev Reverts with {NotContractOwner} if the sender is not the contract owner. /// @dev Reverts with {InconsistentArrayLengths} `accounts` and `amounts` do not have the same length. /// @dev Reverts if one of the ETH transfers fails for any reason. /// @param accounts the list of accounts to transfer the tokens to. /// @param amounts the list of token amounts to transfer. function recoverETH(address payable[] calldata accounts, uint256[] calldata amounts) public virtual { ContractOwnershipStorage.layout().enforceIsContractOwner(_msgSender()); uint256 length = accounts.length; if (length != amounts.length) revert InconsistentArrayLengths(); for (uint256 i; i < length; ++i) { accounts[i].sendValue(amounts[i]); } } /// @notice Extract ERC20 tokens which were accidentally sent to the contract to a list of accounts. /// @dev Warning: this function should be overriden for contracts which are supposed to hold ERC20 tokens /// so that the extraction is limited to only amounts sent accidentally. /// @dev Reverts with {NotContractOwner} if the sender is not the contract owner. /// @dev Reverts with {InconsistentArrayLengths} if `accounts`, `tokens` and `amounts` do not have the same length. /// @dev Reverts if one of the ERC20 transfers fails for any reason. /// @param accounts the list of accounts to transfer the tokens to. /// @param tokens the list of ERC20 token addresses. /// @param amounts the list of token amounts to transfer. function recoverERC20s(address[] calldata accounts, IERC20[] calldata tokens, uint256[] calldata amounts) public virtual { ContractOwnershipStorage.layout().enforceIsContractOwner(_msgSender()); uint256 length = accounts.length; if (length != tokens.length || length != amounts.length) revert InconsistentArrayLengths(); for (uint256 i; i < length; ++i) { tokens[i].safeTransfer(accounts[i], amounts[i]); } } /// @notice Extract ERC721 tokens which were accidentally sent to the contract to a list of accounts. /// @dev Warning: this function should be overriden for contracts which are supposed to hold ERC721 tokens /// so that the extraction is limited to only tokens sent accidentally. /// @dev Reverts with {NotContractOwner} if the sender is not the contract owner. /// @dev Reverts with {InconsistentArrayLengths} if `accounts`, `contracts` and `amounts` do not have the same length. /// @dev Reverts if one of the ERC721 transfers fails for any reason. /// @param accounts the list of accounts to transfer the tokens to. /// @param contracts the list of ERC721 contract addresses. /// @param tokenIds the list of token ids to transfer. function recoverERC721s(address[] calldata accounts, IERC721[] calldata contracts, uint256[] calldata tokenIds) public virtual { ContractOwnershipStorage.layout().enforceIsContractOwner(_msgSender()); uint256 length = accounts.length; if (length != contracts.length || length != tokenIds.length) revert InconsistentArrayLengths(); for (uint256 i; i < length; ++i) { contracts[i].transferFrom(address(this), accounts[i], tokenIds[i]); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {ERC1155Storage} from "./libraries/ERC1155Storage.sol"; import {ERC1155BurnableBase} from "./base/ERC1155BurnableBase.sol"; /// @title ERC1155 Multi Token Standard, optional extension: Burnable (immutable version). /// @dev This contract is to be used via inheritance in an immutable (non-proxied) implementation. abstract contract ERC1155Burnable is ERC1155BurnableBase { /// @notice Marks the fllowing ERC165 interface(s) as supported: ERC1155Burnable constructor() { ERC1155Storage.initERC1155Burnable(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {ERC1155Storage} from "./libraries/ERC1155Storage.sol"; import {ERC1155DeliverableBase} from "./base/ERC1155DeliverableBase.sol"; import {AccessControl} from "./../../access/AccessControl.sol"; /// @title ERC1155 Multi Token Standard, optional extension: Deliverable (immutable version). /// @dev This contract is to be used via inheritance in an immutable (non-proxied) implementation. abstract contract ERC1155Deliverable is ERC1155DeliverableBase, AccessControl { /// @notice Marks the fllowing ERC165 interface(s) as supported: ERC1155Deliverable constructor() { ERC1155Storage.initERC1155Deliverable(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {ITokenMetadataResolver} from "./../metadata/interfaces/ITokenMetadataResolver.sol"; import {TokenMetadataStorage} from "./../metadata/libraries/TokenMetadataStorage.sol"; import {ERC1155Storage} from "./libraries/ERC1155Storage.sol"; import {ERC1155MetadataBase} from "./base/ERC1155MetadataBase.sol"; /// @title ERC1155 Multi Token Standard, optional extension: Metadata (immutable version). /// @notice This contracts uses an external resolver for managing individual tokens metadata. /// @dev This contract is to be used via inheritance in an immutable (non-proxied) implementation. abstract contract ERC1155Metadata is ERC1155MetadataBase { using TokenMetadataStorage for TokenMetadataStorage.Layout; /// @notice Marks the following ERC165 interfaces as supported: ERC1155MetadataURI. /// @param name The name of the token. /// @param symbol The symbol of the token. /// @param metadataResolver The address of the metadata resolver contract. constructor(string memory name, string memory symbol, ITokenMetadataResolver metadataResolver) { TokenMetadataStorage.layout().constructorInit(name, symbol, metadataResolver); ERC1155Storage.initERC1155MetadataURI(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {ERC1155Storage} from "./libraries/ERC1155Storage.sol"; import {ERC1155MintableBase} from "./base/ERC1155MintableBase.sol"; import {AccessControl} from "./../../access/AccessControl.sol"; /// @title ERC1155 Multi Token Standard, optional extension: Mintable (immutable version). /// @dev This contract is to be used via inheritance in an immutable (non-proxied) implementation. abstract contract ERC1155Mintable is ERC1155MintableBase, AccessControl { /// @notice Marks the fllowing ERC165 interface(s) as supported: ERC1155Mintable constructor() { ERC1155Storage.initERC1155Mintable(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {IOperatorFilterRegistry} from "./../royalty/interfaces/IOperatorFilterRegistry.sol"; import {ERC1155Storage} from "./libraries/ERC1155Storage.sol"; import {OperatorFiltererStorage} from "./../royalty/libraries/OperatorFiltererStorage.sol"; import {ERC1155WithOperatorFiltererBase} from "./base/ERC1155WithOperatorFiltererBase.sol"; import {OperatorFiltererBase} from "./../royalty/base/OperatorFiltererBase.sol"; import {ContractOwnership} from "./../../access/ContractOwnership.sol"; /// @title ERC1155 Multi Token Standard with Operator Filterer (immutable version). /// @dev This contract is to be used via inheritance in an immutable (non-proxied) implementation. abstract contract ERC1155WithOperatorFilterer is ERC1155WithOperatorFiltererBase, OperatorFiltererBase, ContractOwnership { using OperatorFiltererStorage for OperatorFiltererStorage.Layout; /// @notice Marks the following ERC165 interfaces as supported: ERC1155. /// @notice Sets the address that the contract will make OperatorFilter checks against. /// @param operatorFilterRegistry The operator filter registry address. When set to the zero address, checks will be bypassed. constructor(IOperatorFilterRegistry operatorFilterRegistry) { ERC1155Storage.init(); OperatorFiltererStorage.layout().constructorInit(operatorFilterRegistry); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {IERC1155Burnable} from "./../interfaces/IERC1155Burnable.sol"; import {ERC1155Storage} from "./../libraries/ERC1155Storage.sol"; import {Context} from "@openzeppelin/contracts/utils/Context.sol"; /// @title ERC1155 Multi Token Standard, optional extension: Burnable (proxiable version). /// @dev This contract is to be used via inheritance in a proxied implementation. /// @dev Note: This contract requires ERC1155 (Multi Token Standard). abstract contract ERC1155BurnableBase is IERC1155Burnable, Context { using ERC1155Storage for ERC1155Storage.Layout; /// @inheritdoc IERC1155Burnable function burnFrom(address from, uint256 id, uint256 value) external virtual { ERC1155Storage.layout().burnFrom(_msgSender(), from, id, value); } /// @inheritdoc IERC1155Burnable function batchBurnFrom(address from, uint256[] calldata ids, uint256[] calldata values) external virtual { ERC1155Storage.layout().batchBurnFrom(_msgSender(), from, ids, values); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {IERC1155Deliverable} from "./../interfaces/IERC1155Deliverable.sol"; import {ERC1155Storage} from "./../libraries/ERC1155Storage.sol"; import {AccessControlStorage} from "./../../../access/libraries/AccessControlStorage.sol"; import {Context} from "@openzeppelin/contracts/utils/Context.sol"; /// @title ERC1155 Multi Token Standard, optional extension: Deliverable (proxiable version). /// @dev This contract is to be used via inheritance in a proxied implementation. /// @dev Note: This contract requires ERC1155 (Multi Token Standard). /// @dev Note: This contract requires AccessControl. abstract contract ERC1155DeliverableBase is IERC1155Deliverable, Context { using ERC1155Storage for ERC1155Storage.Layout; using AccessControlStorage for AccessControlStorage.Layout; // prevent variable name clash with public ERC1155MintableBase.MINTER_ROLE bytes32 private constant _MINTER_ROLE = "minter"; /// @inheritdoc IERC1155Deliverable /// @dev Reverts with {NotRoleHolder} if the sender does not have the 'minter' role. function safeDeliver(address[] calldata recipients, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external virtual { address sender = _msgSender(); AccessControlStorage.layout().enforceHasRole(_MINTER_ROLE, sender); ERC1155Storage.layout().safeDeliver(sender, recipients, ids, values, data); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {InconsistentArrayLengths} from "./../../../CommonErrors.sol"; import {NotMetadataResolver} from "./../../metadata/errors/TokenMetadataErrors.sol"; import {URI} from "./../events/ERC1155Events.sol"; import {IERC1155MetadataURI} from "./../interfaces/IERC1155MetadataURI.sol"; import {IERC1155MetadataSetter} from "./../interfaces/IERC1155MetadataSetter.sol"; import {TokenMetadataStorage} from "./../../metadata/libraries/TokenMetadataStorage.sol"; import {TokenMetadataBase} from "./../../metadata/base/TokenMetadataBase.sol"; /// @title ERC1155 Multi Token Standard, optional extension: Metadata (proxiable version). /// @notice This contracts uses an external resolver for managing individual tokens metadata. /// @dev This contract is to be used via inheritance in a proxied implementation. /// @dev Note: This contract requires ERC1155 (Multi Token Standard). abstract contract ERC1155MetadataBase is TokenMetadataBase, IERC1155MetadataURI, IERC1155MetadataSetter { using TokenMetadataStorage for TokenMetadataStorage.Layout; /// @inheritdoc IERC1155MetadataURI function uri(uint256 tokenId) external view virtual returns (string memory metadataURI) { return TokenMetadataStorage.layout().tokenMetadataURI(address(this), tokenId); } /// @notice Emits the URI event when a token metadata URI is set by the metadata resolver. /// @dev Reverts if the caller is not the metadata resolver. /// @dev Emits a {URI} event. /// @param tokenId The token identifier. /// @param tokenURI The token metadata URI. function setTokenURI(uint256 tokenId, string calldata tokenURI) external virtual { if (msg.sender != address(TokenMetadataStorage.layout().metadataResolver())) revert NotMetadataResolver(msg.sender); emit URI(tokenURI, tokenId); } /// @notice Emits URI events when a batch of token metadata URIs is set by the metadata resolver. /// @dev Reverts if `tokenIds` and `tokenURIs` have different lengths. /// @dev Reverts if the caller is not the metadata resolver. /// @dev Emits a {URI} event for each token. /// @param tokenIds The token identifiers. /// @param tokenURIs The token metadata URIs. function batchSetTokenURI(uint256[] calldata tokenIds, string[] calldata tokenURIs) external virtual { if (tokenIds.length != tokenURIs.length) revert InconsistentArrayLengths(); if (msg.sender != address(TokenMetadataStorage.layout().metadataResolver())) revert NotMetadataResolver(msg.sender); for (uint256 i; i < tokenIds.length; ++i) { emit URI(tokenURIs[i], tokenIds[i]); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {IERC1155Mintable} from "./../interfaces/IERC1155Mintable.sol"; import {ERC1155Storage} from "./../libraries/ERC1155Storage.sol"; import {AccessControlStorage} from "./../../../access/libraries/AccessControlStorage.sol"; import {Context} from "@openzeppelin/contracts/utils/Context.sol"; /// @title ERC1155 Multi Token Standard, optional extension: Mintable (proxiable version). /// @dev This contract is to be used via inheritance in a proxied implementation. /// @dev Note: This contract requires ERC1155 (Multi Token Standard). /// @dev Note: This contract requires AccessControl. abstract contract ERC1155MintableBase is IERC1155Mintable, Context { using ERC1155Storage for ERC1155Storage.Layout; using AccessControlStorage for AccessControlStorage.Layout; bytes32 public constant MINTER_ROLE = "minter"; /// @inheritdoc IERC1155Mintable /// @dev Reverts with {NotRoleHolder} if the sender does not have the 'minter' role. function safeMint(address to, uint256 id, uint256 value, bytes calldata data) external virtual { address sender = _msgSender(); AccessControlStorage.layout().enforceHasRole(MINTER_ROLE, sender); ERC1155Storage.layout().safeMint(sender, to, id, value, data); } /// @inheritdoc IERC1155Mintable /// @dev Reverts with {NotRoleHolder} if the sender does not have the 'minter' role. function safeBatchMint(address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external virtual { address sender = _msgSender(); AccessControlStorage.layout().enforceHasRole(MINTER_ROLE, sender); ERC1155Storage.layout().safeBatchMint(sender, to, ids, values, data); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {IERC1155} from "./../interfaces/IERC1155.sol"; import {ERC1155Storage} from "./../libraries/ERC1155Storage.sol"; import {OperatorFiltererStorage} from "./../../royalty/libraries/OperatorFiltererStorage.sol"; import {Context} from "@openzeppelin/contracts/utils/Context.sol"; /// @title ERC1155 Multi Token Standard with Operator Filterer (proxiable version). /// @dev This contract is to be used via inheritance in a proxied implementation. /// @dev Note: This contract requires ERC165 (Interface Detection Standard). abstract contract ERC1155WithOperatorFiltererBase is IERC1155, Context { using ERC1155Storage for ERC1155Storage.Layout; using OperatorFiltererStorage for OperatorFiltererStorage.Layout; /// @inheritdoc IERC1155 /// @dev Reverts with {OperatorNotAllowed} if the sender is not `from` and is not allowed by the operator registry. function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external virtual { address sender = _msgSender(); OperatorFiltererStorage.layout().requireAllowedOperatorForTransfer(sender, from); ERC1155Storage.layout().safeTransferFrom(sender, from, to, id, value, data); } /// @inheritdoc IERC1155 /// @dev Reverts with {OperatorNotAllowed} if the sender is not `from` and is not allowed by the operator registry. function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external virtual { address sender = _msgSender(); OperatorFiltererStorage.layout().requireAllowedOperatorForTransfer(sender, from); ERC1155Storage.layout().safeBatchTransferFrom(sender, from, to, ids, values, data); } /// @inheritdoc IERC1155 /// @dev Reverts with {OperatorNotAllowed} if `operator` is not allowed by the operator registry. function setApprovalForAll(address operator, bool approved) external virtual { if (approved) { OperatorFiltererStorage.layout().requireAllowedOperatorForApproval(operator); } ERC1155Storage.layout().setApprovalForAll(_msgSender(), operator, approved); } /// @inheritdoc IERC1155 function isApprovedForAll(address owner, address operator) external view returns (bool approvedForAll) { return ERC1155Storage.layout().isApprovedForAll(owner, operator); } /// @inheritdoc IERC1155 function balanceOf(address owner, uint256 id) external view virtual returns (uint256 balance) { return ERC1155Storage.layout().balanceOf(owner, id); } /// @inheritdoc IERC1155 function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) external view virtual returns (uint256[] memory balances) { return ERC1155Storage.layout().balanceOfBatch(owners, ids); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @notice Thrown when trying to approveForAll oneself. /// @param account The account trying to approveForAll itself. error ERC1155SelfApprovalForAll(address account); /// @notice Thrown when transferring tokens to the zero address. error ERC1155TransferToAddressZero(); /// @notice Thrown when a sender tries to transfer tokens but is neither the owner nor approved by the owner. /// @param sender The sender. /// @param owner The owner. error ERC1155NonApproved(address sender, address owner); /// @notice Thrown when transferring an amount of tokens greater than the current balance. /// @param owner The owner. /// @param id The token identifier. /// @param balance The current balance. /// @param value The amount of tokens to transfer. error ERC1155InsufficientBalance(address owner, uint256 id, uint256 balance, uint256 value); /// @notice Thrown when minting or transferring an amount of tokens that would overflow the recipient's balance. /// @param recipient The recipient. /// @param id The token identifier. /// @param balance The current balance. /// @param value The amount of tokens to transfer. error ERC1155BalanceOverflow(address recipient, uint256 id, uint256 balance, uint256 value); /// @notice Thrown when a safe transfer is rejected by the recipient contract. /// @param recipient The recipient contract. /// @param id The token identifier. /// @param value The amount of tokens to transfer. error ERC1155SafeTransferRejected(address recipient, uint256 id, uint256 value); /// @notice Thrown when a safe batch transfer is rejected by the recipient contract. /// @param recipient The recipient contract. /// @param ids The token identifiers. /// @param values The amounts of tokens to transfer. error ERC1155SafeBatchTransferRejected(address recipient, uint256[] ids, uint256[] values); /// @notice Thrown when querying the balance of the zero address. error ERC1155BalanceOfAddressZero();
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @notice Thrown when minting tokens to the zero address. error ERC1155MintToAddressZero();
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @notice Emitted when some token is transferred. /// @param operator The initiator of the transfer. /// @param from The previous token owner. /// @param to The new token owner. /// @param id The transferred token identifier. /// @param value The amount of token. event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /// @notice Emitted when a batch of tokens is transferred. /// @param operator The initiator of the transfer. /// @param from The previous tokens owner. /// @param to The new tokens owner. /// @param ids The transferred tokens identifiers. /// @param values The amounts of tokens. event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values); /// @notice Emitted when an approval for all tokens is set or unset. /// @param owner The tokens owner. /// @param operator The approved address. /// @param approved True when then approval is set, false when it is unset. event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /// @notice Emitted when a token metadata URI is set updated. /// @param value The token metadata URI. /// @param id The token identifier. event URI(string value, uint256 indexed id);
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @title ERC1155 Multi Token Standard, basic interface (functions). /// @dev See https://eips.ethereum.org/EIPS/eip-1155 /// @dev Note: The ERC-165 identifier for this interface is 0xd9b67a26. interface IERC1155 { /// @notice Safely transfers some token. /// @dev Reverts if `to` is the zero address. /// @dev Reverts if the sender is not `from` and has not been approved by `from`. /// @dev Reverts if `from` has an insufficient balance of `id`. /// @dev Reverts if `to` is a contract and the call to {IERC1155TokenReceiver-onERC1155Received} fails, reverts or is rejected. /// @dev Emits a {TransferSingle} event. /// @param from Current token owner. /// @param to Address of the new token owner. /// @param id Identifier of the token to transfer. /// @param value Amount of token to transfer. /// @param data Optional data to send along to a receiver contract. function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external; /// @notice Safely transfers a batch of tokens. /// @dev Reverts if `to` is the zero address. /// @dev Reverts if `ids` and `values` have different lengths. /// @dev Reverts if the sender is not `from` and has not been approved by `from`. /// @dev Reverts if `from` has an insufficient balance for any of `ids`. /// @dev Reverts if `to` is a contract and the call to {IERC1155TokenReceiver-onERC1155BatchReceived} fails, reverts or is rejected. /// @dev Emits a {TransferBatch} event. /// @param from Current tokens owner. /// @param to Address of the new tokens owner. /// @param ids Identifiers of the tokens to transfer. /// @param values Amounts of tokens to transfer. /// @param data Optional data to send along to a receiver contract. function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external; /// @notice Enables or disables an operator's approval. /// @dev Emits an {ApprovalForAll} event. /// @param operator Address of the operator. /// @param approved True to approve the operator, false to revoke its approval. function setApprovalForAll(address operator, bool approved) external; /// @notice Retrieves the approval status of an operator for a given owner. /// @param owner Address of the authorisation giver. /// @param operator Address of the operator. /// @return approved True if the operator is approved, false if not. function isApprovedForAll(address owner, address operator) external view returns (bool approved); /// @notice Retrieves the balance of `id` owned by account `owner`. /// @param owner The account to retrieve the balance of. /// @param id The identifier to retrieve the balance of. /// @return balance The balance of `id` owned by account `owner`. function balanceOf(address owner, uint256 id) external view returns (uint256 balance); /// @notice Retrieves the balances of `ids` owned by accounts `owners`. /// @dev Reverts if `owners` and `ids` have different lengths. /// @param owners The addresses of the token holders /// @param ids The identifiers to retrieve the balance of. /// @return balances The balances of `ids` owned by accounts `owners`. function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) external view returns (uint256[] memory balances); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @title ERC1155 Multi Token Standard, optional extension: Burnable. /// @dev See https://eips.ethereum.org/EIPS/eip-1155 /// @dev Note: The ERC-165 identifier for this interface is 0x921ed8d1. interface IERC1155Burnable { /// @notice Burns some token. /// @dev Reverts if the sender is not `from` and has not been approved by `from`. /// @dev Reverts if `from` has an insufficient balance of `id`. /// @dev Emits an {IERC1155-TransferSingle} event. /// @param from Address of the current token owner. /// @param id Identifier of the token to burn. /// @param value Amount of token to burn. function burnFrom(address from, uint256 id, uint256 value) external; /// @notice Burns multiple tokens. /// @dev Reverts if `ids` and `values` have different lengths. /// @dev Reverts if the sender is not `from` and has not been approved by `from`. /// @dev Reverts if `from` has an insufficient balance for any of `ids`. /// @dev Emits an {IERC1155-TransferBatch} event. /// @param from Address of the current tokens owner. /// @param ids Identifiers of the tokens to burn. /// @param values Amounts of tokens to burn. function batchBurnFrom(address from, uint256[] calldata ids, uint256[] calldata values) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @title ERC1155 Multi Token Standard, optional extension: Deliverable. /// @dev See https://eips.ethereum.org/EIPS/eip-1155 /// @dev Note: The ERC-165 identifier for this interface is 0xe8ab9ccc. interface IERC1155Deliverable { /// @notice Safely mints tokens to multiple recipients. /// @dev Reverts if `recipients`, `ids` and `values` have different lengths. /// @dev Reverts if one of `recipients` is the zero address. /// @dev Reverts if one of `recipients` balance overflows. /// @dev Reverts if one of `recipients` is a contract and the call to {IERC1155TokenReceiver-onERC1155Received} fails, reverts or is rejected. /// @dev Emits an {IERC1155-TransferSingle} event from the zero address for each transfer. /// @param recipients Addresses of the new tokens owners. /// @param ids Identifiers of the tokens to mint. /// @param values Amounts of tokens to mint. /// @param data Optional data to send along to a receiver contract. function safeDeliver(address[] calldata recipients, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; interface IERC1155MetadataSetter { /// @notice Sets the metadata URI for a token. /// @dev Emits a {URI} event. /// @param tokenId The token identifier. /// @param tokenURI The token metadata URI. function setTokenURI(uint256 tokenId, string calldata tokenURI) external; /// @notice Sets the metadata URIs for a batch of tokens. /// @dev Reverts with {InconsistentArrayLengths} if the arrays are of inconsistent lengths. /// @dev Emits a {URI} event for each token. /// @param tokenIds The token identifiers. /// @param tokenURIs The token metadata URIs. function batchSetTokenURI(uint256[] calldata tokenIds, string[] calldata tokenURIs) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @title ERC1155 Multi Token Standard, optional extension: Metadata URI. /// @dev See https://eips.ethereum.org/EIPS/eip-1155 /// @dev Note: The ERC-165 identifier for this interface is 0x0e89341c. interface IERC1155MetadataURI { /// @notice Retrieves the URI for a given token. /// @dev URIs are defined in RFC 3986. /// @dev The URI MUST point to a JSON file that conforms to the "ERC1155 Metadata URI JSON Schema". /// @dev The uri function SHOULD be used to retrieve values if no event was emitted. /// @dev The uri function MUST return the same value as the latest event for an _id if it was emitted. /// @dev The uri function MUST NOT be used to check for the existence of a token as it is possible for /// an implementation to return a valid string even if the token does not exist. /// @return metadataURI The URI associated to the token. function uri(uint256 id) external view returns (string memory metadataURI); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @title ERC1155 Multi Token Standard, optional extension: Mintable. /// @dev See https://eips.ethereum.org/EIPS/eip-1155 /// @dev Note: The ERC-165 identifier for this interface is 0x5190c92c. interface IERC1155Mintable { /// @notice Safely mints some token. /// @dev Reverts if `to` is the zero address. /// @dev Reverts if `to`'s balance of `id` overflows. /// @dev Reverts if `to` is a contract and the call to {IERC1155TokenReceiver-onERC1155Received} fails, reverts or is rejected. /// @dev Emits an {IERC1155-TransferSingle} event. /// @param to Address of the new token owner. /// @param id Identifier of the token to mint. /// @param value Amount of token to mint. /// @param data Optional data to send along to a receiver contract. function safeMint(address to, uint256 id, uint256 value, bytes calldata data) external; /// @notice Safely mints a batch of tokens. /// @dev Reverts if `ids` and `values` have different lengths. /// @dev Reverts if `to` is the zero address. /// @dev Reverts if `to`'s balance overflows for one of `ids`. /// @dev Reverts if `to` is a contract and the call to {IERC1155TokenReceiver-onERC1155batchReceived} fails, reverts or is rejected. /// @dev Emits an {IERC1155-TransferBatch} event. /// @param to Address of the new tokens owner. /// @param ids Identifiers of the tokens to mint. /// @param values Amounts of tokens to mint. /// @param data Optional data to send along to a receiver contract. function safeBatchMint(address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @title ERC1155 Multi Token Standard, Tokens Receiver. /// @notice Interface for any contract that wants to support transfers from ERC1155 asset contracts. /// @dev See https://eips.ethereum.org/EIPS/eip-1155 /// @dev Note: The ERC-165 identifier for this interface is 0x4e2312e0. interface IERC1155TokenReceiver { /// @notice Handles the receipt of a single ERC1155 token type. /// @notice ERC1155 contracts MUST call this function on a recipient contract, at the end of a `safeTransferFrom` after the balance update. /// @dev Return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` (`0xf23a6e61`) to accept the transfer. /// @dev Return of any other value than the prescribed keccak256 generated value will result in the transaction being reverted by the caller. /// @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 magicValue `0xf23a6e61` to accept the transfer, or any other value to reject it. function onERC1155Received(address operator, address from, uint256 id, uint256 value, bytes calldata data) external returns (bytes4 magicValue); /// @notice Handles the receipt of multiple ERC1155 token types. /// @notice ERC1155 contracts MUST call this function on a recipient contract, at the end of a `safeBatchTransferFrom` after the balance updates. /// @dev Return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` (`0xbc197c81`) to accept the transfer. /// @dev Return of any other value than the prescribed keccak256 generated value will result in the transaction being reverted by the caller. /// @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 magicValue `0xbc197c81` to accept the transfer, or any other value to reject it. function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4 magicValue); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; // solhint-disable-next-line max-line-length import {ERC1155SelfApprovalForAll, ERC1155TransferToAddressZero, ERC1155NonApproved, ERC1155InsufficientBalance, ERC1155BalanceOverflow, ERC1155SafeTransferRejected, ERC1155SafeBatchTransferRejected, ERC1155BalanceOfAddressZero} from "./../errors/ERC1155Errors.sol"; import {ERC1155MintToAddressZero} from "./../errors/ERC1155MintableErrors.sol"; import {InconsistentArrayLengths} from "./../../../CommonErrors.sol"; import {TransferSingle, TransferBatch, ApprovalForAll} from "./../events/ERC1155Events.sol"; import {IERC1155} from "./../interfaces/IERC1155.sol"; import {IERC1155MetadataURI} from "./../interfaces/IERC1155MetadataURI.sol"; import {IERC1155Mintable} from "./../interfaces/IERC1155Mintable.sol"; import {IERC1155Deliverable} from "./../interfaces/IERC1155Deliverable.sol"; import {IERC1155Burnable} from "./../interfaces/IERC1155Burnable.sol"; import {IERC1155TokenReceiver} from "./../interfaces/IERC1155TokenReceiver.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {InterfaceDetectionStorage} from "./../../../introspection/libraries/InterfaceDetectionStorage.sol"; library ERC1155Storage { using Address for address; using ERC1155Storage for ERC1155Storage.Layout; using InterfaceDetectionStorage for InterfaceDetectionStorage.Layout; struct Layout { mapping(uint256 => mapping(address => uint256)) balances; mapping(address => mapping(address => bool)) operators; } bytes32 internal constant LAYOUT_STORAGE_SLOT = bytes32(uint256(keccak256("animoca.token.ERC1155.ERC1155.storage")) - 1); bytes4 internal constant ERC1155_SINGLE_RECEIVED = IERC1155TokenReceiver.onERC1155Received.selector; bytes4 internal constant ERC1155_BATCH_RECEIVED = IERC1155TokenReceiver.onERC1155BatchReceived.selector; /// @notice Marks the following ERC165 interface(s) as supported: ERC1155. function init() internal { InterfaceDetectionStorage.layout().setSupportedInterface(type(IERC1155).interfaceId, true); } /// @notice Marks the following ERC165 interface(s) as supported: ERC1155MetadataURI. function initERC1155MetadataURI() internal { InterfaceDetectionStorage.layout().setSupportedInterface(type(IERC1155MetadataURI).interfaceId, true); } /// @notice Marks the following ERC165 interface(s) as supported: ERC1155Mintable. function initERC1155Mintable() internal { InterfaceDetectionStorage.layout().setSupportedInterface(type(IERC1155Mintable).interfaceId, true); } /// @notice Marks the following ERC165 interface(s) as supported: ERC1155Deliverable. function initERC1155Deliverable() internal { InterfaceDetectionStorage.layout().setSupportedInterface(type(IERC1155Deliverable).interfaceId, true); } /// @notice Marks the following ERC165 interface(s) as supported: ERC1155Burnable. function initERC1155Burnable() internal { InterfaceDetectionStorage.layout().setSupportedInterface(type(IERC1155Burnable).interfaceId, true); } /// @notice Safely transfers some token by a sender. /// @dev Note: This function implements {ERC1155-safeTransferFrom(address,address,uint256,uint256,bytes)}. /// @dev Warning: Since a `to` contract can run arbitrary code, developers should be aware of potential re-entrancy attacks. /// @dev Reverts with {ERC1155TransferToAddressZero} if `to` is the zero address. /// @dev Reverts with {ERC1155NonApproved} if `sender` is not `from` and has not been approved by `from`. /// @dev Reverts with {ERC1155InsufficientBalance} if `from` has an insufficient balance of `id`. /// @dev Reverts with {ERC1155BalanceOverflow} if `to`'s balance of `id` overflows. /// @dev Reverts with {ERC1155SafeTransferRejected} if `to` is a contract and the call to /// {IERC1155TokenReceiver-onERC1155Received} fails, reverts or is rejected. /// @dev Emits a {TransferSingle} event. /// @param sender The message sender. /// @param from Current token owner. /// @param to Address of the new token owner. /// @param id Identifier of the token to transfer. /// @param value Amount of token to transfer. /// @param data Optional data to send along to a receiver contract. function safeTransferFrom(Layout storage s, address sender, address from, address to, uint256 id, uint256 value, bytes calldata data) internal { if (to == address(0)) revert ERC1155TransferToAddressZero(); if (!_isOperatable(s, from, sender)) revert ERC1155NonApproved(sender, from); _transferToken(s, from, to, id, value); emit TransferSingle(sender, from, to, id, value); if (to.isContract()) { _callOnERC1155Received(sender, from, to, id, value, data); } } /// @notice Safely transfers a batch of tokens by a sender. /// @dev Note: This function implements {ERC1155-safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)}. /// @dev Warning: Since a `to` contract can run arbitrary code, developers should be aware of potential re-entrancy attacks. /// @dev Reverts with {ERC1155TransferToAddressZero} if `to` is the zero address. /// @dev Reverts with {InconsistentArrayLengths} if `ids` and `values` have different lengths. /// @dev Reverts with {ERC1155NonApproved} if `sender` is not `from` and has not been approved by `from`. /// @dev Reverts with {ERC1155InsufficientBalance} if `from` has an insufficient balance for any of `ids`. /// @dev Reverts with {ERC1155BalanceOverflow} if `to`'s balance of any of `ids` overflows. /// @dev Reverts with {ERC1155SafeBatchTransferRejected} if `to` is a contract and the call to /// {IERC1155TokenReceiver-onERC1155BatchReceived} fails, reverts or is rejected. /// @dev Emits a {TransferBatch} event. /// @param sender The message sender. /// @param from Current tokens owner. /// @param to Address of the new tokens owner. /// @param ids Identifiers of the tokens to transfer. /// @param values Amounts of tokens to transfer. /// @param data Optional data to send along to a receiver contract. function safeBatchTransferFrom( Layout storage s, address sender, address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) internal { if (to == address(0)) revert ERC1155TransferToAddressZero(); uint256 length = ids.length; if (length != values.length) revert InconsistentArrayLengths(); if (!_isOperatable(s, from, sender)) revert ERC1155NonApproved(sender, from); for (uint256 i; i < length; ++i) { _transferToken(s, from, to, ids[i], values[i]); } emit TransferBatch(sender, from, to, ids, values); if (to.isContract()) { _callOnERC1155BatchReceived(sender, from, to, ids, values, data); } } /// @notice Safely mints some token by a sender. /// @dev Note: This function implements {ERC1155Mintable-safeMint(address,uint256,uint256,bytes)}. /// @dev Warning: Since a `to` contract can run arbitrary code, developers should be aware of potential re-entrancy attacks. /// @dev Reverts with {ERC1155MintToAddressZero} if `to` is the zero address. /// @dev Reverts with {ERC1155BalanceOverflow} if `to`'s balance of `id` overflows. /// @dev Reverts with {ERC1155SafeTransferRejected} if `to` is a contract and the call to /// {IERC1155TokenReceiver-onERC1155Received} fails, reverts or is rejected. /// @dev Emits a {TransferSingle} event. /// @param sender The message sender. /// @param to Address of the new token owner. /// @param id Identifier of the token to mint. /// @param value Amount of token to mint. /// @param data Optional data to send along to a receiver contract. function safeMint(Layout storage s, address sender, address to, uint256 id, uint256 value, bytes memory data) internal { if (to == address(0)) revert ERC1155MintToAddressZero(); _mintToken(s, to, id, value); emit TransferSingle(sender, address(0), to, id, value); if (to.isContract()) { _callOnERC1155Received(sender, address(0), to, id, value, data); } } /// @notice Safely mints a batch of tokens by a sender. /// @dev Note: This function implements {ERC1155Mintable-safeBatchMint(address,uint256[],uint256[],bytes)}. /// @dev Warning: Since a `to` contract can run arbitrary code, developers should be aware of potential re-entrancy attacks. /// @dev Reverts with {ERC1155MintToAddressZero} if `to` is the zero address. /// @dev Reverts with {InconsistentArrayLengths} if `ids` and `values` have different lengths. /// @dev Reverts with {ERC1155BalanceOverflow} if `to`'s balance overflows for one of `ids`. /// @dev Reverts with {ERC1155SafeBatchTransferRejected} if `to` is a contract and the call to /// {IERC1155TokenReceiver-onERC1155batchReceived} fails, reverts or is rejected. /// @dev Emits a {TransferBatch} event. /// @param sender The message sender. /// @param to Address of the new tokens owner. /// @param ids Identifiers of the tokens to mint. /// @param values Amounts of tokens to mint. /// @param data Optional data to send along to a receiver contract. function safeBatchMint(Layout storage s, address sender, address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal { if (to == address(0)) revert ERC1155MintToAddressZero(); uint256 length = ids.length; if (length != values.length) revert InconsistentArrayLengths(); for (uint256 i; i < length; ++i) { _mintToken(s, to, ids[i], values[i]); } emit TransferBatch(sender, address(0), to, ids, values); if (to.isContract()) { _callOnERC1155BatchReceived(sender, address(0), to, ids, values, data); } } /// @notice Safely mints tokens to multiple recipients by a sender. /// @dev Note: This function implements {ERC1155Deliverable-safeDeliver(address[],uint256[],uint256[],bytes)}. /// @dev Warning: Since a `to` contract can run arbitrary code, developers should be aware of potential re-entrancy attacks. /// @dev Reverts with {InconsistentArrayLengths} if `recipients`, `ids` and `values` have different lengths. /// @dev Reverts with {ERC1155MintToAddressZero} if one of `recipients` is the zero address. /// @dev Reverts with {ERC1155BalanceOverflow} if one of the `recipients`' balance overflows for the associated `ids`. /// @dev Reverts with {ERC1155SafeTransferRejected} if one of `recipients` is a contract and the call to /// {IERC1155TokenReceiver-onERC1155Received} fails, reverts or is rejected. /// @dev Emits a {TransferSingle} event from the zero address for each transfer. /// @param sender The message sender. /// @param recipients Addresses of the new tokens owners. /// @param ids Identifiers of the tokens to mint. /// @param values Amounts of tokens to mint. /// @param data Optional data to send along to a receiver contract. function safeDeliver( Layout storage s, address sender, address[] memory recipients, uint256[] memory ids, uint256[] memory values, bytes memory data ) internal { uint256 length = recipients.length; if (length != ids.length || length != values.length) revert InconsistentArrayLengths(); for (uint256 i; i < length; ++i) { s.safeMint(sender, recipients[i], ids[i], values[i], data); } } /// @notice Burns some token by a sender. /// @dev Reverts with {ERC1155NonApproved} if `sender` is not `from` and has not been approved by `from`. /// @dev Reverts with {ERC1155InsufficientBalance} if `from` has an insufficient balance of `id`. /// @dev Emits a {TransferSingle} event. /// @param sender The message sender. /// @param from Address of the current token owner. /// @param id Identifier of the token to burn. /// @param value Amount of token to burn. function burnFrom(Layout storage s, address sender, address from, uint256 id, uint256 value) internal { if (!_isOperatable(s, from, sender)) revert ERC1155NonApproved(sender, from); _burnToken(s, from, id, value); emit TransferSingle(sender, from, address(0), id, value); } /// @notice Burns multiple tokens by a sender. /// @dev Reverts with {InconsistentArrayLengths} if `ids` and `values` have different lengths. /// @dev Reverts with {ERC1155NonApproved} if `sender` is not `from` and has not been approved by `from`. /// @dev Reverts with {ERC1155InsufficientBalance} if `from` has an insufficient balance for any of `ids`. /// @dev Emits an {IERC1155-TransferBatch} event. /// @param sender The message sender. /// @param from Address of the current tokens owner. /// @param ids Identifiers of the tokens to burn. /// @param values Amounts of tokens to burn. function batchBurnFrom(Layout storage s, address sender, address from, uint256[] calldata ids, uint256[] calldata values) internal { uint256 length = ids.length; if (length != values.length) revert InconsistentArrayLengths(); if (!_isOperatable(s, from, sender)) revert ERC1155NonApproved(sender, from); for (uint256 i; i < length; ++i) { _burnToken(s, from, ids[i], values[i]); } emit TransferBatch(sender, from, address(0), ids, values); } /// @notice Enables or disables an operator's approval by a sender. /// @dev Reverts with {ERC1155SelfApprovalForAll} if `sender` is `operator`. /// @dev Emits an {ApprovalForAll} event. /// @param sender The message sender. /// @param operator Address of the operator. /// @param approved True to approve the operator, false to revoke its approval. function setApprovalForAll(Layout storage s, address sender, address operator, bool approved) internal { if (operator == sender) revert ERC1155SelfApprovalForAll(sender); s.operators[sender][operator] = approved; emit ApprovalForAll(sender, operator, approved); } /// @notice Retrieves the approval status of an operator for a given owner. /// @param owner Address of the authorisation giver. /// @param operator Address of the operator. /// @return approved True if the operator is approved, false if not. function isApprovedForAll(Layout storage s, address owner, address operator) internal view returns (bool approved) { return s.operators[owner][operator]; } /// @notice Retrieves the balance of `id` owned by account `owner`. /// @dev Reverts with {ERC1155BalanceOfAddressZero} if `owner` is the zero address. /// @param owner The account to retrieve the balance of. /// @param id The identifier to retrieve the balance of. /// @return balance The balance of `id` owned by account `owner`. function balanceOf(Layout storage s, address owner, uint256 id) internal view returns (uint256 balance) { if (owner == address(0)) revert ERC1155BalanceOfAddressZero(); return s.balances[id][owner]; } /// @notice Retrieves the balances of `ids` owned by accounts `owners`. /// @dev Reverts with {InconsistentArrayLengths} if `owners` and `ids` have different lengths. /// @dev Reverts with {ERC1155BalanceOfAddressZero} if one of `owners` is the zero address. /// @param owners The addresses of the token holders /// @param ids The identifiers to retrieve the balance of. /// @return balances The balances of `ids` owned by accounts `owners`. function balanceOfBatch(Layout storage s, address[] calldata owners, uint256[] calldata ids) internal view returns (uint256[] memory balances) { uint256 length = owners.length; if (length != ids.length) revert InconsistentArrayLengths(); balances = new uint256[](owners.length); for (uint256 i; i < length; ++i) { balances[i] = s.balanceOf(owners[i], ids[i]); } } function layout() internal pure returns (Layout storage s) { bytes32 position = LAYOUT_STORAGE_SLOT; assembly { s.slot := position } } /// @notice Returns whether an account is authorised to make a transfer on behalf of an owner. /// @param owner The token owner. /// @param account The account to check the operatability of. /// @return operatable True if `account` is `owner` or is an operator for `owner`, false otherwise. function _isOperatable(Layout storage s, address owner, address account) private view returns (bool operatable) { return (owner == account) || s.operators[owner][account]; } function _transferToken(Layout storage s, address from, address to, uint256 id, uint256 value) private { if (value != 0) { uint256 fromBalance = s.balances[id][from]; unchecked { uint256 newFromBalance = fromBalance - value; if (newFromBalance >= fromBalance) revert ERC1155InsufficientBalance(from, id, fromBalance, value); if (from != to) { uint256 toBalance = s.balances[id][to]; uint256 newToBalance = toBalance + value; if (newToBalance <= toBalance) revert ERC1155BalanceOverflow(to, id, toBalance, value); s.balances[id][from] = newFromBalance; s.balances[id][to] = newToBalance; } } } } function _mintToken(Layout storage s, address to, uint256 id, uint256 value) private { if (value != 0) { unchecked { uint256 balance = s.balances[id][to]; uint256 newBalance = balance + value; if (newBalance <= balance) revert ERC1155BalanceOverflow(to, id, balance, value); s.balances[id][to] = newBalance; } } } function _burnToken(Layout storage s, address from, uint256 id, uint256 value) private { if (value != 0) { uint256 balance = s.balances[id][from]; unchecked { uint256 newBalance = balance - value; if (newBalance >= balance) revert ERC1155InsufficientBalance(from, id, balance, value); s.balances[id][from] = newBalance; } } } /// @notice Calls {IERC1155TokenReceiver-onERC1155Received} on a target contract. /// @dev Reverts with {ERC1155SafeTransferRejected} if the call to the target fails, reverts or is rejected. /// @param sender The message sender. /// @param from Previous token owner. /// @param to New token owner. /// @param id Identifier of the token transferred. /// @param value Value transferred. /// @param data Optional data to send along with the receiver contract call. function _callOnERC1155Received(address sender, address from, address to, uint256 id, uint256 value, bytes memory data) private { if (IERC1155TokenReceiver(to).onERC1155Received(sender, from, id, value, data) != ERC1155_SINGLE_RECEIVED) revert ERC1155SafeTransferRejected(to, id, value); } /// @notice Calls {IERC1155TokenReceiver-onERC1155BatchReceived} on a target contract. /// @dev Reverts with {ERC1155SafeBatchTransferRejected} if the call to the target fails, reverts or is rejected. /// @param sender The message sender. /// @param from Previous token owner. /// @param to New token owner. /// @param ids Identifiers of the tokens transferred. /// @param values Values transferred. /// @param data Optional data to send along with the receiver contract call. function _callOnERC1155BatchReceived( address sender, address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) private { if (IERC1155TokenReceiver(to).onERC1155BatchReceived(sender, from, ids, values, data) != ERC1155_BATCH_RECEIVED) revert ERC1155SafeBatchTransferRejected(to, ids, values); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @title ERC721 Non-Fungible Token Standard, basic interface (functions). /// @dev See https://eips.ethereum.org/EIPS/eip-721 /// @dev This interface only contains the standard functions. See IERC721Events for the events. /// @dev Note: The ERC-165 identifier for this interface is 0x80ac58cd. interface IERC721 { /// @notice Sets or unsets an approval to transfer a single token on behalf of its owner. /// @dev Note: There can only be one approved address per token at a given time. /// @dev Note: A token approval gets reset when this token is transferred, including a self-transfer. /// @dev Reverts if `tokenId` does not exist. /// @dev Reverts if `to` is the token owner. /// @dev Reverts if the sender is not the token owner and has not been approved by the token owner. /// @dev Emits an {Approval} event. /// @param to The address to approve, or the zero address to remove any existing approval. /// @param tokenId The token identifier to give approval for. function approve(address to, uint256 tokenId) external; /// @notice Sets or unsets an approval to transfer all tokens on behalf of their owner. /// @dev Reverts if the sender is the same as `operator`. /// @dev Emits an {ApprovalForAll} event. /// @param operator The address to approve for all tokens. /// @param approved True to set an approval for all tokens, false to unset it. function setApprovalForAll(address operator, bool approved) external; /// @notice Unsafely transfers the ownership of a token to a recipient. /// @dev Note: Usage of this method is discouraged, use `safeTransferFrom` whenever possible. /// @dev Resets the token approval for `tokenId`. /// @dev Reverts if `to` is the zero address. /// @dev Reverts if `from` is not the owner of `tokenId`. /// @dev Reverts if the sender is not `from` and has not been approved by `from` for `tokenId`. /// @dev Emits a {Transfer} event. /// @param from The current token owner. /// @param to The recipient of the token transfer. Self-transfers are possible. /// @param tokenId The identifier of the token to transfer. function transferFrom(address from, address to, uint256 tokenId) external; /// @notice Safely transfers the ownership of a token to a recipient. /// @dev Resets the token approval for `tokenId`. /// @dev Reverts if `to` is the zero address. /// @dev Reverts if `from` is not the owner of `tokenId`. /// @dev Reverts if the sender is not `from` and has not been approved by `from` for `tokenId`. /// @dev Reverts if `to` is a contract and the call to {IERC721Receiver-onERC721Received} fails, reverts or is rejected. /// @dev Emits a {Transfer} event. /// @param from The current token owner. /// @param to The recipient of the token transfer. /// @param tokenId The identifier of the token to transfer. function safeTransferFrom(address from, address to, uint256 tokenId) external; /// @notice Safely transfers the ownership of a token to a recipient. /// @dev Resets the token approval for `tokenId`. /// @dev Reverts if `to` is the zero address. /// @dev Reverts if `from` is not the owner of `tokenId`. /// @dev Reverts if the sender is not `from` and has not been approved by `from` for `tokenId`. /// @dev Reverts if `to` is a contract and the call to {IERC721Receiver-onERC721Received} fails, reverts or is rejected. /// @dev Emits a {Transfer} event. /// @param from The current token owner. /// @param to The recipient of the token transfer. /// @param tokenId The identifier of the token to transfer. /// @param data Optional data to send along to a receiver contract. function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /// @notice Gets the balance of an address. /// @dev Reverts if `owner` is the zero address. /// @param owner The address to query the balance of. /// @return balance The amount owned by the owner. function balanceOf(address owner) external view returns (uint256 balance); /// @notice Gets the owner of a token. /// @dev Reverts if `tokenId` does not exist. /// @param tokenId The token identifier to query the owner of. /// @return tokenOwner The owner of the token identifier. function ownerOf(uint256 tokenId) external view returns (address tokenOwner); /// @notice Gets the approved address for a token. /// @dev Reverts if `tokenId` does not exist. /// @param tokenId The token identifier to query the approval of. /// @return approved The approved address for the token identifier, or the zero address if no approval is set. function getApproved(uint256 tokenId) external view returns (address approved); /// @notice Gets whether an operator is approved for all tokens by an owner. /// @param owner The address which gives the approval for all tokens. /// @param operator The address which receives the approval for all tokens. /// @return approvedForAll Whether the operator is approved for all tokens by the owner. function isApprovedForAll(address owner, address operator) external view returns (bool approvedForAll); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {ITokenMetadataResolver} from "./../interfaces/ITokenMetadataResolver.sol"; import {TokenMetadataStorage} from "./../libraries/TokenMetadataStorage.sol"; /// @title TokenMetadataBase (proxiable version). /// @notice Provides metadata management for token contracts (ERC721/ERC1155) which uses an external resolver for managing individual tokens metadata. /// @dev This contract is to be used via inheritance in a proxied implementation. abstract contract TokenMetadataBase { using TokenMetadataStorage for TokenMetadataStorage.Layout; /// @notice Gets the token name. E.g. "My Token". /// @return tokenName The token name. function name() public view virtual returns (string memory tokenName) { return TokenMetadataStorage.layout().name(); } /// @notice Gets the token symbol. E.g. "TOK". /// @return tokenSymbol The token symbol. function symbol() public view virtual returns (string memory tokenSymbol) { return TokenMetadataStorage.layout().symbol(); } /// @notice Gets the token metadata resolver address. /// @return tokenMetadataResolver The token metadata resolver address. function metadataResolver() external view virtual returns (ITokenMetadataResolver tokenMetadataResolver) { return TokenMetadataStorage.layout().metadataResolver(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @notice Thrown when an account is not the metadata resolver but is required to. /// @param account The account that was checked. error NotMetadataResolver(address account);
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @title ITokenMetadataResolver /// @notice Interface for Token Metadata Resolvers. interface ITokenMetadataResolver { /// @notice Gets the token metadata URI for a token. /// @param tokenContract The token contract for which to retrieve the token URI. /// @param tokenId The token identifier. /// @return tokenURI The token metadata URI. function tokenMetadataURI(address tokenContract, uint256 tokenId) external view returns (string memory tokenURI); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {ITokenMetadataResolver} from "./../interfaces/ITokenMetadataResolver.sol"; import {ProxyInitialization} from "./../../../proxy/libraries/ProxyInitialization.sol"; library TokenMetadataStorage { struct Layout { string tokenName; string tokenSymbol; ITokenMetadataResolver tokenMetadataResolver; } bytes32 internal constant LAYOUT_STORAGE_SLOT = bytes32(uint256(keccak256("animoca.token.metadata.TokenMetadata.storage")) - 1); bytes32 internal constant PROXY_INIT_PHASE_SLOT = bytes32(uint256(keccak256("animoca.token.metadata.TokenMetadata.phase")) - 1); /// @notice Initializes the metadata storage (immutable version). /// @dev Note: This function should be called ONLY in the constructor of an immutable (non-proxied) contract. /// @param tokenName The token name. /// @param tokenSymbol The token symbol. /// @param tokenMetadataResolver The address of the metadata resolver contract. function constructorInit( Layout storage s, string memory tokenName, string memory tokenSymbol, ITokenMetadataResolver tokenMetadataResolver ) internal { s.tokenName = tokenName; s.tokenSymbol = tokenSymbol; s.tokenMetadataResolver = tokenMetadataResolver; } /// @notice Initializes the metadata storage (proxied version). /// @notice Sets the proxy initialization phase to `1`. /// @dev Note: This function should be called ONLY in the init function of a proxied contract. /// @dev Reverts with {InitializationPhaseAlreadyReached} if the proxy initialization phase is set to `1` or above. /// @param tokenName The token name. /// @param tokenSymbol The token symbol. /// @param tokenMetadataResolver The address of the metadata resolver contract. function proxyInit( Layout storage s, string calldata tokenName, string calldata tokenSymbol, ITokenMetadataResolver tokenMetadataResolver ) internal { ProxyInitialization.setPhase(PROXY_INIT_PHASE_SLOT, 1); s.tokenName = tokenName; s.tokenSymbol = tokenSymbol; s.tokenMetadataResolver = tokenMetadataResolver; } /// @notice Gets the name of the token. /// @return tokenName The name of the token contract. function name(Layout storage s) internal view returns (string memory tokenName) { return s.tokenName; } /// @notice Gets the symbol of the token. /// @return tokenSymbol The symbol of the token contract. function symbol(Layout storage s) internal view returns (string memory tokenSymbol) { return s.tokenSymbol; } /// @notice Gets the address of the token metadata resolver. /// @return tokenMetadataResolver The address of the token metadata resolver. function metadataResolver(Layout storage s) internal view returns (ITokenMetadataResolver tokenMetadataResolver) { return s.tokenMetadataResolver; } /// @notice Gets the token metadata URI retieved from the metadata resolver contract. /// @param tokenContract The address of the token contract. /// @param tokenId The ID of the token. function tokenMetadataURI(Layout storage s, address tokenContract, uint256 tokenId) internal view returns (string memory) { return s.tokenMetadataResolver.tokenMetadataURI(tokenContract, tokenId); } function layout() internal pure returns (Layout storage s) { bytes32 position = LAYOUT_STORAGE_SLOT; assembly { s.slot := position } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {ERC2981Storage} from "./libraries/ERC2981Storage.sol"; import {ERC2981Base} from "./base/ERC2981Base.sol"; import {ContractOwnership} from "./../../access/ContractOwnership.sol"; /// @title ERC2981 NFT Royalty Standard (immutable version). /// @dev This contract is to be used via inheritance in an immutable (non-proxied) implementation. abstract contract ERC2981 is ERC2981Base, ContractOwnership { /// @notice Marks the following ERC165 interface(s) as supported: ERC2981. constructor() { ERC2981Storage.init(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {IERC2981} from "./../interfaces/IERC2981.sol"; import {ERC2981Storage} from "./../libraries/ERC2981Storage.sol"; import {ContractOwnershipStorage} from "./../../../access/libraries/ContractOwnershipStorage.sol"; import {Context} from "@openzeppelin/contracts/utils/Context.sol"; /// @title ERC2981 NFT Royalty Standard (proxiable version). /// @dev This contract is to be used via inheritance in a proxied implementation. /// @dev Note: This contract requires ERC165 (Interface Detection Standard). /// @dev Note: This contract requires ERC173 (Contract Ownership standard). abstract contract ERC2981Base is Context, IERC2981 { using ERC2981Storage for ERC2981Storage.Layout; using ContractOwnershipStorage for ContractOwnershipStorage.Layout; uint256 public constant ROYALTY_FEE_DENOMINATOR = ERC2981Storage.ROYALTY_FEE_DENOMINATOR; /// @notice Sets the royalty percentage. /// @dev Reverts with {NotContractOwner} if the sender is not the contract owner. /// @dev Reverts with {IncorrectRoyaltyPercentage} if `percentage` is above 100% (> FEE_DENOMINATOR). /// @param percentage The new percentage to set. For example 50000 sets 50% royalty. function setRoyaltyPercentage(uint256 percentage) external { ContractOwnershipStorage.layout().enforceIsContractOwner(_msgSender()); ERC2981Storage.layout().setRoyaltyPercentage(percentage); } /// @notice Sets the royalty receiver. /// @dev Reverts with {NotContractOwner} if the sender is not the contract owner. /// @dev Reverts with {IncorrectRoyaltyReceiver} if `receiver` is the zero address. /// @param receiver The new receiver to set. function setRoyaltyReceiver(address receiver) external { ContractOwnershipStorage.layout().enforceIsContractOwner(_msgSender()); ERC2981Storage.layout().setRoyaltyReceiver(receiver); } /// @inheritdoc IERC2981 function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount) { return ERC2981Storage.layout().royaltyInfo(tokenId, salePrice); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {IOperatorFilterRegistry} from "./../interfaces/IOperatorFilterRegistry.sol"; import {OperatorFiltererStorage} from "./../libraries/OperatorFiltererStorage.sol"; import {ContractOwnershipStorage} from "./../../../access/libraries/ContractOwnershipStorage.sol"; import {Context} from "@openzeppelin/contracts/utils/Context.sol"; /// @title Operator Filterer for token contracts (proxiable version). /// @dev This contract is to be used via inheritance in a proxied implementation. /// @dev Note: This contract requires ERC173 (Contract Ownership standard). abstract contract OperatorFiltererBase is Context { using OperatorFiltererStorage for OperatorFiltererStorage.Layout; using ContractOwnershipStorage for ContractOwnershipStorage.Layout; /// @notice Updates the address that the contract will make OperatorFilter checks against. /// @dev Reverts with {NotContractOwner} if the sender is not the contract owner. /// @param registry The new operator filter registry address. When set to the zero address, checks will be bypassed. function updateOperatorFilterRegistry(IOperatorFilterRegistry registry) external { ContractOwnershipStorage.layout().enforceIsContractOwner(_msgSender()); OperatorFiltererStorage.layout().updateOperatorFilterRegistry(registry); } /// @notice Gets the operator filter registry address. function operatorFilterRegistry() external view returns (IOperatorFilterRegistry) { return OperatorFiltererStorage.layout().operatorFilterRegistry(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @notice Thrown when setting a royalty percentage that is above 100% (> FEE_DENOMINATOR). /// @param percentage The royalty percentage that was attempted to be set. error ERC2981IncorrectRoyaltyPercentage(uint256 percentage); /// @notice Thrown when setting a royalty receiver that is the zero address. error ERC2981IncorrectRoyaltyReceiver();
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @notice Thrown when transferring to or giving approval to a non-authorized operator. /// @param operator The address that is not authorized. error OperatorNotAllowed(address operator);
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; /// @title ERC2981 NFT Royalty Standard. /// @dev See https://eips.ethereum.org/EIPS/eip-2981 /// @dev Note: The ERC-165 identifier for this interface is 0x2a55205a. interface IERC2981 { /// @notice Called with the sale price to determine how much royalty is owed and to whom. /// @param tokenId The NFT asset queried for royalty information /// @param salePrice The sale price of the NFT asset specified by `tokenId` /// @return receiver Address of who should be sent the royalty payment /// @return royaltyAmount The royalty payment amount for `salePrice` function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; interface IOperatorFilterRegistry { function isOperatorAllowed(address registrant, address operator) external view returns (bool); function register(address registrant) external; function registerAndSubscribe(address registrant, address subscription) external; function registerAndCopyEntries(address registrant, address registrantToCopy) external; function unregister(address addr) external; function updateOperator(address registrant, address operator, bool filtered) external; function updateOperators(address registrant, address[] calldata operators, bool filtered) external; function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external; function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external; function subscribe(address registrant, address registrantToSubscribe) external; function unsubscribe(address registrant, bool copyExistingEntries) external; function subscriptionOf(address addr) external returns (address registrant); function subscribers(address registrant) external returns (address[] memory); function subscriberAt(address registrant, uint256 index) external returns (address); function copyEntriesOf(address registrant, address registrantToCopy) external; function isOperatorFiltered(address registrant, address operator) external returns (bool); function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool); function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool); function filteredOperators(address addr) external returns (address[] memory); function filteredCodeHashes(address addr) external returns (bytes32[] memory); function filteredOperatorAt(address registrant, uint256 index) external returns (address); function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32); function isRegistered(address addr) external returns (bool); function codeHashOf(address addr) external returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {ERC2981IncorrectRoyaltyReceiver, ERC2981IncorrectRoyaltyPercentage} from "./../errors/ERC2981Errors.sol"; import {IERC2981} from "./../interfaces/IERC2981.sol"; import {InterfaceDetectionStorage} from "./../../../introspection/libraries/InterfaceDetectionStorage.sol"; library ERC2981Storage { using InterfaceDetectionStorage for InterfaceDetectionStorage.Layout; struct Layout { address royaltyReceiver; uint96 royaltyPercentage; } bytes32 internal constant LAYOUT_STORAGE_SLOT = bytes32(uint256(keccak256("animoca.token.royalty.ERC2981.storage")) - 1); uint256 internal constant ROYALTY_FEE_DENOMINATOR = 100000; /// @notice Marks the following ERC165 interface(s) as supported: ERC2981. function init() internal { InterfaceDetectionStorage.layout().setSupportedInterface(type(IERC2981).interfaceId, true); } /// @notice Sets the royalty percentage. /// @dev Reverts with {ERC2981IncorrectRoyaltyPercentage} if `percentage` is above 100% (> FEE_DENOMINATOR). /// @param percentage The new percentage to set. For example 50000 sets 50% royalty. function setRoyaltyPercentage(Layout storage s, uint256 percentage) internal { if (percentage > ROYALTY_FEE_DENOMINATOR) { revert ERC2981IncorrectRoyaltyPercentage(percentage); } s.royaltyPercentage = uint96(percentage); } /// @notice Sets the royalty receiver. /// @dev Reverts with {ERC2981IncorrectRoyaltyReceiver} if `receiver` is the zero address. /// @param receiver The new receiver to set. function setRoyaltyReceiver(Layout storage s, address receiver) internal { if (receiver == address(0)) { revert ERC2981IncorrectRoyaltyReceiver(); } s.royaltyReceiver = receiver; } /// @notice Called with the sale price to determine how much royalty is owed and to whom. // / @param tokenId The NFT asset queried for royalty information /// @param salePrice The sale price of the NFT asset specified by `tokenId` /// @return receiver Address of who should be sent the royalty payment /// @return royaltyAmount The royalty payment amount for `salePrice` function royaltyInfo(Layout storage s, uint256, uint256 salePrice) internal view returns (address receiver, uint256 royaltyAmount) { receiver = s.royaltyReceiver; uint256 royaltyPercentage = s.royaltyPercentage; if (salePrice == 0 || royaltyPercentage == 0) { royaltyAmount = 0; } else { if (salePrice < ROYALTY_FEE_DENOMINATOR) { royaltyAmount = (salePrice * royaltyPercentage) / ROYALTY_FEE_DENOMINATOR; } else { royaltyAmount = (salePrice / ROYALTY_FEE_DENOMINATOR) * royaltyPercentage; } } } function layout() internal pure returns (Layout storage s) { bytes32 position = LAYOUT_STORAGE_SLOT; assembly { s.slot := position } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {OperatorNotAllowed} from "./../errors/OperatorFiltererErrors.sol"; import {IOperatorFilterRegistry} from "./../interfaces/IOperatorFilterRegistry.sol"; import {ProxyInitialization} from "./../../../proxy/libraries/ProxyInitialization.sol"; library OperatorFiltererStorage { using OperatorFiltererStorage for OperatorFiltererStorage.Layout; struct Layout { IOperatorFilterRegistry registry; } bytes32 internal constant PROXY_INIT_PHASE_SLOT = bytes32(uint256(keccak256("animoca.token.royalty.OperatorFilterer.phase")) - 1); bytes32 internal constant LAYOUT_STORAGE_SLOT = bytes32(uint256(keccak256("animoca.token.royalty.OperatorFilterer.storage")) - 1); /// @notice Sets the address that the contract will make OperatorFilter checks against. /// @dev Note: This function should be called ONLY in the constructor of an immutable (non-proxied) contract. /// @param registry The operator filter registry address. When set to the zero address, checks will be bypassed. function constructorInit(Layout storage s, IOperatorFilterRegistry registry) internal { s.registry = registry; } /// @notice Sets the address that the contract will make OperatorFilter checks against. /// @dev Note: This function should be called ONLY in the init function of a proxied contract. /// @dev Reverts with {InitializationPhaseAlreadyReached} if the proxy initialization phase is set to `1` or above. /// @param registry The operator filter registry address. When set to the zero address, checks will be bypassed. function proxyInit(Layout storage s, IOperatorFilterRegistry registry) internal { ProxyInitialization.setPhase(PROXY_INIT_PHASE_SLOT, 1); s.constructorInit(registry); } /// @notice Updates the address that the contract will make OperatorFilter checks against. /// @param registry The new operator filter registry address. When set to the zero address, checks will be bypassed. function updateOperatorFilterRegistry(Layout storage s, IOperatorFilterRegistry registry) internal { s.registry = registry; } /// @dev Reverts with {OperatorNotAllowed} if `sender` is not `from` and is not allowed by a valid operator registry. function requireAllowedOperatorForTransfer(Layout storage s, address sender, address from) internal view { // Allow spending tokens from addresses with balance // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred from an EOA. if (sender != from) { _checkFilterOperator(s, sender); } } /// @dev Reverts with {OperatorNotAllowed} if `sender` is not allowed by a valid operator registry. function requireAllowedOperatorForApproval(Layout storage s, address operator) internal view { _checkFilterOperator(s, operator); } function operatorFilterRegistry(Layout storage s) internal view returns (IOperatorFilterRegistry) { return s.registry; } function layout() internal pure returns (Layout storage s) { bytes32 position = LAYOUT_STORAGE_SLOT; assembly { s.slot := position } } function _checkFilterOperator(Layout storage s, address operator) private view { IOperatorFilterRegistry registry = s.registry; // Check registry code length to facilitate testing in environments without a deployed registry. if (address(registry) != address(0) && address(registry).code.length > 0) { if (!registry.isOperatorAllowed(address(this), operator)) { revert OperatorNotAllowed(operator); } } } }
{ "evmVersion": "paris", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 99999 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"tokenName","type":"string"},{"internalType":"string","name":"tokenSymbol","type":"string"},{"internalType":"contract ITokenMetadataResolver","name":"metadataResolver","type":"address"},{"internalType":"contract IOperatorFilterRegistry","name":"filterRegistry","type":"address"},{"internalType":"contract IForwarderRegistry","name":"forwarderRegistry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ERC1155BalanceOfAddressZero","type":"error"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"ERC1155BalanceOverflow","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[],"name":"ERC1155MintToAddressZero","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155NonApproved","type":"error"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"ERC1155SafeBatchTransferRejected","type":"error"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"ERC1155SafeTransferRejected","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"ERC1155SelfApprovalForAll","type":"error"},{"inputs":[],"name":"ERC1155TransferToAddressZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"percentage","type":"uint256"}],"name":"ERC2981IncorrectRoyaltyPercentage","type":"error"},{"inputs":[],"name":"ERC2981IncorrectRoyaltyReceiver","type":"error"},{"inputs":[],"name":"IllegalInterfaceId","type":"error"},{"inputs":[],"name":"InconsistentArrayLengths","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NotContractOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NotMetadataResolver","type":"error"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"NotRoleHolder","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROYALTY_FEE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"batchBurnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"string[]","name":"tokenURIs","type":"string[]"}],"name":"batchSetTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"forwarderRegistry","outputs":[{"internalType":"contract IForwarderRegistry","name":"","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":"hasRole_","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"approvedForAll","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataResolver","outputs":[{"internalType":"contract ITokenMetadataResolver","name":"tokenMetadataResolver","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"tokenName","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operatorFilterRegistry","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"recoverERC20s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"contract IERC721[]","name":"contracts","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"recoverERC721s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"recoverETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"renounceRole","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":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeDeliver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percentage","type":"uint256"}],"name":"setRoyaltyPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"setRoyaltyReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"tokenURI","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"tokenSymbol","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IOperatorFilterRegistry","name":"registry","type":"address"}],"name":"updateOperatorFilterRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"metadataURI","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b506040516200473c3803806200473c833981016040819052620000349162000446565b8080868686863362000051816200004a620000f3565b9062000129565b506200005c620001a4565b62000089816200006b620001be565b9081546001600160a01b0319166001600160a01b0391909116179055565b50620000a48383836200009b620001ee565b9291906200021e565b620000ae62000265565b50620000bc9150506200027d565b620000c662000295565b620000d0620002ad565b620000da620002c5565b6001600160a01b03166080525062000671945050505050565b6000806200012360017fc9ed16f33ab3a66c84bfd83099ccb2a8845871e2e1c1928f63797152f0fd54cd620004f2565b92915050565b6001600160a01b03811615620001805781546001600160a01b0319166001600160a01b03821690811783556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35b620001a06307f5828d60e41b600162000198620002d8565b919062000308565b5050565b620001bc636cdb3d1360e11b600162000198620002d8565b565b6000806200012360017f609b85bcafa81ecfaf3ff62cdde2c6c9082a68dbe4922f07399c706bdeb7cd31620004f2565b6000806200012360017f7ea68fd2dcf1c056b94db6a0a537aa80d26fa9ab1eacd85da1ba0b61b7e7a8a5620004f2565b836200022b8482620005a5565b50600184016200023c8382620005a5565b5060029390930180546001600160a01b0319166001600160a01b03909416939093179092555050565b620001bc6303a24d0760e21b600162000198620002d8565b620001bc631464324b60e21b600162000198620002d8565b620001bc633a2ae73360e21b600162000198620002d8565b620001bc63921ed8d160e01b600162000198620002d8565b620001bc63152a902d60e11b6001620001985b6000806200012360017fca9d3e17f264b0f3984e2634e94adb37fa3e6a8103f06aeae6fa59e21c769f5e620004f2565b600160e01b6001600160e01b031983160162000337576040516372c683bb60e01b815260040160405180910390fd5b6001600160e01b03199190911660009081526020929092526040909120805460ff1916911515919091179055565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200038d57600080fd5b81516001600160401b0380821115620003aa57620003aa62000365565b604051601f8301601f19908116603f01168101908282118183101715620003d557620003d562000365565b8160405283815260209250866020858801011115620003f357600080fd5b600091505b83821015620004175785820183015181830184015290820190620003f8565b6000602085830101528094505050505092915050565b6001600160a01b03811681146200044357600080fd5b50565b600080600080600060a086880312156200045f57600080fd5b85516001600160401b03808211156200047757600080fd5b6200048589838a016200037b565b965060208801519150808211156200049c57600080fd5b50620004ab888289016200037b565b9450506040860151620004be816200042d565b6060870151909350620004d1816200042d565b6080870151909250620004e4816200042d565b809150509295509295909350565b818103818111156200012357634e487b7160e01b600052601160045260246000fd5b600181811c908216806200052957607f821691505b6020821081036200054a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620005a0576000816000526020600020601f850160051c810160208610156200057b5750805b601f850160051c820191505b818110156200059c5782815560010162000587565b5050505b505050565b81516001600160401b03811115620005c157620005c162000365565b620005d981620005d2845462000514565b8462000550565b602080601f831160018114620006115760008415620005f85750858301515b600019600386901b1c1916600185901b1785556200059c565b600085815260208120601f198616915b82811015620006425788860151825594840194600190910190840162000621565b5085821015620006615787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805161409a620006a260003960008181610360015281816103fb015281816129a00152612a28015261409a6000f3fe608060405234801561001057600080fd5b506004361061025b5760003560e01c80638053493411610145578063c3666c36116100bd578063e8ab9ccc1161008c578063f242432a11610071578063f242432a14610580578063f2fde38b14610593578063f7ba94bd146105a657600080fd5b8063e8ab9ccc1461055a578063e985e9c51461056d57600080fd5b8063c3666c3614610503578063d539139314610516578063d547741f1461053d578063e1a8bf2c1461055057600080fd5b806391d1485411610114578063a0c76f62116100f9578063a0c76f62146104e0578063a22cb465146104e8578063b0ccc31e146104fb57600080fd5b806391d14854146104c557806395d89b41146104d857600080fd5b806380534934146104845780638bb9c5bf146104975780638da5cb5b146104aa5780638dc251e3146104b257600080fd5b80632b4c9f16116101d8578063572b6c05116101a757806361ba27da1161018c57806361ba27da1461044b5780636706467b1461045e57806373c8a9581461047157600080fd5b8063572b6c05146103eb5780635cfa92971461043857600080fd5b80632b4c9f161461035e5780632eb2c2d6146103a55780632f2ff15d146103b85780634e1273f4146103cb57600080fd5b80630e89341c1161022f578063124d91e511610214578063124d91e5146102f9578063162094c41461030c5780632a55205a1461031f57600080fd5b80630e89341c146102d3578063114ba8ee146102e657600080fd5b8062fdd58e1461026057806301ffc9a71461028657806306fdde03146102a95780630d6a5bbb146102be575b600080fd5b61027361026e366004613419565b6105b9565b6040519081526020015b60405180910390f35b610299610294366004613473565b6105d8565b604051901515815260200161027d565b6102b16105ec565b60405161027d9190613505565b6102d16102cc36600461359f565b610603565b005b6102b16102e136600461364c565b6106fe565b6102d16102f4366004613665565b610714565b6102d1610307366004613682565b61077f565b6102d161031a3660046136b7565b6107a3565b61033261032d366004613703565b610875565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260208301919091520161027d565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161027d565b6102d16103b3366004613725565b610898565b6102d16103c63660046137e4565b6108e5565b6103de6103d9366004613814565b610913565b60405161027d91906138bc565b6102996103f9366004613665565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102d16104463660046138cf565b610938565b6102d161045936600461364c565b6109ca565b6102d161046c366004613814565b6109e7565b6102d161047f366004613939565b610b1f565b6102d16104923660046139d3565b610c0b565b6102d16104a536600461364c565b610c2e565b610380610c49565b6102d16104c0366004613665565b610c70565b6102996104d33660046137e4565b610c8d565b6102b1610cd1565b610380610ce3565b6102d16104f6366004613a53565b610cf0565b610380610d29565b6102d1610511366004613939565b610d36565b6102737f6d696e746572000000000000000000000000000000000000000000000000000081565b6102d161054b3660046137e4565b610eae565b610273620186a081565b6102d1610568366004613a81565b610edc565b61029961057b366004613b24565b610ff6565b6102d161058e366004613b52565b611044565b6102d16105a1366004613665565b611084565b6102d16105b4366004613814565b61109f565b60006105cf83836105c8611156565b9190611184565b90505b92915050565b60006105d2826105e6611208565b90611236565b60606105fe6105f9611310565b61133e565b905090565b600061060d6113d4565b90506106437f6d696e74657200000000000000000000000000000000000000000000000000008261063c6113de565b919061140c565b6106f4818989898080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b91829185019084908082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284376000920191909152506106ea9250611156915050565b9493929190611492565b5050505050505050565b60606105d2308361070d611310565b9190611618565b61072d61071f6113d4565b6107276116d8565b90611706565b61077c81610739611771565b9081547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff91909116179055565b50565b61079e61078a6113d4565b848484610795611156565b939291906117e1565b505050565b6107cb6107ae611310565b6002015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610836576040517f220606710000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b827f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b8383604051610868929190613bbc565b60405180910390a2505050565b60008061088c84846108856118ae565b91906118dc565b915091505b9250929050565b60006108a26113d4565b90506108b8818a6108b1611771565b9190611986565b6108da818a8a8a8a8a8a8a8a6108cc611156565b9897969594939291906119c3565b505050505050505050565b60006108ef6113d4565b90506108fd816107276116d8565b61079e83838361090b6113de565b929190611c4c565b606061092d85858585610924611156565b93929190611d23565b90505b949350505050565b60006109426113d4565b90506109717f6d696e74657200000000000000000000000000000000000000000000000000008261063c6113de565b6109c28187878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506109b89250611156915050565b9493929190611e32565b505050505050565b6109d561071f6113d4565b61077c816109e16118ae565b90611f10565b828114610a20576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a2b6107ae611310565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a91576040517f2206067100000000000000000000000000000000000000000000000000000000815233600482015260240161082d565b60005b83811015610b1857848482818110610aae57610aae613c09565b905060200201357f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b848484818110610ae857610ae8613c09565b9050602002810190610afa9190613c38565b604051610b08929190613bbc565b60405180910390a2600101610a94565b5050505050565b610b2a61071f6113d4565b848381141580610b3a5750808214155b15610b71576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156106f457610c03888883818110610b9157610b91613c09565b9050602002016020810190610ba69190613665565b858584818110610bb857610bb8613c09565b90506020020135888885818110610bd157610bd1613c09565b9050602002016020810190610be69190613665565b73ffffffffffffffffffffffffffffffffffffffff169190611f96565b600101610b74565b610b18610c166113d4565b8686868686610c23611156565b959493929190612023565b61077c610c396113d4565b82610c426113de565b919061219b565b60006105fe610c566116d8565b5473ffffffffffffffffffffffffffffffffffffffff1690565b610c7b61071f6113d4565b61077c81610c876118ae565b9061223f565b60006105cf8383610c9c6113de565b60009283526020908152604080842073ffffffffffffffffffffffffffffffffffffffff909316845291905290205460ff1690565b60606105fe610cde611310565b61228c565b60006105fe6107ae611310565b8015610d0857610d0882610d02611771565b9061229d565b610d25610d136113d4565b8383610d1d611156565b9291906122a7565b5050565b60006105fe610c56611771565b610d4161071f6113d4565b848381141580610d515750808214155b15610d88576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156106f457858582818110610da557610da5613c09565b9050602002016020810190610dba9190613665565b73ffffffffffffffffffffffffffffffffffffffff166323b872dd308a8a85818110610de857610de8613c09565b9050602002016020810190610dfd9190613665565b878786818110610e0f57610e0f613c09565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b16815273ffffffffffffffffffffffffffffffffffffffff958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b158015610e8b57600080fd5b505af1158015610e9f573d6000803e3d6000fd5b50505050806001019050610d8b565b6000610eb86113d4565b9050610ec6816107276116d8565b61079e838383610ed46113de565b9291906123bf565b6000610ee66113d4565b9050610f157f6d696e74657200000000000000000000000000000000000000000000000000008261063c6113de565b6108da818a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b91829185019084908082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a9150899081908401838280828437600092019190915250610fec9250611156915050565b9493929190612489565b60006105cf8383611005611156565b919073ffffffffffffffffffffffffffffffffffffffff9182166000908152600193909301602090815260408085209290931684525290205460ff1690565b600061104e6113d4565b905061105d81886108b1611771565b61107b8188888888888861106f611156565b9695949392919061254c565b50505050505050565b61077c61108f6113d4565b826110986116d8565b91906126ef565b6110aa61071f6113d4565b828181146110e4576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156109c25761114e84848381811061110457611104613c09565b9050602002013587878481811061111d5761111d613c09565b90506020020160208101906111329190613665565b73ffffffffffffffffffffffffffffffffffffffff1690612803565b6001016110e7565b6000806105d260017f5ccf5846fa27a68fafc8e588671a68f5e67c2f9b56af4263806a4d71735e8613613ccc565b600073ffffffffffffffffffffffffffffffffffffffff83166111d3576040517fca2434a500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060009081526020928352604080822073ffffffffffffffffffffffffffffffffffffffff9390931682529190925290205490565b6000806105d260017fca9d3e17f264b0f3984e2634e94adb37fa3e6a8103f06aeae6fa59e21c769f5e613ccc565b60007c01000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601611286575060006105d2565b7ffe003659000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016112d7575060016105d2565b507fffffffff00000000000000000000000000000000000000000000000000000000166000908152602091909152604090205460ff1690565b6000806105d260017f7ea68fd2dcf1c056b94db6a0a537aa80d26fa9ab1eacd85da1ba0b61b7e7a8a5613ccc565b606081600001805461134f90613cdf565b80601f016020809104026020016040519081016040528092919081815260200182805461137b90613cdf565b80156113c85780601f1061139d576101008083540402835291602001916113c8565b820191906000526020600020905b8154815290600101906020018083116113ab57829003601f168201915b50505050509050919050565b60006105fe61295d565b6000806105d260017fc8827d3282af6f37b64c3e9e6f3ac9df286ab0bb0fccd6f8661bf19adb368b23613ccc565b60008281526020848152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1661079e576040517f7aa728820000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff8216602482015260440161082d565b73ffffffffffffffffffffffffffffffffffffffff84166114df576040517f021149bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82518251811461151b576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561156c57611564888787848151811061153d5761153d613c09565b602002602001015187858151811061155757611557613c09565b6020026020010151612aa4565b60010161151e565b508473ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516115e4929190613d32565b60405180910390a473ffffffffffffffffffffffffffffffffffffffff85163b1561107b5761107b86600087878787612b75565b60028301546040517ff724dad700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015260248201849052606092169063f724dad790604401600060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526109309190810190613d8f565b6000806105d260017fc9ed16f33ab3a66c84bfd83099ccb2a8845871e2e1c1928f63797152f0fd54cd613ccc565b815473ffffffffffffffffffffffffffffffffffffffff828116911614610d25576040517f2ef4875e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161082d565b6000806105d260017f609b85bcafa81ecfaf3ff62cdde2c6c9082a68dbe4922f07399c706bdeb7cd31613ccc565b81547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff91909116179055565b6117ec858486612c73565b611842576040517f05bbb9c400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80861660048301528416602482015260440161082d565b61184e85848484612ce8565b604080518381526020810183905260009173ffffffffffffffffffffffffffffffffffffffff86811692908816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b6000806105d260017f2c0cf10337caabbd02dcf226f05f5fd19a0919a41a8df8958c39b80007826858613ccc565b825473ffffffffffffffffffffffffffffffffffffffff8116906000907401000000000000000000000000000000000000000090046bffffffffffffffffffffffff1683158061192a575080155b15611938576000915061197d565b620186a084101561196257620186a06119518286613e4f565b61195b9190613e66565b915061197d565b80611970620186a086613e66565b61197a9190613e4f565b91505b50935093915050565b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461079e5761079e8383612d85565b73ffffffffffffffffffffffffffffffffffffffff8716611a10576040517fb5e8901500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84838114611a4a576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611a558b8a8c612c73565b611aab576040517f05bbb9c400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808c1660048301528a16602482015260440161082d565b60005b81811015611afb57611af38c8b8b8b8b86818110611ace57611ace613c09565b905060200201358a8a87818110611ae757611ae7613c09565b90506020020135612eac565b600101611aae565b508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8a8a8a8a604051611b769493929190613eec565b60405180910390a473ffffffffffffffffffffffffffffffffffffffff88163b15611c3f57611c3f8a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c91829185019084908082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a9081908401838280828437600092019190915250612b7592505050565b5050505050505050505050565b60008381526020858152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290205460ff16611d1d5760008381526020858152604080832073ffffffffffffffffffffffffffffffffffffffff8681168086529184529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055815187815292830152918316918101919091527f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d906060015b60405180910390a15b50505050565b606083828114611d5f576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8467ffffffffffffffff811115611d7857611d78613d60565b604051908082528060200260200182016040528015611da1578160200160208202803683370190505b50915060005b81811015611e2757611e02878783818110611dc457611dc4613c09565b9050602002016020810190611dd99190613665565b868684818110611deb57611deb613c09565b905060200201358a6111849092919063ffffffff16565b838281518110611e1457611e14613c09565b6020908102919091010152600101611da7565b505095945050505050565b73ffffffffffffffffffffffffffffffffffffffff8416611e7f576040517f021149bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e8b86858585612aa4565b604080518481526020810184905273ffffffffffffffffffffffffffffffffffffffff80871692600092918916917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a473ffffffffffffffffffffffffffffffffffffffff84163b156109c2576109c285600086868686613059565b620186a0811115611f50576040517fac0404080000000000000000000000000000000000000000000000000000000081526004810182905260240161082d565b81546bffffffffffffffffffffffff909116740100000000000000000000000000000000000000000273ffffffffffffffffffffffffffffffffffffffff909116179055565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261079e908490613177565b8281811461205d576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612068888789612c73565b6120be576040517f05bbb9c400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80891660048301528716602482015260440161082d565b60005b8181101561210d5761210589888888858181106120e0576120e0613c09565b905060200201358787868181106120f9576120f9613c09565b90506020020135612ce8565b6001016120c1565b50600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb888888886040516121899493929190613eec565b60405180910390a45050505050505050565b6121a683828461140c565b60008181526020848152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905580518481529182018390528101919091527ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9060600160405180910390a1505050565b73ffffffffffffffffffffffffffffffffffffffff811661179f576040517f16de0c8000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606081600101805461134f90613cdf565b610d258282612d85565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612324576040517ffb0fdf6100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161082d565b73ffffffffffffffffffffffffffffffffffffffff838116600081815260018701602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a350505050565b60008381526020858152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290205460ff1615611d1d5760008381526020858152604080832073ffffffffffffffffffffffffffffffffffffffff8681168086529184529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055815187815292830152918316918101919091527ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b90606001611d14565b835183518114158061249c575082518114155b156124d3576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156106f457612544878783815181106124f4576124f4613c09565b602002602001015187848151811061250e5761250e613c09565b602002602001015187858151811061252857612528613c09565b6020026020010151878d611e329095949392919063ffffffff16565b6001016124d6565b73ffffffffffffffffffffffffffffffffffffffff8516612599576040517fb5e8901500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6125a4888789612c73565b6125fa576040517f05bbb9c400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80891660048301528716602482015260440161082d565b6126078887878787612eac565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628787604051612686929190918252602082015260400190565b60405180910390a473ffffffffffffffffffffffffffffffffffffffff85163b156106f4576106f4878787878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061305992505050565b825473ffffffffffffffffffffffffffffffffffffffff908116908316811461275c576040517f2ef4875e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161082d565b8173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611d1d5783547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8381169182178655604051908316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350505050565b8047101561286d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015260640161082d565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146128c7576040519150601f19603f3d011682016040523d82523d6000602084013e6128cc565b606091505b505090508061079e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d61792068617665207265766572746564000000000000606482015260840161082d565b60003332148061296d5750601836105b1561297757503390565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec36013560601c7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16331480612a9357506040517f8929a8ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301523360248301527f00000000000000000000000000000000000000000000000000000000000000001690638929a8ca90604401602060405180830381865afa158015612a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a939190613f13565b15612a9d57919050565b3391505090565b8015611d1d5760008281526020858152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054818101818111612b41576040517f42fb00bc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8616600482015260248101859052604481018390526064810184905260840161082d565b60009384526020958652604080852073ffffffffffffffffffffffffffffffffffffffff9690961685529490955250502055565b6040517fbc197c81000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff86169063bc197c8190612bd1908a908a90899089908990600401613f30565b6020604051808303816000875af1158015612bf0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c149190613f9b565b7fffffffff0000000000000000000000000000000000000000000000000000000016146109c2578383836040517fc287817e00000000000000000000000000000000000000000000000000000000815260040161082d93929190613fb8565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16148061093057505073ffffffffffffffffffffffffffffffffffffffff9182166000908152600193909301602090815260408085209290931684525290205460ff1690565b8015611d1d5760008281526020858152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054818103818110612b41576040517f03dee4c500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8616600482015260248101859052604481018390526064810184905260840161082d565b815473ffffffffffffffffffffffffffffffffffffffff168015801590612dc3575060008173ffffffffffffffffffffffffffffffffffffffff163b115b1561079e576040517fc617113400000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015282169063c617113490604401602060405180830381865afa158015612e3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e5e9190613f13565b61079e576040517fede71dcc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260240161082d565b8015610b185760008281526020868152604080832073ffffffffffffffffffffffffffffffffffffffff88168452909152902054818103818110612f49576040517f03dee4c500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8716600482015260248101859052604481018390526064810184905260840161082d565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161461107b5760008481526020888152604080832073ffffffffffffffffffffffffffffffffffffffff89168452909152902054838101818111613013576040517f42fb00bc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8816600482015260248101879052604481018390526064810186905260840161082d565b600086815260208a8152604080832073ffffffffffffffffffffffffffffffffffffffff808d1685528184528285208890558b1684529091529020555050505050505050565b6040517ff23a6e61000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff86169063f23a6e61906130b5908a908a90899089908990600401614003565b6020604051808303816000875af11580156130d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130f89190613f9b565b7fffffffff0000000000000000000000000000000000000000000000000000000016146109c2576040517f40f39d3800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602481018490526044810183905260640161082d565b60006131d9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166132869092919063ffffffff16565b90508051600014806131fa5750808060200190518101906131fa9190613f13565b61079e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161082d565b60606109308484600085856000808673ffffffffffffffffffffffffffffffffffffffff1685876040516132ba9190614048565b60006040518083038185875af1925050503d80600081146132f7576040519150601f19603f3d011682016040523d82523d6000602084013e6132fc565b606091505b509150915061330d87838387613318565b979650505050505050565b606083156133ae5782516000036133a75773ffffffffffffffffffffffffffffffffffffffff85163b6133a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161082d565b5081610930565b61093083838151156133c35781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082d9190613505565b73ffffffffffffffffffffffffffffffffffffffff8116811461077c57600080fd5b6000806040838503121561342c57600080fd5b8235613437816133f7565b946020939093013593505050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461077c57600080fd5b60006020828403121561348557600080fd5b813561349081613445565b9392505050565b60005b838110156134b257818101518382015260200161349a565b50506000910152565b600081518084526134d3816020860160208601613497565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006105cf60208301846134bb565b60008083601f84011261352a57600080fd5b50813567ffffffffffffffff81111561354257600080fd5b6020830191508360208260051b850101111561089157600080fd5b60008083601f84011261356f57600080fd5b50813567ffffffffffffffff81111561358757600080fd5b60208301915083602082850101111561089157600080fd5b60008060008060008060006080888a0312156135ba57600080fd5b87356135c5816133f7565b9650602088013567ffffffffffffffff808211156135e257600080fd5b6135ee8b838c01613518565b909850965060408a013591508082111561360757600080fd5b6136138b838c01613518565b909650945060608a013591508082111561362c57600080fd5b506136398a828b0161355d565b989b979a50959850939692959293505050565b60006020828403121561365e57600080fd5b5035919050565b60006020828403121561367757600080fd5b8135613490816133f7565b60008060006060848603121561369757600080fd5b83356136a2816133f7565b95602085013595506040909401359392505050565b6000806000604084860312156136cc57600080fd5b83359250602084013567ffffffffffffffff8111156136ea57600080fd5b6136f68682870161355d565b9497909650939450505050565b6000806040838503121561371657600080fd5b50508035926020909101359150565b60008060008060008060008060a0898b03121561374157600080fd5b883561374c816133f7565b9750602089013561375c816133f7565b9650604089013567ffffffffffffffff8082111561377957600080fd5b6137858c838d01613518565b909850965060608b013591508082111561379e57600080fd5b6137aa8c838d01613518565b909650945060808b01359150808211156137c357600080fd5b506137d08b828c0161355d565b999c989b5096995094979396929594505050565b600080604083850312156137f757600080fd5b823591506020830135613809816133f7565b809150509250929050565b6000806000806040858703121561382a57600080fd5b843567ffffffffffffffff8082111561384257600080fd5b61384e88838901613518565b9096509450602087013591508082111561386757600080fd5b5061387487828801613518565b95989497509550505050565b60008151808452602080850194506020840160005b838110156138b157815187529582019590820190600101613895565b509495945050505050565b6020815260006105cf6020830184613880565b6000806000806000608086880312156138e757600080fd5b85356138f2816133f7565b94506020860135935060408601359250606086013567ffffffffffffffff81111561391c57600080fd5b6139288882890161355d565b969995985093965092949392505050565b6000806000806000806060878903121561395257600080fd5b863567ffffffffffffffff8082111561396a57600080fd5b6139768a838b01613518565b9098509650602089013591508082111561398f57600080fd5b61399b8a838b01613518565b909650945060408901359150808211156139b457600080fd5b506139c189828a01613518565b979a9699509497509295939492505050565b6000806000806000606086880312156139eb57600080fd5b85356139f6816133f7565b9450602086013567ffffffffffffffff80821115613a1357600080fd5b613a1f89838a01613518565b90965094506040880135915080821115613a3857600080fd5b5061392888828901613518565b801515811461077c57600080fd5b60008060408385031215613a6657600080fd5b8235613a71816133f7565b9150602083013561380981613a45565b6000806000806000806000806080898b031215613a9d57600080fd5b883567ffffffffffffffff80821115613ab557600080fd5b613ac18c838d01613518565b909a50985060208b0135915080821115613ada57600080fd5b613ae68c838d01613518565b909850965060408b0135915080821115613aff57600080fd5b613b0b8c838d01613518565b909650945060608b01359150808211156137c357600080fd5b60008060408385031215613b3757600080fd5b8235613b42816133f7565b91506020830135613809816133f7565b60008060008060008060a08789031215613b6b57600080fd5b8635613b76816133f7565b95506020870135613b86816133f7565b94506040870135935060608701359250608087013567ffffffffffffffff811115613bb057600080fd5b6139c189828a0161355d565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613c6d57600080fd5b83018035915067ffffffffffffffff821115613c8857600080fd5b60200191503681900382131561089157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105d2576105d2613c9d565b600181811c90821680613cf357607f821691505b602082108103613d2c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b604081526000613d456040830185613880565b8281036020840152613d578185613880565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215613da157600080fd5b815167ffffffffffffffff80821115613db957600080fd5b818401915084601f830112613dcd57600080fd5b815181811115613ddf57613ddf613d60565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715613e2557613e25613d60565b81604052828152876020848701011115613e3e57600080fd5b61330d836020830160208801613497565b80820281158282048414176105d2576105d2613c9d565b600082613e9c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115613ed357600080fd5b8260051b80836020870137939093016020019392505050565b604081526000613f00604083018688613ea1565b828103602084015261330d818587613ea1565b600060208284031215613f2557600080fd5b815161349081613a45565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152613f6960a0830186613880565b8281036060840152613f7b8186613880565b90508281036080840152613f8f81856134bb565b98975050505050505050565b600060208284031215613fad57600080fd5b815161349081613445565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000613fe76060830185613880565b8281036040840152613ff98185613880565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015283606083015260a0608083015261330d60a08301846134bb565b6000825161405a818460208701613497565b919091019291505056fea2646970667358221220e9680e560ccf9b231c3045d8bb0d991ca6013fac9803a3900b0ade6e46854f8064736f6c6343000816003300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000faf5d68fc49f647b7bb61b9fd02c3a96f97aedf9000000000000000000000000000000000000aaeb6d7670e522a718067333cd4e0000000000000000000000003f547f87251710f70109ae0409d461b2707096930000000000000000000000000000000000000000000000000000000000000018416e69636865737320546865204d697373696e67204f7262000000000000000000000000000000000000000000000000000000000000000000000000000000044d4f524200000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061025b5760003560e01c80638053493411610145578063c3666c36116100bd578063e8ab9ccc1161008c578063f242432a11610071578063f242432a14610580578063f2fde38b14610593578063f7ba94bd146105a657600080fd5b8063e8ab9ccc1461055a578063e985e9c51461056d57600080fd5b8063c3666c3614610503578063d539139314610516578063d547741f1461053d578063e1a8bf2c1461055057600080fd5b806391d1485411610114578063a0c76f62116100f9578063a0c76f62146104e0578063a22cb465146104e8578063b0ccc31e146104fb57600080fd5b806391d14854146104c557806395d89b41146104d857600080fd5b806380534934146104845780638bb9c5bf146104975780638da5cb5b146104aa5780638dc251e3146104b257600080fd5b80632b4c9f16116101d8578063572b6c05116101a757806361ba27da1161018c57806361ba27da1461044b5780636706467b1461045e57806373c8a9581461047157600080fd5b8063572b6c05146103eb5780635cfa92971461043857600080fd5b80632b4c9f161461035e5780632eb2c2d6146103a55780632f2ff15d146103b85780634e1273f4146103cb57600080fd5b80630e89341c1161022f578063124d91e511610214578063124d91e5146102f9578063162094c41461030c5780632a55205a1461031f57600080fd5b80630e89341c146102d3578063114ba8ee146102e657600080fd5b8062fdd58e1461026057806301ffc9a71461028657806306fdde03146102a95780630d6a5bbb146102be575b600080fd5b61027361026e366004613419565b6105b9565b6040519081526020015b60405180910390f35b610299610294366004613473565b6105d8565b604051901515815260200161027d565b6102b16105ec565b60405161027d9190613505565b6102d16102cc36600461359f565b610603565b005b6102b16102e136600461364c565b6106fe565b6102d16102f4366004613665565b610714565b6102d1610307366004613682565b61077f565b6102d161031a3660046136b7565b6107a3565b61033261032d366004613703565b610875565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260208301919091520161027d565b7f0000000000000000000000003f547f87251710f70109ae0409d461b2707096935b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161027d565b6102d16103b3366004613725565b610898565b6102d16103c63660046137e4565b6108e5565b6103de6103d9366004613814565b610913565b60405161027d91906138bc565b6102996103f9366004613665565b7f0000000000000000000000003f547f87251710f70109ae0409d461b27070969373ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102d16104463660046138cf565b610938565b6102d161045936600461364c565b6109ca565b6102d161046c366004613814565b6109e7565b6102d161047f366004613939565b610b1f565b6102d16104923660046139d3565b610c0b565b6102d16104a536600461364c565b610c2e565b610380610c49565b6102d16104c0366004613665565b610c70565b6102996104d33660046137e4565b610c8d565b6102b1610cd1565b610380610ce3565b6102d16104f6366004613a53565b610cf0565b610380610d29565b6102d1610511366004613939565b610d36565b6102737f6d696e746572000000000000000000000000000000000000000000000000000081565b6102d161054b3660046137e4565b610eae565b610273620186a081565b6102d1610568366004613a81565b610edc565b61029961057b366004613b24565b610ff6565b6102d161058e366004613b52565b611044565b6102d16105a1366004613665565b611084565b6102d16105b4366004613814565b61109f565b60006105cf83836105c8611156565b9190611184565b90505b92915050565b60006105d2826105e6611208565b90611236565b60606105fe6105f9611310565b61133e565b905090565b600061060d6113d4565b90506106437f6d696e74657200000000000000000000000000000000000000000000000000008261063c6113de565b919061140c565b6106f4818989898080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b91829185019084908082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284376000920191909152506106ea9250611156915050565b9493929190611492565b5050505050505050565b60606105d2308361070d611310565b9190611618565b61072d61071f6113d4565b6107276116d8565b90611706565b61077c81610739611771565b9081547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff91909116179055565b50565b61079e61078a6113d4565b848484610795611156565b939291906117e1565b505050565b6107cb6107ae611310565b6002015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610836576040517f220606710000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b827f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b8383604051610868929190613bbc565b60405180910390a2505050565b60008061088c84846108856118ae565b91906118dc565b915091505b9250929050565b60006108a26113d4565b90506108b8818a6108b1611771565b9190611986565b6108da818a8a8a8a8a8a8a8a6108cc611156565b9897969594939291906119c3565b505050505050505050565b60006108ef6113d4565b90506108fd816107276116d8565b61079e83838361090b6113de565b929190611c4c565b606061092d85858585610924611156565b93929190611d23565b90505b949350505050565b60006109426113d4565b90506109717f6d696e74657200000000000000000000000000000000000000000000000000008261063c6113de565b6109c28187878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506109b89250611156915050565b9493929190611e32565b505050505050565b6109d561071f6113d4565b61077c816109e16118ae565b90611f10565b828114610a20576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a2b6107ae611310565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a91576040517f2206067100000000000000000000000000000000000000000000000000000000815233600482015260240161082d565b60005b83811015610b1857848482818110610aae57610aae613c09565b905060200201357f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b848484818110610ae857610ae8613c09565b9050602002810190610afa9190613c38565b604051610b08929190613bbc565b60405180910390a2600101610a94565b5050505050565b610b2a61071f6113d4565b848381141580610b3a5750808214155b15610b71576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156106f457610c03888883818110610b9157610b91613c09565b9050602002016020810190610ba69190613665565b858584818110610bb857610bb8613c09565b90506020020135888885818110610bd157610bd1613c09565b9050602002016020810190610be69190613665565b73ffffffffffffffffffffffffffffffffffffffff169190611f96565b600101610b74565b610b18610c166113d4565b8686868686610c23611156565b959493929190612023565b61077c610c396113d4565b82610c426113de565b919061219b565b60006105fe610c566116d8565b5473ffffffffffffffffffffffffffffffffffffffff1690565b610c7b61071f6113d4565b61077c81610c876118ae565b9061223f565b60006105cf8383610c9c6113de565b60009283526020908152604080842073ffffffffffffffffffffffffffffffffffffffff909316845291905290205460ff1690565b60606105fe610cde611310565b61228c565b60006105fe6107ae611310565b8015610d0857610d0882610d02611771565b9061229d565b610d25610d136113d4565b8383610d1d611156565b9291906122a7565b5050565b60006105fe610c56611771565b610d4161071f6113d4565b848381141580610d515750808214155b15610d88576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156106f457858582818110610da557610da5613c09565b9050602002016020810190610dba9190613665565b73ffffffffffffffffffffffffffffffffffffffff166323b872dd308a8a85818110610de857610de8613c09565b9050602002016020810190610dfd9190613665565b878786818110610e0f57610e0f613c09565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b16815273ffffffffffffffffffffffffffffffffffffffff958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b158015610e8b57600080fd5b505af1158015610e9f573d6000803e3d6000fd5b50505050806001019050610d8b565b6000610eb86113d4565b9050610ec6816107276116d8565b61079e838383610ed46113de565b9291906123bf565b6000610ee66113d4565b9050610f157f6d696e74657200000000000000000000000000000000000000000000000000008261063c6113de565b6108da818a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b91829185019084908082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a9150899081908401838280828437600092019190915250610fec9250611156915050565b9493929190612489565b60006105cf8383611005611156565b919073ffffffffffffffffffffffffffffffffffffffff9182166000908152600193909301602090815260408085209290931684525290205460ff1690565b600061104e6113d4565b905061105d81886108b1611771565b61107b8188888888888861106f611156565b9695949392919061254c565b50505050505050565b61077c61108f6113d4565b826110986116d8565b91906126ef565b6110aa61071f6113d4565b828181146110e4576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156109c25761114e84848381811061110457611104613c09565b9050602002013587878481811061111d5761111d613c09565b90506020020160208101906111329190613665565b73ffffffffffffffffffffffffffffffffffffffff1690612803565b6001016110e7565b6000806105d260017f5ccf5846fa27a68fafc8e588671a68f5e67c2f9b56af4263806a4d71735e8613613ccc565b600073ffffffffffffffffffffffffffffffffffffffff83166111d3576040517fca2434a500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060009081526020928352604080822073ffffffffffffffffffffffffffffffffffffffff9390931682529190925290205490565b6000806105d260017fca9d3e17f264b0f3984e2634e94adb37fa3e6a8103f06aeae6fa59e21c769f5e613ccc565b60007c01000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601611286575060006105d2565b7ffe003659000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016112d7575060016105d2565b507fffffffff00000000000000000000000000000000000000000000000000000000166000908152602091909152604090205460ff1690565b6000806105d260017f7ea68fd2dcf1c056b94db6a0a537aa80d26fa9ab1eacd85da1ba0b61b7e7a8a5613ccc565b606081600001805461134f90613cdf565b80601f016020809104026020016040519081016040528092919081815260200182805461137b90613cdf565b80156113c85780601f1061139d576101008083540402835291602001916113c8565b820191906000526020600020905b8154815290600101906020018083116113ab57829003601f168201915b50505050509050919050565b60006105fe61295d565b6000806105d260017fc8827d3282af6f37b64c3e9e6f3ac9df286ab0bb0fccd6f8661bf19adb368b23613ccc565b60008281526020848152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1661079e576040517f7aa728820000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff8216602482015260440161082d565b73ffffffffffffffffffffffffffffffffffffffff84166114df576040517f021149bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82518251811461151b576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561156c57611564888787848151811061153d5761153d613c09565b602002602001015187858151811061155757611557613c09565b6020026020010151612aa4565b60010161151e565b508473ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516115e4929190613d32565b60405180910390a473ffffffffffffffffffffffffffffffffffffffff85163b1561107b5761107b86600087878787612b75565b60028301546040517ff724dad700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015260248201849052606092169063f724dad790604401600060405180830381865afa158015611692573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526109309190810190613d8f565b6000806105d260017fc9ed16f33ab3a66c84bfd83099ccb2a8845871e2e1c1928f63797152f0fd54cd613ccc565b815473ffffffffffffffffffffffffffffffffffffffff828116911614610d25576040517f2ef4875e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161082d565b6000806105d260017f609b85bcafa81ecfaf3ff62cdde2c6c9082a68dbe4922f07399c706bdeb7cd31613ccc565b81547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff91909116179055565b6117ec858486612c73565b611842576040517f05bbb9c400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80861660048301528416602482015260440161082d565b61184e85848484612ce8565b604080518381526020810183905260009173ffffffffffffffffffffffffffffffffffffffff86811692908816917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050505050565b6000806105d260017f2c0cf10337caabbd02dcf226f05f5fd19a0919a41a8df8958c39b80007826858613ccc565b825473ffffffffffffffffffffffffffffffffffffffff8116906000907401000000000000000000000000000000000000000090046bffffffffffffffffffffffff1683158061192a575080155b15611938576000915061197d565b620186a084101561196257620186a06119518286613e4f565b61195b9190613e66565b915061197d565b80611970620186a086613e66565b61197a9190613e4f565b91505b50935093915050565b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461079e5761079e8383612d85565b73ffffffffffffffffffffffffffffffffffffffff8716611a10576040517fb5e8901500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84838114611a4a576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611a558b8a8c612c73565b611aab576040517f05bbb9c400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808c1660048301528a16602482015260440161082d565b60005b81811015611afb57611af38c8b8b8b8b86818110611ace57611ace613c09565b905060200201358a8a87818110611ae757611ae7613c09565b90506020020135612eac565b600101611aae565b508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8a8a8a8a604051611b769493929190613eec565b60405180910390a473ffffffffffffffffffffffffffffffffffffffff88163b15611c3f57611c3f8a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c91829185019084908082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a9081908401838280828437600092019190915250612b7592505050565b5050505050505050505050565b60008381526020858152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290205460ff16611d1d5760008381526020858152604080832073ffffffffffffffffffffffffffffffffffffffff8681168086529184529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055815187815292830152918316918101919091527f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d906060015b60405180910390a15b50505050565b606083828114611d5f576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8467ffffffffffffffff811115611d7857611d78613d60565b604051908082528060200260200182016040528015611da1578160200160208202803683370190505b50915060005b81811015611e2757611e02878783818110611dc457611dc4613c09565b9050602002016020810190611dd99190613665565b868684818110611deb57611deb613c09565b905060200201358a6111849092919063ffffffff16565b838281518110611e1457611e14613c09565b6020908102919091010152600101611da7565b505095945050505050565b73ffffffffffffffffffffffffffffffffffffffff8416611e7f576040517f021149bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e8b86858585612aa4565b604080518481526020810184905273ffffffffffffffffffffffffffffffffffffffff80871692600092918916917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a473ffffffffffffffffffffffffffffffffffffffff84163b156109c2576109c285600086868686613059565b620186a0811115611f50576040517fac0404080000000000000000000000000000000000000000000000000000000081526004810182905260240161082d565b81546bffffffffffffffffffffffff909116740100000000000000000000000000000000000000000273ffffffffffffffffffffffffffffffffffffffff909116179055565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261079e908490613177565b8281811461205d576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612068888789612c73565b6120be576040517f05bbb9c400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80891660048301528716602482015260440161082d565b60005b8181101561210d5761210589888888858181106120e0576120e0613c09565b905060200201358787868181106120f9576120f9613c09565b90506020020135612ce8565b6001016120c1565b50600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb888888886040516121899493929190613eec565b60405180910390a45050505050505050565b6121a683828461140c565b60008181526020848152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905580518481529182018390528101919091527ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9060600160405180910390a1505050565b73ffffffffffffffffffffffffffffffffffffffff811661179f576040517f16de0c8000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606081600101805461134f90613cdf565b610d258282612d85565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612324576040517ffb0fdf6100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161082d565b73ffffffffffffffffffffffffffffffffffffffff838116600081815260018701602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a350505050565b60008381526020858152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290205460ff1615611d1d5760008381526020858152604080832073ffffffffffffffffffffffffffffffffffffffff8681168086529184529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055815187815292830152918316918101919091527ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b90606001611d14565b835183518114158061249c575082518114155b156124d3576040517f6582533600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156106f457612544878783815181106124f4576124f4613c09565b602002602001015187848151811061250e5761250e613c09565b602002602001015187858151811061252857612528613c09565b6020026020010151878d611e329095949392919063ffffffff16565b6001016124d6565b73ffffffffffffffffffffffffffffffffffffffff8516612599576040517fb5e8901500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6125a4888789612c73565b6125fa576040517f05bbb9c400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80891660048301528716602482015260440161082d565b6126078887878787612eac565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628787604051612686929190918252602082015260400190565b60405180910390a473ffffffffffffffffffffffffffffffffffffffff85163b156106f4576106f4878787878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061305992505050565b825473ffffffffffffffffffffffffffffffffffffffff908116908316811461275c576040517f2ef4875e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161082d565b8173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611d1d5783547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8381169182178655604051908316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350505050565b8047101561286d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015260640161082d565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146128c7576040519150601f19603f3d011682016040523d82523d6000602084013e6128cc565b606091505b505090508061079e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d61792068617665207265766572746564000000000000606482015260840161082d565b60003332148061296d5750601836105b1561297757503390565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec36013560601c7f0000000000000000000000003f547f87251710f70109ae0409d461b27070969373ffffffffffffffffffffffffffffffffffffffff16331480612a9357506040517f8929a8ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301523360248301527f0000000000000000000000003f547f87251710f70109ae0409d461b2707096931690638929a8ca90604401602060405180830381865afa158015612a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a939190613f13565b15612a9d57919050565b3391505090565b8015611d1d5760008281526020858152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054818101818111612b41576040517f42fb00bc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8616600482015260248101859052604481018390526064810184905260840161082d565b60009384526020958652604080852073ffffffffffffffffffffffffffffffffffffffff9690961685529490955250502055565b6040517fbc197c81000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff86169063bc197c8190612bd1908a908a90899089908990600401613f30565b6020604051808303816000875af1158015612bf0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c149190613f9b565b7fffffffff0000000000000000000000000000000000000000000000000000000016146109c2578383836040517fc287817e00000000000000000000000000000000000000000000000000000000815260040161082d93929190613fb8565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16148061093057505073ffffffffffffffffffffffffffffffffffffffff9182166000908152600193909301602090815260408085209290931684525290205460ff1690565b8015611d1d5760008281526020858152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054818103818110612b41576040517f03dee4c500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8616600482015260248101859052604481018390526064810184905260840161082d565b815473ffffffffffffffffffffffffffffffffffffffff168015801590612dc3575060008173ffffffffffffffffffffffffffffffffffffffff163b115b1561079e576040517fc617113400000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015282169063c617113490604401602060405180830381865afa158015612e3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e5e9190613f13565b61079e576040517fede71dcc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260240161082d565b8015610b185760008281526020868152604080832073ffffffffffffffffffffffffffffffffffffffff88168452909152902054818103818110612f49576040517f03dee4c500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8716600482015260248101859052604481018390526064810184905260840161082d565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161461107b5760008481526020888152604080832073ffffffffffffffffffffffffffffffffffffffff89168452909152902054838101818111613013576040517f42fb00bc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8816600482015260248101879052604481018390526064810186905260840161082d565b600086815260208a8152604080832073ffffffffffffffffffffffffffffffffffffffff808d1685528184528285208890558b1684529091529020555050505050505050565b6040517ff23a6e61000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff86169063f23a6e61906130b5908a908a90899089908990600401614003565b6020604051808303816000875af11580156130d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130f89190613f9b565b7fffffffff0000000000000000000000000000000000000000000000000000000016146109c2576040517f40f39d3800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602481018490526044810183905260640161082d565b60006131d9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166132869092919063ffffffff16565b90508051600014806131fa5750808060200190518101906131fa9190613f13565b61079e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161082d565b60606109308484600085856000808673ffffffffffffffffffffffffffffffffffffffff1685876040516132ba9190614048565b60006040518083038185875af1925050503d80600081146132f7576040519150601f19603f3d011682016040523d82523d6000602084013e6132fc565b606091505b509150915061330d87838387613318565b979650505050505050565b606083156133ae5782516000036133a75773ffffffffffffffffffffffffffffffffffffffff85163b6133a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161082d565b5081610930565b61093083838151156133c35781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082d9190613505565b73ffffffffffffffffffffffffffffffffffffffff8116811461077c57600080fd5b6000806040838503121561342c57600080fd5b8235613437816133f7565b946020939093013593505050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461077c57600080fd5b60006020828403121561348557600080fd5b813561349081613445565b9392505050565b60005b838110156134b257818101518382015260200161349a565b50506000910152565b600081518084526134d3816020860160208601613497565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006105cf60208301846134bb565b60008083601f84011261352a57600080fd5b50813567ffffffffffffffff81111561354257600080fd5b6020830191508360208260051b850101111561089157600080fd5b60008083601f84011261356f57600080fd5b50813567ffffffffffffffff81111561358757600080fd5b60208301915083602082850101111561089157600080fd5b60008060008060008060006080888a0312156135ba57600080fd5b87356135c5816133f7565b9650602088013567ffffffffffffffff808211156135e257600080fd5b6135ee8b838c01613518565b909850965060408a013591508082111561360757600080fd5b6136138b838c01613518565b909650945060608a013591508082111561362c57600080fd5b506136398a828b0161355d565b989b979a50959850939692959293505050565b60006020828403121561365e57600080fd5b5035919050565b60006020828403121561367757600080fd5b8135613490816133f7565b60008060006060848603121561369757600080fd5b83356136a2816133f7565b95602085013595506040909401359392505050565b6000806000604084860312156136cc57600080fd5b83359250602084013567ffffffffffffffff8111156136ea57600080fd5b6136f68682870161355d565b9497909650939450505050565b6000806040838503121561371657600080fd5b50508035926020909101359150565b60008060008060008060008060a0898b03121561374157600080fd5b883561374c816133f7565b9750602089013561375c816133f7565b9650604089013567ffffffffffffffff8082111561377957600080fd5b6137858c838d01613518565b909850965060608b013591508082111561379e57600080fd5b6137aa8c838d01613518565b909650945060808b01359150808211156137c357600080fd5b506137d08b828c0161355d565b999c989b5096995094979396929594505050565b600080604083850312156137f757600080fd5b823591506020830135613809816133f7565b809150509250929050565b6000806000806040858703121561382a57600080fd5b843567ffffffffffffffff8082111561384257600080fd5b61384e88838901613518565b9096509450602087013591508082111561386757600080fd5b5061387487828801613518565b95989497509550505050565b60008151808452602080850194506020840160005b838110156138b157815187529582019590820190600101613895565b509495945050505050565b6020815260006105cf6020830184613880565b6000806000806000608086880312156138e757600080fd5b85356138f2816133f7565b94506020860135935060408601359250606086013567ffffffffffffffff81111561391c57600080fd5b6139288882890161355d565b969995985093965092949392505050565b6000806000806000806060878903121561395257600080fd5b863567ffffffffffffffff8082111561396a57600080fd5b6139768a838b01613518565b9098509650602089013591508082111561398f57600080fd5b61399b8a838b01613518565b909650945060408901359150808211156139b457600080fd5b506139c189828a01613518565b979a9699509497509295939492505050565b6000806000806000606086880312156139eb57600080fd5b85356139f6816133f7565b9450602086013567ffffffffffffffff80821115613a1357600080fd5b613a1f89838a01613518565b90965094506040880135915080821115613a3857600080fd5b5061392888828901613518565b801515811461077c57600080fd5b60008060408385031215613a6657600080fd5b8235613a71816133f7565b9150602083013561380981613a45565b6000806000806000806000806080898b031215613a9d57600080fd5b883567ffffffffffffffff80821115613ab557600080fd5b613ac18c838d01613518565b909a50985060208b0135915080821115613ada57600080fd5b613ae68c838d01613518565b909850965060408b0135915080821115613aff57600080fd5b613b0b8c838d01613518565b909650945060608b01359150808211156137c357600080fd5b60008060408385031215613b3757600080fd5b8235613b42816133f7565b91506020830135613809816133f7565b60008060008060008060a08789031215613b6b57600080fd5b8635613b76816133f7565b95506020870135613b86816133f7565b94506040870135935060608701359250608087013567ffffffffffffffff811115613bb057600080fd5b6139c189828a0161355d565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613c6d57600080fd5b83018035915067ffffffffffffffff821115613c8857600080fd5b60200191503681900382131561089157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105d2576105d2613c9d565b600181811c90821680613cf357607f821691505b602082108103613d2c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b604081526000613d456040830185613880565b8281036020840152613d578185613880565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215613da157600080fd5b815167ffffffffffffffff80821115613db957600080fd5b818401915084601f830112613dcd57600080fd5b815181811115613ddf57613ddf613d60565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715613e2557613e25613d60565b81604052828152876020848701011115613e3e57600080fd5b61330d836020830160208801613497565b80820281158282048414176105d2576105d2613c9d565b600082613e9c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115613ed357600080fd5b8260051b80836020870137939093016020019392505050565b604081526000613f00604083018688613ea1565b828103602084015261330d818587613ea1565b600060208284031215613f2557600080fd5b815161349081613a45565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152613f6960a0830186613880565b8281036060840152613f7b8186613880565b90508281036080840152613f8f81856134bb565b98975050505050505050565b600060208284031215613fad57600080fd5b815161349081613445565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000613fe76060830185613880565b8281036040840152613ff98185613880565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015283606083015260a0608083015261330d60a08301846134bb565b6000825161405a818460208701613497565b919091019291505056fea2646970667358221220e9680e560ccf9b231c3045d8bb0d991ca6013fac9803a3900b0ade6e46854f8064736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000faf5d68fc49f647b7bb61b9fd02c3a96f97aedf9000000000000000000000000000000000000aaeb6d7670e522a718067333cd4e0000000000000000000000003f547f87251710f70109ae0409d461b2707096930000000000000000000000000000000000000000000000000000000000000018416e69636865737320546865204d697373696e67204f7262000000000000000000000000000000000000000000000000000000000000000000000000000000044d4f524200000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : tokenName (string): Anichess The Missing Orb
Arg [1] : tokenSymbol (string): MORB
Arg [2] : metadataResolver (address): 0xfaF5d68FC49f647B7BB61B9FD02c3a96f97AEdF9
Arg [3] : filterRegistry (address): 0x000000000000AAeB6D7670E522A718067333cd4E
Arg [4] : forwarderRegistry (address): 0x3f547F87251710F70109Ae0409d461b270709693
-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 000000000000000000000000faf5d68fc49f647b7bb61b9fd02c3a96f97aedf9
Arg [3] : 000000000000000000000000000000000000aaeb6d7670e522a718067333cd4e
Arg [4] : 0000000000000000000000003f547f87251710f70109ae0409d461b270709693
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000018
Arg [6] : 416e69636865737320546865204d697373696e67204f72620000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [8] : 4d4f524200000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.