Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 300 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Set Minter For P... | 23713628 | 4 days ago | IN | 0 ETH | 0.00028058 | ||||
| Set Minter For P... | 23672943 | 10 days ago | IN | 0 ETH | 0.00027503 | ||||
| Set Minter For P... | 23647738 | 13 days ago | IN | 0 ETH | 0.00027111 | ||||
| Set Minter For P... | 23647697 | 13 days ago | IN | 0 ETH | 0.00004627 | ||||
| Approve Minter F... | 23642528 | 14 days ago | IN | 0 ETH | 0.00025947 | ||||
| Set Minter For P... | 23613964 | 18 days ago | IN | 0 ETH | 0.00012021 | ||||
| Set Minter For P... | 23613957 | 18 days ago | IN | 0 ETH | 0.00021522 | ||||
| Set Minter For P... | 23597079 | 20 days ago | IN | 0 ETH | 0.00063918 | ||||
| Set Minter For P... | 23596980 | 20 days ago | IN | 0 ETH | 0.00020442 | ||||
| Set Minter For P... | 23574107 | 24 days ago | IN | 0 ETH | 0.00022007 | ||||
| Set Minter For P... | 23520413 | 31 days ago | IN | 0 ETH | 0.00025593 | ||||
| Set Minter For P... | 23515737 | 32 days ago | IN | 0 ETH | 0.00001779 | ||||
| Set Minter For P... | 23423648 | 45 days ago | IN | 0 ETH | 0.00014754 | ||||
| Set Minter For P... | 23377096 | 51 days ago | IN | 0 ETH | 0.00028287 | ||||
| Set Minter For P... | 23369401 | 52 days ago | IN | 0 ETH | 0.00049729 | ||||
| Set Minter For P... | 23364984 | 53 days ago | IN | 0 ETH | 0.00015045 | ||||
| Set Minter For P... | 23364164 | 53 days ago | IN | 0 ETH | 0.00014858 | ||||
| Set Minter For P... | 23364030 | 53 days ago | IN | 0 ETH | 0.00008508 | ||||
| Set Minter For P... | 23364001 | 53 days ago | IN | 0 ETH | 0.00008449 | ||||
| Set Minter For P... | 23363996 | 53 days ago | IN | 0 ETH | 0.00014745 | ||||
| Set Minter For P... | 23363822 | 53 days ago | IN | 0 ETH | 0.00014741 | ||||
| Set Minter For P... | 23361105 | 53 days ago | IN | 0 ETH | 0.00015194 | ||||
| Set Minter For P... | 23357336 | 54 days ago | IN | 0 ETH | 0.00002901 | ||||
| Set Minter For P... | 23347169 | 55 days ago | IN | 0 ETH | 0.00024514 | ||||
| Set Minter For P... | 23249708 | 69 days ago | IN | 0 ETH | 0.00005586 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
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
Contract ABI
API[{"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 | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.