Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 586 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Redeem | 16621781 | 567 days ago | IN | 0 ETH | 0.00408373 | ||||
Redeem | 16583327 | 573 days ago | IN | 0 ETH | 0.00385385 | ||||
Redeem | 16474317 | 588 days ago | IN | 0 ETH | 0.00208005 | ||||
Redeem | 16404478 | 597 days ago | IN | 0 ETH | 0.00258223 | ||||
Redeem | 15422460 | 737 days ago | IN | 0 ETH | 0.00231565 | ||||
Redeem | 15374783 | 745 days ago | IN | 0 ETH | 0.00065989 | ||||
Redeem | 15374095 | 745 days ago | IN | 0 ETH | 0.00155508 | ||||
Redeem | 15090802 | 789 days ago | IN | 0 ETH | 0.00545379 | ||||
Redeem | 14942178 | 815 days ago | IN | 0 ETH | 0.00180623 | ||||
Redeem | 14717882 | 851 days ago | IN | 0 ETH | 0.00681572 | ||||
Update Role | 14080252 | 951 days ago | IN | 0 ETH | 0.0054202 | ||||
Redeem | 13815017 | 992 days ago | IN | 0 ETH | 0.00696475 | ||||
Redeem | 13814696 | 992 days ago | IN | 0 ETH | 0.00628671 | ||||
Update Features | 13802358 | 994 days ago | IN | 0 ETH | 0.00248095 | ||||
Set Input Data R... | 13765313 | 999 days ago | IN | 0 ETH | 0.00283736 | ||||
Update Features | 13758021 | 1000 days ago | IN | 0 ETH | 0.00274841 | ||||
Redeem | 13757797 | 1001 days ago | IN | 0 ETH | 0.0076751 | ||||
Set Input Data R... | 13735612 | 1004 days ago | IN | 0 ETH | 0.00351461 | ||||
Redeem | 13689495 | 1011 days ago | IN | 0 ETH | 0.01432148 | ||||
Redeem | 13684363 | 1012 days ago | IN | 0 ETH | 0.01371924 | ||||
Redeem | 13656050 | 1017 days ago | IN | 0 ETH | 0.0021597 | ||||
Redeem | 13645179 | 1018 days ago | IN | 0 ETH | 0.00827046 | ||||
Redeem | 13643135 | 1019 days ago | IN | 0 ETH | 0.01447184 | ||||
Redeem | 13640697 | 1019 days ago | IN | 0 ETH | 0.00594747 | ||||
Redeem | 13640656 | 1019 days ago | IN | 0 ETH | 0.02194075 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
PersonalityDrop
Compiler Version
v0.8.7+commit.e28d00a7
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.7; import "../interfaces/ERC721Spec.sol"; import "../interfaces/AletheaERC721Spec.sol"; import "../utils/AccessControl.sol"; import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; /** * @title Personality Pod Airdrop * * @notice During the release 2.0 distribution event of 10,000 personality pods, * it became clear there is a need to distribute around 10% for free, as an Airdrop. * * @notice PersonalityDrop contract introduces a scalable mechanism to mint NFTs to an arbitrary * amount of addresses by leveraging the power of Merkle trees to "compress" minting data. * * @notice The input data is an array of (address, tokenId) pairs; Merkle tree is built out * from this array, and the tree root is stored on the contract by its data manager. * When minting (address, tokenId), executor specifies also the Merkle proof for an * element (address, tokenId) to mint. */ contract PersonalityDrop is AccessControl { // Use Zeppelin MerkleProof Library to verify Merkle proofs using MerkleProof for bytes32[]; /** * @notice Input data root, Merkle tree root for an array of (address, tokenId) pairs, * available for minting * * @notice Merkle root effectively "compresses" the (potentially) huge array of data elements * and allows to store it in a single 256-bits storage slot on-chain */ bytes32 public root; /** * @dev Mintable ERC721 contract address to mint tokens of */ address public immutable targetContract; /** * @notice Enables the airdrop, redeeming the tokens * * @dev Feature FEATURE_REDEEM_ACTIVE must be enabled in order for * `mint()` function to succeed */ uint32 public constant FEATURE_REDEEM_ACTIVE = 0x0000_0001; /** * @notice Data manager is responsible for supplying the valid input data array * Merkle root which then can be used to mint tokens, meaning effectively, * that data manager may act as a minter on the target NFT contract * * @dev Role ROLE_DATA_MANAGER allows setting the Merkle tree root via setInputDataRoot() */ uint32 public constant ROLE_DATA_MANAGER = 0x0001_0000; /** * @dev Fired in setInputDataRoot() * * @param _by an address which executed the operation * @param _root new Merkle root value */ event RootChanged(address indexed _by, bytes32 _root); /** * @dev Fired in redeem() * * @param _by an address which executed the operation * @param _to an address the token was minted to * @param _tokenId token ID minted * @param _proof Merkle proof for the (_to, _tokenId) pair */ event Redeemed(address indexed _by, address indexed _to, uint256 indexed _tokenId, bytes32[] _proof); /** * @dev Creates/deploys PersonalityDrop and binds it to AI Personality smart contract on construction * * @param _target deployed Mintable ERC721 smart contract; contract will mint NFTs of that type */ constructor(address _target) { // verify the input is set require(_target != address(0), "target contract is not set"); // verify the input is valid smart contract of the expected interfaces require( ERC165(_target).supportsInterface(type(ERC721).interfaceId) && ERC165(_target).supportsInterface(type(MintableERC721).interfaceId), "unexpected target type" ); // assign the address targetContract = _target; } /** * @notice Restricted access function to update input data root (Merkle tree root), * and to define, effectively, the tokens to be created by this smart contract * * @dev Requires executor to have `ROLE_DATA_MANAGER` permission * * @param _root Merkle tree root for the input data array */ function setInputDataRoot(bytes32 _root) public { // verify the access permission require(isSenderInRole(ROLE_DATA_MANAGER), "access denied"); // update input data Merkle tree root root = _root; // emit an event emit RootChanged(msg.sender, _root); } /** * @notice Verifies the validity of a `(_to, _tokenId)` pair supplied based on the Merkle root * of the entire `(_to, _tokenId)` data array (pre-stored in the contract), and the Merkle * proof `_proof` for the particular `(_to, _tokenId)` pair supplied * * @dev Merkle tree and proof can be constructed using the `web3-utils`, `merkletreejs`, * and `keccak256` npm packages: * 1. Hash the original array data elements (_to, _tokenId) via `web3.utils.soliditySha3`, * making sure the packing order and types are exactly as in `mint()` signature * 2. Create a sorted MerkleTree (`merkletreejs`) from the hashed array, use `keccak256` * from the `keccak256` npm package as a hashing function, do not hash leaves * (already hashed in step 1); Ex. MerkleTree options: {hashLeaves: false, sortPairs: true} * 3. For any given data element (_to, _tokenId) the proof is constructed by hashing it * (as in step 1) and querying the MerkleTree for a proof, providing the hashed element * as a leaf * * @param _to an address to mint token to * @param _tokenId token ID to mint * @param _proof Merkle proof for the (_to, _tokenId) pair supplied * @return true if Merkle proof is valid (data belongs to the original array), false otherwise */ function isTokenValid(address _to, uint256 _tokenId, bytes32[] memory _proof) public view returns(bool) { // construct Merkle tree leaf from the inputs supplied bytes32 leaf = keccak256(abi.encodePacked(_to, _tokenId)); // verify the proof supplied, and return the verification result return _proof.verify(root, leaf); } /** * @notice Mints token `_tokenId` to an address `_to`, verifying the validity * of a `(_to, _tokenId)` pair via the Merkle proof `_proof` * * @dev Merkle tree and proof can be constructed using the `web3-utils`, `merkletreejs`, * and `keccak256` npm packages: * 1. Hash the original array data elements (_to, _tokenId) via `web3.utils.soliditySha3`, * making sure the packing order and types are exactly as in `mint()` signature * 2. Create a sorted MerkleTree (`merkletreejs`) from the hashed array, use `keccak256` * from the `keccak256` npm package as a hashing function, do not hash leaves * (already hashed in step 1); Ex. MerkleTree options: {hashLeaves: false, sortPairs: true} * 3. For any given data element (_to, _tokenId) the proof is constructed by hashing it * (as in step 1) and querying the MerkleTree for a proof, providing the hashed element * as a leaf * * @dev Throws is the data or merkle proof supplied is not valid * * @param _to an address to mint token to * @param _tokenId token ID to mint * @param _proof Merkle proof for the (_to, _tokenId) pair supplied */ function redeem(address _to, uint256 _tokenId, bytes32[] memory _proof) public { // verify airdrop is in active state require(isFeatureEnabled(FEATURE_REDEEM_ACTIVE), "redeems are disabled"); // verify the `(_to, _tokenId)` pair is valid require(isTokenValid(_to, _tokenId, _proof), "invalid token"); // mint the token MintableERC721(targetContract).safeMint(_to, _tokenId); // emit an event emit Redeemed(msg.sender, _to, _tokenId, _proof); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.7; import "./ERC165Spec.sol"; /** * @title ERC-721 Non-Fungible Token Standard * * @notice See https://eips.ethereum.org/EIPS/eip-721 * * @dev Solidity issue #3412: The ERC721 interfaces include explicit mutability guarantees for each function. * Mutability guarantees are, in order weak to strong: payable, implicit nonpayable, view, and pure. * Implementation MUST meet the mutability guarantee in this interface and MAY meet a stronger guarantee. * For example, a payable function in this interface may be implemented as nonpayable * (no state mutability specified) in implementing contract. * It is expected a later Solidity release will allow stricter contract to inherit from this interface, * but current workaround is that we edit this interface to add stricter mutability before inheriting: * we have removed all "payable" modifiers. * * @dev The ERC-165 identifier for this interface is 0x80ac58cd. * * @author William Entriken, Dieter Shirley, Jacob Evans, Nastassia Sachs */ interface ERC721 is ERC165 { /// @dev This emits when ownership of any NFT changes by any mechanism. /// This event emits when NFTs are created (`from` == 0) and destroyed /// (`to` == 0). Exception: during contract creation, any number of NFTs /// may be created and assigned without emitting Transfer. At the time of /// any transfer, the approved address for that NFT (if any) is reset to none. event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); /// @dev This emits when the approved address for an NFT is changed or /// reaffirmed. The zero address indicates there is no approved address. /// When a Transfer event emits, this also indicates that the approved /// address for that NFT (if any) is reset to none. event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); /// @dev This emits when an operator is enabled or disabled for an owner. /// The operator can manage all NFTs of the owner. event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); /// @notice Count all NFTs assigned to an owner /// @dev NFTs assigned to the zero address are considered invalid, and this /// function throws for queries about the zero address. /// @param _owner An address for whom to query the balance /// @return The number of NFTs owned by `_owner`, possibly zero function balanceOf(address _owner) external view returns (uint256); /// @notice Find the owner of an NFT /// @dev NFTs assigned to zero address are considered invalid, and queries /// about them do throw. /// @param _tokenId The identifier for an NFT /// @return The address of the owner of the NFT function ownerOf(uint256 _tokenId) external view returns (address); /// @notice Transfers the ownership of an NFT from one address to another address /// @dev Throws unless `msg.sender` is the current owner, an authorized /// operator, or the approved address for this NFT. Throws if `_from` is /// not the current owner. Throws if `_to` is the zero address. Throws if /// `_tokenId` is not a valid NFT. When transfer is complete, this function /// checks if `_to` is a smart contract (code size > 0). If so, it calls /// `onERC721Received` on `_to` and throws if the return value is not /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. /// @param _from The current owner of the NFT /// @param _to The new owner /// @param _tokenId The NFT to transfer /// @param _data Additional data with no specified format, sent in call to `_to` function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata _data) external /*payable*/; /// @notice Transfers the ownership of an NFT from one address to another address /// @dev This works identically to the other function with an extra data parameter, /// except this function just sets data to "". /// @param _from The current owner of the NFT /// @param _to The new owner /// @param _tokenId The NFT to transfer function safeTransferFrom(address _from, address _to, uint256 _tokenId) external /*payable*/; /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE /// THEY MAY BE PERMANENTLY LOST /// @dev Throws unless `msg.sender` is the current owner, an authorized /// operator, or the approved address for this NFT. Throws if `_from` is /// not the current owner. Throws if `_to` is the zero address. Throws if /// `_tokenId` is not a valid NFT. /// @param _from The current owner of the NFT /// @param _to The new owner /// @param _tokenId The NFT to transfer function transferFrom(address _from, address _to, uint256 _tokenId) external /*payable*/; /// @notice Change or reaffirm the approved address for an NFT /// @dev The zero address indicates there is no approved address. /// Throws unless `msg.sender` is the current NFT owner, or an authorized /// operator of the current owner. /// @param _approved The new approved NFT controller /// @param _tokenId The NFT to approve function approve(address _approved, uint256 _tokenId) external /*payable*/; /// @notice Enable or disable approval for a third party ("operator") to manage /// all of `msg.sender`'s assets /// @dev Emits the ApprovalForAll event. The contract MUST allow /// multiple operators per owner. /// @param _operator Address to add to the set of authorized operators /// @param _approved True if the operator is approved, false to revoke approval function setApprovalForAll(address _operator, bool _approved) external; /// @notice Get the approved address for a single NFT /// @dev Throws if `_tokenId` is not a valid NFT. /// @param _tokenId The NFT to find the approved address for /// @return The approved address for this NFT, or the zero address if there is none function getApproved(uint256 _tokenId) external view returns (address); /// @notice Query if an address is an authorized operator for another address /// @param _owner The address that owns the NFTs /// @param _operator The address that acts on behalf of the owner /// @return True if `_operator` is an approved operator for `_owner`, false otherwise function isApprovedForAll(address _owner, address _operator) external view returns (bool); } /// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02. interface ERC721TokenReceiver { /// @notice Handle the receipt of an NFT /// @dev The ERC721 smart contract calls this function on the recipient /// after a `transfer`. This function MAY throw to revert and reject the /// transfer. Return of other than the magic value MUST result in the /// transaction being reverted. /// Note: the contract address is always the message sender. /// @param _operator The address which called `safeTransferFrom` function /// @param _from The address which previously owned the token /// @param _tokenId The NFT identifier which is being transferred /// @param _data Additional data with no specified format /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` /// unless throwing function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) external returns(bytes4); } /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * * @notice See https://eips.ethereum.org/EIPS/eip-721 * * @dev The ERC-165 identifier for this interface is 0x5b5e139f. * * @author William Entriken, Dieter Shirley, Jacob Evans, Nastassia Sachs */ interface ERC721Metadata is ERC721 { /// @notice A descriptive name for a collection of NFTs in this contract function name() external view returns (string memory _name); /// @notice An abbreviated name for NFTs in this contract function symbol() external view returns (string memory _symbol); /// @notice A distinct Uniform Resource Identifier (URI) for a given asset. /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC /// 3986. The URI may point to a JSON file that conforms to the "ERC721 /// Metadata JSON Schema". function tokenURI(uint256 _tokenId) external view returns (string memory); } /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * * @notice See https://eips.ethereum.org/EIPS/eip-721 * * @dev The ERC-165 identifier for this interface is 0x780e9d63. * * @author William Entriken, Dieter Shirley, Jacob Evans, Nastassia Sachs */ interface ERC721Enumerable is ERC721 { /// @notice Count NFTs tracked by this contract /// @return A count of valid NFTs tracked by this contract, where each one of /// them has an assigned and queryable owner not equal to the zero address function totalSupply() external view returns (uint256); /// @notice Enumerate valid NFTs /// @dev Throws if `_index` >= `totalSupply()`. /// @param _index A counter less than `totalSupply()` /// @return The token identifier for the `_index`th NFT, /// (sort order not specified) function tokenByIndex(uint256 _index) external view returns (uint256); /// @notice Enumerate NFTs assigned to an owner /// @dev Throws if `_index` >= `balanceOf(_owner)` or if /// `_owner` is the zero address, representing invalid NFTs. /// @param _owner An address where we are interested in NFTs owned by them /// @param _index A counter less than `balanceOf(_owner)` /// @return The token identifier for the `_index`th NFT assigned to `_owner`, /// (sort order not specified) function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.7; /** * @title Alethea Mintable ERC721 * * @notice Defines mint capabilities for Alethea ERC721 tokens. * This interface should be treated as a definition of what mintable means for ERC721 */ interface MintableERC721 { /** * @notice Checks if specified token exists * * @dev Returns whether the specified token ID has an ownership * information associated with it * * @param _tokenId ID of the token to query existence for * @return whether the token exists (true - exists, false - doesn't exist) */ function exists(uint256 _tokenId) external view returns(bool); /** * @dev Creates new token with token ID specified * and assigns an ownership `_to` for this token * * @dev Unsafe: doesn't execute `onERC721Received` on the receiver. * Prefer the use of `saveMint` instead of `mint`. * * @dev Should have a restricted access handled by the implementation * * @param _to an address to mint token to * @param _tokenId ID of the token to mint */ function mint(address _to, uint256 _tokenId) external; /** * @dev Creates new tokens starting with token ID specified * and assigns an ownership `_to` for these tokens * * @dev Token IDs to be minted: [_tokenId, _tokenId + n) * * @dev n must be greater or equal 2: `n > 1` * * @dev Unsafe: doesn't execute `onERC721Received` on the receiver. * Prefer the use of `saveMintBatch` instead of `mintBatch`. * * @dev Should have a restricted access handled by the implementation * * @param _to an address to mint tokens to * @param _tokenId ID of the first token to mint * @param n how many tokens to mint, sequentially increasing the _tokenId */ function mintBatch(address _to, uint256 _tokenId, uint256 n) external; /** * @dev Creates new token with token ID specified * and assigns an ownership `_to` for this token * * @dev Checks if `_to` is a smart contract (code size > 0). If so, it calls * `onERC721Received` on `_to` and throws if the return value is not * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. * * @dev Should have a restricted access handled by the implementation * * @param _to an address to mint token to * @param _tokenId ID of the token to mint */ function safeMint(address _to, uint256 _tokenId) external; /** * @dev Creates new token with token ID specified * and assigns an ownership `_to` for this token * * @dev Checks if `_to` is a smart contract (code size > 0). If so, it calls * `onERC721Received` on `_to` and throws if the return value is not * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. * * @dev Should have a restricted access handled by the implementation * * @param _to an address to mint token to * @param _tokenId ID of the token to mint * @param _data additional data with no specified format, sent in call to `_to` */ function safeMint(address _to, uint256 _tokenId, bytes memory _data) external; /** * @dev Creates new tokens starting with token ID specified * and assigns an ownership `_to` for these tokens * * @dev Token IDs to be minted: [_tokenId, _tokenId + n) * * @dev n must be greater or equal 2: `n > 1` * * @dev Checks if `_to` is a smart contract (code size > 0). If so, it calls * `onERC721Received` on `_to` and throws if the return value is not * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. * * @dev Should have a restricted access handled by the implementation * * @param _to an address to mint token to * @param _tokenId ID of the token to mint * @param n how many tokens to mint, sequentially increasing the _tokenId */ function safeMintBatch(address _to, uint256 _tokenId, uint256 n) external; /** * @dev Creates new tokens starting with token ID specified * and assigns an ownership `_to` for these tokens * * @dev Token IDs to be minted: [_tokenId, _tokenId + n) * * @dev n must be greater or equal 2: `n > 1` * * @dev Checks if `_to` is a smart contract (code size > 0). If so, it calls * `onERC721Received` on `_to` and throws if the return value is not * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. * * @dev Should have a restricted access handled by the implementation * * @param _to an address to mint token to * @param _tokenId ID of the token to mint * @param n how many tokens to mint, sequentially increasing the _tokenId * @param _data additional data with no specified format, sent in call to `_to` */ function safeMintBatch(address _to, uint256 _tokenId, uint256 n, bytes memory _data) external; } /** * @title Alethea Burnable ERC721 * * @notice Defines burn capabilities for Alethea ERC721 tokens. * This interface should be treated as a definition of what burnable means for ERC721 */ interface BurnableERC721 { /** * @notice Destroys the token with token ID specified * * @dev Should be accessible publicly by token owners. * May have a restricted access handled by the implementation * * @param _tokenId ID of the token to burn */ function burn(uint256 _tokenId) external; } /** * @title With Base URI * * @notice A marker interface for the contracts having the baseURI() function * or public string variable named baseURI * NFT implementations like TinyERC721, or ShortERC721 are example of such smart contracts */ interface WithBaseURI { /** * @dev Usually used in NFT implementations to construct ERC721Metadata.tokenURI as * `base URI + token ID` if token URI is not set (not present in `_tokenURIs` mapping) * * @dev For example, if base URI is https://api.com/token/, then token #1 * will have an URI https://api.com/token/1 */ function baseURI() external view returns(string memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.7; /** * @title Access Control List * * @notice Access control smart contract provides an API to check * if specific operation is permitted globally and/or * if particular user has a permission to execute it. * * @notice It deals with two main entities: features and roles. * * @notice Features are designed to be used to enable/disable specific * functions (public functions) of the smart contract for everyone. * @notice User roles are designed to restrict access to specific * functions (restricted functions) of the smart contract to some users. * * @notice Terms "role", "permissions" and "set of permissions" have equal meaning * in the documentation text and may be used interchangeably. * @notice Terms "permission", "single permission" implies only one permission bit set. * * @notice Access manager is a special role which allows to grant/revoke other roles. * Access managers can only grant/revoke permissions which they have themselves. * As an example, access manager with no other roles set can only grant/revoke its own * access manager permission and nothing else. * * @notice Access manager permission should be treated carefully, as a super admin permission: * Access manager with even no other permission can interfere with another account by * granting own access manager permission to it and effectively creating more powerful * permission set than its own. * * @dev Both current and OpenZeppelin AccessControl implementations feature a similar API * to check/know "who is allowed to do this thing". * @dev Zeppelin implementation is more flexible: * - it allows setting unlimited number of roles, while current is limited to 256 different roles * - it allows setting an admin for each role, while current allows having only one global admin * @dev Current implementation is more lightweight: * - it uses only 1 bit per role, while Zeppelin uses 256 bits * - it allows setting up to 256 roles at once, in a single transaction, while Zeppelin allows * setting only one role in a single transaction * * @dev This smart contract is designed to be inherited by other * smart contracts which require access control management capabilities. * * @dev Access manager permission has a bit 255 set. * This bit must not be used by inheriting contracts for any other permissions/features. */ contract AccessControl { /** * @notice Access manager is responsible for assigning the roles to users, * enabling/disabling global features of the smart contract * @notice Access manager can add, remove and update user roles, * remove and update global features * * @dev Role ROLE_ACCESS_MANAGER allows modifying user roles and global features * @dev Role ROLE_ACCESS_MANAGER has single bit at position 255 enabled */ uint256 public constant ROLE_ACCESS_MANAGER = 0x8000000000000000000000000000000000000000000000000000000000000000; /** * @dev Bitmask representing all the possible permissions (super admin role) * @dev Has all the bits are enabled (2^256 - 1 value) */ uint256 private constant FULL_PRIVILEGES_MASK = type(uint256).max; // before 0.8.0: uint256(-1) overflows to 0xFFFF... /** * @notice Privileged addresses with defined roles/permissions * @notice In the context of ERC20/ERC721 tokens these can be permissions to * allow minting or burning tokens, transferring on behalf and so on * * @dev Maps user address to the permissions bitmask (role), where each bit * represents a permission * @dev Bitmask 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF * represents all possible permissions * @dev 'This' address mapping represents global features of the smart contract */ mapping(address => uint256) public userRoles; /** * @dev Fired in updateRole() and updateFeatures() * * @param _by operator which called the function * @param _to address which was granted/revoked permissions * @param _requested permissions requested * @param _actual permissions effectively set */ event RoleUpdated(address indexed _by, address indexed _to, uint256 _requested, uint256 _actual); /** * @notice Creates an access control instance, * setting contract creator to have full privileges */ constructor() { // contract creator has full privileges userRoles[msg.sender] = FULL_PRIVILEGES_MASK; } /** * @notice Retrieves globally set of features enabled * * @dev Effectively reads userRoles role for the contract itself * * @return 256-bit bitmask of the features enabled */ function features() public view returns(uint256) { // features are stored in 'this' address mapping of `userRoles` structure return userRoles[address(this)]; } /** * @notice Updates set of the globally enabled features (`features`), * taking into account sender's permissions * * @dev Requires transaction sender to have `ROLE_ACCESS_MANAGER` permission * @dev Function is left for backward compatibility with older versions * * @param _mask bitmask representing a set of features to enable/disable */ function updateFeatures(uint256 _mask) public { // delegate call to `updateRole` updateRole(address(this), _mask); } /** * @notice Updates set of permissions (role) for a given user, * taking into account sender's permissions. * * @dev Setting role to zero is equivalent to removing an all permissions * @dev Setting role to `FULL_PRIVILEGES_MASK` is equivalent to * copying senders' permissions (role) to the user * @dev Requires transaction sender to have `ROLE_ACCESS_MANAGER` permission * * @param operator address of a user to alter permissions for or zero * to alter global features of the smart contract * @param role bitmask representing a set of permissions to * enable/disable for a user specified */ function updateRole(address operator, uint256 role) public { // caller must have a permission to update user roles require(isSenderInRole(ROLE_ACCESS_MANAGER), "access denied"); // evaluate the role and reassign it userRoles[operator] = evaluateBy(msg.sender, userRoles[operator], role); // fire an event emit RoleUpdated(msg.sender, operator, role, userRoles[operator]); } /** * @notice Determines the permission bitmask an operator can set on the * target permission set * @notice Used to calculate the permission bitmask to be set when requested * in `updateRole` and `updateFeatures` functions * * @dev Calculated based on: * 1) operator's own permission set read from userRoles[operator] * 2) target permission set - what is already set on the target * 3) desired permission set - what do we want set target to * * @dev Corner cases: * 1) Operator is super admin and its permission set is `FULL_PRIVILEGES_MASK`: * `desired` bitset is returned regardless of the `target` permission set value * (what operator sets is what they get) * 2) Operator with no permissions (zero bitset): * `target` bitset is returned regardless of the `desired` value * (operator has no authority and cannot modify anything) * * @dev Example: * Consider an operator with the permissions bitmask 00001111 * is about to modify the target permission set 01010101 * Operator wants to set that permission set to 00110011 * Based on their role, an operator has the permissions * to update only lowest 4 bits on the target, meaning that * high 4 bits of the target set in this example is left * unchanged and low 4 bits get changed as desired: 01010011 * * @param operator address of the contract operator which is about to set the permissions * @param target input set of permissions to operator is going to modify * @param desired desired set of permissions operator would like to set * @return resulting set of permissions given operator will set */ function evaluateBy(address operator, uint256 target, uint256 desired) public view returns(uint256) { // read operator's permissions uint256 p = userRoles[operator]; // taking into account operator's permissions, // 1) enable the permissions desired on the `target` target |= p & desired; // 2) disable the permissions desired on the `target` target &= FULL_PRIVILEGES_MASK ^ (p & (FULL_PRIVILEGES_MASK ^ desired)); // return calculated result return target; } /** * @notice Checks if requested set of features is enabled globally on the contract * * @param required set of features to check against * @return true if all the features requested are enabled, false otherwise */ function isFeatureEnabled(uint256 required) public view returns(bool) { // delegate call to `__hasRole`, passing `features` property return __hasRole(features(), required); } /** * @notice Checks if transaction sender `msg.sender` has all the permissions required * * @param required set of permissions (role) to check against * @return true if all the permissions requested are enabled, false otherwise */ function isSenderInRole(uint256 required) public view returns(bool) { // delegate call to `isOperatorInRole`, passing transaction sender return isOperatorInRole(msg.sender, required); } /** * @notice Checks if operator has all the permissions (role) required * * @param operator address of the user to check role for * @param required set of permissions (role) to check * @return true if all the permissions requested are enabled, false otherwise */ function isOperatorInRole(address operator, uint256 required) public view returns(bool) { // delegate call to `__hasRole`, passing operator's permissions (role) return __hasRole(userRoles[operator], required); } /** * @dev Checks if role `actual` contains all the permissions required `required` * * @param actual existent role * @param required required role * @return true if actual has required role (all permissions), false otherwise */ function __hasRole(uint256 actual, uint256 required) internal pure returns(bool) { // check the bitmask for the role required and return the result return actual & required == required; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Trees proofs. * * The proofs can be generated using the JavaScript library * https://github.com/miguelmota/merkletreejs[merkletreejs]. * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled. * * See `test/utils/cryptography/MerkleProof.test.js` for some examples. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { bytes32 proofElement = proof[i]; if (computedHash <= proofElement) { // Hash(current computed hash + current element of the proof) computedHash = keccak256(abi.encodePacked(computedHash, proofElement)); } else { // Hash(current element of the proof + current computed hash) computedHash = keccak256(abi.encodePacked(proofElement, computedHash)); } } // Check if the computed hash (root) is equal to the provided root return computedHash == root; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.7; /** * @title ERC-165 Standard Interface Detection * * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * @dev Implementers can declare support of contract interfaces, * which can then be queried by others. * * @author Christian Reitwießner, Nick Johnson, Fabian Vogelsteller, Jordi Baylina, Konrad Feldmeier, William Entriken */ interface ERC165 { /** * @notice Query if a contract implements an interface * * @dev Interface identification is specified in ERC-165. * This function uses less than 30,000 gas. * * @param interfaceID The interface identifier, as specified in ERC-165 * @return `true` if the contract implements `interfaceID` and * `interfaceID` is not 0xffffffff, `false` otherwise */ function supportsInterface(bytes4 interfaceID) external view returns (bool); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_target","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"Redeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_requested","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_actual","type":"uint256"}],"name":"RoleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":false,"internalType":"bytes32","name":"_root","type":"bytes32"}],"name":"RootChanged","type":"event"},{"inputs":[],"name":"FEATURE_REDEEM_ACTIVE","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_ACCESS_MANAGER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_DATA_MANAGER","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"target","type":"uint256"},{"internalType":"uint256","name":"desired","type":"uint256"}],"name":"evaluateBy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"features","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"required","type":"uint256"}],"name":"isFeatureEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"isOperatorInRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"required","type":"uint256"}],"name":"isSenderInRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"isTokenValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"root","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_root","type":"bytes32"}],"name":"setInputDataRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"targetContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mask","type":"uint256"}],"name":"updateFeatures","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"role","type":"uint256"}],"name":"updateRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRoles","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a060405234801561001057600080fd5b50604051610ba7380380610ba783398101604081905261002f91610202565b33600090815260208190526040902060001990556001600160a01b03811661009e5760405162461bcd60e51b815260206004820152601a60248201527f74617267657420636f6e7472616374206973206e6f742073657400000000000060448201526064015b60405180910390fd5b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526001600160a01b038216906301ffc9a79060240160206040518083038186803b1580156100e457600080fd5b505afa1580156100f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061011c9190610232565b80156101a157506040516301ffc9a760e01b8152633197b5d160e21b60048201526001600160a01b038216906301ffc9a79060240160206040518083038186803b15801561016957600080fd5b505afa15801561017d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101a19190610232565b6101ed5760405162461bcd60e51b815260206004820152601660248201527f756e6578706563746564207461726765742074797065000000000000000000006044820152606401610095565b60601b6001600160601b031916608052610254565b60006020828403121561021457600080fd5b81516001600160a01b038116811461022b57600080fd5b9392505050565b60006020828403121561024457600080fd5b8151801515811461022b57600080fd5b60805160601c61092e610279600039600081816101e7015261033f015261092e6000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c8063ae682e2e11610097578063e889889311610066578063e889889314610247578063ebf0c71714610251578063f822d5aa1461025a578063fcc2c0781461026d57600080fd5b8063ae682e2e146101d7578063bd90df70146101e2578063c688d69314610221578063d5bb7f671461023457600080fd5b80636fe41ee4116100d35780636fe41ee414610174578063725f36261461019157806374d5e100146101a4578063ae5b102e146101c457600080fd5b806314132f4814610105578063275efe1a1461011a5780632b521416146101425780636f8a751314610161575b600080fd5b610118610113366004610732565b610280565b005b61012d610128366004610732565b6103ec565b60405190151581526020015b60405180910390f35b306000908152602081905260409020545b604051908152602001610139565b61011861016f366004610846565b61044f565b61017c600181565b60405163ffffffff9091168152602001610139565b61012d61019f366004610846565b6104d4565b6101536101b23660046106ed565b60006020819052908152604090205481565b6101186101d2366004610708565b6104ef565b610153600160ff1b81565b6102097f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610139565b61012d61022f366004610708565b6105b9565b610118610242366004610846565b6105de565b61017c6201000081565b61015360015481565b610153610268366004610813565b6105eb565b61012d61027b366004610846565b610616565b61028a60016104d4565b6102d25760405162461bcd60e51b81526020600482015260146024820152731c995919595b5cc8185c9948191a5cd8589b195960621b60448201526064015b60405180910390fd5b6102dd8383836103ec565b6103195760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b2103a37b5b2b760991b60448201526064016102c9565b604051632851206560e21b81526001600160a01b038481166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a144819490604401600060405180830381600087803b15801561038357600080fd5b505af1158015610397573d6000803e3d6000fd5b5050505081836001600160a01b0316336001600160a01b03167f04cbe77933f1e0f8a0430d3275c961a84ee4a6900a4018f222eb842119f85237846040516103df919061085f565b60405180910390a4505050565b6040516bffffffffffffffffffffffff19606085901b16602082015260348101839052600090819060540160405160208183030381529060405280519060200120905061044660015482856106229092919063ffffffff16565b95945050505050565b61045b62010000610616565b6104975760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b60448201526064016102c9565b600181905560405181815233907f714dceb37ab5c7fb26ab805d3dc0423f5d90c3dac9f6702a2ea1402ea847851c9060200160405180910390a250565b30600090815260208190526040812054821682145b92915050565b6104fc600160ff1b610616565b6105385760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b60448201526064016102c9565b6001600160a01b03821660009081526020819052604090205461055d903390836105eb565b6001600160a01b03831660008181526020818152604091829020849055815185815290810193909352909133917f5a10526456f5116c0b7b80582c217d666243fd51b6a2d92c8011e601c2462e5f910160405180910390a35050565b6001600160a01b038216600090815260208190526040812054821682145b9392505050565b6105e830826104ef565b50565b6001600160a01b03929092166000908152602081905260409020546000198084188216189216171690565b60006104e933836105b9565b600081815b85518110156106c6576000868281518110610644576106446108cc565b602002602001015190508083116106865760408051602081018590529081018290526060016040516020818303038152906040528051906020012092506106b3565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b50806106be816108a3565b915050610627565b509092149392505050565b80356001600160a01b03811681146106e857600080fd5b919050565b6000602082840312156106ff57600080fd5b6105d7826106d1565b6000806040838503121561071b57600080fd5b610724836106d1565b946020939093013593505050565b60008060006060848603121561074757600080fd5b610750846106d1565b92506020808501359250604085013567ffffffffffffffff8082111561077557600080fd5b818701915087601f83011261078957600080fd5b81358181111561079b5761079b6108e2565b8060051b604051601f19603f830116810181811085821117156107c0576107c06108e2565b604052828152858101935084860182860187018c10156107df57600080fd5b600095505b838610156108025780358552600195909501949386019386016107e4565b508096505050505050509250925092565b60008060006060848603121561082857600080fd5b610831846106d1565b95602085013595506040909401359392505050565b60006020828403121561085857600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156108975783518352928401929184019160010161087b565b50909695505050505050565b60006000198214156108c557634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220fa66486709bf7164129bbfbeb1ea07f48117217ab0d3862268fbf8ac027fc06f64736f6c63430008070033000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101005760003560e01c8063ae682e2e11610097578063e889889311610066578063e889889314610247578063ebf0c71714610251578063f822d5aa1461025a578063fcc2c0781461026d57600080fd5b8063ae682e2e146101d7578063bd90df70146101e2578063c688d69314610221578063d5bb7f671461023457600080fd5b80636fe41ee4116100d35780636fe41ee414610174578063725f36261461019157806374d5e100146101a4578063ae5b102e146101c457600080fd5b806314132f4814610105578063275efe1a1461011a5780632b521416146101425780636f8a751314610161575b600080fd5b610118610113366004610732565b610280565b005b61012d610128366004610732565b6103ec565b60405190151581526020015b60405180910390f35b306000908152602081905260409020545b604051908152602001610139565b61011861016f366004610846565b61044f565b61017c600181565b60405163ffffffff9091168152602001610139565b61012d61019f366004610846565b6104d4565b6101536101b23660046106ed565b60006020819052908152604090205481565b6101186101d2366004610708565b6104ef565b610153600160ff1b81565b6102097f000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c81565b6040516001600160a01b039091168152602001610139565b61012d61022f366004610708565b6105b9565b610118610242366004610846565b6105de565b61017c6201000081565b61015360015481565b610153610268366004610813565b6105eb565b61012d61027b366004610846565b610616565b61028a60016104d4565b6102d25760405162461bcd60e51b81526020600482015260146024820152731c995919595b5cc8185c9948191a5cd8589b195960621b60448201526064015b60405180910390fd5b6102dd8383836103ec565b6103195760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b2103a37b5b2b760991b60448201526064016102c9565b604051632851206560e21b81526001600160a01b038481166004830152602482018490527f000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c169063a144819490604401600060405180830381600087803b15801561038357600080fd5b505af1158015610397573d6000803e3d6000fd5b5050505081836001600160a01b0316336001600160a01b03167f04cbe77933f1e0f8a0430d3275c961a84ee4a6900a4018f222eb842119f85237846040516103df919061085f565b60405180910390a4505050565b6040516bffffffffffffffffffffffff19606085901b16602082015260348101839052600090819060540160405160208183030381529060405280519060200120905061044660015482856106229092919063ffffffff16565b95945050505050565b61045b62010000610616565b6104975760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b60448201526064016102c9565b600181905560405181815233907f714dceb37ab5c7fb26ab805d3dc0423f5d90c3dac9f6702a2ea1402ea847851c9060200160405180910390a250565b30600090815260208190526040812054821682145b92915050565b6104fc600160ff1b610616565b6105385760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b60448201526064016102c9565b6001600160a01b03821660009081526020819052604090205461055d903390836105eb565b6001600160a01b03831660008181526020818152604091829020849055815185815290810193909352909133917f5a10526456f5116c0b7b80582c217d666243fd51b6a2d92c8011e601c2462e5f910160405180910390a35050565b6001600160a01b038216600090815260208190526040812054821682145b9392505050565b6105e830826104ef565b50565b6001600160a01b03929092166000908152602081905260409020546000198084188216189216171690565b60006104e933836105b9565b600081815b85518110156106c6576000868281518110610644576106446108cc565b602002602001015190508083116106865760408051602081018590529081018290526060016040516020818303038152906040528051906020012092506106b3565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b50806106be816108a3565b915050610627565b509092149392505050565b80356001600160a01b03811681146106e857600080fd5b919050565b6000602082840312156106ff57600080fd5b6105d7826106d1565b6000806040838503121561071b57600080fd5b610724836106d1565b946020939093013593505050565b60008060006060848603121561074757600080fd5b610750846106d1565b92506020808501359250604085013567ffffffffffffffff8082111561077557600080fd5b818701915087601f83011261078957600080fd5b81358181111561079b5761079b6108e2565b8060051b604051601f19603f830116810181811085821117156107c0576107c06108e2565b604052828152858101935084860182860187018c10156107df57600080fd5b600095505b838610156108025780358552600195909501949386019386016107e4565b508096505050505050509250925092565b60008060006060848603121561082857600080fd5b610831846106d1565b95602085013595506040909401359392505050565b60006020828403121561085857600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156108975783518352928401929184019160010161087b565b50909695505050505050565b60006000198214156108c557634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220fa66486709bf7164129bbfbeb1ea07f48117217ab0d3862268fbf8ac027fc06f64736f6c63430008070033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c
-----Decoded View---------------
Arg [0] : _target (address): 0xDd70AF84BA86F29bf437756B655110D134b5651C
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.