Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 105 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Set Minter For P... | 20268410 | 22 hrs ago | IN | 0 ETH | 0.00059072 | ||||
Set Minter For P... | 20261113 | 46 hrs ago | IN | 0 ETH | 0.00044455 | ||||
Set Minter For P... | 20222015 | 7 days ago | IN | 0 ETH | 0.00046727 | ||||
Set Minter For P... | 20147437 | 17 days ago | IN | 0 ETH | 0.00060667 | ||||
Set Minter For P... | 20146283 | 17 days ago | IN | 0 ETH | 0.00029146 | ||||
Set Minter For P... | 20138186 | 19 days ago | IN | 0 ETH | 0.00018194 | ||||
Set Minter For P... | 20134145 | 19 days ago | IN | 0 ETH | 0.00188612 | ||||
Set Minter For P... | 20068827 | 28 days ago | IN | 0 ETH | 0.00115185 | ||||
Set Minter For P... | 20041286 | 32 days ago | IN | 0 ETH | 0.00140039 | ||||
Set Minter For P... | 20034481 | 33 days ago | IN | 0 ETH | 0.00265365 | ||||
Set Minter For P... | 20033327 | 33 days ago | IN | 0 ETH | 0.00187605 | ||||
Set Minter For P... | 19989424 | 39 days ago | IN | 0 ETH | 0.00106743 | ||||
Set Minter For P... | 19988627 | 40 days ago | IN | 0 ETH | 0.00076031 | ||||
Set Minter For P... | 19988578 | 40 days ago | IN | 0 ETH | 0.00099005 | ||||
Set Minter For P... | 19934133 | 47 days ago | IN | 0 ETH | 0.00091025 | ||||
Set Minter For P... | 19934115 | 47 days ago | IN | 0 ETH | 0.00098061 | ||||
Set Minter For P... | 19927991 | 48 days ago | IN | 0 ETH | 0.00215305 | ||||
Set Minter For P... | 19909123 | 51 days ago | IN | 0 ETH | 0.00037723 | ||||
Set Minter For P... | 19907131 | 51 days ago | IN | 0 ETH | 0.00033688 | ||||
Set Minter For P... | 19836846 | 61 days ago | IN | 0 ETH | 0.00020704 | ||||
Set Minter For P... | 19836776 | 61 days ago | IN | 0 ETH | 0.00024293 | ||||
Set Minter For P... | 19805453 | 65 days ago | IN | 0 ETH | 0.00053898 | ||||
Set Minter For P... | 19762191 | 71 days ago | IN | 0 ETH | 0.00099882 | ||||
Set Minter For P... | 19762102 | 71 days ago | IN | 0 ETH | 0.00096217 | ||||
Set Minter For P... | 19742007 | 74 days ago | IN | 0 ETH | 0.0008708 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
MinterFilterV2
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 25 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. // @dev fixed to specific solidity version for clarity and for more clear // source code verification purposes. pragma solidity 0.8.19; import {IMinterFilterV1} from "../../interfaces/v0.8.x/IMinterFilterV1.sol"; import {ISharedMinterV0} from "../../interfaces/v0.8.x/ISharedMinterV0.sol"; import {IGenArt721CoreContractV3_Base} from "../../interfaces/v0.8.x/IGenArt721CoreContractV3_Base.sol"; import {ICoreRegistryV1} from "../../interfaces/v0.8.x/ICoreRegistryV1.sol"; import {IAdminACLV0} from "../../interfaces/v0.8.x/IAdminACLV0.sol"; import {Bytes32Strings} from "../../libs/v0.8.x/Bytes32Strings.sol"; import {Ownable} from "@openzeppelin-4.7/contracts/access/Ownable.sol"; import {EnumerableMap} from "@openzeppelin-4.7/contracts/utils/structs/EnumerableMap.sol"; import {EnumerableSet} from "@openzeppelin-4.7/contracts/utils/structs/EnumerableSet.sol"; import {Math} from "@openzeppelin-4.7/contracts/utils/math/Math.sol"; /** * @title MinterFilterV2 * @dev At the time of deployment, this contract is intended to be used with * core contracts that implement IGenArt721CoreContractV3_Base. * @author Art Blocks Inc. * @notice This Minter Filter V2 contract allows minters to be set on a * per-project basis, for any registered core contract. This minter filter does * not extend the previous version of the minter filters, as the previous * version is not compatible with multiple core contracts. * * This contract is designed to be managed by an Admin ACL contract, as well as * delegated privileges to core contract artists and Admin ACL contracts. * These roles hold extensive power and can arbitrarily control and modify * how a project's tokens may be minted. * Care must be taken to ensure that the admin ACL contract and artist * addresses are secure behind a multi-sig or other access control mechanism. * ---------------------------------------------------------------------------- * The following functions are restricted as allowed by this contract's Admin * ACL: * - updateCoreRegistry * - approveMinterGlobally * - revokeMinterGlobally * ---------------------------------------------------------------------------- * The following functions are restricted as allowed by each core contract's * Admin ACL contract: * - approveMinterForContract * - revokeMinterForContract * - removeMintersForProjectsOnContract * ---------------------------------------------------------------------------- * The following functions are restricted as allowed by each core contract's * Admin ACL contract, or to the artist address of the project: * - setMinterForProject * - removeMinterForProject * ---------------------------------------------------------------------------- * Additional admin and artist privileged roles may be described on minters, * registries, and other contracts that may interact with this contract. */ contract MinterFilterV2 is Ownable, IMinterFilterV1 { // add Enumerable Map, Enumerable Set methods using EnumerableMap for EnumerableMap.UintToAddressMap; using EnumerableSet for EnumerableSet.AddressSet; // add Bytes32Strings methods using Bytes32Strings for bytes32; /// @notice Version of this minter filter contract // @dev use function minterFilterVersion to get this as a string bytes32 constant MINTER_FILTER_VERSION = "v2.0.0"; /// @notice Type of this minter filter contract // @dev use function minterFilterType to get this as a string bytes32 constant MINTER_FILTER_TYPE = "MinterFilterV2"; /// @notice Admin ACL contract for this minter filter IAdminACLV0 public adminACLContract; /** * @notice Core registry, that tracks all registered core contracts */ ICoreRegistryV1 public coreRegistry; /// @notice Minter address => qty projects across all core contracts currently /// using the minter mapping(address minterAddress => uint256 numProjects) public numProjectsUsingMinter; /** * @notice Enumerable Set of globally approved minters. * This is a Set of addresses that are approved to mint on any * project, for any core contract. * @dev note that contract admins can extend a separate Set of minters for * their core contract via the `approveMinterForContract` function. */ EnumerableSet.AddressSet private _globallyApprovedMinters; /** * @notice Mapping of core contract addresses to Enumerable Sets of approved * minters for that core contract. * @dev note that contract admins can extend this Set for their core * contract by via the `approveMinterForContract` function, and can remove * minters from this Set via the `revokeMinterForContract` function. */ mapping(address coreContract => EnumerableSet.AddressSet approvedMintersForContract) private _contractApprovedMinters; /** * @notice Mapping of core contract addresses to Enumerable Maps of project IDs to * minter addresses. */ mapping(address coreContract => EnumerableMap.UintToAddressMap projectIdToMinterAddress) private _minterForProject; /** * @notice Function to validate an address is non-zero. * @param address_ Address to validate */ function _onlyNonZeroAddress(address address_) internal pure { require(address_ != address(0), "Only non-zero address"); } /** * @notice Function to restrict access to only AdminACL allowed calls * on this minter filter's admin ACL contract. * @param selector function selector to be checked */ function _onlyAdminACL(bytes4 selector) internal { require( adminACLAllowed(msg.sender, address(this), selector), "Only Admin ACL allowed" ); } /** * @notice Function to restrict access to only AdminACL allowed calls * on a given core contract. * @dev defers to the ACL contract used by the core contract * @param coreContract core contract address * @param selector function selector to be checked */ function _onlyCoreAdminACL(address coreContract, bytes4 selector) internal { require( IGenArt721CoreContractV3_Base(coreContract).adminACLAllowed({ _sender: msg.sender, _contract: address(this), _selector: selector }), "Only Core AdminACL allowed" ); } /** * @notice Function to restrict access to only core AdminACL or the project artist. * @dev Defers to the ACL contract used by the core contract * @param coreContract core contract address * @param selector function selector to be checked */ function _onlyCoreAdminACLOrArtist( uint256 projectId, address coreContract, bytes4 selector ) internal { IGenArt721CoreContractV3_Base genArtCoreContract_Base = IGenArt721CoreContractV3_Base( coreContract ); require( (msg.sender == genArtCoreContract_Base.projectIdToArtistAddress(projectId)) || ( genArtCoreContract_Base.adminACLAllowed({ _sender: msg.sender, _contract: address(this), _selector: selector }) ), "Only Artist or Core Admin ACL" ); } /** * @notice Function to restrict access to only core contracts registered with the * currently configured core registry. This is used to prevent non-registered core * contracts from being used with this minter filter. * @param coreContract core contract address */ function _onlyRegisteredCoreContract(address coreContract) internal view { // @dev use core registry to check if core contract is registered require( coreRegistry.isRegisteredContract(coreContract), "Only registered core contract" ); } /** * @notice Function to restrict access to only valid project IDs. * @param projectId Project ID to validate. * @param coreContract core contract address */ function _onlyValidProjectId( uint256 projectId, address coreContract ) internal view { IGenArt721CoreContractV3_Base genArtCoreContract = IGenArt721CoreContractV3_Base( coreContract ); require( (projectId >= genArtCoreContract.startingProjectId()) && (projectId < genArtCoreContract.nextProjectId()), "Only valid project ID" ); } /** * @notice Function to check if minter is globally approved or approved for a core contract. * @param coreContract core contract address * @param minter Minter to validate. */ function _onlyApprovedMinter( address coreContract, address minter ) internal view { require( isApprovedMinterForContract({ coreContract: coreContract, minter: minter }), "Only approved minters" ); } /** * @notice Initializes contract to be a Minter for `genArt721Address`. * @param adminACLContract_ Address of admin access control contract, to be * set as contract owner. * @param coreRegistry_ Address of core registry contract. */ constructor(address adminACLContract_, address coreRegistry_) { // set AdminACL management contract as owner _transferOwnership(adminACLContract_); // set core registry contract _updateCoreRegistry(coreRegistry_); emit Deployed(); } /** * @notice returns the version of this minter filter contract */ function minterFilterVersion() external pure returns (string memory) { return MINTER_FILTER_VERSION.toString(); } /** * @notice returns the type of this minter filter contract */ function minterFilterType() external pure returns (string memory) { return MINTER_FILTER_TYPE.toString(); } /** * @notice Updates the core registry contract to be used by this contract. * Only callable as allowed by AdminACL of this contract. * @param coreRegistry_ Address of the new core registry contract. */ function updateCoreRegistry(address coreRegistry_) external { _onlyAdminACL(this.updateCoreRegistry.selector); _updateCoreRegistry(coreRegistry_); } /** * @notice Globally approves minter `minter` to be available for * minting on any project, for any core contract. * Only callable as allowed by AdminACL of this contract. * @dev Reverts if minter is already globally approved, or does not * implement minterType(). * @param minter Minter to be approved. */ function approveMinterGlobally(address minter) external { _onlyAdminACL(this.approveMinterGlobally.selector); // @dev add() return true if the value was added to the set require( _globallyApprovedMinters.add(minter), "Minter already approved" ); emit MinterApprovedGlobally({ minter: minter, minterType: ISharedMinterV0(minter).minterType() }); } /** * @notice Removes previously globally approved minter `minter` * from the list of globally approved minters. * Only callable as allowed by AdminACL of this contract. * Reverts if minter is not globally approved. * @dev intentionally do not check if minter is still in use by any * project, meaning that any projects currently using the minter will * continue to be able to use it. If existing projects should be forced * to discontinue using a minter, the minter may be removed by the minter * filter admin in bulk via the `removeMintersForProjectsOnContract` * function. * @param minter Minter to remove. */ function revokeMinterGlobally(address minter) external { _onlyAdminACL(this.revokeMinterGlobally.selector); // @dev remove() returns true only if the value was already in the Set require( _globallyApprovedMinters.remove(minter), "Only previously approved minter" ); emit MinterRevokedGlobally(minter); } /** * @notice Approves minter `minter` to be available for minting on * any project on core contarct `coreContract`. * Only callable as allowed by AdminACL of core contract `coreContract`. * Reverts if core contract is not registered, if minter is already * approved for the contract, or if minter does not implement minterType(). * @param coreContract Core contract to approve minter for. * @param minter Minter to be approved. */ function approveMinterForContract( address coreContract, address minter ) external { _onlyRegisteredCoreContract(coreContract); _onlyCoreAdminACL({ coreContract: coreContract, selector: this.approveMinterForContract.selector }); // @dev add() returns true if the value was added to the Set require( _contractApprovedMinters[coreContract].add(minter), "Minter already approved" ); emit MinterApprovedForContract({ coreContract: coreContract, minter: minter, minterType: ISharedMinterV0(minter).minterType() }); } /** * @notice Removes previously approved minter `minter` from the * list of approved minters on core contract `coreContract`. * Only callable as allowed by AdminACL of core contract `coreContract`. * Reverts if core contract is not registered, or if minter is not approved * on contract. * @dev intentionally does not check if minter is still in use by any * project, meaning that any projects currently using the minter will * continue to be able to use it. If existing projects should be forced * to discontinue using a minter, the minter may be removed by the contract * admin in bulk via the `removeMintersForProjectsOnContract` function. * @param coreContract Core contract to remove minter from. * @param minter Minter to remove. */ function revokeMinterForContract( address coreContract, address minter ) external { _onlyRegisteredCoreContract(coreContract); _onlyCoreAdminACL({ coreContract: coreContract, selector: this.revokeMinterForContract.selector }); // @dev intentionally do not check if minter is still in use by any // project, since it is possible that a different contract's project is // using the minter // @dev remove() returns true only if the value was already in the Set require( _contractApprovedMinters[coreContract].remove(minter), "Only previously approved minter" ); emit MinterRevokedForContract({ coreContract: coreContract, minter: minter }); } /** * @notice Sets minter for project `projectId` on contract `coreContract` * to minter `minter`. * Only callable by the project's artist or as allowed by AdminACL of * core contract `coreContract`. * Reverts if: * - core contract is not registered * - minter is not approved globally on this minter filter or for the * project's core contract * - project is not valid on the core contract * - function is called by an address other than the project's artist * or a sender allowed by the core contract's admin ACL * - minter does not implement minterType() * @param projectId Project ID to set minter for. * @param coreContract Core contract of project. * @param minter Minter to be the project's minter. */ function setMinterForProject( uint256 projectId, address coreContract, address minter ) external { /// CHECKS _onlyRegisteredCoreContract(coreContract); _onlyCoreAdminACLOrArtist({ projectId: projectId, coreContract: coreContract, selector: this.setMinterForProject.selector }); _onlyApprovedMinter({coreContract: coreContract, minter: minter}); _onlyValidProjectId({projectId: projectId, coreContract: coreContract}); /// EFFECTS // decrement number of projects using a previous minter (bool hasPreviousMinter, address previousMinter) = _minterForProject[ coreContract ].tryGet(projectId); if (hasPreviousMinter) { numProjectsUsingMinter[previousMinter]--; } // assign new minter numProjectsUsingMinter[minter]++; _minterForProject[coreContract].set(projectId, minter); emit ProjectMinterRegistered({ projectId: projectId, coreContract: coreContract, minter: minter, minterType: ISharedMinterV0(minter).minterType() }); } /** * @notice Updates project `projectId` on contract `coreContract` to have * no configured minter. * Only callable by the project's artist or as allowed by AdminACL of * core contract `coreContract`. * Reverts if: * - core contract is not registered * - project does not already have a minter assigned * - function is called by an address other than the project's artist * or a sender allowed by the core contract's admin ACL * @param projectId Project ID to remove minter for. * @param coreContract Core contract of project. * @dev requires project to have an assigned minter */ function removeMinterForProject( uint256 projectId, address coreContract ) external { _onlyRegisteredCoreContract(coreContract); _onlyCoreAdminACLOrArtist({ projectId: projectId, coreContract: coreContract, selector: this.removeMinterForProject.selector }); // @dev this will revert if project does not have a minter _removeMinterForProject({ projectId: projectId, coreContract: coreContract }); } /** * @notice Updates an array of project IDs to have no configured minter. * Only callable as allowed by AdminACL of core contract `coreContract`. * Reverts if the core contract is not registered, or if any project does * not already have a minter assigned. * @param projectIds Array of project IDs to remove minters for. * @param coreContract Core contract of projects. * @dev caution with respect to single tx gas limits */ function removeMintersForProjectsOnContract( uint256[] calldata projectIds, address coreContract ) external { _onlyRegisteredCoreContract(coreContract); _onlyCoreAdminACL({ coreContract: coreContract, selector: this.removeMintersForProjectsOnContract.selector }); uint256 numProjects = projectIds.length; for (uint256 i; i < numProjects; ) { _removeMinterForProject({ projectId: projectIds[i], coreContract: coreContract }); unchecked { ++i; } } } /** * @notice Mint a token from project `projectId` on contract * `coreContract` to `to`, originally purchased by `sender`. * @param to The new token's owner. * @param projectId Project ID to mint a new token on. * @param sender Address purchasing a new token. * @param coreContract Core contract of project. * @return tokenId Token ID of minted token * @dev reverts w/nonexistent key error when project has no assigned minter * @dev does not check if core contract is registered, for gas efficiency * and because project must have already been assigned a minter, which * requires the core contract to have been previously registered. If core * contract was unregistered but the project still has an assigned minter, * minting will remain possible. * @dev function name is optimized for gas. */ function mint_joo( address to, uint256 projectId, address coreContract, address sender ) external returns (uint256 tokenId) { // CHECKS // minter is the project's minter require( msg.sender == _minterForProject[coreContract].get(projectId), "Only assigned minter" ); // INTERACTIONS tokenId = IGenArt721CoreContractV3_Base(coreContract).mint_Ecf({ _to: to, _projectId: projectId, _by: sender }); return tokenId; } /** * @notice Gets the assigned minter for project `projectId` on core * contract `coreContract`. * Reverts if project does not have an assigned minter. * @param projectId Project ID to query. * @param coreContract Core contract of project. * @return address Minter address assigned to project * @dev requires project to have an assigned minter * @dev this function intentionally does not check that the core contract * is registered, since it must have been registered at the time the * project was assigned a minter */ function getMinterForProject( uint256 projectId, address coreContract ) external view returns (address) { // @dev use tryGet to control revert message if no minter assigned (bool hasMinter, address currentMinter) = _minterForProject[ coreContract ].tryGet(projectId); require(hasMinter, "No minter assigned"); return currentMinter; } /** * @notice Queries if project `projectId` on core contract `coreContract` * has an assigned minter. * @param projectId Project ID to query. * @param coreContract Core contract of project. * @return bool true if project has an assigned minter, else false * @dev requires project to have an assigned minter * @dev this function intentionally does not check that the core contract * is registered, since it must have been registered at the time the * project was assigned a minter */ function projectHasMinter( uint256 projectId, address coreContract ) external view returns (bool) { (bool hasMinter, ) = _minterForProject[coreContract].tryGet(projectId); return hasMinter; } /** * @notice Gets quantity of projects on a given core contract that have * assigned minters. * @param coreContract Core contract to query. * @return uint256 quantity of projects that have assigned minters * @dev this function intentionally does not check that the core contract * is registered, since it must have been registered at the time the * project was assigned a minter */ function getNumProjectsOnContractWithMinters( address coreContract ) external view returns (uint256) { return _minterForProject[coreContract].length(); } /** * @notice Get project ID and minter address at index `index` of * enumerable map. * @param coreContract Core contract to query. * @param index enumerable map index to query. * @return projectId project ID at index `index` * @return minterAddress minter address for project at index `index` * @return minterType minter type of minter at minterAddress * @dev index must be < quantity of projects that have assigned minters, * otherwise reverts * @dev reverts if minter does not implement minterType() function * @dev this function intentionally does not check that the core contract * is registered, since it must have been registered at the time the * project was assigned a minter */ function getProjectAndMinterInfoOnContractAt( address coreContract, uint256 index ) external view returns ( uint256 projectId, address minterAddress, string memory minterType ) { // @dev at() reverts if index is out of bounds (projectId, minterAddress) = _minterForProject[coreContract].at(index); minterType = ISharedMinterV0(minterAddress).minterType(); } /** * @notice View that returns if a core contract is registered with the * core registry, allowing this minter filter to service it. * @param coreContract core contract address to be checked * @return bool true if core contract is registered, else false */ function isRegisteredCoreContract( address coreContract ) external view override returns (bool) { return coreRegistry.isRegisteredContract(coreContract); } /** * @notice Gets all projects on core contract `coreContract` that are * using minter `minter`. * Warning: Unbounded gas limit. This function is gas-intensive and should * only be used for off-chain queries. Alternatively, the subgraph indexing * layer may be used to query these values. * @param coreContract core contract to query * @param minter minter to query */ function getProjectsOnContractUsingMinter( address coreContract, address minter ) external view returns (uint256[] memory projectIds) { EnumerableMap.UintToAddressMap storage minterMap = _minterForProject[ coreContract ]; // initialize arrays with maximum potential length // @dev use lesser of num projects using minter across all contracts // and number of projects on the contract with minters assigned, since // both values represent an upper bound on the number of projects that // could be using the minter on the contract uint256 maxNumProjects = Math.min( numProjectsUsingMinter[minter], minterMap.length() ); projectIds = new uint256[](maxNumProjects); // iterate over all projects on contract, adding to array if using // `minter` uint256 numProjects = minterMap.length(); uint256 numProjectsOnContractUsingMinter; for (uint256 i; i < numProjects; ) { (uint256 projectId, address minter_) = minterMap.at(i); unchecked { if (minter_ == minter) { projectIds[numProjectsOnContractUsingMinter++] = projectId; } ++i; } } // trim array if necessary if (maxNumProjects > numProjectsOnContractUsingMinter) { assembly ("memory-safe") { mstore(projectIds, numProjectsOnContractUsingMinter) } } return projectIds; } /** * @notice Gets all minters that are globally approved on this minter * filter. Returns an array of MinterWithType structs, which contain the * minter address and minter type. * This function has unbounded gas, and should only be used for off-chain * queries. * Alternatively, the subgraph indexing layer may be used to query these * values. * @return mintersWithTypes Array of MinterWithType structs, which contain * the minter address and minter type. */ function getAllGloballyApprovedMinters() external view returns (MinterWithType[] memory mintersWithTypes) { // initialize arrays with appropriate length uint256 numMinters = _globallyApprovedMinters.length(); mintersWithTypes = new MinterWithType[](numMinters); // iterate over all globally approved minters, adding to array for (uint256 i; i < numMinters; ) { address minterAddress = _globallyApprovedMinters.at(i); // @dev we know minterType() does not revert, because it was called // when globally approving the minter string memory minterType = ISharedMinterV0(minterAddress) .minterType(); mintersWithTypes[i] = MinterWithType({ minterAddress: minterAddress, minterType: minterType }); unchecked { ++i; } } } /** * @notice Gets all minters that are approved for a specific core contract. * Returns an array of MinterWithType structs, which contain the minter * address and minter type. * This function has unbounded gas, and should only be used for off-chain * queries. * @param coreContract Core contract to query. * @return mintersWithTypes Array of MinterWithType structs, which contain * the minter address and minter type. */ function getAllContractApprovedMinters( address coreContract ) external view returns (MinterWithType[] memory mintersWithTypes) { // initialize arrays with appropriate length EnumerableSet.AddressSet storage contractApprovedMinters = _contractApprovedMinters[ coreContract ]; uint256 numMinters = contractApprovedMinters.length(); mintersWithTypes = new MinterWithType[](numMinters); // iterate over all minters approved for a given contract, adding to // array for (uint256 i; i < numMinters; ) { address minterAddress = contractApprovedMinters.at(i); // @dev we know minterType() does not revert, because it was called // when approving the minter for a contract string memory minterType = ISharedMinterV0(minterAddress) .minterType(); mintersWithTypes[i] = MinterWithType({ minterAddress: minterAddress, minterType: minterType }); unchecked { ++i; } } } /** * @notice Convenience function that returns whether `sender` is allowed * to call function with selector `selector` on contract `contract`, as * determined by this contract's current Admin ACL contract. Expected use * cases include minter contracts checking if caller is allowed to call * admin-gated functions on minter contracts. * @param sender Address of the sender calling function with selector * `selector` on contract `contract`. * @param contract_ Address of the contract being called by `sender`. * @param selector Function selector of the function being called by * `sender`. * @return bool Whether `sender` is allowed to call function with selector * `selector` on contract `contract`. * @dev assumes the Admin ACL contract is the owner of this contract, which * is expected to always be true. * @dev adminACLContract is expected to not be null address (owner cannot * renounce ownership on this contract), and conform to IAdminACLV0 * interface. */ function adminACLAllowed( address sender, address contract_, bytes4 selector ) public returns (bool) { return adminACLContract.allowed({ _sender: sender, _contract: contract_, _selector: selector }); } /** * @notice Returns whether `minter` is globally approved to mint tokens * on any contract. * @param minter Address of minter to check. */ function isGloballyApprovedMinter( address minter ) public view returns (bool) { return _globallyApprovedMinters.contains(minter); } /** * @notice Returns whether `minter` is approved to mint tokens on * core contract `coreContract`. * @param coreContract Address of core contract to check. * @param minter Address of minter to check. */ function isApprovedMinterForContract( address coreContract, address minter ) public view returns (bool) { return isGloballyApprovedMinter(minter) || _contractApprovedMinters[coreContract].contains(minter); } /** * @notice Returns contract owner. Set to deployer's address by default on * contract deployment. * @return address Address of contract owner. * @dev ref: https://docs.openzeppelin.com/contracts/4.x/api/access#Ownable * @dev owner role was called `admin` prior to V3 core contract */ function owner() public view override(Ownable, IMinterFilterV1) returns (address) { return Ownable.owner(); } /// @dev override to prevent renouncing ownership /// @dev not permission gated since this immediately reverts function renounceOwnership() public pure override { revert("Cannot renounce ownership"); } /** * @notice Updates project `projectId` to have no configured minter * Reverts if project does not already have an assigned minter. * @param projectId Project ID to remove minter. * @param coreContract Core contract of project. * @dev requires project to have an assigned minter * @dev this function intentionally does not check that the core contract * is registered, since it must have been registered at the time the * project was assigned a minter */ function _removeMinterForProject( uint256 projectId, address coreContract ) internal { // remove minter for project and emit // @dev `minterForProject.get()` reverts tx if no minter set for project numProjectsUsingMinter[ _minterForProject[coreContract].get(projectId, "No minter assigned") ]--; _minterForProject[coreContract].remove(projectId); emit ProjectMinterRemoved({ projectId: projectId, coreContract: coreContract }); } /** * @notice Transfers ownership of the contract to a new account (`owner`). * Internal function without access restriction. * @param owner_ New owner. * @dev owner role was called `admin` prior to V3 core contract. * @dev Overrides and wraps OpenZeppelin's _transferOwnership function to * also update adminACLContract for improved introspection. */ function _transferOwnership(address owner_) internal override { Ownable._transferOwnership(owner_); adminACLContract = IAdminACLV0(owner_); } /** * @notice Updates this contract's core registry contract to * `coreRegistry`. * @param coreRegistry_ New core registry contract address. */ function _updateCoreRegistry(address coreRegistry_) internal { _onlyNonZeroAddress(coreRegistry_); coreRegistry = ICoreRegistryV1(coreRegistry_); emit CoreRegistryUpdated(coreRegistry_); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// 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.7.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`. // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`. // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a // good first aproximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1; uint256 x = a; if (x >> 128 > 0) { x >>= 128; result <<= 64; } if (x >> 64 > 0) { x >>= 64; result <<= 32; } if (x >> 32 > 0) { x >>= 32; result <<= 16; } if (x >> 16 > 0) { x >>= 16; result <<= 8; } if (x >> 8 > 0) { x >>= 8; result <<= 4; } if (x >> 4 > 0) { x >>= 4; result <<= 2; } if (x >> 2 > 0) { result <<= 1; } // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { uint256 result = sqrt(a); if (rounding == Rounding.Up && result * result < a) { result += 1; } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableMap.sol) pragma solidity ^0.8.0; import "./EnumerableSet.sol"; /** * @dev Library for managing an enumerable variant of Solidity's * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] * type. * * Maps have the following properties: * * - Entries are added, removed, and checked for existence in constant time * (O(1)). * - Entries are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableMap for EnumerableMap.UintToAddressMap; * * // Declare a set state variable * EnumerableMap.UintToAddressMap private myMap; * } * ``` * * The following map types are supported: * * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 * - `address -> uint256` (`AddressToUintMap`) since v4.6.0 * - `bytes32 -> bytes32` (`Bytes32ToBytes32`) since v4.6.0 * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0 * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0 * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an array of EnumerableMap. * ==== */ library EnumerableMap { using EnumerableSet for EnumerableSet.Bytes32Set; // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Map type with // bytes32 keys and values. // The Map implementation uses private functions, and user-facing // implementations (such as Uint256ToAddressMap) are just wrappers around // the underlying Map. // This means that we can only create new EnumerableMaps for types that fit // in bytes32. struct Bytes32ToBytes32Map { // Storage of keys EnumerableSet.Bytes32Set _keys; mapping(bytes32 => bytes32) _values; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set( Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value ) internal returns (bool) { map._values[key] = value; return map._keys.add(key); } /** * @dev Removes a key-value pair from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) { delete map._values[key]; return map._keys.remove(key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) { return map._keys.contains(key); } /** * @dev Returns the number of key-value pairs in the map. O(1). */ function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) { return map._keys.length(); } /** * @dev Returns the key-value pair stored at position `index` in the map. O(1). * * Note that there are no guarantees on the ordering of entries inside the * array, and it may change when more entries are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) { bytes32 key = map._keys.at(index); return (key, map._values[key]); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) { bytes32 value = map._values[key]; if (value == bytes32(0)) { return (contains(map, key), bytes32(0)); } else { return (true, value); } } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) { bytes32 value = map._values[key]; require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key"); return value; } /** * @dev Same as {_get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {_tryGet}. */ function get( Bytes32ToBytes32Map storage map, bytes32 key, string memory errorMessage ) internal view returns (bytes32) { bytes32 value = map._values[key]; require(value != 0 || contains(map, key), errorMessage); return value; } // UintToUintMap struct UintToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set( UintToUintMap storage map, uint256 key, uint256 value ) internal returns (bool) { return set(map._inner, bytes32(key), bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToUintMap storage map, uint256 key) internal returns (bool) { return remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) { return contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (uint256(key), uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) { return uint256(get(map._inner, bytes32(key))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( UintToUintMap storage map, uint256 key, string memory errorMessage ) internal view returns (uint256) { return uint256(get(map._inner, bytes32(key), errorMessage)); } // UintToAddressMap struct UintToAddressMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set( UintToAddressMap storage map, uint256 key, address value ) internal returns (bool) { return set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { return remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { return contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToAddressMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { (bytes32 key, bytes32 value) = at(map._inner, index); return (uint256(key), address(uint160(uint256(value)))); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. * * _Available since v3.4._ */ function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); return (success, address(uint160(uint256(value)))); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { return address(uint160(uint256(get(map._inner, bytes32(key))))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( UintToAddressMap storage map, uint256 key, string memory errorMessage ) internal view returns (address) { return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage)))); } // AddressToUintMap struct AddressToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set( AddressToUintMap storage map, address key, uint256 value ) internal returns (bool) { return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(AddressToUintMap storage map, address key) internal returns (bool) { return remove(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(AddressToUintMap storage map, address key) internal view returns (bool) { return contains(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns the number of elements in the map. O(1). */ function length(AddressToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (address(uint160(uint256(key))), uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(AddressToUintMap storage map, address key) internal view returns (uint256) { return uint256(get(map._inner, bytes32(uint256(uint160(key))))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( AddressToUintMap storage map, address key, string memory errorMessage ) internal view returns (uint256) { return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage)); } // Bytes32ToUintMap struct Bytes32ToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set( Bytes32ToUintMap storage map, bytes32 key, uint256 value ) internal returns (bool) { return set(map._inner, key, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) { return remove(map._inner, key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) { return contains(map._inner, key); } /** * @dev Returns the number of elements in the map. O(1). */ function length(Bytes32ToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (key, uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, key); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) { return uint256(get(map._inner, key)); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( Bytes32ToUintMap storage map, bytes32 key, string memory errorMessage ) internal view returns (uint256) { return uint256(get(map._inner, key, errorMessage)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. pragma solidity ^0.8.0; interface IAdminACLV0 { /** * @notice Token ID `_tokenId` minted to `_to`. * @param previousSuperAdmin The previous superAdmin address. * @param newSuperAdmin The new superAdmin address. * @param genArt721CoreAddressesToUpdate Array of genArt721Core * addresses to update to the new superAdmin, for indexing purposes only. */ event SuperAdminTransferred( address indexed previousSuperAdmin, address indexed newSuperAdmin, address[] genArt721CoreAddressesToUpdate ); /// Type of the Admin ACL contract, e.g. "AdminACLV0" function AdminACLType() external view returns (string memory); /// super admin address function superAdmin() external view returns (address); /** * @notice Calls transferOwnership on other contract from this contract. * This is useful for updating to a new AdminACL contract. * @dev this function should be gated to only superAdmin-like addresses. */ function transferOwnershipOn( address _contract, address _newAdminACL ) external; /** * @notice Calls renounceOwnership on other contract from this contract. * @dev this function should be gated to only superAdmin-like addresses. */ function renounceOwnershipOn(address _contract) external; /** * @notice Checks if sender `_sender` is allowed to call function with selector * `_selector` on contract `_contract`. */ function allowed( address _sender, address _contract, bytes4 _selector ) external returns (bool); }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. pragma solidity ^0.8.0; import "./IEngineRegistryV0.sol"; interface ICoreRegistryV1 is IEngineRegistryV0 { function registerContracts( address[] calldata contractAddresses, bytes32[] calldata coreVersions, bytes32[] calldata coreTypes ) external; function unregisterContracts(address[] calldata contractAddresses) external; function getNumRegisteredContracts() external view returns (uint256); function getRegisteredContractAt( uint256 index ) external view returns (address); function isRegisteredContract( address contractAddress ) external view returns (bool isRegistered); }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. pragma solidity ^0.8.0; interface IEngineRegistryV0 { /// ADDRESS /** * @notice contract has been registered as a contract that is powered by the Art Blocks Engine. */ event ContractRegistered( address indexed _contractAddress, bytes32 _coreVersion, bytes32 _coreType ); /// ADDRESS /** * @notice contract has been unregistered as a contract that is powered by the Art Blocks Engine. */ event ContractUnregistered(address indexed _contractAddress); /** * @notice Emits a `ContractRegistered` event with the provided information. * @dev this function should be gated to only deployer addresses. */ function registerContract( address _contractAddress, bytes32 _coreVersion, bytes32 _coreType ) external; /** * @notice Emits a `ContractUnregistered` event with the provided information, validating that the provided * address was indeed previously registered. * @dev this function should be gated to only deployer addresses. */ function unregisterContract(address _contractAddress) external; }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. pragma solidity ^0.8.0; import "./IAdminACLV0.sol"; /// use the Royalty Registry's IManifold interface for token royalties import "./IManifold.sol"; /** * @title This interface is intended to house interface items that are common * across all GenArt721CoreContractV3 flagship and derivative implementations. * This interface extends the IManifold royalty interface in order to * add support the Royalty Registry by default. * @author Art Blocks Inc. */ interface IGenArt721CoreContractV3_Base is IManifold { /** * @notice Token ID `_tokenId` minted to `_to`. */ event Mint(address indexed _to, uint256 indexed _tokenId); /** * @notice currentMinter updated to `_currentMinter`. * @dev Implemented starting with V3 core */ event MinterUpdated(address indexed _currentMinter); /** * @notice Platform updated on bytes32-encoded field `_field`. */ event PlatformUpdated(bytes32 indexed _field); /** * @notice Project ID `_projectId` updated on bytes32-encoded field * `_update`. */ event ProjectUpdated(uint256 indexed _projectId, bytes32 indexed _update); event ProposedArtistAddressesAndSplits( uint256 indexed _projectId, address _artistAddress, address _additionalPayeePrimarySales, uint256 _additionalPayeePrimarySalesPercentage, address _additionalPayeeSecondarySales, uint256 _additionalPayeeSecondarySalesPercentage ); event AcceptedArtistAddressesAndSplits(uint256 indexed _projectId); // version and type of the core contract // coreVersion is a string of the form "0.x.y" function coreVersion() external view returns (string memory); // coreType is a string of the form "GenArt721CoreV3" function coreType() external view returns (string memory); // owner (pre-V3 was named admin) of contract // this is expected to be an Admin ACL contract for V3 function owner() external view returns (address); // Admin ACL contract for V3, will be at the address owner() function adminACLContract() external returns (IAdminACLV0); // backwards-compatible (pre-V3) admin - equal to owner() function admin() external view returns (address); /** * Function determining if _sender is allowed to call function with * selector _selector on contract `_contract`. Intended to be used with * peripheral contracts such as minters, as well as internally by the * core contract itself. */ function adminACLAllowed( address _sender, address _contract, bytes4 _selector ) external returns (bool); /// getter function of public variable function startingProjectId() external view returns (uint256); // getter function of public variable function nextProjectId() external view returns (uint256); // getter function of public mapping function tokenIdToProjectId( uint256 tokenId ) external view returns (uint256 projectId); // @dev this is not available in V0 function isMintWhitelisted(address minter) external view returns (bool); function projectIdToArtistAddress( uint256 _projectId ) external view returns (address payable); function projectIdToAdditionalPayeePrimarySales( uint256 _projectId ) external view returns (address payable); function projectIdToAdditionalPayeePrimarySalesPercentage( uint256 _projectId ) external view returns (uint256); function projectIdToSecondaryMarketRoyaltyPercentage( uint256 _projectId ) external view returns (uint256); function projectURIInfo( uint256 _projectId ) external view returns (string memory projectBaseURI); // @dev new function in V3 function projectStateData( uint256 _projectId ) external view returns ( uint256 invocations, uint256 maxInvocations, bool active, bool paused, uint256 completedTimestamp, bool locked ); function projectDetails( uint256 _projectId ) external view returns ( string memory projectName, string memory artist, string memory description, string memory website, string memory license ); function projectScriptDetails( uint256 _projectId ) external view returns ( string memory scriptTypeAndVersion, string memory aspectRatio, uint256 scriptCount ); function projectScriptByIndex( uint256 _projectId, uint256 _index ) external view returns (string memory); function tokenIdToHash(uint256 _tokenId) external view returns (bytes32); // function to set a token's hash (must be guarded) function setTokenHash_8PT(uint256 _tokenId, bytes32 _hash) external; // @dev gas-optimized signature in V3 for `mint` function mint_Ecf( address _to, uint256 _projectId, address _by ) external returns (uint256 tokenId); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @dev Royalty Registry interface, used to support the Royalty Registry. /// @dev Source: https://github.com/manifoldxyz/royalty-registry-solidity/blob/main/contracts/specs/IManifold.sol /// @author: manifold.xyz /** * @dev Royalty interface for creator core classes */ interface IManifold { /** * @dev Get royalites of a token. Returns list of receivers and basisPoints * * bytes4(keccak256('getRoyalties(uint256)')) == 0xbb3bafd6 * * => 0xbb3bafd6 = 0xbb3bafd6 */ function getRoyalties( uint256 tokenId ) external view returns (address payable[] memory, uint256[] memory); }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. pragma solidity ^0.8.0; import "./ICoreRegistryV1.sol"; import "./IAdminACLV0.sol"; /** * @title IMinterFilterV1 * @author Art Blocks Inc. * @notice Interface for a new minter filter contract. * This interface does not extend the previous version of the minter filter * interface, as the previous version is not compatible with the new * minter filter architecture. * @dev This interface is for a minter filter that supports multiple core * contracts, and allows for a minter to be set on a per-project basis. */ interface IMinterFilterV1 { /** * @notice Emitted when contract is deployed to notify indexing services * of the new contract deployment. */ event Deployed(); /** * @notice Globally approved minter `minter`. */ event MinterApprovedGlobally(address indexed minter, string minterType); /** * @notice Globally revoked minter `minter`. * @dev contract owner may still approve this minter on a per-contract * basis. */ event MinterRevokedGlobally(address indexed minter); /** * @notice Approved minter `minter` on core contract * `coreContract`. */ event MinterApprovedForContract( address indexed coreContract, address indexed minter, string minterType ); /** * @notice Revoked minter `minter` on core contract `coreContract`. * @dev minter filter owner may still globally approve this minter for all * contracts. */ event MinterRevokedForContract( address indexed coreContract, address indexed minter ); /** * @notice Minter at address `minter` set as minter for project * `projectId` on core contract `coreContract`. */ event ProjectMinterRegistered( uint256 indexed projectId, address indexed coreContract, address indexed minter, string minterType ); /** * @notice Minter removed for project `projectId` on core contract * `coreContract`. */ event ProjectMinterRemoved( uint256 indexed projectId, address indexed coreContract ); /** * @notice Admin ACL contract updated to `adminACLContract`. */ event AdminACLUpdated(address indexed adminACLContract); /** * @notice Core Registry contract updated to `coreRegistry`. */ event CoreRegistryUpdated(address indexed coreRegistry); // struct used to return minter info // @dev this is not used for storage of data struct MinterWithType { address minterAddress; string minterType; } function setMinterForProject( uint256 projectId, address coreContract, address minter ) external; function removeMinterForProject( uint256 projectId, address coreContract ) external; // @dev function name is optimized for gas function mint_joo( address to, uint256 projectId, address coreContract, address sender ) external returns (uint256); function updateCoreRegistry(address coreRegistry) external; /** * @notice Returns if `sender` is allowed to call function on `contract` * with `selector` selector, according to the MinterFilter's Admin ACL. */ function adminACLAllowed( address sender, address contract_, bytes4 selector ) external returns (bool); function minterFilterType() external pure returns (string memory); function getMinterForProject( uint256 projectId, address coreContract ) external view returns (address); function projectHasMinter( uint256 projectId, address coreContract ) external view returns (bool); /** * @notice View that returns if a core contract is registered with the * core registry, allowing this minter filter to service it. * @param coreContract core contract address to be checked */ function isRegisteredCoreContract( address coreContract ) external view returns (bool); /// Address of current core registry contract function coreRegistry() external view returns (ICoreRegistryV1); /// The current admin ACL contract function adminACLContract() external view returns (IAdminACLV0); /// The quantity of projects on a core contract that have assigned minters function getNumProjectsOnContractWithMinters( address coreContract ) external view returns (uint256); function getProjectAndMinterInfoOnContractAt( address coreContract, uint256 index ) external view returns ( uint256 projectId, address minterAddress, string memory minterType ); function getAllGloballyApprovedMinters() external view returns (MinterWithType[] memory mintersWithTypes); function getAllContractApprovedMinters( address coreContract ) external view returns (MinterWithType[] memory mintersWithTypes); /** * Owner of contract. * @dev This returns the address of the Admin ACL contract. */ function owner() external view returns (address); }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. pragma solidity ^0.8.0; interface ISharedMinterV0 { // Sets the local max invocations for a given project, checking that the provided max invocations is // less than or equal to the global max invocations for the project set on the core contract. // This does not impact the max invocations value defined on the core contract. function manuallyLimitProjectMaxInvocations( uint256 projectId, address coreContract, uint24 maxInvocations ) external; // Called to make the minter contract aware of the max invocations for a // given project. function syncProjectMaxInvocationsToCore( uint256 projectId, address coreContract ) external; // getter function of public variable function minterType() external view returns (string memory); function minterFilterAddress() external returns (address); // Gets if token price is configured, token price in wei, currency symbol, // and currency address, assuming this is project's minter. // Supersedes any defined core price. function getPriceInfo( uint256 projectId, address coreContract ) external view returns ( bool isConfigured, uint256 tokenPriceInWei, string memory currencySymbol, address currencyAddress ); }
// SPDX-License-Identifier: LGPL-3.0-only // Created By: Art Blocks Inc. // Inspired by: https://ethereum.stackexchange.com/a/123950/103422 pragma solidity ^0.8.0; /** * @dev Operations on bytes32 data type, dealing with conversion to string. */ library Bytes32Strings { /** * @notice Intended to convert a `bytes32`-encoded string literal to `string`. * Trims zero padding to arrive at original string literal. */ function toString( bytes32 source ) internal pure returns (string memory result) { uint8 length; while (source[length] != 0 && length < 32) { length++; } assembly { // free memory pointer result := mload(0x40) // update free memory pointer to new "memory end" // (offset is 64-bytes: 32 for length, 32 for data) mstore(0x40, add(result, 0x40)) // store length in first 32-byte memory slot mstore(result, length) // write actual data in second 32-byte memory slot mstore(add(result, 0x20), source) } } /** * @notice Intended to check if a `bytes32`-encoded string contains a given * character with UTF-8 character code `utf8CharCode exactly `targetQty` * times. Does not support searching for multi-byte characters, only * characters with UTF-8 character codes < 0x80. */ function containsExactCharacterQty( bytes32 source, uint8 utf8CharCode, uint8 targetQty ) internal pure returns (bool) { uint8 _occurrences; uint8 i; for (i; i < 32; ) { uint8 _charCode = uint8(source[i]); // if not a null byte, or a multi-byte UTF-8 character, check match if (_charCode != 0 && _charCode < 0x80) { if (_charCode == utf8CharCode) { unchecked { // no risk of overflow since max 32 iterations < max uin8=255 ++_occurrences; } } } unchecked { // no risk of overflow since max 32 iterations < max uin8=255 ++i; } } return _occurrences == targetQty; } }
{ "optimizer": { "enabled": true, "runs": 25 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"adminACLContract_","type":"address"},{"internalType":"address","name":"coreRegistry_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"adminACLContract","type":"address"}],"name":"AdminACLUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"coreRegistry","type":"address"}],"name":"CoreRegistryUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"Deployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"coreContract","type":"address"},{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"string","name":"minterType","type":"string"}],"name":"MinterApprovedForContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"string","name":"minterType","type":"string"}],"name":"MinterApprovedGlobally","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"coreContract","type":"address"},{"indexed":true,"internalType":"address","name":"minter","type":"address"}],"name":"MinterRevokedForContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"}],"name":"MinterRevokedGlobally","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"projectId","type":"uint256"},{"indexed":true,"internalType":"address","name":"coreContract","type":"address"},{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"string","name":"minterType","type":"string"}],"name":"ProjectMinterRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"projectId","type":"uint256"},{"indexed":true,"internalType":"address","name":"coreContract","type":"address"}],"name":"ProjectMinterRemoved","type":"event"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"adminACLAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"adminACLContract","outputs":[{"internalType":"contract IAdminACLV0","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"coreContract","type":"address"},{"internalType":"address","name":"minter","type":"address"}],"name":"approveMinterForContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"approveMinterGlobally","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"coreRegistry","outputs":[{"internalType":"contract ICoreRegistryV1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"coreContract","type":"address"}],"name":"getAllContractApprovedMinters","outputs":[{"components":[{"internalType":"address","name":"minterAddress","type":"address"},{"internalType":"string","name":"minterType","type":"string"}],"internalType":"struct IMinterFilterV1.MinterWithType[]","name":"mintersWithTypes","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllGloballyApprovedMinters","outputs":[{"components":[{"internalType":"address","name":"minterAddress","type":"address"},{"internalType":"string","name":"minterType","type":"string"}],"internalType":"struct IMinterFilterV1.MinterWithType[]","name":"mintersWithTypes","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"address","name":"coreContract","type":"address"}],"name":"getMinterForProject","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"coreContract","type":"address"}],"name":"getNumProjectsOnContractWithMinters","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"coreContract","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getProjectAndMinterInfoOnContractAt","outputs":[{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"address","name":"minterAddress","type":"address"},{"internalType":"string","name":"minterType","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"coreContract","type":"address"},{"internalType":"address","name":"minter","type":"address"}],"name":"getProjectsOnContractUsingMinter","outputs":[{"internalType":"uint256[]","name":"projectIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"coreContract","type":"address"},{"internalType":"address","name":"minter","type":"address"}],"name":"isApprovedMinterForContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"isGloballyApprovedMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"coreContract","type":"address"}],"name":"isRegisteredCoreContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"address","name":"coreContract","type":"address"},{"internalType":"address","name":"sender","type":"address"}],"name":"mint_joo","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minterFilterType","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"minterFilterVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"minterAddress","type":"address"}],"name":"numProjectsUsingMinter","outputs":[{"internalType":"uint256","name":"numProjects","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"address","name":"coreContract","type":"address"}],"name":"projectHasMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"address","name":"coreContract","type":"address"}],"name":"removeMinterForProject","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"projectIds","type":"uint256[]"},{"internalType":"address","name":"coreContract","type":"address"}],"name":"removeMintersForProjectsOnContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"coreContract","type":"address"},{"internalType":"address","name":"minter","type":"address"}],"name":"revokeMinterForContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"revokeMinterGlobally","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"address","name":"coreContract","type":"address"},{"internalType":"address","name":"minter","type":"address"}],"name":"setMinterForProject","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"coreRegistry_","type":"address"}],"name":"updateCoreRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506040516200245b3803806200245b8339810160408190526200003491620001d3565b6200003f3362000086565b6200004a8262000086565b6200005581620000b3565b6040517f3fad920548ed9f22deb8333b4cc1e4f9bc36666a1c2aa30ad59a0a3bb9dcbb9290600090a150506200020b565b620000918162000108565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b620000be8162000158565b600280546001600160a01b0319166001600160a01b0383169081179091556040517fb7b620c2c1cece07219b2ac19100c3f8629a9752c3c5484ed6524e99d0bddeed90600090a250565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038116620001b35760405162461bcd60e51b815260206004820152601560248201527f4f6e6c79206e6f6e2d7a65726f20616464726573730000000000000000000000604482015260640160405180910390fd5b50565b80516001600160a01b0381168114620001ce57600080fd5b919050565b60008060408385031215620001e757600080fd5b620001f283620001b6565b91506200020260208401620001b6565b90509250929050565b612240806200021b6000396000f3fe608060405234801561001057600080fd5b50600436106101625760003560e01c8063765aabff116100c9578063765aabff1461029c57806384b19f1e146102af5780638da5cb5b146102c25780638e5b9056146102ca5780638f48e2c0146102dd57806395139f66146102f0578063969c3ed714610303578063a02b095214610323578063a365254714610343578063af439a311461034b578063e420c9541461036d578063ea6e376114610380578063f2fde38b14610393578063fd9ca435146103a657600080fd5b80615f34146101675780630a3eecb21461018d5780631e9bef46146101a25780631f8608c6146101c257806320f2ccb7146101e5578063230448b1146101fa57806326df17b51461020d57806341946f0f1461022d57806353114de4146102405780635845de1f146102535780635e94e3de146102665780636bf3d05a146102795780637136b93e1461028c578063715018a614610294575b600080fd5b61017a610175366004611c52565b6103b9565b6040519081526020015b60405180910390f35b6101a061019b366004611ca5565b6104b7565b005b6001546101b5906001600160a01b031681565b6040516101849190611cde565b6101d56101d0366004611cf2565b610553565b6040519015158152602001610184565b6101ed6105cb565b6040516101849190611d5f565b6101d5610208366004611d72565b6105ec565b61017a61021b366004611cf2565b60036020526000908152604090205481565b6101a061023b366004611dca565b61066b565b6101a061024e366004611e01565b6107f7565b6101b5610261366004611e7b565b61084e565b6101a0610274366004611ca5565b6108ba565b6002546101b5906001600160a01b031681565b6101ed6109c6565b6101a06109da565b6101a06102aa366004611e7b565b610a1e565b6101a06102bd366004611cf2565b610a47565b6101b5610b27565b6101d56102d8366004611ca5565b610b36565b6101d56102eb366004611cf2565b610b70565b6101a06102fe366004611cf2565b610b7d565b610316610311366004611ca5565b610b99565b6040516101849190611ea0565b610336610331366004611cf2565b610ca9565b6040516101849190611ee4565b610336610e00565b61035e610359366004611f61565b610f3f565b60405161018493929190611f8d565b6101a061037b366004611cf2565b610fdd565b6101d561038e366004611e7b565b61104b565b6101a06103a1366004611cf2565b611078565b61017a6103b4366004611cf2565b6110ee565b6001600160a01b03821660009081526007602052604081206103db908561110f565b6001600160a01b0316336001600160a01b0316146104375760405162461bcd60e51b815260206004820152601460248201527327b7363c9030b9b9b4b3b732b21036b4b73a32b960611b60448201526064015b60405180910390fd5b604051615de560e01b81526001600160a01b038681166004830152602482018690528381166044830152841690615de5906064016020604051808303816000875af115801561048a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ae9190611fb7565b95945050505050565b6104c08261111b565b6104d18263051f765960e11b6111d8565b6001600160a01b03821660009081526006602052604090206104f39082611294565b61050f5760405162461bcd60e51b815260040161042e90611fd0565b806001600160a01b0316826001600160a01b03167f60ecff7c83062c43d6aae585dca525293afec7a4f4c378d12927ce8f7525da2460405160405180910390a35050565b60025460405163f1052af560e01b81526000916001600160a01b03169063f1052af590610584908590600401611cde565b602060405180830381865afa1580156105a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c59190612007565b92915050565b60606105e76d26b4b73a32b92334b63a32b92b1960911b6112a9565b905090565b6001546040516217798b60e61b81526000916001600160a01b0316906305de62c09061062090879087908790600401612029565b6020604051808303816000875af115801561063f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106639190612007565b949350505050565b6106748261111b565b61068683836341946f0f60e01b611314565b610690828261145e565b61069a83836114ac565b6001600160a01b038216600090815260076020526040812081906106be90866115cb565b9150915081156106f2576001600160a01b03811660009081526003602052604081208054916106ec8361206c565b91905055505b6001600160a01b038316600090815260036020526040812080549161071683612083565b90915550506001600160a01b038416600090815260076020526040902061073e9086856115e9565b50826001600160a01b0316846001600160a01b0316867ff012149282a4a83d5c0326ace29c04e9133d41afa355fa606583817a27077d3f866001600160a01b031663e9d1e8ac6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156107b3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107db91908101906120b2565b6040516107e89190611d5f565b60405180910390a45050505050565b6108008161111b565b610811816314c4537960e21b6111d8565b8160005b818110156108475761083f8585838181106108325761083261215e565b90506020020135846115ff565b600101610815565b5050505050565b6001600160a01b03811660009081526007602052604081208190819061087490866115cb565b91509150816106635760405162461bcd60e51b8152602060048201526012602482015271139bc81b5a5b9d195c88185cdcda59db995960721b604482015260640161042e565b6108c38261111b565b6108d482632f4a71ef60e11b6111d8565b6001600160a01b03821660009081526006602052604090206108f690826116db565b6109125760405162461bcd60e51b815260040161042e90612174565b806001600160a01b0316826001600160a01b03167ff85412168568a1b1d7fda7902afcdb9b2b5380b30d67881d704a1c77cab63045836001600160a01b031663e9d1e8ac6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610985573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109ad91908101906120b2565b6040516109ba9190611d5f565b60405180910390a35050565b60606105e765076322e302e360d41b6112a9565b60405162461bcd60e51b8152602060048201526019602482015278043616e6e6f742072656e6f756e6365206f776e65727368697603c1b604482015260640161042e565b610a278161111b565b610a39828263765aabff60e01b611314565b610a4382826115ff565b5050565b610a57634258cf8f60e11b6116f0565b610a626004826116db565b610a7e5760405162461bcd60e51b815260040161042e90612174565b806001600160a01b03167f0d736cadcb29a6b8ae53b321e79e808a23cd1a48e960e4b566bcb2e9d6cccba8826001600160a01b031663e9d1e8ac6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610ae7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b0f91908101906120b2565b604051610b1c9190611d5f565b60405180910390a250565b6000546001600160a01b031690565b6000610b4182610b70565b80610b6957506001600160a01b0383166000908152600660205260409020610b699083611740565b9392505050565b60006105c5600483611740565b610b8d634a89cfb360e11b6116f0565b610b9681611755565b50565b6001600160a01b038083166000908152600760209081526040808320938516835260039091528120546060929190610bd990610bd4846117a8565b6117b3565b9050806001600160401b03811115610bf357610bf361209c565b604051908082528060200260200182016040528015610c1c578160200160208202803683370190505b5092506000610c2a836117a8565b90506000805b82811015610c9257600080610c4587846117c9565b91509150886001600160a01b0316816001600160a01b031603610c885781888580600101965081518110610c7b57610c7b61215e565b6020026020010181815250505b5050600101610c30565b5080831115610c9f578085525b5050505092915050565b6001600160a01b0381166000908152600660205260408120606091610ccd826117d8565b9050806001600160401b03811115610ce757610ce761209c565b604051908082528060200260200182016040528015610d2d57816020015b604080518082019091526000815260606020820152815260200190600190039081610d055790505b50925060005b81811015610df8576000610d4784836117e2565b90506000816001600160a01b031663e9d1e8ac6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d89573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610db191908101906120b2565b90506040518060400160405280836001600160a01b0316815260200182815250868481518110610de357610de361215e565b60209081029190910101525050600101610d33565b505050919050565b60606000610e0e60046117d8565b9050806001600160401b03811115610e2857610e2861209c565b604051908082528060200260200182016040528015610e6e57816020015b604080518082019091526000815260606020820152815260200190600190039081610e465790505b50915060005b81811015610f3a576000610e896004836117e2565b90506000816001600160a01b031663e9d1e8ac6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610ecb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ef391908101906120b2565b90506040518060400160405280836001600160a01b0316815260200182815250858481518110610f2557610f2561215e565b60209081029190910101525050600101610e74565b505090565b6001600160a01b03821660009081526007602052604081208190606090610f6690856117c9565b8093508194505050816001600160a01b031663e9d1e8ac6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610fac573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610fd491908101906120b2565b90509250925092565b610fed633908325560e21b6116f0565b610ff8600482611294565b6110145760405162461bcd60e51b815260040161042e90611fd0565b6040516001600160a01b038216907f370244067623daed110e586dc655aa7544b64008c7bfebe6cc5d235933a3395890600090a250565b6001600160a01b0381166000908152600760205260408120819061106f90856115cb565b50949350505050565b6110806117ee565b6001600160a01b0381166110e55760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161042e565b610b968161184f565b6001600160a01b03811660009081526007602052604081206105c5906117a8565b6000610b69838361187a565b60025460405163f1052af560e01b81526001600160a01b039091169063f1052af59061114b908490600401611cde565b602060405180830381865afa158015611168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118c9190612007565b610b965760405162461bcd60e51b815260206004820152601d60248201527f4f6e6c79207265676973746572656420636f726520636f6e7472616374000000604482015260640161042e565b60405163230448b160e01b81526001600160a01b0383169063230448b19061120890339030908690600401612029565b6020604051808303816000875af1158015611227573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124b9190612007565b610a435760405162461bcd60e51b815260206004820152601a60248201527913db9b1e4810dbdc994810591b5a5b9050d308185b1b1bddd95960321b604482015260640161042e565b6000610b69836001600160a01b0384166118ea565b606060005b828160ff16602081106112c3576112c361215e565b1a60f81b6001600160f81b031916158015906112e2575060208160ff16105b156112f957806112f1816121a5565b9150506112ae565b60405191506040820160405280825282602083015250919050565b60405163a47d29cb60e01b81526004810184905282906001600160a01b0382169063a47d29cb90602401602060405180830381865afa15801561135b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137f91906121c4565b6001600160a01b0316336001600160a01b0316148061140c575060405163230448b160e01b81526001600160a01b0382169063230448b1906113c990339030908790600401612029565b6020604051808303816000875af11580156113e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140c9190612007565b6114585760405162461bcd60e51b815260206004820152601d60248201527f4f6e6c7920417274697374206f7220436f72652041646d696e2041434c000000604482015260640161042e565b50505050565b6114688282610b36565b610a435760405162461bcd60e51b81526020600482015260156024820152744f6e6c7920617070726f766564206d696e7465727360581b604482015260640161042e565b6000819050806001600160a01b031663f893c07b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115139190611fb7565b83101580156115825750806001600160a01b031663e935b7b16040518163ffffffff1660e01b8152600401602060405180830381865afa15801561155b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157f9190611fb7565b83105b6115c65760405162461bcd60e51b815260206004820152601560248201527413db9b1e481d985b1a59081c1c9bda9958dd081251605a1b604482015260640161042e565b505050565b60008080806115da86866119dd565b909450925050505b9250929050565b600061066384846001600160a01b038516611a17565b6040805180820182526012815271139bc81b5a5b9d195c88185cdcda59db995960721b6020808301919091526001600160a01b038416600090815260079091529182206003929161165291908690611a34565b6001600160a01b03168152602081019190915260400160009081208054916116798361206c565b90915550506001600160a01b03811660009081526007602052604090206116a09083611a41565b506040516001600160a01b0382169083907f08cccda053ef9dd4d5864c1af5303d9ef0277a79c21cacee3cd0b34dd4e9160590600090a35050565b6000610b69836001600160a01b038416611a4d565b6116fb3330836105ec565b610b965760405162461bcd60e51b815260206004820152601660248201527513db9b1e4810591b5a5b881050d308185b1b1bddd95960521b604482015260640161042e565b6000610b69836001600160a01b038416611a97565b61175e81611aaf565b600280546001600160a01b0319166001600160a01b0383169081179091556040517fb7b620c2c1cece07219b2ac19100c3f8629a9752c3c5484ed6524e99d0bddeed90600090a250565b60006105c582611afd565b60008183106117c25781610b69565b5090919050565b60008080806115da8686611b08565b60006105c5825490565b6000610b698383611b33565b336117f7610b27565b6001600160a01b03161461184d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161042e565b565b61185881611b5d565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60008181526002830160205260408120548015158061189e575061189e8484611bad565b610b695760405162461bcd60e51b815260206004820152601e60248201527f456e756d657261626c654d61703a206e6f6e6578697374656e74206b65790000604482015260640161042e565b600081815260018301602052604081205480156119d357600061190e6001836121e1565b8554909150600090611922906001906121e1565b90508181146119875760008660000182815481106119425761194261215e565b90600052602060002001549050808760000184815481106119655761196561215e565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611998576119986121f4565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105c5565b60009150506105c5565b6000818152600283016020526040812054819080611a0c576119ff8585611bad565b9250600091506115e29050565b6001925090506115e2565b600082815260028401602052604081208290556106638484611bb9565b6000610663848484611bc5565b6000610b698383611c08565b6000611a598383611a97565b611a8f575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105c5565b5060006105c5565b60009081526001919091016020526040902054151590565b6001600160a01b038116610b965760405162461bcd60e51b81526020600482015260156024820152744f6e6c79206e6f6e2d7a65726f206164647265737360581b604482015260640161042e565b60006105c5826117d8565b60008080611b1685856117e2565b600081815260029690960160205260409095205494959350505050565b6000826000018281548110611b4a57611b4a61215e565b9060005260206000200154905092915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000610b698383611c25565b6000610b698383611a4d565b600082815260028401602052604081205480151580611be95750611be98585611bad565b839061106f5760405162461bcd60e51b815260040161042e9190611d5f565b60008181526002830160205260408120819055610b698383611c31565b6000610b698383611a97565b6000610b6983836118ea565b6001600160a01b0381168114610b9657600080fd5b60008060008060808587031215611c6857600080fd5b8435611c7381611c3d565b9350602085013592506040850135611c8a81611c3d565b91506060850135611c9a81611c3d565b939692955090935050565b60008060408385031215611cb857600080fd5b8235611cc381611c3d565b91506020830135611cd381611c3d565b809150509250929050565b6001600160a01b0391909116815260200190565b600060208284031215611d0457600080fd5b8135610b6981611c3d565b60005b83811015611d2a578181015183820152602001611d12565b50506000910152565b60008151808452611d4b816020860160208601611d0f565b601f01601f19169290920160200192915050565b602081526000610b696020830184611d33565b600080600060608486031215611d8757600080fd5b8335611d9281611c3d565b92506020840135611da281611c3d565b915060408401356001600160e01b031981168114611dbf57600080fd5b809150509250925092565b600080600060608486031215611ddf57600080fd5b833592506020840135611df181611c3d565b91506040840135611dbf81611c3d565b600080600060408486031215611e1657600080fd5b83356001600160401b0380821115611e2d57600080fd5b818601915086601f830112611e4157600080fd5b813581811115611e5057600080fd5b8760208260051b8501011115611e6557600080fd5b60209283019550935050840135611dbf81611c3d565b60008060408385031215611e8e57600080fd5b823591506020830135611cd381611c3d565b6020808252825182820181905260009190848201906040850190845b81811015611ed857835183529284019291840191600101611ebc565b50909695505050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611f5357888303603f19018552815180516001600160a01b03168452870151878401879052611f4087850182611d33565b9588019593505090860190600101611f0b565b509098975050505050505050565b60008060408385031215611f7457600080fd5b8235611f7f81611c3d565b946020939093013593505050565b8381526001600160a01b03831660208201526060604082018190526000906104ae90830184611d33565b600060208284031215611fc957600080fd5b5051919050565b6020808252601f908201527f4f6e6c792070726576696f75736c7920617070726f766564206d696e74657200604082015260600190565b60006020828403121561201957600080fd5b81518015158114610b6957600080fd5b6001600160a01b0393841681529190921660208201526001600160e01b0319909116604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60008161207b5761207b612056565b506000190190565b60006001820161209557612095612056565b5060010190565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156120c457600080fd5b81516001600160401b03808211156120db57600080fd5b818401915084601f8301126120ef57600080fd5b8151818111156121015761210161209c565b604051601f8201601f19908116603f011681019083821181831017156121295761212961209c565b8160405282815287602084870101111561214257600080fd5b612153836020830160208801611d0f565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b602080825260179082015276135a5b9d195c88185b1c9958591e48185c1c1c9bdd9959604a1b604082015260600190565b600060ff821660ff81036121bb576121bb612056565b60010192915050565b6000602082840312156121d657600080fd5b8151610b6981611c3d565b818103818111156105c5576105c5612056565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220d086cd837f4af5b72d1752ec2b8754222402401d43a56569df878a1e5335b0f964736f6c63430008130033000000000000000000000000fafda82cde1502c41e597e4656953533c16ca9940000000000000000000000002ee7b9bb2e038be7323a119701a191c030a61ec6
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101625760003560e01c8063765aabff116100c9578063765aabff1461029c57806384b19f1e146102af5780638da5cb5b146102c25780638e5b9056146102ca5780638f48e2c0146102dd57806395139f66146102f0578063969c3ed714610303578063a02b095214610323578063a365254714610343578063af439a311461034b578063e420c9541461036d578063ea6e376114610380578063f2fde38b14610393578063fd9ca435146103a657600080fd5b80615f34146101675780630a3eecb21461018d5780631e9bef46146101a25780631f8608c6146101c257806320f2ccb7146101e5578063230448b1146101fa57806326df17b51461020d57806341946f0f1461022d57806353114de4146102405780635845de1f146102535780635e94e3de146102665780636bf3d05a146102795780637136b93e1461028c578063715018a614610294575b600080fd5b61017a610175366004611c52565b6103b9565b6040519081526020015b60405180910390f35b6101a061019b366004611ca5565b6104b7565b005b6001546101b5906001600160a01b031681565b6040516101849190611cde565b6101d56101d0366004611cf2565b610553565b6040519015158152602001610184565b6101ed6105cb565b6040516101849190611d5f565b6101d5610208366004611d72565b6105ec565b61017a61021b366004611cf2565b60036020526000908152604090205481565b6101a061023b366004611dca565b61066b565b6101a061024e366004611e01565b6107f7565b6101b5610261366004611e7b565b61084e565b6101a0610274366004611ca5565b6108ba565b6002546101b5906001600160a01b031681565b6101ed6109c6565b6101a06109da565b6101a06102aa366004611e7b565b610a1e565b6101a06102bd366004611cf2565b610a47565b6101b5610b27565b6101d56102d8366004611ca5565b610b36565b6101d56102eb366004611cf2565b610b70565b6101a06102fe366004611cf2565b610b7d565b610316610311366004611ca5565b610b99565b6040516101849190611ea0565b610336610331366004611cf2565b610ca9565b6040516101849190611ee4565b610336610e00565b61035e610359366004611f61565b610f3f565b60405161018493929190611f8d565b6101a061037b366004611cf2565b610fdd565b6101d561038e366004611e7b565b61104b565b6101a06103a1366004611cf2565b611078565b61017a6103b4366004611cf2565b6110ee565b6001600160a01b03821660009081526007602052604081206103db908561110f565b6001600160a01b0316336001600160a01b0316146104375760405162461bcd60e51b815260206004820152601460248201527327b7363c9030b9b9b4b3b732b21036b4b73a32b960611b60448201526064015b60405180910390fd5b604051615de560e01b81526001600160a01b038681166004830152602482018690528381166044830152841690615de5906064016020604051808303816000875af115801561048a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ae9190611fb7565b95945050505050565b6104c08261111b565b6104d18263051f765960e11b6111d8565b6001600160a01b03821660009081526006602052604090206104f39082611294565b61050f5760405162461bcd60e51b815260040161042e90611fd0565b806001600160a01b0316826001600160a01b03167f60ecff7c83062c43d6aae585dca525293afec7a4f4c378d12927ce8f7525da2460405160405180910390a35050565b60025460405163f1052af560e01b81526000916001600160a01b03169063f1052af590610584908590600401611cde565b602060405180830381865afa1580156105a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c59190612007565b92915050565b60606105e76d26b4b73a32b92334b63a32b92b1960911b6112a9565b905090565b6001546040516217798b60e61b81526000916001600160a01b0316906305de62c09061062090879087908790600401612029565b6020604051808303816000875af115801561063f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106639190612007565b949350505050565b6106748261111b565b61068683836341946f0f60e01b611314565b610690828261145e565b61069a83836114ac565b6001600160a01b038216600090815260076020526040812081906106be90866115cb565b9150915081156106f2576001600160a01b03811660009081526003602052604081208054916106ec8361206c565b91905055505b6001600160a01b038316600090815260036020526040812080549161071683612083565b90915550506001600160a01b038416600090815260076020526040902061073e9086856115e9565b50826001600160a01b0316846001600160a01b0316867ff012149282a4a83d5c0326ace29c04e9133d41afa355fa606583817a27077d3f866001600160a01b031663e9d1e8ac6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156107b3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107db91908101906120b2565b6040516107e89190611d5f565b60405180910390a45050505050565b6108008161111b565b610811816314c4537960e21b6111d8565b8160005b818110156108475761083f8585838181106108325761083261215e565b90506020020135846115ff565b600101610815565b5050505050565b6001600160a01b03811660009081526007602052604081208190819061087490866115cb565b91509150816106635760405162461bcd60e51b8152602060048201526012602482015271139bc81b5a5b9d195c88185cdcda59db995960721b604482015260640161042e565b6108c38261111b565b6108d482632f4a71ef60e11b6111d8565b6001600160a01b03821660009081526006602052604090206108f690826116db565b6109125760405162461bcd60e51b815260040161042e90612174565b806001600160a01b0316826001600160a01b03167ff85412168568a1b1d7fda7902afcdb9b2b5380b30d67881d704a1c77cab63045836001600160a01b031663e9d1e8ac6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610985573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109ad91908101906120b2565b6040516109ba9190611d5f565b60405180910390a35050565b60606105e765076322e302e360d41b6112a9565b60405162461bcd60e51b8152602060048201526019602482015278043616e6e6f742072656e6f756e6365206f776e65727368697603c1b604482015260640161042e565b610a278161111b565b610a39828263765aabff60e01b611314565b610a4382826115ff565b5050565b610a57634258cf8f60e11b6116f0565b610a626004826116db565b610a7e5760405162461bcd60e51b815260040161042e90612174565b806001600160a01b03167f0d736cadcb29a6b8ae53b321e79e808a23cd1a48e960e4b566bcb2e9d6cccba8826001600160a01b031663e9d1e8ac6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610ae7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b0f91908101906120b2565b604051610b1c9190611d5f565b60405180910390a250565b6000546001600160a01b031690565b6000610b4182610b70565b80610b6957506001600160a01b0383166000908152600660205260409020610b699083611740565b9392505050565b60006105c5600483611740565b610b8d634a89cfb360e11b6116f0565b610b9681611755565b50565b6001600160a01b038083166000908152600760209081526040808320938516835260039091528120546060929190610bd990610bd4846117a8565b6117b3565b9050806001600160401b03811115610bf357610bf361209c565b604051908082528060200260200182016040528015610c1c578160200160208202803683370190505b5092506000610c2a836117a8565b90506000805b82811015610c9257600080610c4587846117c9565b91509150886001600160a01b0316816001600160a01b031603610c885781888580600101965081518110610c7b57610c7b61215e565b6020026020010181815250505b5050600101610c30565b5080831115610c9f578085525b5050505092915050565b6001600160a01b0381166000908152600660205260408120606091610ccd826117d8565b9050806001600160401b03811115610ce757610ce761209c565b604051908082528060200260200182016040528015610d2d57816020015b604080518082019091526000815260606020820152815260200190600190039081610d055790505b50925060005b81811015610df8576000610d4784836117e2565b90506000816001600160a01b031663e9d1e8ac6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d89573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610db191908101906120b2565b90506040518060400160405280836001600160a01b0316815260200182815250868481518110610de357610de361215e565b60209081029190910101525050600101610d33565b505050919050565b60606000610e0e60046117d8565b9050806001600160401b03811115610e2857610e2861209c565b604051908082528060200260200182016040528015610e6e57816020015b604080518082019091526000815260606020820152815260200190600190039081610e465790505b50915060005b81811015610f3a576000610e896004836117e2565b90506000816001600160a01b031663e9d1e8ac6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610ecb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ef391908101906120b2565b90506040518060400160405280836001600160a01b0316815260200182815250858481518110610f2557610f2561215e565b60209081029190910101525050600101610e74565b505090565b6001600160a01b03821660009081526007602052604081208190606090610f6690856117c9565b8093508194505050816001600160a01b031663e9d1e8ac6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610fac573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610fd491908101906120b2565b90509250925092565b610fed633908325560e21b6116f0565b610ff8600482611294565b6110145760405162461bcd60e51b815260040161042e90611fd0565b6040516001600160a01b038216907f370244067623daed110e586dc655aa7544b64008c7bfebe6cc5d235933a3395890600090a250565b6001600160a01b0381166000908152600760205260408120819061106f90856115cb565b50949350505050565b6110806117ee565b6001600160a01b0381166110e55760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161042e565b610b968161184f565b6001600160a01b03811660009081526007602052604081206105c5906117a8565b6000610b69838361187a565b60025460405163f1052af560e01b81526001600160a01b039091169063f1052af59061114b908490600401611cde565b602060405180830381865afa158015611168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118c9190612007565b610b965760405162461bcd60e51b815260206004820152601d60248201527f4f6e6c79207265676973746572656420636f726520636f6e7472616374000000604482015260640161042e565b60405163230448b160e01b81526001600160a01b0383169063230448b19061120890339030908690600401612029565b6020604051808303816000875af1158015611227573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124b9190612007565b610a435760405162461bcd60e51b815260206004820152601a60248201527913db9b1e4810dbdc994810591b5a5b9050d308185b1b1bddd95960321b604482015260640161042e565b6000610b69836001600160a01b0384166118ea565b606060005b828160ff16602081106112c3576112c361215e565b1a60f81b6001600160f81b031916158015906112e2575060208160ff16105b156112f957806112f1816121a5565b9150506112ae565b60405191506040820160405280825282602083015250919050565b60405163a47d29cb60e01b81526004810184905282906001600160a01b0382169063a47d29cb90602401602060405180830381865afa15801561135b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137f91906121c4565b6001600160a01b0316336001600160a01b0316148061140c575060405163230448b160e01b81526001600160a01b0382169063230448b1906113c990339030908790600401612029565b6020604051808303816000875af11580156113e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140c9190612007565b6114585760405162461bcd60e51b815260206004820152601d60248201527f4f6e6c7920417274697374206f7220436f72652041646d696e2041434c000000604482015260640161042e565b50505050565b6114688282610b36565b610a435760405162461bcd60e51b81526020600482015260156024820152744f6e6c7920617070726f766564206d696e7465727360581b604482015260640161042e565b6000819050806001600160a01b031663f893c07b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115139190611fb7565b83101580156115825750806001600160a01b031663e935b7b16040518163ffffffff1660e01b8152600401602060405180830381865afa15801561155b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157f9190611fb7565b83105b6115c65760405162461bcd60e51b815260206004820152601560248201527413db9b1e481d985b1a59081c1c9bda9958dd081251605a1b604482015260640161042e565b505050565b60008080806115da86866119dd565b909450925050505b9250929050565b600061066384846001600160a01b038516611a17565b6040805180820182526012815271139bc81b5a5b9d195c88185cdcda59db995960721b6020808301919091526001600160a01b038416600090815260079091529182206003929161165291908690611a34565b6001600160a01b03168152602081019190915260400160009081208054916116798361206c565b90915550506001600160a01b03811660009081526007602052604090206116a09083611a41565b506040516001600160a01b0382169083907f08cccda053ef9dd4d5864c1af5303d9ef0277a79c21cacee3cd0b34dd4e9160590600090a35050565b6000610b69836001600160a01b038416611a4d565b6116fb3330836105ec565b610b965760405162461bcd60e51b815260206004820152601660248201527513db9b1e4810591b5a5b881050d308185b1b1bddd95960521b604482015260640161042e565b6000610b69836001600160a01b038416611a97565b61175e81611aaf565b600280546001600160a01b0319166001600160a01b0383169081179091556040517fb7b620c2c1cece07219b2ac19100c3f8629a9752c3c5484ed6524e99d0bddeed90600090a250565b60006105c582611afd565b60008183106117c25781610b69565b5090919050565b60008080806115da8686611b08565b60006105c5825490565b6000610b698383611b33565b336117f7610b27565b6001600160a01b03161461184d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161042e565b565b61185881611b5d565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60008181526002830160205260408120548015158061189e575061189e8484611bad565b610b695760405162461bcd60e51b815260206004820152601e60248201527f456e756d657261626c654d61703a206e6f6e6578697374656e74206b65790000604482015260640161042e565b600081815260018301602052604081205480156119d357600061190e6001836121e1565b8554909150600090611922906001906121e1565b90508181146119875760008660000182815481106119425761194261215e565b90600052602060002001549050808760000184815481106119655761196561215e565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611998576119986121f4565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105c5565b60009150506105c5565b6000818152600283016020526040812054819080611a0c576119ff8585611bad565b9250600091506115e29050565b6001925090506115e2565b600082815260028401602052604081208290556106638484611bb9565b6000610663848484611bc5565b6000610b698383611c08565b6000611a598383611a97565b611a8f575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105c5565b5060006105c5565b60009081526001919091016020526040902054151590565b6001600160a01b038116610b965760405162461bcd60e51b81526020600482015260156024820152744f6e6c79206e6f6e2d7a65726f206164647265737360581b604482015260640161042e565b60006105c5826117d8565b60008080611b1685856117e2565b600081815260029690960160205260409095205494959350505050565b6000826000018281548110611b4a57611b4a61215e565b9060005260206000200154905092915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000610b698383611c25565b6000610b698383611a4d565b600082815260028401602052604081205480151580611be95750611be98585611bad565b839061106f5760405162461bcd60e51b815260040161042e9190611d5f565b60008181526002830160205260408120819055610b698383611c31565b6000610b698383611a97565b6000610b6983836118ea565b6001600160a01b0381168114610b9657600080fd5b60008060008060808587031215611c6857600080fd5b8435611c7381611c3d565b9350602085013592506040850135611c8a81611c3d565b91506060850135611c9a81611c3d565b939692955090935050565b60008060408385031215611cb857600080fd5b8235611cc381611c3d565b91506020830135611cd381611c3d565b809150509250929050565b6001600160a01b0391909116815260200190565b600060208284031215611d0457600080fd5b8135610b6981611c3d565b60005b83811015611d2a578181015183820152602001611d12565b50506000910152565b60008151808452611d4b816020860160208601611d0f565b601f01601f19169290920160200192915050565b602081526000610b696020830184611d33565b600080600060608486031215611d8757600080fd5b8335611d9281611c3d565b92506020840135611da281611c3d565b915060408401356001600160e01b031981168114611dbf57600080fd5b809150509250925092565b600080600060608486031215611ddf57600080fd5b833592506020840135611df181611c3d565b91506040840135611dbf81611c3d565b600080600060408486031215611e1657600080fd5b83356001600160401b0380821115611e2d57600080fd5b818601915086601f830112611e4157600080fd5b813581811115611e5057600080fd5b8760208260051b8501011115611e6557600080fd5b60209283019550935050840135611dbf81611c3d565b60008060408385031215611e8e57600080fd5b823591506020830135611cd381611c3d565b6020808252825182820181905260009190848201906040850190845b81811015611ed857835183529284019291840191600101611ebc565b50909695505050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611f5357888303603f19018552815180516001600160a01b03168452870151878401879052611f4087850182611d33565b9588019593505090860190600101611f0b565b509098975050505050505050565b60008060408385031215611f7457600080fd5b8235611f7f81611c3d565b946020939093013593505050565b8381526001600160a01b03831660208201526060604082018190526000906104ae90830184611d33565b600060208284031215611fc957600080fd5b5051919050565b6020808252601f908201527f4f6e6c792070726576696f75736c7920617070726f766564206d696e74657200604082015260600190565b60006020828403121561201957600080fd5b81518015158114610b6957600080fd5b6001600160a01b0393841681529190921660208201526001600160e01b0319909116604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60008161207b5761207b612056565b506000190190565b60006001820161209557612095612056565b5060010190565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156120c457600080fd5b81516001600160401b03808211156120db57600080fd5b818401915084601f8301126120ef57600080fd5b8151818111156121015761210161209c565b604051601f8201601f19908116603f011681019083821181831017156121295761212961209c565b8160405282815287602084870101111561214257600080fd5b612153836020830160208801611d0f565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b602080825260179082015276135a5b9d195c88185b1c9958591e48185c1c1c9bdd9959604a1b604082015260600190565b600060ff821660ff81036121bb576121bb612056565b60010192915050565b6000602082840312156121d657600080fd5b8151610b6981611c3d565b818103818111156105c5576105c5612056565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220d086cd837f4af5b72d1752ec2b8754222402401d43a56569df878a1e5335b0f964736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000fafda82cde1502c41e597e4656953533c16ca9940000000000000000000000002ee7b9bb2e038be7323a119701a191c030a61ec6
-----Decoded View---------------
Arg [0] : adminACLContract_ (address): 0xfaFda82CDe1502c41e597e4656953533c16ca994
Arg [1] : coreRegistry_ (address): 0x2eE7B9bB2E038bE7323A119701A191c030A61ec6
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000fafda82cde1502c41e597e4656953533c16ca994
Arg [1] : 0000000000000000000000002ee7b9bb2e038be7323a119701a191c030a61ec6
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.