More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 8,559 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Unstake Batch | 20381041 | 31 hrs ago | IN | 0 ETH | 0.00140632 | ||||
Unstake Batch | 20351789 | 5 days ago | IN | 0 ETH | 0.00023708 | ||||
Unstake Batch | 20288736 | 14 days ago | IN | 0 ETH | 0.00069209 | ||||
Unstake Batch | 20214942 | 24 days ago | IN | 0 ETH | 0.00238655 | ||||
Unstake Batch | 20213181 | 24 days ago | IN | 0 ETH | 0.0023828 | ||||
Unstake | 20178931 | 29 days ago | IN | 0 ETH | 0.00059261 | ||||
Unstake | 20178921 | 29 days ago | IN | 0 ETH | 0.00059261 | ||||
Unstake Batch | 20134611 | 35 days ago | IN | 0 ETH | 0.00197937 | ||||
Unstake Batch | 20131988 | 36 days ago | IN | 0 ETH | 0.00103269 | ||||
Unstake Batch | 20001851 | 54 days ago | IN | 0 ETH | 0.00097332 | ||||
Unstake Batch | 19992071 | 55 days ago | IN | 0 ETH | 0.00114821 | ||||
Unstake | 19972238 | 58 days ago | IN | 0 ETH | 0.00154079 | ||||
Unstake | 19972188 | 58 days ago | IN | 0 ETH | 0.00090898 | ||||
Unstake Batch | 19935697 | 63 days ago | IN | 0 ETH | 0.00300573 | ||||
Unstake Batch | 19885043 | 70 days ago | IN | 0 ETH | 0.00033005 | ||||
Unstake Batch | 19885020 | 70 days ago | IN | 0 ETH | 0.00034578 | ||||
Unstake Batch | 19885007 | 70 days ago | IN | 0 ETH | 0.00031484 | ||||
Unstake Batch | 19884980 | 70 days ago | IN | 0 ETH | 0.00033016 | ||||
Unstake Batch | 19884957 | 70 days ago | IN | 0 ETH | 0.0003557 | ||||
Unstake Batch | 19884951 | 70 days ago | IN | 0 ETH | 0.00036169 | ||||
Unstake Batch | 19884939 | 70 days ago | IN | 0 ETH | 0.00046654 | ||||
Unstake Batch | 19884259 | 70 days ago | IN | 0 ETH | 0.00064083 | ||||
Unstake Batch | 19884192 | 70 days ago | IN | 0 ETH | 0.00074251 | ||||
Unstake Batch | 19883873 | 70 days ago | IN | 0 ETH | 0.00084462 | ||||
Unstake Batch | 19883830 | 70 days ago | IN | 0 ETH | 0.00074015 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
NFTStaking
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/ERC20Spec.sol"; import "../interfaces/ERC721Spec.sol"; import "../utils/AccessControl.sol"; /** * @title NFT Staking * * @notice Enables NFT staking for a given NFT smart contract defined on deployment * * @notice Doesn't introduce any rewards, just tracks the stake/unstake dates for each * token/owner, this data will be used later on to process the rewards */ contract NFTStaking is AccessControl { /** * @dev Main staking data structure keeping track of a stake, * used in `tokenStakes` array mapping */ struct StakeData { /** * @dev Who owned and staked the token, who will be the token * returned to once unstaked */ address owner; /** * @dev When the token was staked and transferred from the owner, * unix timestamp */ uint32 stakedOn; /** * @dev When token was unstaked and returned back to the owner, * unix timestamp * @dev Zero value means the token is still staked */ uint32 unstakedOn; } /** * @dev Auxiliary data structure to help iterate over NFT owner stakes, * used in `userStakes` array mapping */ struct StakeIndex { /** * @dev Staked token ID */ uint32 tokenId; /** * @dev Where to look for main staking data `StakeData` * in `tokenStakes` array mapping */ uint32 index; } /** * @dev NFT smart contract to stake/unstake tokens of */ address public immutable targetContract; /** * @notice For each token ID stores the history of its stakes, * last element of the history may be "open" (unstakedOn = 0), * meaning the token is still staked and is ot be returned to the `owner` * * @dev Maps token ID => StakeData[] */ mapping(uint32 => StakeData[]) public tokenStakes; /** * @notice For each owner address stores the links to its stakes, * the link is represented as StakeIndex data struct * * @dev Maps owner address => StakeIndex[] */ mapping(address => StakeIndex[]) public userStakes; /** * @dev Enables staking, stake(), stakeBatch() */ uint32 public constant FEATURE_STAKING = 0x0000_0001; /** * @dev Enables unstaking, unstake(), unstakeBatch() */ uint32 public constant FEATURE_UNSTAKING = 0x0000_0002; /** * @notice People do mistake and may send tokens by mistake; since * staking contract is not designed to accept the tokens directly, * it allows the rescue manager to "rescue" such lost tokens * * @notice Rescue manager is responsible for "rescuing" ERC20/ERC721 tokens * accidentally sent to the smart contract * * @dev Role ROLE_RESCUE_MANAGER allows withdrawing non-staked ERC20/ERC721 * tokens stored on the smart contract balance */ uint32 public constant ROLE_RESCUE_MANAGER = 0x0001_0000; /** * @dev Fired in stake(), stakeBatch() * * @param _by token owner, tx executor * @param _tokenId token ID staked and transferred into the smart contract * @param _when unix timestamp of when staking happened */ event Staked(address indexed _by, uint32 indexed _tokenId, uint32 _when); /** * @dev Fired in unstake(), unstakeBatch() * * @param _by token owner, tx executor * @param _tokenId token ID unstaked and transferred back to owner * @param _when unix timestamp of when unstaking happened */ event Unstaked(address indexed _by, uint32 indexed _tokenId, uint32 _when); /** * @dev Creates/deploys NFT staking contract bound to the already deployed * target NFT ERC721 smart contract to be staked * * @param _nft address of the deployed NFT smart contract instance */ constructor(address _nft) { // verify input is set require(_nft != address(0), "target contract is not set"); // verify input is valid smart contract of the expected interface require(ERC165(_nft).supportsInterface(type(ERC721).interfaceId), "unexpected target type"); // setup smart contract internal state targetContract = _nft; } /** * @notice How many times a particular token was staked * * @dev Used to iterate `tokenStakes(tokenId, i)`, `i < numStakes(tokenId)` * * @param tokenId token ID to query number of times staked for * @return number of times token was staked */ function numStakes(uint32 tokenId) public view returns(uint256) { // just read the array length and return it return tokenStakes[tokenId].length; } /** * @notice How many stakes a particular address has done * * @dev Used to iterate `userStakes(owner, i)`, `i < numStakes(owner)` * * @param owner an address to query number of times it staked * @return number of times a particular address has staked */ function numStakes(address owner) public view returns(uint256) { // just read the array length and return it return userStakes[owner].length; } /** * @notice Determines if the token is currently staked or not * * @param tokenId token ID to check state for * @return true if token is staked, false otherwise */ function isStaked(uint32 tokenId) public view returns(bool) { // get an idea of current stakes for the token uint256 n = tokenStakes[tokenId].length; // evaluate based on the last stake element in the array return n > 0 && tokenStakes[tokenId][n - 1].unstakedOn == 0; } /** * @notice Stakes the NFT; the token is transferred from its owner to the staking contract; * token must be owned by the tx executor and be transferable by staking contract * * @param tokenId token ID to stake */ function stake(uint32 tokenId) public { // verify staking is enabled require(isFeatureEnabled(FEATURE_STAKING), "staking is disabled"); // get an idea of current stakes for the token uint256 n = tokenStakes[tokenId].length; // verify the token is not currently staked require(n == 0 || tokenStakes[tokenId][n - 1].unstakedOn != 0, "already staked"); // verify token belongs to the address which executes staking require(ERC721(targetContract).ownerOf(tokenId) == msg.sender, "access denied"); // transfer the token from owner into the staking contract ERC721(targetContract).transferFrom(msg.sender, address(this), tokenId); // current timestamp to be set as `stakedOn` uint32 stakedOn = now32(); // save token stake data tokenStakes[tokenId].push(StakeData({ owner: msg.sender, stakedOn: stakedOn, unstakedOn: 0 })); // save token stake index userStakes[msg.sender].push(StakeIndex({ tokenId: tokenId, index: uint32(n) })); // emit an event emit Staked(msg.sender, tokenId, stakedOn); } /** * @notice Stakes several NFTs; tokens are transferred from their owner to the staking contract; * tokens must be owned by the tx executor and be transferable by staking contract * * @param tokenIds token IDs to stake */ function stakeBatch(uint32[] memory tokenIds) public { // iterate the collection passed for(uint256 i = 0; i < tokenIds.length; i++) { // and stake each token one by one stake(tokenIds[i]); } } /** * @notice Unstakes the NFT; the token is transferred from staking contract back * its previous owner * * @param tokenId token ID to unstake */ function unstake(uint32 tokenId) public { // verify staking is enabled require(isFeatureEnabled(FEATURE_UNSTAKING), "unstaking is disabled"); // get an idea of current stakes for the token uint256 n = tokenStakes[tokenId].length; // verify the token is not currently staked require(n != 0, "not staked"); require(tokenStakes[tokenId][n - 1].unstakedOn == 0, "already unstaked"); // verify token belongs to the address which executes unstaking require(tokenStakes[tokenId][n - 1].owner == msg.sender, "access denied"); // current timestamp to be set as `unstakedOn` uint32 unstakedOn = now32(); // update token stake data tokenStakes[tokenId][n - 1].unstakedOn = unstakedOn; // transfer the token back to owner ERC721(targetContract).transferFrom(address(this), msg.sender, tokenId); // emit an event emit Unstaked(msg.sender, tokenId, unstakedOn); } /** * @notice Unstakes several NFTs; tokens are transferred from staking contract back * their previous owner * * @param tokenIds token IDs to unstake */ function unstakeBatch(uint32[] memory tokenIds) public { // iterate the collection passed for(uint256 i = 0; i < tokenIds.length; i++) { // and unstake each token one by one unstake(tokenIds[i]); } } /** * @dev Restricted access function to rescue accidentally sent ERC20 tokens, * the tokens are rescued via `transfer` function call on the * contract address specified and with the parameters specified: * `_contract.transfer(_to, _value)` * * @dev Requires executor to have `ROLE_RESCUE_MANAGER` permission * * @param _contract smart contract address to execute `transfer` function on * @param _to to address in `transfer(_to, _value)` * @param _value value to transfer in `transfer(_to, _value)` */ function rescueErc20(address _contract, address _to, uint256 _value) public { // verify the access permission require(isSenderInRole(ROLE_RESCUE_MANAGER), "access denied"); // perform the transfer as requested, without any checks ERC20(_contract).transfer(_to, _value); } /** * @dev Restricted access function to rescue accidentally sent ERC721 tokens, * the tokens are rescued via `transferFrom` function call on the * contract address specified and with the parameters specified: * `_contract.transferFrom(this, _to, _tokenId)` * * @dev Requires executor to have `ROLE_RESCUE_MANAGER` permission * * @param _contract smart contract address to execute `transferFrom` function on * @param _to to address in `transferFrom(this, _to, _tokenId)` * @param _tokenId token ID to transfer in `transferFrom(this, _to, _tokenId)` */ function rescueErc721(address _contract, address _to, uint256 _tokenId) public { // verify the access permission require(isSenderInRole(ROLE_RESCUE_MANAGER), "access denied"); // verify the NFT is not staked require(_contract != targetContract || !isStaked(uint32(_tokenId)), "token is staked"); // perform the transfer as requested, without any checks ERC721(_contract).transferFrom(address(this), _to, _tokenId); } /** * @dev Testing time-dependent functionality may be difficult; * we override time in the helper test smart contract (mock) * * @return `block.timestamp` in mainnet, custom values in testnets (if overridden) */ function now32() public view virtual returns (uint32) { // return current block timestamp return uint32(block.timestamp); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.7; /** * @title EIP-20: ERC-20 Token Standard * * @notice The ERC-20 (Ethereum Request for Comments 20), proposed by Fabian Vogelsteller in November 2015, * is a Token Standard that implements an API for tokens within Smart Contracts. * * @notice It provides functionalities like to transfer tokens from one account to another, * to get the current token balance of an account and also the total supply of the token available on the network. * Besides these it also has some other functionalities like to approve that an amount of * token from an account can be spent by a third party account. * * @notice If a Smart Contract implements the following methods and events it can be called an ERC-20 Token * Contract and, once deployed, it will be responsible to keep track of the created tokens on Ethereum. * * @notice See https://ethereum.org/en/developers/docs/standards/tokens/erc-20/ * @notice See https://eips.ethereum.org/EIPS/eip-20 */ interface ERC20 { /** * @dev Fired in transfer(), transferFrom() to indicate that token transfer happened * * @param from an address tokens were consumed from * @param to an address tokens were sent to * @param value number of tokens transferred */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Fired in approve() to indicate an approval event happened * * @param owner an address which granted a permission to transfer * tokens on its behalf * @param spender an address which received a permission to transfer * tokens on behalf of the owner `_owner` * @param value amount of tokens granted to transfer on behalf */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @return name of the token (ex.: USD Coin) */ // OPTIONAL - This method can be used to improve usability, // but interfaces and other contracts MUST NOT expect these values to be present. // function name() external view returns (string memory); /** * @return symbol of the token (ex.: USDC) */ // OPTIONAL - This method can be used to improve usability, // but interfaces and other contracts MUST NOT expect these values to be present. // function symbol() external view returns (string memory); /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * @dev Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * @dev NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. * * @return token decimals */ // OPTIONAL - This method can be used to improve usability, // but interfaces and other contracts MUST NOT expect these values to be present. // function decimals() external view returns (uint8); /** * @return the amount of tokens in existence */ function totalSupply() external view returns (uint256); /** * @notice Gets the balance of a particular address * * @param _owner the address to query the the balance for * @return balance an amount of tokens owned by the address specified */ function balanceOf(address _owner) external view returns (uint256 balance); /** * @notice Transfers some tokens to an external address or a smart contract * * @dev Called by token owner (an address which has a * positive token balance tracked by this smart contract) * @dev Throws on any error like * * insufficient token balance or * * incorrect `_to` address: * * zero address or * * self address or * * smart contract which doesn't support ERC20 * * @param _to an address to transfer tokens to, * must be either an external address or a smart contract, * compliant with the ERC20 standard * @param _value amount of tokens to be transferred,, zero * value is allowed * @return success true on success, throws otherwise */ function transfer(address _to, uint256 _value) external returns (bool success); /** * @notice Transfers some tokens on behalf of address `_from' (token owner) * to some other address `_to` * * @dev Called by token owner on his own or approved address, * an address approved earlier by token owner to * transfer some amount of tokens on its behalf * @dev Throws on any error like * * insufficient token balance or * * incorrect `_to` address: * * zero address or * * same as `_from` address (self transfer) * * smart contract which doesn't support ERC20 * * @param _from token owner which approved caller (transaction sender) * to transfer `_value` of tokens on its behalf * @param _to an address to transfer tokens to, * must be either an external address or a smart contract, * compliant with the ERC20 standard * @param _value amount of tokens to be transferred,, zero * value is allowed * @return success true on success, throws otherwise */ function transferFrom(address _from, address _to, uint256 _value) external returns (bool success); /** * @notice Approves address called `_spender` to transfer some amount * of tokens on behalf of the owner (transaction sender) * * @dev Transaction sender must not necessarily own any tokens to grant the permission * * @param _spender an address approved by the caller (token owner) * to spend some tokens on its behalf * @param _value an amount of tokens spender `_spender` is allowed to * transfer on behalf of the token owner * @return success true on success, throws otherwise */ function approve(address _spender, uint256 _value) external returns (bool success); /** * @notice Returns the amount which _spender is still allowed to withdraw from _owner. * * @dev A function to check an amount of tokens owner approved * to transfer on its behalf by some other address called "spender" * * @param _owner an address which approves transferring some tokens on its behalf * @param _spender an address approved to transfer some tokens on behalf * @return remaining an amount of tokens approved address `_spender` can transfer on behalf * of token owner `_owner` */ function allowance(address _owner, address _spender) external view returns (uint256 remaining); }
// 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 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.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":"_nft","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":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":true,"internalType":"uint32","name":"_tokenId","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"_when","type":"uint32"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":true,"internalType":"uint32","name":"_tokenId","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"_when","type":"uint32"}],"name":"Unstaked","type":"event"},{"inputs":[],"name":"FEATURE_STAKING","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEATURE_UNSTAKING","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_RESCUE_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":"uint32","name":"tokenId","type":"uint32"}],"name":"isStaked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"now32","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"numStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"tokenId","type":"uint32"}],"name":"numStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"rescueErc20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"rescueErc721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"tokenId","type":"uint32"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"tokenIds","type":"uint32[]"}],"name":"stakeBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"targetContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenStakes","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint32","name":"stakedOn","type":"uint32"},{"internalType":"uint32","name":"unstakedOn","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"tokenId","type":"uint32"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"tokenIds","type":"uint32[]"}],"name":"unstakeBatch","outputs":[],"stateMutability":"nonpayable","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"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userStakes","outputs":[{"internalType":"uint32","name":"tokenId","type":"uint32"},{"internalType":"uint32","name":"index","type":"uint32"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b50604051620013f8380380620013f883398101604081905262000034916200018a565b33600090815260208190526040902060001990556001600160a01b038116620000a45760405162461bcd60e51b815260206004820152601a60248201527f74617267657420636f6e7472616374206973206e6f742073657400000000000060448201526064015b60405180910390fd5b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526001600160a01b038216906301ffc9a79060240160206040518083038186803b158015620000eb57600080fd5b505afa15801562000100573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001269190620001bc565b620001745760405162461bcd60e51b815260206004820152601660248201527f756e65787065637465642074617267657420747970650000000000000000000060448201526064016200009b565b60601b6001600160601b031916608052620001e0565b6000602082840312156200019d57600080fd5b81516001600160a01b0381168114620001b557600080fd5b9392505050565b600060208284031215620001cf57600080fd5b81518015158114620001b557600080fd5b60805160601c6111dd6200021b60003960008181610324015281816104350152818161074f015281816108160152610bcc01526111dd6000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c8063809ee57d116100de578063c688d69311610097578063e60999ab11610071578063e60999ab146103c3578063f13b42fe146103c9578063f822d5aa146103dc578063fcc2c078146103ef57600080fd5b8063c688d6931461035e578063d5bb7f6714610371578063db6d98df1461038457600080fd5b8063809ee57d146102ab578063a69cb327146102be578063ae5b102e146102d1578063ae682e2e146102e4578063b5d5b5fa146102ef578063bd90df701461031f57600080fd5b80633a90b569116101305780633a90b56914610214578063490b7b9a1461023a57806355a38f2814610242578063725f36261461025557806374d5e100146102785780637fcfb7c21461029857600080fd5b806316ce9f0c14610178578063243feb991461018d5780632b521416146101a05780632d17f8bc146101c45780633467e9e1146101e3578063366d4f881461020c575b600080fd5b61018b610186366004610f17565b610402565b005b61018b61019b366004610f17565b610525565b306000908152602081905260409020545b6040519081526020015b60405180910390f35b6101ce6201000081565b60405163ffffffff90911681526020016101bb565b6101b16101f1366004610edd565b6001600160a01b031660009081526002602052604090205490565b6101ce600281565b6101b16102223660046110c0565b63ffffffff1660009081526001602052604090205490565b6101ce600181565b61018b610250366004610fb9565b6105d5565b6102686102633660046110a7565b610619565b60405190151581526020016101bb565b6101b1610286366004610edd565b60006020819052908152604090205481565b61018b6102a63660046110c0565b610634565b61018b6102b93660046110c0565b6109ba565b61018b6102cc366004610fb9565b610c6c565b61018b6102df366004610f58565b610cac565b6101b1600160ff1b81565b6103026102fd366004610f58565b610d56565b6040805163ffffffff9384168152929091166020830152016101bb565b6103467f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101bb565b61026861036c366004610f58565b610d97565b61018b61037f3660046110a7565b610dbc565b6103976103923660046110db565b610dc9565b604080516001600160a01b03909416845263ffffffff92831660208501529116908201526060016101bb565b426101ce565b6102686103d73660046110c0565b610e19565b6101b16103ea366004610f84565b610e8d565b6102686103fd3660046110a7565b610eb8565b61040e62010000610eb8565b6104335760405162461bcd60e51b815260040161042a906110f7565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614158061047a575061047881610e19565b155b6104b85760405162461bcd60e51b815260206004820152600f60248201526e1d1bdad95b881a5cc81cdd185ad959608a1b604482015260640161042a565b6040516323b872dd60e01b81523060048201526001600160a01b038381166024830152604482018390528416906323b872dd90606401600060405180830381600087803b15801561050857600080fd5b505af115801561051c573d6000803e3d6000fd5b50505050505050565b61053162010000610eb8565b61054d5760405162461bcd60e51b815260040161042a906110f7565b60405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb90604401602060405180830381600087803b15801561059757600080fd5b505af11580156105ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105cf9190611085565b50505050565b60005b8151811015610615576106038282815181106105f6576105f6611166565b6020026020010151610634565b8061060d81611135565b9150506105d8565b5050565b30600090815260208190526040812054821682145b92915050565b61063e6001610619565b6106805760405162461bcd60e51b81526020600482015260136024820152721cdd185ada5b99c81a5cc8191a5cd8589b1959606a1b604482015260640161042a565b63ffffffff81166000908152600160205260409020548015806106ed575063ffffffff82166000908152600160208190526040909120906106c1908361111e565b815481106106d1576106d1611166565b600091825260209091200154600160c01b900463ffffffff1615155b61072a5760405162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481cdd185ad95960921b604482015260640161042a565b6040516331a9108f60e11b815263ffffffff8316600482015233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e9060240160206040518083038186803b15801561079157600080fd5b505afa1580156107a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c99190610efa565b6001600160a01b0316146107ef5760405162461bcd60e51b815260040161042a906110f7565b6040516323b872dd60e01b815233600482015230602482015263ffffffff831660448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd90606401600060405180830381600087803b15801561086257600080fd5b505af1158015610876573d6000803e3d6000fd5b5050505060006108834290565b63ffffffff8085166000818152600160208181526040808420815160608101835233808252888a16828601908152828501888152845480890186559489528689209351939094018054915194518b16600160c01b0263ffffffff60c01b19958c16600160a01b026001600160c01b03199093166001600160a01b03959095169490941791909117939093169190911790915580855260028352818520825180840184528781528b891681860190815282549687018355918752939095209251929093018054945187166401000000000267ffffffffffffffff1990951692909616919091179290921790935551929350917f8d014b746c7fb511963855f62ef66b6859e8ce4e0524803ad565394fca8a8779906109ad90859063ffffffff91909116815260200190565b60405180910390a3505050565b6109c46002610619565b610a085760405162461bcd60e51b81526020600482015260156024820152741d5b9cdd185ada5b99c81a5cc8191a5cd8589b1959605a1b604482015260640161042a565b63ffffffff811660009081526001602052604090205480610a585760405162461bcd60e51b815260206004820152600a6024820152691b9bdd081cdd185ad95960b21b604482015260640161042a565b63ffffffff8216600090815260016020819052604090912090610a7b908361111e565b81548110610a8b57610a8b611166565b600091825260209091200154600160c01b900463ffffffff1615610ae45760405162461bcd60e51b815260206004820152601060248201526f185b1c9958591e481d5b9cdd185ad95960821b604482015260640161042a565b63ffffffff821660009081526001602081905260409091203391610b08908461111e565b81548110610b1857610b18611166565b6000918252602090912001546001600160a01b031614610b4a5760405162461bcd60e51b815260040161042a906110f7565b63ffffffff821660009081526001602081905260409091204291829190610b71908561111e565b81548110610b8157610b81611166565b6000918252602090912001805463ffffffff60c01b1916600160c01b63ffffffff938416021790556040516323b872dd60e01b815230600482015233602482015290841660448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd90606401600060405180830381600087803b158015610c1857600080fd5b505af1158015610c2c573d6000803e3d6000fd5b505060405163ffffffff8481168252861692503391507f1559f9d134d7761c724b694e7080cc95b2950bd40608ca802f85fcc0b23c586c906020016109ad565b60005b815181101561061557610c9a828281518110610c8d57610c8d611166565b60200260200101516109ba565b80610ca481611135565b915050610c6f565b610cb9600160ff1b610eb8565b610cd55760405162461bcd60e51b815260040161042a906110f7565b6001600160a01b038216600090815260208190526040902054610cfa90339083610e8d565b6001600160a01b03831660008181526020818152604091829020849055815185815290810193909352909133917f5a10526456f5116c0b7b80582c217d666243fd51b6a2d92c8011e601c2462e5f910160405180910390a35050565b60026020528160005260406000208181548110610d7257600080fd5b60009182526020909120015463ffffffff808216935064010000000090910416905082565b6001600160a01b038216600090815260208190526040812054821682145b9392505050565b610dc63082610cac565b50565b60016020528160005260406000208181548110610de557600080fd5b6000918252602090912001546001600160a01b038116925063ffffffff600160a01b820481169250600160c01b9091041683565b63ffffffff81166000908152600160205260408120548015801590610db5575063ffffffff8316600090815260016020819052604090912090610e5c908361111e565b81548110610e6c57610e6c611166565b600091825260209091200154600160c01b900463ffffffff16159392505050565b6001600160a01b03929092166000908152602081905260409020546000198084188216189216171690565b600061062e3383610d97565b803563ffffffff81168114610ed857600080fd5b919050565b600060208284031215610eef57600080fd5b8135610db581611192565b600060208284031215610f0c57600080fd5b8151610db581611192565b600080600060608486031215610f2c57600080fd5b8335610f3781611192565b92506020840135610f4781611192565b929592945050506040919091013590565b60008060408385031215610f6b57600080fd5b8235610f7681611192565b946020939093013593505050565b600080600060608486031215610f9957600080fd5b8335610fa481611192565b95602085013595506040909401359392505050565b60006020808385031215610fcc57600080fd5b823567ffffffffffffffff80821115610fe457600080fd5b818501915085601f830112610ff857600080fd5b81358181111561100a5761100a61117c565b8060051b604051601f19603f8301168101818110858211171561102f5761102f61117c565b604052828152858101935084860182860187018a101561104e57600080fd5b600095505b838610156110785761106481610ec4565b855260019590950194938601938601611053565b5098975050505050505050565b60006020828403121561109757600080fd5b81518015158114610db557600080fd5b6000602082840312156110b957600080fd5b5035919050565b6000602082840312156110d257600080fd5b610db582610ec4565b600080604083850312156110ee57600080fd5b610f7683610ec4565b6020808252600d908201526c1858d8d95cdcc819195b9a5959609a1b604082015260600190565b60008282101561113057611130611150565b500390565b600060001982141561114957611149611150565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610dc657600080fdfea26469706673582212207cdb496931f82b95d6b28fbbd143a992dfe26c8284a53304f3494d110ec876dd64736f6c63430008070033000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101735760003560e01c8063809ee57d116100de578063c688d69311610097578063e60999ab11610071578063e60999ab146103c3578063f13b42fe146103c9578063f822d5aa146103dc578063fcc2c078146103ef57600080fd5b8063c688d6931461035e578063d5bb7f6714610371578063db6d98df1461038457600080fd5b8063809ee57d146102ab578063a69cb327146102be578063ae5b102e146102d1578063ae682e2e146102e4578063b5d5b5fa146102ef578063bd90df701461031f57600080fd5b80633a90b569116101305780633a90b56914610214578063490b7b9a1461023a57806355a38f2814610242578063725f36261461025557806374d5e100146102785780637fcfb7c21461029857600080fd5b806316ce9f0c14610178578063243feb991461018d5780632b521416146101a05780632d17f8bc146101c45780633467e9e1146101e3578063366d4f881461020c575b600080fd5b61018b610186366004610f17565b610402565b005b61018b61019b366004610f17565b610525565b306000908152602081905260409020545b6040519081526020015b60405180910390f35b6101ce6201000081565b60405163ffffffff90911681526020016101bb565b6101b16101f1366004610edd565b6001600160a01b031660009081526002602052604090205490565b6101ce600281565b6101b16102223660046110c0565b63ffffffff1660009081526001602052604090205490565b6101ce600181565b61018b610250366004610fb9565b6105d5565b6102686102633660046110a7565b610619565b60405190151581526020016101bb565b6101b1610286366004610edd565b60006020819052908152604090205481565b61018b6102a63660046110c0565b610634565b61018b6102b93660046110c0565b6109ba565b61018b6102cc366004610fb9565b610c6c565b61018b6102df366004610f58565b610cac565b6101b1600160ff1b81565b6103026102fd366004610f58565b610d56565b6040805163ffffffff9384168152929091166020830152016101bb565b6103467f000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c81565b6040516001600160a01b0390911681526020016101bb565b61026861036c366004610f58565b610d97565b61018b61037f3660046110a7565b610dbc565b6103976103923660046110db565b610dc9565b604080516001600160a01b03909416845263ffffffff92831660208501529116908201526060016101bb565b426101ce565b6102686103d73660046110c0565b610e19565b6101b16103ea366004610f84565b610e8d565b6102686103fd3660046110a7565b610eb8565b61040e62010000610eb8565b6104335760405162461bcd60e51b815260040161042a906110f7565b60405180910390fd5b7f000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c6001600160a01b0316836001600160a01b031614158061047a575061047881610e19565b155b6104b85760405162461bcd60e51b815260206004820152600f60248201526e1d1bdad95b881a5cc81cdd185ad959608a1b604482015260640161042a565b6040516323b872dd60e01b81523060048201526001600160a01b038381166024830152604482018390528416906323b872dd90606401600060405180830381600087803b15801561050857600080fd5b505af115801561051c573d6000803e3d6000fd5b50505050505050565b61053162010000610eb8565b61054d5760405162461bcd60e51b815260040161042a906110f7565b60405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb90604401602060405180830381600087803b15801561059757600080fd5b505af11580156105ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105cf9190611085565b50505050565b60005b8151811015610615576106038282815181106105f6576105f6611166565b6020026020010151610634565b8061060d81611135565b9150506105d8565b5050565b30600090815260208190526040812054821682145b92915050565b61063e6001610619565b6106805760405162461bcd60e51b81526020600482015260136024820152721cdd185ada5b99c81a5cc8191a5cd8589b1959606a1b604482015260640161042a565b63ffffffff81166000908152600160205260409020548015806106ed575063ffffffff82166000908152600160208190526040909120906106c1908361111e565b815481106106d1576106d1611166565b600091825260209091200154600160c01b900463ffffffff1615155b61072a5760405162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481cdd185ad95960921b604482015260640161042a565b6040516331a9108f60e11b815263ffffffff8316600482015233906001600160a01b037f000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c1690636352211e9060240160206040518083038186803b15801561079157600080fd5b505afa1580156107a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c99190610efa565b6001600160a01b0316146107ef5760405162461bcd60e51b815260040161042a906110f7565b6040516323b872dd60e01b815233600482015230602482015263ffffffff831660448201527f000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c6001600160a01b0316906323b872dd90606401600060405180830381600087803b15801561086257600080fd5b505af1158015610876573d6000803e3d6000fd5b5050505060006108834290565b63ffffffff8085166000818152600160208181526040808420815160608101835233808252888a16828601908152828501888152845480890186559489528689209351939094018054915194518b16600160c01b0263ffffffff60c01b19958c16600160a01b026001600160c01b03199093166001600160a01b03959095169490941791909117939093169190911790915580855260028352818520825180840184528781528b891681860190815282549687018355918752939095209251929093018054945187166401000000000267ffffffffffffffff1990951692909616919091179290921790935551929350917f8d014b746c7fb511963855f62ef66b6859e8ce4e0524803ad565394fca8a8779906109ad90859063ffffffff91909116815260200190565b60405180910390a3505050565b6109c46002610619565b610a085760405162461bcd60e51b81526020600482015260156024820152741d5b9cdd185ada5b99c81a5cc8191a5cd8589b1959605a1b604482015260640161042a565b63ffffffff811660009081526001602052604090205480610a585760405162461bcd60e51b815260206004820152600a6024820152691b9bdd081cdd185ad95960b21b604482015260640161042a565b63ffffffff8216600090815260016020819052604090912090610a7b908361111e565b81548110610a8b57610a8b611166565b600091825260209091200154600160c01b900463ffffffff1615610ae45760405162461bcd60e51b815260206004820152601060248201526f185b1c9958591e481d5b9cdd185ad95960821b604482015260640161042a565b63ffffffff821660009081526001602081905260409091203391610b08908461111e565b81548110610b1857610b18611166565b6000918252602090912001546001600160a01b031614610b4a5760405162461bcd60e51b815260040161042a906110f7565b63ffffffff821660009081526001602081905260409091204291829190610b71908561111e565b81548110610b8157610b81611166565b6000918252602090912001805463ffffffff60c01b1916600160c01b63ffffffff938416021790556040516323b872dd60e01b815230600482015233602482015290841660448201527f000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c6001600160a01b0316906323b872dd90606401600060405180830381600087803b158015610c1857600080fd5b505af1158015610c2c573d6000803e3d6000fd5b505060405163ffffffff8481168252861692503391507f1559f9d134d7761c724b694e7080cc95b2950bd40608ca802f85fcc0b23c586c906020016109ad565b60005b815181101561061557610c9a828281518110610c8d57610c8d611166565b60200260200101516109ba565b80610ca481611135565b915050610c6f565b610cb9600160ff1b610eb8565b610cd55760405162461bcd60e51b815260040161042a906110f7565b6001600160a01b038216600090815260208190526040902054610cfa90339083610e8d565b6001600160a01b03831660008181526020818152604091829020849055815185815290810193909352909133917f5a10526456f5116c0b7b80582c217d666243fd51b6a2d92c8011e601c2462e5f910160405180910390a35050565b60026020528160005260406000208181548110610d7257600080fd5b60009182526020909120015463ffffffff808216935064010000000090910416905082565b6001600160a01b038216600090815260208190526040812054821682145b9392505050565b610dc63082610cac565b50565b60016020528160005260406000208181548110610de557600080fd5b6000918252602090912001546001600160a01b038116925063ffffffff600160a01b820481169250600160c01b9091041683565b63ffffffff81166000908152600160205260408120548015801590610db5575063ffffffff8316600090815260016020819052604090912090610e5c908361111e565b81548110610e6c57610e6c611166565b600091825260209091200154600160c01b900463ffffffff16159392505050565b6001600160a01b03929092166000908152602081905260409020546000198084188216189216171690565b600061062e3383610d97565b803563ffffffff81168114610ed857600080fd5b919050565b600060208284031215610eef57600080fd5b8135610db581611192565b600060208284031215610f0c57600080fd5b8151610db581611192565b600080600060608486031215610f2c57600080fd5b8335610f3781611192565b92506020840135610f4781611192565b929592945050506040919091013590565b60008060408385031215610f6b57600080fd5b8235610f7681611192565b946020939093013593505050565b600080600060608486031215610f9957600080fd5b8335610fa481611192565b95602085013595506040909401359392505050565b60006020808385031215610fcc57600080fd5b823567ffffffffffffffff80821115610fe457600080fd5b818501915085601f830112610ff857600080fd5b81358181111561100a5761100a61117c565b8060051b604051601f19603f8301168101818110858211171561102f5761102f61117c565b604052828152858101935084860182860187018a101561104e57600080fd5b600095505b838610156110785761106481610ec4565b855260019590950194938601938601611053565b5098975050505050505050565b60006020828403121561109757600080fd5b81518015158114610db557600080fd5b6000602082840312156110b957600080fd5b5035919050565b6000602082840312156110d257600080fd5b610db582610ec4565b600080604083850312156110ee57600080fd5b610f7683610ec4565b6020808252600d908201526c1858d8d95cdcc819195b9a5959609a1b604082015260600190565b60008282101561113057611130611150565b500390565b600060001982141561114957611149611150565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610dc657600080fdfea26469706673582212207cdb496931f82b95d6b28fbbd143a992dfe26c8284a53304f3494d110ec876dd64736f6c63430008070033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000dd70af84ba86f29bf437756b655110d134b5651c
-----Decoded View---------------
Arg [0] : _nft (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.