Overview
BERA Balance
BERA Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 31 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Set Max Id | 1661716 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1661716 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1661716 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Set Max Id | 1661612 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1661612 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1661612 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Set Max Id | 1660814 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1660814 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1660814 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Set Max Id | 1660800 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1660800 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1660800 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Set Max Id | 1660716 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1660716 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1660716 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Set Max Id | 1660696 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1660696 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1660696 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Set Max Id | 1660609 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1660609 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1660609 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Set Max Id | 1660528 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1660528 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Grant Role | 1660528 | 55 days ago | IN | 0 BERA | 0.00000002 | ||||
Set Max Id | 1658927 | 55 days ago | IN | 0 BERA | 0.00000002 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
HenloTheGameCollection
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@solady/tokens/ERC1155.sol"; import "@openzeppelin/contracts/access/AccessControl.sol"; /// @title HenloTheGameCollection - A non-transferable ERC1155 collection /// @notice This contract manages a collection of non-transferable tokens for Henlo The Game /// @dev Inherits from ERC1155, Pausable, and AccessControl contract HenloTheGameCollection is ERC1155, AccessControl { /// @notice Role identifier for addresses that can mint tokens /// @dev Set to bytes32(uint256(0x01)) bytes32 public constant MINTER = bytes32(uint256(0x01)); /// @notice Mapping of token IDs to their respective URIs mapping(uint256 => string) uris; /// @notice Maximum allowed token ID is MAX_ID - 1 /// @dev Used to restrict the range of valid token types uint256 public MAX_ID; error TransferDisabled(); constructor() ERC1155() { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(MINTER, msg.sender); MAX_ID = 3; } /// @notice Mints a new token to the specified account /// @dev Only callable by addresses with MINTER role /// @param account The address that will receive the minted token /// @param id The token ID to mint (must be less than MAX_ID) /// @param data Additional data to pass to the mint function function mint(address account, uint256 id, bytes memory data) external onlyRole(MINTER) { require(id < MAX_ID, "Invalid collection type"); _mint(account, id, 1, data); } function uri(uint256 id) public view override returns (string memory) { return uris[id]; } /// @notice Sets the URI for a specific token ID /// @dev Only callable by addresses with DEFAULT_ADMIN_ROLE /// @param _id The token ID to set the URI for /// @param _uri The new URI to set function setUri(uint256 _id, string calldata _uri) external onlyRole(DEFAULT_ADMIN_ROLE) { uris[_id] = _uri; emit URI(_uri, _id); } /// @notice Updates the maximum allowed token ID /// @dev Only callable by addresses with DEFAULT_ADMIN_ROLE /// @param _maxId The exclusice upper boundary for valid token IDs function setMaxId(uint256 _maxId) external onlyRole(DEFAULT_ADMIN_ROLE) { MAX_ID = _maxId; } function _useBeforeTokenTransfer() internal pure override returns (bool) { return true; } function _beforeTokenTransfer(address from, address, uint256[] memory, uint256[] memory, bytes memory) internal pure override { if (from != address(0)) { revert TransferDisabled(); } } function supportsInterface(bytes4 interfaceId) public view override(ERC1155, AccessControl) returns (bool result) { return ERC1155.supportsInterface(interfaceId) || AccessControl.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple ERC1155 implementation. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC1155.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC1155/ERC1155.sol) /// /// @dev Note: /// - The ERC1155 standard allows for self-approvals. /// For performance, this implementation WILL NOT revert for such actions. /// Please add any checks with overrides if desired. /// - The transfer functions use the identity precompile (0x4) /// to copy memory internally. /// /// If you are overriding: /// - Make sure all variables written to storage are properly cleaned // (e.g. the bool value for `isApprovedForAll` MUST be either 1 or 0 under the hood). /// - Check that the overridden function is actually used in the function you want to /// change the behavior of. Much of the code has been manually inlined for performance. abstract contract ERC1155 { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The lengths of the input arrays are not the same. error ArrayLengthsMismatch(); /// @dev Cannot mint or transfer to the zero address. error TransferToZeroAddress(); /// @dev The recipient's balance has overflowed. error AccountBalanceOverflow(); /// @dev Insufficient balance. error InsufficientBalance(); /// @dev Only the token owner or an approved account can manage the tokens. error NotOwnerNorApproved(); /// @dev Cannot safely transfer to a contract that does not implement /// the ERC1155Receiver interface. error TransferToNonERC1155ReceiverImplementer(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Emitted when `amount` of token `id` is transferred /// from `from` to `to` by `operator`. event TransferSingle( address indexed operator, address indexed from, address indexed to, uint256 id, uint256 amount ); /// @dev Emitted when `amounts` of token `ids` are transferred /// from `from` to `to` by `operator`. event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); /// @dev Emitted when `owner` enables or disables `operator` to manage all of their tokens. event ApprovalForAll(address indexed owner, address indexed operator, bool isApproved); /// @dev Emitted when the Uniform Resource Identifier (URI) for token `id` /// is updated to `value`. This event is not used in the base contract. /// You may need to emit this event depending on your URI logic. /// /// See: https://eips.ethereum.org/EIPS/eip-1155#metadata event URI(string value, uint256 indexed id); /// @dev `keccak256(bytes("TransferSingle(address,address,address,uint256,uint256)"))`. uint256 private constant _TRANSFER_SINGLE_EVENT_SIGNATURE = 0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62; /// @dev `keccak256(bytes("TransferBatch(address,address,address,uint256[],uint256[])"))`. uint256 private constant _TRANSFER_BATCH_EVENT_SIGNATURE = 0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb; /// @dev `keccak256(bytes("ApprovalForAll(address,address,bool)"))`. uint256 private constant _APPROVAL_FOR_ALL_EVENT_SIGNATURE = 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The `ownerSlotSeed` of a given owner is given by. /// ``` /// let ownerSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, owner)) /// ``` /// /// The balance slot of `owner` is given by. /// ``` /// mstore(0x20, ownerSlotSeed) /// mstore(0x00, id) /// let balanceSlot := keccak256(0x00, 0x40) /// ``` /// /// The operator approval slot of `owner` is given by. /// ``` /// mstore(0x20, ownerSlotSeed) /// mstore(0x00, operator) /// let operatorApprovalSlot := keccak256(0x0c, 0x34) /// ``` uint256 private constant _ERC1155_MASTER_SLOT_SEED = 0x9a31110384e0b0c9; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC1155 METADATA */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the URI for token `id`. /// /// You can either return the same templated URI for all token IDs, /// (e.g. "https://example.com/api/{id}.json"), /// or return a unique URI for each `id`. /// /// See: https://eips.ethereum.org/EIPS/eip-1155#metadata function uri(uint256 id) public view virtual returns (string memory); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC1155 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the amount of `id` owned by `owner`. function balanceOf(address owner, uint256 id) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, _ERC1155_MASTER_SLOT_SEED) mstore(0x14, owner) mstore(0x00, id) result := sload(keccak256(0x00, 0x40)) } } /// @dev Returns whether `operator` is approved to manage the tokens of `owner`. function isApprovedForAll(address owner, address operator) public view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, _ERC1155_MASTER_SLOT_SEED) mstore(0x14, owner) mstore(0x00, operator) result := sload(keccak256(0x0c, 0x34)) } } /// @dev Sets whether `operator` is approved to manage the tokens of the caller. /// /// Emits a {ApprovalForAll} event. function setApprovalForAll(address operator, bool isApproved) public virtual { /// @solidity memory-safe-assembly assembly { // Convert to 0 or 1. isApproved := iszero(iszero(isApproved)) // Update the `isApproved` for (`msg.sender`, `operator`). mstore(0x20, _ERC1155_MASTER_SLOT_SEED) mstore(0x14, caller()) mstore(0x00, operator) sstore(keccak256(0x0c, 0x34), isApproved) // Emit the {ApprovalForAll} event. mstore(0x00, isApproved) // forgefmt: disable-next-line log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, caller(), shr(96, shl(96, operator))) } } /// @dev Transfers `amount` of `id` from `from` to `to`. /// /// Requirements: /// - `to` cannot be the zero address. /// - `from` must have at least `amount` of `id`. /// - If the caller is not `from`, /// it must be approved to manage the tokens of `from`. /// - If `to` refers to a smart contract, it must implement /// {ERC1155-onERC1155Received}, which is called upon a batch transfer. /// /// Emits a {TransferSingle} event. function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) public virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(from, to, _single(id), _single(amount), data); } /// @solidity memory-safe-assembly assembly { let fromSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, from)) let toSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, to)) mstore(0x20, fromSlotSeed) // Clear the upper 96 bits. from := shr(96, fromSlotSeed) to := shr(96, toSlotSeed) // Revert if `to` is the zero address. if iszero(to) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // If the caller is not `from`, do the authorization check. if iszero(eq(caller(), from)) { mstore(0x00, caller()) if iszero(sload(keccak256(0x0c, 0x34))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Subtract and store the updated balance of `from`. { mstore(0x00, id) let fromBalanceSlot := keccak256(0x00, 0x40) let fromBalance := sload(fromBalanceSlot) if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } sstore(fromBalanceSlot, sub(fromBalance, amount)) } // Increase and store the updated balance of `to`. { mstore(0x20, toSlotSeed) let toBalanceSlot := keccak256(0x00, 0x40) let toBalanceBefore := sload(toBalanceSlot) let toBalanceAfter := add(toBalanceBefore, amount) if lt(toBalanceAfter, toBalanceBefore) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceAfter) } // Emit a {TransferSingle} event. mstore(0x20, amount) log4(0x00, 0x40, _TRANSFER_SINGLE_EVENT_SIGNATURE, caller(), from, to) } if (_useAfterTokenTransfer()) { _afterTokenTransfer(from, to, _single(id), _single(amount), data); } /// @solidity memory-safe-assembly assembly { // Do the {onERC1155Received} check if `to` is a smart contract. if extcodesize(to) { // Prepare the calldata. let m := mload(0x40) // `onERC1155Received(address,address,uint256,uint256,bytes)`. mstore(m, 0xf23a6e61) mstore(add(m, 0x20), caller()) mstore(add(m, 0x40), from) mstore(add(m, 0x60), id) mstore(add(m, 0x80), amount) mstore(add(m, 0xa0), 0xa0) mstore(add(m, 0xc0), data.length) calldatacopy(add(m, 0xe0), data.offset, data.length) // Revert if the call reverts. if iszero(call(gas(), to, 0, add(m, 0x1c), add(0xc4, data.length), m, 0x20)) { if returndatasize() { // Bubble up the revert if the call reverts. returndatacopy(m, 0x00, returndatasize()) revert(m, returndatasize()) } } // Load the returndata and compare it with the function selector. if iszero(eq(mload(m), shl(224, 0xf23a6e61))) { mstore(0x00, 0x9c05499b) // `TransferToNonERC1155ReceiverImplementer()`. revert(0x1c, 0x04) } } } } /// @dev Transfers `amounts` of `ids` from `from` to `to`. /// /// Requirements: /// - `to` cannot be the zero address. /// - `from` must have at least `amount` of `id`. /// - `ids` and `amounts` must have the same length. /// - If the caller is not `from`, /// it must be approved to manage the tokens of `from`. /// - If `to` refers to a smart contract, it must implement /// {ERC1155-onERC1155BatchReceived}, which is called upon a batch transfer. /// /// Emits a {TransferBatch} event. function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(from, to, ids, amounts, data); } /// @solidity memory-safe-assembly assembly { if iszero(eq(ids.length, amounts.length)) { mstore(0x00, 0x3b800a46) // `ArrayLengthsMismatch()`. revert(0x1c, 0x04) } let fromSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, from)) let toSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, to)) mstore(0x20, fromSlotSeed) // Clear the upper 96 bits. from := shr(96, fromSlotSeed) to := shr(96, toSlotSeed) // Revert if `to` is the zero address. if iszero(to) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // If the caller is not `from`, do the authorization check. if iszero(eq(caller(), from)) { mstore(0x00, caller()) if iszero(sload(keccak256(0x0c, 0x34))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Loop through all the `ids` and update the balances. { for { let i := shl(5, ids.length) } i {} { i := sub(i, 0x20) let amount := calldataload(add(amounts.offset, i)) // Subtract and store the updated balance of `from`. { mstore(0x20, fromSlotSeed) mstore(0x00, calldataload(add(ids.offset, i))) let fromBalanceSlot := keccak256(0x00, 0x40) let fromBalance := sload(fromBalanceSlot) if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } sstore(fromBalanceSlot, sub(fromBalance, amount)) } // Increase and store the updated balance of `to`. { mstore(0x20, toSlotSeed) let toBalanceSlot := keccak256(0x00, 0x40) let toBalanceBefore := sload(toBalanceSlot) let toBalanceAfter := add(toBalanceBefore, amount) if lt(toBalanceAfter, toBalanceBefore) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceAfter) } } } // Emit a {TransferBatch} event. { let m := mload(0x40) // Copy the `ids`. mstore(m, 0x40) let n := shl(5, ids.length) mstore(add(m, 0x40), ids.length) calldatacopy(add(m, 0x60), ids.offset, n) // Copy the `amounts`. mstore(add(m, 0x20), add(0x60, n)) let o := add(add(m, n), 0x60) mstore(o, ids.length) calldatacopy(add(o, 0x20), amounts.offset, n) // Do the emit. log4(m, add(add(n, n), 0x80), _TRANSFER_BATCH_EVENT_SIGNATURE, caller(), from, to) } } if (_useAfterTokenTransfer()) { _afterTokenTransferCalldata(from, to, ids, amounts, data); } /// @solidity memory-safe-assembly assembly { // Do the {onERC1155BatchReceived} check if `to` is a smart contract. if extcodesize(to) { mstore(0x00, to) // Cache `to` to prevent stack too deep. let m := mload(0x40) // Prepare the calldata. // `onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)`. mstore(m, 0xbc197c81) mstore(add(m, 0x20), caller()) mstore(add(m, 0x40), from) // Copy the `ids`. mstore(add(m, 0x60), 0xa0) let n := shl(5, ids.length) mstore(add(m, 0xc0), ids.length) calldatacopy(add(m, 0xe0), ids.offset, n) // Copy the `amounts`. mstore(add(m, 0x80), add(0xc0, n)) let o := add(add(m, n), 0xe0) mstore(o, ids.length) calldatacopy(add(o, 0x20), amounts.offset, n) // Copy the `data`. mstore(add(m, 0xa0), add(add(0xe0, n), n)) o := add(add(o, n), 0x20) mstore(o, data.length) calldatacopy(add(o, 0x20), data.offset, data.length) let nAll := add(0x104, add(data.length, add(n, n))) // Revert if the call reverts. if iszero(call(gas(), mload(0x00), 0, add(mload(0x40), 0x1c), nAll, m, 0x20)) { if returndatasize() { // Bubble up the revert if the call reverts. returndatacopy(m, 0x00, returndatasize()) revert(m, returndatasize()) } } // Load the returndata and compare it with the function selector. if iszero(eq(mload(m), shl(224, 0xbc197c81))) { mstore(0x00, 0x9c05499b) // `TransferToNonERC1155ReceiverImplementer()`. revert(0x1c, 0x04) } } } } /// @dev Returns the amounts of `ids` for `owners. /// /// Requirements: /// - `owners` and `ids` must have the same length. function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) public view virtual returns (uint256[] memory balances) { /// @solidity memory-safe-assembly assembly { if iszero(eq(ids.length, owners.length)) { mstore(0x00, 0x3b800a46) // `ArrayLengthsMismatch()`. revert(0x1c, 0x04) } balances := mload(0x40) mstore(balances, ids.length) let o := add(balances, 0x20) let i := shl(5, ids.length) mstore(0x40, add(i, o)) // Loop through all the `ids` and load the balances. for {} i {} { i := sub(i, 0x20) let owner := calldataload(add(owners.offset, i)) mstore(0x20, or(_ERC1155_MASTER_SLOT_SEED, shl(96, owner))) mstore(0x00, calldataload(add(ids.offset, i))) mstore(add(o, i), sload(keccak256(0x00, 0x40))) } } } /// @dev Returns true if this contract implements the interface defined by `interfaceId`. /// See: https://eips.ethereum.org/EIPS/eip-165 /// This function call must use less than 30000 gas. function supportsInterface(bytes4 interfaceId) public view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { let s := shr(224, interfaceId) // ERC165: 0x01ffc9a7, ERC1155: 0xd9b67a26, ERC1155MetadataURI: 0x0e89341c. result := or(or(eq(s, 0x01ffc9a7), eq(s, 0xd9b67a26)), eq(s, 0x0e89341c)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL MINT FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Mints `amount` of `id` to `to`. /// /// Requirements: /// - `to` cannot be the zero address. /// - If `to` refers to a smart contract, it must implement /// {ERC1155-onERC1155Received}, which is called upon a batch transfer. /// /// Emits a {TransferSingle} event. function _mint(address to, uint256 id, uint256 amount, bytes memory data) internal virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(address(0), to, _single(id), _single(amount), data); } /// @solidity memory-safe-assembly assembly { let to_ := shl(96, to) // Revert if `to` is the zero address. if iszero(to_) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // Increase and store the updated balance of `to`. { mstore(0x20, _ERC1155_MASTER_SLOT_SEED) mstore(0x14, to) mstore(0x00, id) let toBalanceSlot := keccak256(0x00, 0x40) let toBalanceBefore := sload(toBalanceSlot) let toBalanceAfter := add(toBalanceBefore, amount) if lt(toBalanceAfter, toBalanceBefore) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceAfter) } // Emit a {TransferSingle} event. mstore(0x20, amount) log4(0x00, 0x40, _TRANSFER_SINGLE_EVENT_SIGNATURE, caller(), 0, shr(96, to_)) } if (_useAfterTokenTransfer()) { _afterTokenTransfer(address(0), to, _single(id), _single(amount), data); } if (_hasCode(to)) _checkOnERC1155Received(address(0), to, id, amount, data); } /// @dev Mints `amounts` of `ids` to `to`. /// /// Requirements: /// - `to` cannot be the zero address. /// - `ids` and `amounts` must have the same length. /// - If `to` refers to a smart contract, it must implement /// {ERC1155-onERC1155BatchReceived}, which is called upon a batch transfer. /// /// Emits a {TransferBatch} event. function _batchMint( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(address(0), to, ids, amounts, data); } /// @solidity memory-safe-assembly assembly { if iszero(eq(mload(ids), mload(amounts))) { mstore(0x00, 0x3b800a46) // `ArrayLengthsMismatch()`. revert(0x1c, 0x04) } let to_ := shl(96, to) // Revert if `to` is the zero address. if iszero(to_) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // Loop through all the `ids` and update the balances. { mstore(0x20, or(_ERC1155_MASTER_SLOT_SEED, to_)) for { let i := shl(5, mload(ids)) } i { i := sub(i, 0x20) } { let amount := mload(add(amounts, i)) // Increase and store the updated balance of `to`. { mstore(0x00, mload(add(ids, i))) let toBalanceSlot := keccak256(0x00, 0x40) let toBalanceBefore := sload(toBalanceSlot) let toBalanceAfter := add(toBalanceBefore, amount) if lt(toBalanceAfter, toBalanceBefore) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceAfter) } } } // Emit a {TransferBatch} event. { let m := mload(0x40) // Copy the `ids`. mstore(m, 0x40) let n := add(0x20, shl(5, mload(ids))) let o := add(m, 0x40) pop(staticcall(gas(), 4, ids, n, o, n)) // Copy the `amounts`. mstore(add(m, 0x20), add(0x40, returndatasize())) o := add(o, returndatasize()) n := add(0x20, shl(5, mload(amounts))) pop(staticcall(gas(), 4, amounts, n, o, n)) n := sub(add(o, returndatasize()), m) // Do the emit. log4(m, n, _TRANSFER_BATCH_EVENT_SIGNATURE, caller(), 0, shr(96, to_)) } } if (_useAfterTokenTransfer()) { _afterTokenTransfer(address(0), to, ids, amounts, data); } if (_hasCode(to)) _checkOnERC1155BatchReceived(address(0), to, ids, amounts, data); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL BURN FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Equivalent to `_burn(address(0), from, id, amount)`. function _burn(address from, uint256 id, uint256 amount) internal virtual { _burn(address(0), from, id, amount); } /// @dev Destroys `amount` of `id` from `from`. /// /// Requirements: /// - `from` must have at least `amount` of `id`. /// - If `by` is not the zero address, it must be either `from`, /// or approved to manage the tokens of `from`. /// /// Emits a {TransferSingle} event. function _burn(address by, address from, uint256 id, uint256 amount) internal virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(from, address(0), _single(id), _single(amount), ""); } /// @solidity memory-safe-assembly assembly { let from_ := shl(96, from) mstore(0x20, or(_ERC1155_MASTER_SLOT_SEED, from_)) // If `by` is not the zero address, and not equal to `from`, // check if it is approved to manage all the tokens of `from`. if iszero(or(iszero(shl(96, by)), eq(shl(96, by), from_))) { mstore(0x00, by) if iszero(sload(keccak256(0x0c, 0x34))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Decrease and store the updated balance of `from`. { mstore(0x00, id) let fromBalanceSlot := keccak256(0x00, 0x40) let fromBalance := sload(fromBalanceSlot) if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } sstore(fromBalanceSlot, sub(fromBalance, amount)) } // Emit a {TransferSingle} event. mstore(0x20, amount) log4(0x00, 0x40, _TRANSFER_SINGLE_EVENT_SIGNATURE, caller(), shr(96, from_), 0) } if (_useAfterTokenTransfer()) { _afterTokenTransfer(from, address(0), _single(id), _single(amount), ""); } } /// @dev Equivalent to `_batchBurn(address(0), from, ids, amounts)`. function _batchBurn(address from, uint256[] memory ids, uint256[] memory amounts) internal virtual { _batchBurn(address(0), from, ids, amounts); } /// @dev Destroys `amounts` of `ids` from `from`. /// /// Requirements: /// - `ids` and `amounts` must have the same length. /// - `from` must have at least `amounts` of `ids`. /// - If `by` is not the zero address, it must be either `from`, /// or approved to manage the tokens of `from`. /// /// Emits a {TransferBatch} event. function _batchBurn(address by, address from, uint256[] memory ids, uint256[] memory amounts) internal virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(from, address(0), ids, amounts, ""); } /// @solidity memory-safe-assembly assembly { if iszero(eq(mload(ids), mload(amounts))) { mstore(0x00, 0x3b800a46) // `ArrayLengthsMismatch()`. revert(0x1c, 0x04) } let from_ := shl(96, from) mstore(0x20, or(_ERC1155_MASTER_SLOT_SEED, from_)) // If `by` is not the zero address, and not equal to `from`, // check if it is approved to manage all the tokens of `from`. let by_ := shl(96, by) if iszero(or(iszero(by_), eq(by_, from_))) { mstore(0x00, by) if iszero(sload(keccak256(0x0c, 0x34))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Loop through all the `ids` and update the balances. { for { let i := shl(5, mload(ids)) } i { i := sub(i, 0x20) } { let amount := mload(add(amounts, i)) // Decrease and store the updated balance of `from`. { mstore(0x00, mload(add(ids, i))) let fromBalanceSlot := keccak256(0x00, 0x40) let fromBalance := sload(fromBalanceSlot) if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } sstore(fromBalanceSlot, sub(fromBalance, amount)) } } } // Emit a {TransferBatch} event. { let m := mload(0x40) // Copy the `ids`. mstore(m, 0x40) let n := add(0x20, shl(5, mload(ids))) let o := add(m, 0x40) pop(staticcall(gas(), 4, ids, n, o, n)) // Copy the `amounts`. mstore(add(m, 0x20), add(0x40, returndatasize())) o := add(o, returndatasize()) n := add(0x20, shl(5, mload(amounts))) pop(staticcall(gas(), 4, amounts, n, o, n)) n := sub(add(o, returndatasize()), m) // Do the emit. log4(m, n, _TRANSFER_BATCH_EVENT_SIGNATURE, caller(), shr(96, from_), 0) } } if (_useAfterTokenTransfer()) { _afterTokenTransfer(from, address(0), ids, amounts, ""); } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL APPROVAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Approve or remove the `operator` as an operator for `by`, /// without authorization checks. /// /// Emits a {ApprovalForAll} event. function _setApprovalForAll(address by, address operator, bool isApproved) internal virtual { /// @solidity memory-safe-assembly assembly { // Convert to 0 or 1. isApproved := iszero(iszero(isApproved)) // Update the `isApproved` for (`by`, `operator`). mstore(0x20, _ERC1155_MASTER_SLOT_SEED) mstore(0x14, by) mstore(0x00, operator) sstore(keccak256(0x0c, 0x34), isApproved) // Emit the {ApprovalForAll} event. mstore(0x00, isApproved) let m := shr(96, not(0)) log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, and(m, by), and(m, operator)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL TRANSFER FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Equivalent to `_safeTransfer(address(0), from, to, id, amount, data)`. function _safeTransfer(address from, address to, uint256 id, uint256 amount, bytes memory data) internal virtual { _safeTransfer(address(0), from, to, id, amount, data); } /// @dev Transfers `amount` of `id` from `from` to `to`. /// /// Requirements: /// - `to` cannot be the zero address. /// - `from` must have at least `amount` of `id`. /// - If `by` is not the zero address, it must be either `from`, /// or approved to manage the tokens of `from`. /// - If `to` refers to a smart contract, it must implement /// {ERC1155-onERC1155Received}, which is called upon a batch transfer. /// /// Emits a {TransferSingle} event. function _safeTransfer( address by, address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(from, to, _single(id), _single(amount), data); } /// @solidity memory-safe-assembly assembly { let from_ := shl(96, from) let to_ := shl(96, to) // Revert if `to` is the zero address. if iszero(to_) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } mstore(0x20, or(_ERC1155_MASTER_SLOT_SEED, from_)) // If `by` is not the zero address, and not equal to `from`, // check if it is approved to manage all the tokens of `from`. let by_ := shl(96, by) if iszero(or(iszero(by_), eq(by_, from_))) { mstore(0x00, by) if iszero(sload(keccak256(0x0c, 0x34))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Subtract and store the updated balance of `from`. { mstore(0x00, id) let fromBalanceSlot := keccak256(0x00, 0x40) let fromBalance := sload(fromBalanceSlot) if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } sstore(fromBalanceSlot, sub(fromBalance, amount)) } // Increase and store the updated balance of `to`. { mstore(0x20, or(_ERC1155_MASTER_SLOT_SEED, to_)) let toBalanceSlot := keccak256(0x00, 0x40) let toBalanceBefore := sload(toBalanceSlot) let toBalanceAfter := add(toBalanceBefore, amount) if lt(toBalanceAfter, toBalanceBefore) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceAfter) } // Emit a {TransferSingle} event. mstore(0x20, amount) // forgefmt: disable-next-line log4(0x00, 0x40, _TRANSFER_SINGLE_EVENT_SIGNATURE, caller(), shr(96, from_), shr(96, to_)) } if (_useAfterTokenTransfer()) { _afterTokenTransfer(from, to, _single(id), _single(amount), data); } if (_hasCode(to)) _checkOnERC1155Received(from, to, id, amount, data); } /// @dev Equivalent to `_safeBatchTransfer(address(0), from, to, ids, amounts, data)`. function _safeBatchTransfer( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { _safeBatchTransfer(address(0), from, to, ids, amounts, data); } /// @dev Transfers `amounts` of `ids` from `from` to `to`. /// /// Requirements: /// - `to` cannot be the zero address. /// - `ids` and `amounts` must have the same length. /// - `from` must have at least `amounts` of `ids`. /// - If `by` is not the zero address, it must be either `from`, /// or approved to manage the tokens of `from`. /// - If `to` refers to a smart contract, it must implement /// {ERC1155-onERC1155BatchReceived}, which is called upon a batch transfer. /// /// Emits a {TransferBatch} event. function _safeBatchTransfer( address by, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(from, to, ids, amounts, data); } /// @solidity memory-safe-assembly assembly { if iszero(eq(mload(ids), mload(amounts))) { mstore(0x00, 0x3b800a46) // `ArrayLengthsMismatch()`. revert(0x1c, 0x04) } let from_ := shl(96, from) let to_ := shl(96, to) // Revert if `to` is the zero address. if iszero(to_) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } let fromSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, from_) let toSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, to_) mstore(0x20, fromSlotSeed) // If `by` is not the zero address, and not equal to `from`, // check if it is approved to manage all the tokens of `from`. let by_ := shl(96, by) if iszero(or(iszero(by_), eq(by_, from_))) { mstore(0x00, by) if iszero(sload(keccak256(0x0c, 0x34))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Loop through all the `ids` and update the balances. { for { let i := shl(5, mload(ids)) } i { i := sub(i, 0x20) } { let amount := mload(add(amounts, i)) // Subtract and store the updated balance of `from`. { mstore(0x20, fromSlotSeed) mstore(0x00, mload(add(ids, i))) let fromBalanceSlot := keccak256(0x00, 0x40) let fromBalance := sload(fromBalanceSlot) if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } sstore(fromBalanceSlot, sub(fromBalance, amount)) } // Increase and store the updated balance of `to`. { mstore(0x20, toSlotSeed) let toBalanceSlot := keccak256(0x00, 0x40) let toBalanceBefore := sload(toBalanceSlot) let toBalanceAfter := add(toBalanceBefore, amount) if lt(toBalanceAfter, toBalanceBefore) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceAfter) } } } // Emit a {TransferBatch} event. { let m := mload(0x40) // Copy the `ids`. mstore(m, 0x40) let n := add(0x20, shl(5, mload(ids))) let o := add(m, 0x40) pop(staticcall(gas(), 4, ids, n, o, n)) // Copy the `amounts`. mstore(add(m, 0x20), add(0x40, returndatasize())) o := add(o, returndatasize()) n := add(0x20, shl(5, mload(amounts))) pop(staticcall(gas(), 4, amounts, n, o, n)) n := sub(add(o, returndatasize()), m) // Do the emit. log4(m, n, _TRANSFER_BATCH_EVENT_SIGNATURE, caller(), shr(96, from_), shr(96, to_)) } } if (_useAfterTokenTransfer()) { _afterTokenTransfer(from, to, ids, amounts, data); } if (_hasCode(to)) _checkOnERC1155BatchReceived(from, to, ids, amounts, data); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HOOKS FOR OVERRIDING */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Override this function to return true if `_beforeTokenTransfer` is used. /// This is to help the compiler avoid producing dead bytecode. function _useBeforeTokenTransfer() internal view virtual returns (bool) { return false; } /// @dev Hook that is called before any token transfer. /// This includes minting and burning, as well as batched variants. /// /// The same hook is called on both single and batched variants. /// For single transfers, the length of the `id` and `amount` arrays are 1. function _beforeTokenTransfer( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} /// @dev Override this function to return true if `_afterTokenTransfer` is used. /// This is to help the compiler avoid producing dead bytecode. function _useAfterTokenTransfer() internal view virtual returns (bool) { return false; } /// @dev Hook that is called after any token transfer. /// This includes minting and burning, as well as batched variants. /// /// The same hook is called on both single and batched variants. /// For single transfers, the length of the `id` and `amount` arrays are 1. function _afterTokenTransfer( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Helper for calling the `_afterTokenTransfer` hook. /// This is to help the compiler avoid producing dead bytecode. function _afterTokenTransferCalldata( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) private { if (_useAfterTokenTransfer()) { _afterTokenTransfer(from, to, ids, amounts, data); } } /// @dev Returns if `a` has bytecode of non-zero length. function _hasCode(address a) private view returns (bool result) { /// @solidity memory-safe-assembly assembly { result := extcodesize(a) // Can handle dirty upper bits. } } /// @dev Perform a call to invoke {IERC1155Receiver-onERC1155Received} on `to`. /// Reverts if the target does not support the function correctly. function _checkOnERC1155Received( address from, address to, uint256 id, uint256 amount, bytes memory data ) private { /// @solidity memory-safe-assembly assembly { // Prepare the calldata. let m := mload(0x40) // `onERC1155Received(address,address,uint256,uint256,bytes)`. mstore(m, 0xf23a6e61) mstore(add(m, 0x20), caller()) mstore(add(m, 0x40), shr(96, shl(96, from))) mstore(add(m, 0x60), id) mstore(add(m, 0x80), amount) mstore(add(m, 0xa0), 0xa0) let n := mload(data) mstore(add(m, 0xc0), n) if n { pop(staticcall(gas(), 4, add(data, 0x20), n, add(m, 0xe0), n)) } // Revert if the call reverts. if iszero(call(gas(), to, 0, add(m, 0x1c), add(0xc4, n), m, 0x20)) { if returndatasize() { // Bubble up the revert if the call reverts. returndatacopy(m, 0x00, returndatasize()) revert(m, returndatasize()) } } // Load the returndata and compare it with the function selector. if iszero(eq(mload(m), shl(224, 0xf23a6e61))) { mstore(0x00, 0x9c05499b) // `TransferToNonERC1155ReceiverImplementer()`. revert(0x1c, 0x04) } } } /// @dev Perform a call to invoke {IERC1155Receiver-onERC1155BatchReceived} on `to`. /// Reverts if the target does not support the function correctly. function _checkOnERC1155BatchReceived( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { /// @solidity memory-safe-assembly assembly { // Prepare the calldata. let m := mload(0x40) // `onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)`. mstore(m, 0xbc197c81) mstore(add(m, 0x20), caller()) mstore(add(m, 0x40), shr(96, shl(96, from))) // Copy the `ids`. mstore(add(m, 0x60), 0xa0) let n := add(0x20, shl(5, mload(ids))) let o := add(m, 0xc0) pop(staticcall(gas(), 4, ids, n, o, n)) // Copy the `amounts`. let s := add(0xa0, returndatasize()) mstore(add(m, 0x80), s) o := add(o, returndatasize()) n := add(0x20, shl(5, mload(amounts))) pop(staticcall(gas(), 4, amounts, n, o, n)) // Copy the `data`. mstore(add(m, 0xa0), add(s, returndatasize())) o := add(o, returndatasize()) n := add(0x20, mload(data)) pop(staticcall(gas(), 4, data, n, o, n)) n := sub(add(o, returndatasize()), add(m, 0x1c)) // Revert if the call reverts. if iszero(call(gas(), to, 0, add(m, 0x1c), n, m, 0x20)) { if returndatasize() { // Bubble up the revert if the call reverts. returndatacopy(m, 0x00, returndatasize()) revert(m, returndatasize()) } } // Load the returndata and compare it with the function selector. if iszero(eq(mload(m), shl(224, 0xbc197c81))) { mstore(0x00, 0x9c05499b) // `TransferToNonERC1155ReceiverImplementer()`. revert(0x1c, 0x04) } } } /// @dev Returns `x` in an array with a single element. function _single(uint256 x) private pure returns (uint256[] memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) mstore(0x40, add(result, 0x40)) mstore(result, 1) mstore(add(result, 0x20), x) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "./IAccessControl.sol"; import {Context} from "../utils/Context.sol"; import {ERC165} from "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } mapping(bytes32 role => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual returns (bool) { return _roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC-165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "remappings": [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "@solady/=lib/solady/src/", "solady/=lib/solady/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"AccountBalanceOverflow","type":"error"},{"inputs":[],"name":"ArrayLengthsMismatch","type":"error"},{"inputs":[],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"NotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferDisabled","type":"error"},{"inputs":[],"name":"TransferToNonERC1155ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"isApproved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"isApproved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxId","type":"uint256"}],"name":"setMaxId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"string","name":"_uri","type":"string"}],"name":"setUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052346100315761001233610035565b5061001c336100a1565b50600360025560405161117d908161010c8239f35b5f80fd5b6001600160a01b03165f8181525f805160206112c9833981519152602052604090205460ff1661009c575f8181525f805160206112c983398151915260205260408120805460ff191660011790553391905f805160206112898339815191528180a4600190565b505f90565b6001600160a01b03165f8181525f805160206112a9833981519152602052604090205460ff1661009c575f8181525f805160206112a983398151915260205260408120805460ff191660019081179091553392915f805160206112898339815191529080a460019056fe608080604052600480361015610013575f80fd5b5f3560e01c918262fdd58e14610df65750816301ffc9a714610d765781630e89341c14610c8f57816316bd864614610c7057816317bac05214610c53578163248a9ca314610c295781632eb2c2d6146109965781632f2ff15d1461095b57816336568abe146109185781634e1273f414610827578163782f08ae1461066157816391d148541461061a57816394d008ef14610406578163a217fddf146103ec578163a22cb4651461037a578163d547741f1461033d578163e985e9c5146102f8578163f242432a1461010d575063fe6d8124146100ee575f80fd5b34610109575f36600319011261010957602060405160018152f35b5f80fd5b346101095760a036600319011261010957610126610e2e565b61012e610e44565b90604435916064359060843567ffffffffffffffff8111610109576101569036908701610e8b565b909361017386906040519160408301604052600183526020830152565b5061018f84906040519160408301604052600183526020830152565b5061019b368387610eef565b506001600160a01b0381166102e757679a31110384e0b0c99060601b81179260601b17918060205260601c928260601c9283156102db578433036102c2575b865f5260405f2080548084116102b657839003905560205260405f208054908282019182106102aa5755806020528284337fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6260405fa4823b61023857005b602094829160405197889663f23a6e618852338989015260408801526060870152608086015260a0808601528160c086015260e085013760c401905f601c8401915af11561029c575b51630dc5919f60e01b0161029157005b639c05499b5f52601cfd5b3d15610281573d5f823e3d90fd5b886301336cea5f52601cfd5b8963f4d678b85f52601cfd5b335f526034600c20546101da5787634b6e7f185f52601cfd5b8763ea553b345f52601cfd5b60405163a24e573d60e01b81528790fd5b3461010957604036600319011261010957610311610e2e565b610319610e44565b90679a31110384e0b0c96020526014525f5260206034600c20546040519015158152f35b3461010957604036600319011261010957610378903561035b610e44565b90805f525f602052610373600160405f20015461101a565b6110d5565b005b3461010957604036600319011261010957610393610e2e565b60243580151580910361010957679a31110384e0b0c960205233601452815f52806034600c20555f5260018060a01b0316337f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160205fa3005b34610109575f3660031901126101095760206040515f8152f35b346101095760603660031901126101095761041f610e2e565b60243560443567ffffffffffffffff81116101095736602382011215610109576104529036906024818701359101610eef565b335f9081527fada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7d60209081526040909120546001949193929060ff16156105fc576002548310156105b8576104b783906040519160408301604052600183526020830152565b5084846040516040810160405282815201528160601b156105ac57679a31110384e0b0c9845281601452825f5260405f208054908682019182106105a057558484526001600160a01b0382165f337fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62604083a4813b61053257005b60405194859363f23a6e61855233868601525f60408601526060850152608084015260a08084015280518091818060c087015261058d575b505060c401905f601c8401915af11561029c5751630dc5919f60e01b0161029157005b818660e087019201895afa50808761056a565b876301336cea5f52601cfd5b8563ea553b345f52601cfd5b60405162461bcd60e51b8152808701859052601760248201527f496e76616c696420636f6c6c656374696f6e20747970650000000000000000006044820152606490fd5b60405163e2517d3f60e01b8152338188015260248101869052604490fd5b3461010957604036600319011261010957610633610e44565b90355f525f60205260405f209060018060a01b03165f52602052602060ff60405f2054166040519015158152f35b3461010957604036600319011261010957803567ffffffffffffffff602435818111610109576106949036908501610e8b565b9161069d610fc4565b835f52600160209581875260405f2092851161081457506106be8254610f35565b601f81116107ce575b505f601f8511600114610748576040937f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b9697938680809581955f9361073d575b501b905f198560031b1c19161790555b8451958487958652850152848401375f828201840152601f01601f19168101030190a2005b85013592508c610708565b601f19851690835f52875f20915f5b8181106107b95750938693849360409793857f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b9b9c98106107a0575b505083811b019055610718565b8401355f19600387901b60f8161c191690558a80610793565b86830135845592840192918901918901610757565b825f52865f20601f860160051c81019188871061080a575b601f0160051c019082905b8281106107ff5750506106c7565b5f81550182906107f1565b90915081906107e6565b604190634e487b7160e01b5f525260245ffd5b346101095760403660031901126101095767ffffffffffffffff8135818111610109576108579036908401610e5a565b916024359081116101095761086f9036908501610e5a565b939092840361090d57506040519280845260051b6020928184868201016040525b6108d857505050604051918183928301818452825180915281604085019301915f5b8281106108c157505050500390f35b8351855286955093810193928101926001016108b2565b818290601f1980940193828186948801013560601b679a31110384e0b0c9178852840101355f5260405f205490870152610890565b633b800a465f52601cfd5b3461010957604036600319011261010957610931610e44565b336001600160a01b0382160361094b5761037891356110d5565b5060405163334bd91960e11b8152fd5b34610109576040366003190112610109576103789035610979610e44565b90805f525f602052610991600160405f20015461101a565b611059565b346101095760a0366003190112610109576109af610e2e565b6109b7610e44565b67ffffffffffffffff90604435828111610109576109d89036908601610e5a565b606494919435848111610109576109f29036908801610e5a565b91909460843590811161010957610a0c9036908901610e8b565b939092610a1a36848a610f6d565b50610a26368289610f6d565b50610a32368686610eef565b506001600160a01b038216610c18578203610c0c57679a31110384e0b0c99060601b81179460601b1791846020528260601c8015610c00578560601c3303610be7575b8260051b938480955b610b875750508060405160408152846040820152858a60608301378560600160208201528589608082840188606082015201378760601c907f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb339160808980010190a4803b610ae957005b60209685858195610120945f52816040519c8d9b63bc197c818d528c8e3391015260601c60408d015260a060608d01528260c08d015260e08c01378160c00160808b0152818a019060e082015281610100948583013760e08280010160a08b01520191820152013780010161010401601c604051015f80515af115610b79575b516343e6837f60e01b0161029157005b3d15610b69573d5f823e3d90fd5b80601f198092019180828c010135918a6020528c0101355f5260405f208054808311610bdb5782900390558260205260405f20908154908101908110610bcf57829155610a7e565b8c6301336cea5f52601cfd5b8d63f4d678b85f52601cfd5b335f526034600c2054610a755788634b6e7f185f52601cfd5b8863ea553b345f52601cfd5b87633b800a465f52601cfd5b60405163a24e573d60e01b81528990fd5b3461010957602036600319011261010957355f525f6020526020600160405f200154604051908152f35b34610109575f366003190112610109576020600254604051908152f35b3461010957602036600319011261010957610c89610fc4565b35600255005b34610109576020908160031936011261010957355f52600180825260405f2090604051905f9284815492610cc284610f35565b92838652828601946001811690815f14610d565750600114610d1a575b50505050610cf1826040940383610eb9565b825193849281845251918280928501528484015e5f828201840152601f01601f19168101030190f35b5f90815282812092965092915b828410610d4357505050820190920191610cf184604084610cdf565b8054868501880152928601928101610d27565b60ff1916865250505090151560051b8301019250610cf184604084610cdf565b3461010957602036600319011261010957356001600160e01b031981168082036101095760209160e01c630e89341c8114906301ffc9a763d9b67a26821491141717908115610dcb575b506040519015158152f35b637965db0b60e01b811491508115610de5575b5082610dc0565b6301ffc9a760e01b14905082610dde565b3461010957604036600319011261010957602090610e12610e2e565b679a31110384e0b0c983526014526024355f5260405f20548152f35b600435906001600160a01b038216820361010957565b602435906001600160a01b038216820361010957565b9181601f840112156101095782359167ffffffffffffffff8311610109576020808501948460051b01011161010957565b9181601f840112156101095782359167ffffffffffffffff8311610109576020838186019501011161010957565b90601f8019910116810190811067ffffffffffffffff821117610edb57604052565b634e487b7160e01b5f52604160045260245ffd5b92919267ffffffffffffffff8211610edb5760405191610f19601f8201601f191660200184610eb9565b829481845281830111610109578281602093845f960137010152565b90600182811c92168015610f63575b6020831014610f4f57565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610f44565b90929167ffffffffffffffff8411610edb578360051b6020926020604051610f9782850182610eb9565b809781520191810192831161010957905b828210610fb55750505050565b81358152908301908301610fa8565b335f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1615610ffc57565b60405163e2517d3f60e01b81523360048201525f6024820152604490fd5b805f525f60205260405f20335f5260205260ff60405f2054161561103b5750565b6044906040519063e2517d3f60e01b82523360048301526024820152fd5b90815f525f60205260405f209060018060a01b031690815f5260205260ff60405f205416155f146110cf57815f525f60205260405f20815f5260205260405f20600160ff1982541617905533917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b90815f525f60205260405f209060018060a01b031690815f5260205260ff60405f2054165f146110cf57815f525f60205260405f20815f5260205260405f2060ff19815416905533917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a460019056fea26469706673582212201ac90e173ae972597ba8dc5de25cd1610b364a06e3b649389eed4ca580d59c5c64736f6c634300081900332f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0dada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7dad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5
Deployed Bytecode
0x608080604052600480361015610013575f80fd5b5f3560e01c918262fdd58e14610df65750816301ffc9a714610d765781630e89341c14610c8f57816316bd864614610c7057816317bac05214610c53578163248a9ca314610c295781632eb2c2d6146109965781632f2ff15d1461095b57816336568abe146109185781634e1273f414610827578163782f08ae1461066157816391d148541461061a57816394d008ef14610406578163a217fddf146103ec578163a22cb4651461037a578163d547741f1461033d578163e985e9c5146102f8578163f242432a1461010d575063fe6d8124146100ee575f80fd5b34610109575f36600319011261010957602060405160018152f35b5f80fd5b346101095760a036600319011261010957610126610e2e565b61012e610e44565b90604435916064359060843567ffffffffffffffff8111610109576101569036908701610e8b565b909361017386906040519160408301604052600183526020830152565b5061018f84906040519160408301604052600183526020830152565b5061019b368387610eef565b506001600160a01b0381166102e757679a31110384e0b0c99060601b81179260601b17918060205260601c928260601c9283156102db578433036102c2575b865f5260405f2080548084116102b657839003905560205260405f208054908282019182106102aa5755806020528284337fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6260405fa4823b61023857005b602094829160405197889663f23a6e618852338989015260408801526060870152608086015260a0808601528160c086015260e085013760c401905f601c8401915af11561029c575b51630dc5919f60e01b0161029157005b639c05499b5f52601cfd5b3d15610281573d5f823e3d90fd5b886301336cea5f52601cfd5b8963f4d678b85f52601cfd5b335f526034600c20546101da5787634b6e7f185f52601cfd5b8763ea553b345f52601cfd5b60405163a24e573d60e01b81528790fd5b3461010957604036600319011261010957610311610e2e565b610319610e44565b90679a31110384e0b0c96020526014525f5260206034600c20546040519015158152f35b3461010957604036600319011261010957610378903561035b610e44565b90805f525f602052610373600160405f20015461101a565b6110d5565b005b3461010957604036600319011261010957610393610e2e565b60243580151580910361010957679a31110384e0b0c960205233601452815f52806034600c20555f5260018060a01b0316337f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160205fa3005b34610109575f3660031901126101095760206040515f8152f35b346101095760603660031901126101095761041f610e2e565b60243560443567ffffffffffffffff81116101095736602382011215610109576104529036906024818701359101610eef565b335f9081527fada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7d60209081526040909120546001949193929060ff16156105fc576002548310156105b8576104b783906040519160408301604052600183526020830152565b5084846040516040810160405282815201528160601b156105ac57679a31110384e0b0c9845281601452825f5260405f208054908682019182106105a057558484526001600160a01b0382165f337fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62604083a4813b61053257005b60405194859363f23a6e61855233868601525f60408601526060850152608084015260a08084015280518091818060c087015261058d575b505060c401905f601c8401915af11561029c5751630dc5919f60e01b0161029157005b818660e087019201895afa50808761056a565b876301336cea5f52601cfd5b8563ea553b345f52601cfd5b60405162461bcd60e51b8152808701859052601760248201527f496e76616c696420636f6c6c656374696f6e20747970650000000000000000006044820152606490fd5b60405163e2517d3f60e01b8152338188015260248101869052604490fd5b3461010957604036600319011261010957610633610e44565b90355f525f60205260405f209060018060a01b03165f52602052602060ff60405f2054166040519015158152f35b3461010957604036600319011261010957803567ffffffffffffffff602435818111610109576106949036908501610e8b565b9161069d610fc4565b835f52600160209581875260405f2092851161081457506106be8254610f35565b601f81116107ce575b505f601f8511600114610748576040937f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b9697938680809581955f9361073d575b501b905f198560031b1c19161790555b8451958487958652850152848401375f828201840152601f01601f19168101030190a2005b85013592508c610708565b601f19851690835f52875f20915f5b8181106107b95750938693849360409793857f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b9b9c98106107a0575b505083811b019055610718565b8401355f19600387901b60f8161c191690558a80610793565b86830135845592840192918901918901610757565b825f52865f20601f860160051c81019188871061080a575b601f0160051c019082905b8281106107ff5750506106c7565b5f81550182906107f1565b90915081906107e6565b604190634e487b7160e01b5f525260245ffd5b346101095760403660031901126101095767ffffffffffffffff8135818111610109576108579036908401610e5a565b916024359081116101095761086f9036908501610e5a565b939092840361090d57506040519280845260051b6020928184868201016040525b6108d857505050604051918183928301818452825180915281604085019301915f5b8281106108c157505050500390f35b8351855286955093810193928101926001016108b2565b818290601f1980940193828186948801013560601b679a31110384e0b0c9178852840101355f5260405f205490870152610890565b633b800a465f52601cfd5b3461010957604036600319011261010957610931610e44565b336001600160a01b0382160361094b5761037891356110d5565b5060405163334bd91960e11b8152fd5b34610109576040366003190112610109576103789035610979610e44565b90805f525f602052610991600160405f20015461101a565b611059565b346101095760a0366003190112610109576109af610e2e565b6109b7610e44565b67ffffffffffffffff90604435828111610109576109d89036908601610e5a565b606494919435848111610109576109f29036908801610e5a565b91909460843590811161010957610a0c9036908901610e8b565b939092610a1a36848a610f6d565b50610a26368289610f6d565b50610a32368686610eef565b506001600160a01b038216610c18578203610c0c57679a31110384e0b0c99060601b81179460601b1791846020528260601c8015610c00578560601c3303610be7575b8260051b938480955b610b875750508060405160408152846040820152858a60608301378560600160208201528589608082840188606082015201378760601c907f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb339160808980010190a4803b610ae957005b60209685858195610120945f52816040519c8d9b63bc197c818d528c8e3391015260601c60408d015260a060608d01528260c08d015260e08c01378160c00160808b0152818a019060e082015281610100948583013760e08280010160a08b01520191820152013780010161010401601c604051015f80515af115610b79575b516343e6837f60e01b0161029157005b3d15610b69573d5f823e3d90fd5b80601f198092019180828c010135918a6020528c0101355f5260405f208054808311610bdb5782900390558260205260405f20908154908101908110610bcf57829155610a7e565b8c6301336cea5f52601cfd5b8d63f4d678b85f52601cfd5b335f526034600c2054610a755788634b6e7f185f52601cfd5b8863ea553b345f52601cfd5b87633b800a465f52601cfd5b60405163a24e573d60e01b81528990fd5b3461010957602036600319011261010957355f525f6020526020600160405f200154604051908152f35b34610109575f366003190112610109576020600254604051908152f35b3461010957602036600319011261010957610c89610fc4565b35600255005b34610109576020908160031936011261010957355f52600180825260405f2090604051905f9284815492610cc284610f35565b92838652828601946001811690815f14610d565750600114610d1a575b50505050610cf1826040940383610eb9565b825193849281845251918280928501528484015e5f828201840152601f01601f19168101030190f35b5f90815282812092965092915b828410610d4357505050820190920191610cf184604084610cdf565b8054868501880152928601928101610d27565b60ff1916865250505090151560051b8301019250610cf184604084610cdf565b3461010957602036600319011261010957356001600160e01b031981168082036101095760209160e01c630e89341c8114906301ffc9a763d9b67a26821491141717908115610dcb575b506040519015158152f35b637965db0b60e01b811491508115610de5575b5082610dc0565b6301ffc9a760e01b14905082610dde565b3461010957604036600319011261010957602090610e12610e2e565b679a31110384e0b0c983526014526024355f5260405f20548152f35b600435906001600160a01b038216820361010957565b602435906001600160a01b038216820361010957565b9181601f840112156101095782359167ffffffffffffffff8311610109576020808501948460051b01011161010957565b9181601f840112156101095782359167ffffffffffffffff8311610109576020838186019501011161010957565b90601f8019910116810190811067ffffffffffffffff821117610edb57604052565b634e487b7160e01b5f52604160045260245ffd5b92919267ffffffffffffffff8211610edb5760405191610f19601f8201601f191660200184610eb9565b829481845281830111610109578281602093845f960137010152565b90600182811c92168015610f63575b6020831014610f4f57565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610f44565b90929167ffffffffffffffff8411610edb578360051b6020926020604051610f9782850182610eb9565b809781520191810192831161010957905b828210610fb55750505050565b81358152908301908301610fa8565b335f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1615610ffc57565b60405163e2517d3f60e01b81523360048201525f6024820152604490fd5b805f525f60205260405f20335f5260205260ff60405f2054161561103b5750565b6044906040519063e2517d3f60e01b82523360048301526024820152fd5b90815f525f60205260405f209060018060a01b031690815f5260205260ff60405f205416155f146110cf57815f525f60205260405f20815f5260205260405f20600160ff1982541617905533917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b90815f525f60205260405f209060018060a01b031690815f5260205260ff60405f2054165f146110cf57815f525f60205260405f20815f5260205260405f2060ff19815416905533917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a460019056fea26469706673582212201ac90e173ae972597ba8dc5de25cd1610b364a06e3b649389eed4ca580d59c5c64736f6c63430008190033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.