ETH Price: $3,020.54 (+0.13%)
Gas: 11 Gwei

Token

Chiblings (CHIB)
 

Overview

Max Total Supply

6,604 CHIB

Holders

2,551

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
testerbot.eth
Balance
1 CHIB
0x9c9cebfe89ac87a5195f75a6a6964f7ba140e7b5
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
ChiblingMirror

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 2 : ChiblingMirror.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
/*
                                 111110000000000111111                                                                     
                             1110000000000011100000000011111                                                               
                          110000000111           1111000000000111                                                          
                       11000000011                     1111100000111                                                       
                     110000011                               111000011                                                     
                 1110000111                                      11000011                                                  
               110000111                                           11000011                                                
             10000011                                                 1100011                                              
            100001                                                      100001                                             
           10001                                                          000001                                           
          10001                                                            1000011                                         
         10000                                                              1110001                                        
         00001                                                                 00001                                       
        100001                                                               111000111111                                  
        10001                                                          11100000000000000001                                
       10001           1111000000000011111                           10000000111111111100001                               
       10001        110000000011100000000001                        100000111      111000001                               
       10001       100001111        11100001                         1100000001100000000011                                
       1000         10000001111111110000001                             1111000000000111                                   
      10000          11100000000000000011                  11111111           111000                                       
      10001               11111111111                 11100000000000011         10001                                      
      10001                                        11000000000000000000011      10001                                      
      0000                                      1100000011111  1000111000001     0001                                      
     10001                                   1100000011         10001  1100001   0001                                      
     10001                                 1100000011            10001   1100001 0001                                      
     10001                               100000011                111      1000000000                                      
     10001                             10000011                              10000000                                      
     10001                            100001                                   1100001                                     
     10001                            0001                                       1000001                                   
     10001                            0000                                         1000011                                 
     10001                            100011                                        11000011                               
     10001                             100001                                         11000011                             
     10001                              100001                                           100001                            
     0000                                100001                                            100001                          
     0000                                  100011                                            100001                        
    10001                                   1000011                                           1100001                      
    10001                                    1100001                                            1100001                    
    10001                                      100001                                              100001                  
    10001                                        10001                                               100011                
    10001                                         10001                                               100001               
    10001                                          1000011                       111111111111111        10001              
    10001                                            100000111             1111000000000000000000011111110001              
    10001                                              1110000011     111100000001111111111111100000000000011              
    10001                                                 1110000000000000000001111111111111100000000001111                
    10001                                                     110000000000000000000000000000000111                         
    10001                                                               111111111111100001111                              
    1000                                                                             0001                                  
    0001                                                                             1001                                  
   10001                                                                             1001                                  
   10001                                                                             10001                                 
   10001                                                                             10001                                 
   1000                                                                              10001                                 
   0001                                                                              10001                                 
   0001                                                                              10001                                 
  10001                                                                               0001                                 
  1000                                                                                1001                                 
 10000                                                                                1000                                 
 10001                                                                                10001                                
 10001                                                                                10001                                
 1000                                                                                 10001                                
 0001                                                                                 10001                                
10001                                                                                 10001                                
10001                                                                                 10001                                
10001                                                                                 10001                                
00001                                                                                 10001                                
*/
import {DN404Mirror} from "dn404/src/DN404Mirror.sol";

contract ChiblingMirror is DN404Mirror {

    constructor() DN404Mirror(tx.origin) {}
}

File 2 of 2 : DN404Mirror.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @title DN404Mirror
/// @notice DN404Mirror provides an interface for interacting with the
/// NFT tokens in a DN404 implementation.
///
/// @author vectorized.eth (@optimizoor)
/// @author Quit (@0xQuit)
/// @author Michael Amadi (@AmadiMichaels)
/// @author cygaar (@0xCygaar)
/// @author Thomas (@0xjustadev)
/// @author Harrison (@PopPunkOnChain)
///
/// @dev Note:
/// - The ERC721 data is stored in the base DN404 contract.
contract DN404Mirror {
    /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/
    /*                           EVENTS                           */
    /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/

    /// @dev Emitted when token `id` is transferred from `from` to `to`.
    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    /// @dev Emitted when `owner` enables `account` to manage the `id` token.
    event Approval(address indexed owner, address indexed account, uint256 indexed id);

    /// @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 The ownership is transferred from `oldOwner` to `newOwner`.
    /// This is for marketplace signaling purposes. This contract has a `pullOwner()`
    /// function that will sync the owner from the base contract.
    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);

    /// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
    uint256 private constant _TRANSFER_EVENT_SIGNATURE =
        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    /// @dev `keccak256(bytes("Approval(address,address,uint256)"))`.
    uint256 private constant _APPROVAL_EVENT_SIGNATURE =
        0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;

    /// @dev `keccak256(bytes("ApprovalForAll(address,address,bool)"))`.
    uint256 private constant _APPROVAL_FOR_ALL_EVENT_SIGNATURE =
        0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31;

    /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/
    /*                        CUSTOM ERRORS                       */
    /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/

    /// @dev Thrown when a call for an NFT function did not originate
    /// from the base DN404 contract.
    error SenderNotBase();

    /// @dev Thrown when a call for an NFT function did not originate from the deployer.
    error SenderNotDeployer();

    /// @dev Thrown when transferring an NFT to a contract address that
    /// does not implement ERC721Receiver.
    error TransferToNonERC721ReceiverImplementer();

    /// @dev Thrown when linking to the DN404 base contract and the
    /// DN404 supportsInterface check fails or the call reverts.
    error CannotLink();

    /// @dev Thrown when a linkMirrorContract call is received and the
    /// NFT mirror contract has already been linked to a DN404 base contract.
    error AlreadyLinked();

    /// @dev Thrown when retrieving the base DN404 address when a link has not
    /// been established.
    error NotLinked();

    /// @dev The function selector is not recognized.
    error FnSelectorNotRecognized();

    /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/
    /*                          STORAGE                           */
    /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/

    /// @dev Struct contain the NFT mirror contract storage.
    struct DN404NFTStorage {
        address baseERC20;
        address deployer;
        address owner;
    }

    /// @dev Returns a storage pointer for DN404NFTStorage.
    function _getDN404NFTStorage() internal pure virtual returns (DN404NFTStorage storage $) {
        /// @solidity memory-safe-assembly
        assembly {
            // `uint72(bytes9(keccak256("DN404_MIRROR_STORAGE")))`.
            $.slot := 0x3602298b8c10b01230 // Truncate to 9 bytes to reduce bytecode size.
        }
    }

    /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/
    /*                        CONSTRUCTOR                         */
    /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/

    constructor(address deployer) {
        // For non-proxies, we will store the deployer so that only the deployer can
        // link the base contract.
        _getDN404NFTStorage().deployer = deployer;
    }

    /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/
    /*                     ERC721 OPERATIONS                      */
    /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/

    /// @dev Returns the token collection name from the base DN404 contract.
    function name() public view virtual returns (string memory result) {
        return _readString(0x06fdde03, 0); // `name()`.
    }

    /// @dev Returns the token collection symbol from the base DN404 contract.
    function symbol() public view virtual returns (string memory result) {
        return _readString(0x95d89b41, 0); // `symbol()`.
    }

    /// @dev Returns the Uniform Resource Identifier (URI) for token `id` from
    /// the base DN404 contract.
    function tokenURI(uint256 id) public view virtual returns (string memory result) {
        return _readString(0xc87b56dd, id); // `tokenURI()`.
    }

    /// @dev Returns the total NFT supply from the base DN404 contract.
    function totalSupply() public view virtual returns (uint256 result) {
        return _readWord(0xe2c79281, 0, 0); // `totalNFTSupply()`.
    }

    /// @dev Returns the number of NFT tokens owned by `nftOwner` from the base DN404 contract.
    ///
    /// Requirements:
    /// - `nftOwner` must not be the zero address.
    function balanceOf(address nftOwner) public view virtual returns (uint256 result) {
        return _readWord(0xf5b100ea, uint160(nftOwner), 0); // `balanceOfNFT(address)`.
    }

    /// @dev Returns the owner of token `id` from the base DN404 contract.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    function ownerOf(uint256 id) public view virtual returns (address result) {
        return address(uint160(_readWord(0x6352211e, id, 0))); // `ownerOf(uint256)`.
    }

    /// @dev Returns the owner of token `id` from the base DN404 contract.
    /// Returns `address(0)` instead of reverting if the token does not exist.
    function ownerAt(uint256 id) public view virtual returns (address result) {
        return address(uint160(_readWord(0x24359879, id, 0))); // `ownerAt(uint256)`.
    }

    /// @dev Sets `spender` as the approved account to manage token `id` in
    /// the base DN404 contract.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    /// - The caller must be the owner of the token,
    ///   or an approved operator for the token owner.
    ///
    /// Emits an {Approval} event.
    function approve(address spender, uint256 id) public virtual {
        address base = baseERC20();
        /// @solidity memory-safe-assembly
        assembly {
            spender := shr(96, shl(96, spender))
            let m := mload(0x40)
            mstore(0x00, 0xd10b6e0c) // `approveNFT(address,uint256,address)`.
            mstore(0x20, spender)
            mstore(0x40, id)
            mstore(0x60, caller())
            if iszero(
                and(
                    gt(returndatasize(), 0x1f),
                    call(gas(), base, callvalue(), 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                returndatacopy(m, 0x00, returndatasize())
                revert(m, returndatasize())
            }
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero pointer.
            // Emit the {Approval} event.
            log4(codesize(), 0x00, _APPROVAL_EVENT_SIGNATURE, shr(96, mload(0x0c)), spender, id)
        }
    }

    /// @dev Returns the account approved to manage token `id` from
    /// the base DN404 contract.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    function getApproved(uint256 id) public view virtual returns (address) {
        return address(uint160(_readWord(0x081812fc, id, 0))); // `getApproved(uint256)`.
    }

    /// @dev Sets whether `operator` is approved to manage the tokens of the caller in
    /// the base DN404 contract.
    ///
    /// Emits an {ApprovalForAll} event.
    function setApprovalForAll(address operator, bool approved) public virtual {
        address base = baseERC20();
        /// @solidity memory-safe-assembly
        assembly {
            operator := shr(96, shl(96, operator))
            let m := mload(0x40)
            mstore(0x00, 0x813500fc) // `setApprovalForAll(address,bool,address)`.
            mstore(0x20, operator)
            mstore(0x40, iszero(iszero(approved)))
            mstore(0x60, caller())
            if iszero(
                and(eq(mload(0x00), 1), call(gas(), base, callvalue(), 0x1c, 0x64, 0x00, 0x20))
            ) {
                returndatacopy(m, 0x00, returndatasize())
                revert(m, returndatasize())
            }
            // Emit the {ApprovalForAll} event.
            // The `approved` value is already at 0x40.
            log3(0x40, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, caller(), operator)
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero pointer.
        }
    }

    /// @dev Returns whether `operator` is approved to manage the tokens of `nftOwner` from
    /// the base DN404 contract.
    function isApprovedForAll(address nftOwner, address operator)
        public
        view
        virtual
        returns (bool result)
    {
        // `isApprovedForAll(address,address)`.
        return _readWord(0xe985e9c5, uint160(nftOwner), uint160(operator)) != 0;
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - The caller must be the owner of the token, or be approved to manage the token.
    ///
    /// Emits a {Transfer} event.
    function transferFrom(address from, address to, uint256 id) public virtual {
        address base = baseERC20();
        /// @solidity memory-safe-assembly
        assembly {
            from := shr(96, shl(96, from))
            to := shr(96, shl(96, to))
            let m := mload(0x40)
            mstore(m, 0xe5eb36c8) // `transferFromNFT(address,address,uint256,address)`.
            mstore(add(m, 0x20), from)
            mstore(add(m, 0x40), to)
            mstore(add(m, 0x60), id)
            mstore(add(m, 0x80), caller())
            if iszero(
                and(eq(mload(m), 1), call(gas(), base, callvalue(), add(m, 0x1c), 0x84, m, 0x20))
            ) {
                returndatacopy(m, 0x00, returndatasize())
                revert(m, returndatasize())
            }
            // Emit the {Transfer} event.
            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id)
        }
    }

    /// @dev Equivalent to `safeTransferFrom(from, to, id, "")`.
    function safeTransferFrom(address from, address to, uint256 id) public payable virtual {
        transferFrom(from, to, id);

        if (_hasCode(to)) _checkOnERC721Received(from, to, id, "");
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - The caller must be the owner of the token, or be approved to manage the token.
    /// - If `to` refers to a smart contract, it must implement
    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
    ///
    /// Emits a {Transfer} event.
    function safeTransferFrom(address from, address to, uint256 id, bytes calldata data)
        public
        virtual
    {
        transferFrom(from, to, id);

        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);
    }

    /// @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, ERC721: 0x80ac58cd, ERC721Metadata: 0x5b5e139f.
            result := or(or(eq(s, 0x01ffc9a7), eq(s, 0x80ac58cd)), eq(s, 0x5b5e139f))
        }
    }

    /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/
    /*                  OWNER SYNCING OPERATIONS                  */
    /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/

    /// @dev Returns the `owner` of the contract, for marketplace signaling purposes.
    function owner() public view virtual returns (address) {
        return _getDN404NFTStorage().owner;
    }

    /// @dev Permissionless function to pull the owner from the base DN404 contract
    /// if it implements ownable, for marketplace signaling purposes.
    function pullOwner() public virtual {
        address newOwner;
        address base = baseERC20();
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x8da5cb5b) // `owner()`.
            if and(gt(returndatasize(), 0x1f), staticcall(gas(), base, 0x1c, 0x04, 0x00, 0x20)) {
                newOwner := shr(96, mload(0x0c))
            }
        }
        DN404NFTStorage storage $ = _getDN404NFTStorage();
        address oldOwner = $.owner;
        if (oldOwner != newOwner) {
            $.owner = newOwner;
            emit OwnershipTransferred(oldOwner, newOwner);
        }
    }

    /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/
    /*                     MIRROR OPERATIONS                      */
    /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/

    /// @dev Returns the address of the base DN404 contract.
    function baseERC20() public view virtual returns (address base) {
        base = _getDN404NFTStorage().baseERC20;
        if (base == address(0)) revert NotLinked();
    }

    /// @dev Fallback modifier to execute calls from the base DN404 contract.
    modifier dn404NFTFallback() virtual {
        DN404NFTStorage storage $ = _getDN404NFTStorage();

        uint256 fnSelector = _calldataload(0x00) >> 224;

        // `logTransfer(uint256[])`.
        if (fnSelector == 0x263c69d6) {
            if (msg.sender != $.baseERC20) revert SenderNotBase();
            /// @solidity memory-safe-assembly
            assembly {
                let o := add(0x24, calldataload(0x04)) // Packed logs offset.
                let end := add(o, shl(5, calldataload(sub(o, 0x20))))

                for {} iszero(eq(o, end)) { o := add(0x20, o) } {
                    let d := calldataload(o) // Entry in the packed logs.
                    let a := shr(96, d) // The address.
                    let b := and(1, d) // Whether it is a burn.
                    log4(
                        codesize(),
                        0x00,
                        _TRANSFER_EVENT_SIGNATURE,
                        mul(a, b), // `from`.
                        mul(a, iszero(b)), // `to`.
                        shr(168, shl(160, d)) // `id`.
                    )
                }
                mstore(0x00, 0x01)
                return(0x00, 0x20)
            }
        }
        // `logDirectTransfer(address,address,uint256[])`.
        if (fnSelector == 0x144027d3) {
            if (msg.sender != $.baseERC20) revert SenderNotBase();
            /// @solidity memory-safe-assembly
            assembly {
                let from := calldataload(0x04)
                let to := calldataload(0x24)
                let o := add(0x24, calldataload(0x44)) // Direct logs offset.
                let end := add(o, shl(5, calldataload(sub(o, 0x20))))

                for {} iszero(eq(o, end)) { o := add(0x20, o) } {
                    log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, calldataload(o))
                }
                mstore(0x00, 0x01)
                return(0x00, 0x20)
            }
        }
        // `linkMirrorContract(address)`.
        if (fnSelector == 0x0f4599e5) {
            if ($.deployer != address(0)) {
                if (address(uint160(_calldataload(0x04))) != $.deployer) {
                    revert SenderNotDeployer();
                }
            }
            if ($.baseERC20 != address(0)) revert AlreadyLinked();
            $.baseERC20 = msg.sender;
            /// @solidity memory-safe-assembly
            assembly {
                mstore(0x00, 0x01)
                return(0x00, 0x20)
            }
        }
        _;
    }

    /// @dev Fallback function for calls from base DN404 contract.
    /// Override this if you need to implement your custom
    /// fallback with utilities like Solady's `LibZip.cdFallback()`.
    /// And always remember to always wrap the fallback with `dn404NFTFallback`.
    fallback() external payable virtual dn404NFTFallback {
        revert FnSelectorNotRecognized(); // Not mandatory. Just for quality of life.
    }

    /// @dev This is to silence the compiler warning.
    /// Override and remove the revert if you want your contract to receive ETH via receive.
    receive() external payable virtual {
        if (msg.value != 0) revert();
    }

    /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/
    /*                      PRIVATE HELPERS                       */
    /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/

    /// @dev Helper to read a string from the base DN404 contract.
    function _readString(uint256 fnSelector, uint256 arg0)
        private
        view
        returns (string memory result)
    {
        address base = baseERC20();
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            mstore(0x00, fnSelector)
            mstore(0x20, arg0)
            if iszero(staticcall(gas(), base, 0x1c, 0x24, 0x00, 0x00)) {
                returndatacopy(result, 0x00, returndatasize())
                revert(result, returndatasize())
            }
            returndatacopy(0x00, 0x00, 0x20) // Copy the offset of the string in returndata.
            returndatacopy(result, mload(0x00), 0x20) // Copy the length of the string.
            returndatacopy(add(result, 0x20), add(mload(0x00), 0x20), mload(result)) // Copy the string.
            mstore(0x40, add(add(result, 0x20), mload(result))) // Allocate memory.
        }
    }

    /// @dev Helper to read a word from the base DN404 contract.
    function _readWord(uint256 fnSelector, uint256 arg0, uint256 arg1)
        private
        view
        returns (uint256 result)
    {
        address base = baseERC20();
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(0x00, fnSelector)
            mstore(0x20, arg0)
            mstore(0x40, arg1)
            if iszero(
                and(gt(returndatasize(), 0x1f), staticcall(gas(), base, 0x1c, 0x44, 0x00, 0x20))
            ) {
                returndatacopy(m, 0x00, returndatasize())
                revert(m, returndatasize())
            }
            mstore(0x40, m) // Restore the free memory pointer.
            result := mload(0x00)
        }
    }

    /// @dev Returns the calldata value at `offset`.
    function _calldataload(uint256 offset) private pure returns (uint256 value) {
        /// @solidity memory-safe-assembly
        assembly {
            value := calldataload(offset)
        }
    }

    /// @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 {IERC721Receiver-onERC721Received} on `to`.
    /// Reverts if the target does not support the function correctly.
    function _checkOnERC721Received(address from, address to, uint256 id, bytes memory data)
        private
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Prepare the calldata.
            let m := mload(0x40)
            let onERC721ReceivedSelector := 0x150b7a02
            mstore(m, onERC721ReceivedSelector)
            mstore(add(m, 0x20), caller()) // The `operator`, which is always `msg.sender`.
            mstore(add(m, 0x40), shr(96, shl(96, from)))
            mstore(add(m, 0x60), id)
            mstore(add(m, 0x80), 0x80)
            let n := mload(data)
            mstore(add(m, 0xa0), n)
            if n { pop(staticcall(gas(), 4, add(data, 0x20), n, add(m, 0xc0), n)) }
            // Revert if the call reverts.
            if iszero(call(gas(), to, 0, add(m, 0x1c), add(n, 0xa4), 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.
            if iszero(eq(mload(m), shl(224, onERC721ReceivedSelector))) {
                mstore(0x00, 0xd1a57ed6) // `TransferToNonERC721ReceiverImplementer()`.
                revert(0x1c, 0x04)
            }
        }
    }
}

Settings
{
  "remappings": [
    "dn404/=lib/dn404/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "solady/=lib/solady/src/",
    "murky/=lib/dn404/lib/murky/",
    "openzeppelin-contracts/=lib/dn404/lib/murky/lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyLinked","type":"error"},{"inputs":[],"name":"CannotLink","type":"error"},{"inputs":[],"name":"FnSelectorNotRecognized","type":"error"},{"inputs":[],"name":"NotLinked","type":"error"},{"inputs":[],"name":"SenderNotBase","type":"error"},{"inputs":[],"name":"SenderNotDeployer","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"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":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftOwner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseERC20","outputs":[{"internalType":"address","name":"base","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftOwner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"result","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerAt","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pullOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","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":"approved","type":"bool"}],"name":"setApprovalForAll","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":[],"name":"symbol","outputs":[{"internalType":"string","name":"result","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"result","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405234801561001057600080fd5b50683602298b8c10b0123180546001600160a01b03191632179055610d068061003a6000396000f3fe60806040526004361061010d5760003560e01c80636cef16e61161009557806397e5311c1161006457806397e5311c146104f1578063a22cb46514610506578063b88d4fde14610526578063c87b56dd14610546578063e985e9c5146105665761011f565b80636cef16e61461048157806370a08231146104965780638da5cb5b146104b657806395d89b41146104dc5761011f565b806318160ddd116100dc57806318160ddd146103eb57806323b872dd1461040e578063243598791461042e57806342842e0e1461044e5780636352211e146104615761011f565b806301ffc9a71461031f57806306fdde0314610371578063081812fc14610393578063095ea7b3146103cb5761011f565b3661011f57341561011d57600080fd5b005b683602298b8c10b0123060003560e01c63263c69d68190036101d55781546001600160a01b0316331461016557604051631b1e598960e11b815260040160405180910390fd5b600435602401602081033560051b81015b8082146101c85781358060601c816001168260a01b60a81c811583028284027fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600038a4505050816020019150610176565b5050600160005260206000f35b8063144027d30361026b5781546001600160a01b0316331461020a57604051631b1e598960e11b815260040160405180910390fd5b600435602435604435602401602081033560051b81015b80821461025c57813583857fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600038a4816020019150610221565b50505050600160005260206000f35b80630f4599e5036103065760018201546001600160a01b0316156102c15760018201546001600160a01b03166004356001600160a01b0316146102c1576040516362cf623d60e11b815260040160405180910390fd5b81546001600160a01b0316156102ea57604051635fb2b52360e11b815260040160405180910390fd5b81546001600160a01b0319163317825560016000908152602090f35b604051631e085ca760e11b815260040160405180910390fd5b34801561032b57600080fd5b5061035c61033a366004610a90565b6301ffc9a760e09190911c9081146380ac58cd821417635b5e139f9091141790565b60405190151581526020015b60405180910390f35b34801561037d57600080fd5b50610386610586565b6040516103689190610ac1565b34801561039f57600080fd5b506103b36103ae366004610b10565b61059c565b6040516001600160a01b039091168152602001610368565b3480156103d757600080fd5b5061011d6103e6366004610b45565b6105b4565b3480156103f757600080fd5b5061040061063a565b604051908152602001610368565b34801561041a57600080fd5b5061011d610429366004610b6f565b61064c565b34801561043a57600080fd5b506103b3610449366004610b10565b6106db565b61011d61045c366004610b6f565b6106ed565b34801561046d57600080fd5b506103b361047c366004610b10565b61071f565b34801561048d57600080fd5b5061011d610731565b3480156104a257600080fd5b506104006104b1366004610bab565b6107e4565b3480156104c257600080fd5b50683602298b8c10b01232546001600160a01b03166103b3565b3480156104e857600080fd5b506103866107ff565b3480156104fd57600080fd5b506103b3610810565b34801561051257600080fd5b5061011d610521366004610bc6565b610845565b34801561053257600080fd5b5061011d610541366004610c02565b6108c8565b34801561055257600080fd5b50610386610561366004610b10565b610923565b34801561057257600080fd5b5061035c610581366004610c9d565b610933565b60606105976306fdde03600061095f565b905090565b60006105ae63081812fc8360006109bc565b92915050565b60006105be610810565b90508260601b60601c925060405163d10b6e0c600052836020528260405233606052602060006064601c34865af1601f3d11166105fe573d6000823e3d81fd5b806040525060006060528183600c5160601c7f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600038a4505050565b600061059763e2c792816000806109bc565b6000610656610810565b90508360601b60601c93508260601b60601c925060405163e5eb36c881528460208201528360408201528260608201523360808201526020816084601c840134865af16001825114166106ac573d6000823e3d81fd5b508183857fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600038a450505050565b60006105ae63243598798360006109bc565b6106f883838361064c565b813b1561071a5761071a83838360405180602001604052806000815250610a04565b505050565b60006105ae636352211e8360006109bc565b60008061073c610810565b9050638da5cb5b600052602060006004601c845afa601f3d11161561076457600c5160601c91505b683602298b8c10b0123254683602298b8c10b01230906001600160a01b0390811690841681146107de576002820180546001600160a01b0319166001600160a01b0386811691821790925560405190918316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35b50505050565b60006105ae63f5b100ea836001600160a01b031660006109bc565b60606105976395d89b41600061095f565b683602298b8c10b01230546001600160a01b03168061084257604051632d9523d760e11b815260040160405180910390fd5b90565b600061084f610810565b90508260601b60601c925060405163813500fc6000528360205282151560405233606052602060006064601c34865af160016000511416610893573d6000823e3d81fd5b83337f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160206040a36040525050600060605250565b6108d385858561064c565b833b1561091c5761091c85858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a0492505050565b5050505050565b60606105ae63c87b56dd8361095f565b600061095663e985e9c5846001600160a01b0316846001600160a01b03166109bc565b15159392505050565b6060600061096b610810565b9050604051915083600052826020526000806024601c845afa610991573d6000833e3d82fd5b60206000803e6020600051833e8151602060005101602084013e815160208301016040525092915050565b6000806109c7610810565b9050604051856000528460205283604052602060006044601c855afa601f3d11166109f5573d6000823e3d81fd5b60405250506000519392505050565b60405163150b7a028082523360208301528560601b60601c604083015283606083015260808083015282518060a08401528015610a4b578060c08401826020870160045afa505b60208360a48301601c860160008a5af1610a6e573d15610a6e573d6000843e3d83fd5b508060e01b825114610a885763d1a57ed66000526004601cfd5b505050505050565b600060208284031215610aa257600080fd5b81356001600160e01b031981168114610aba57600080fd5b9392505050565b60006020808352835180602085015260005b81811015610aef57858101830151858201604001528201610ad3565b506000604082860101526040601f19601f8301168501019250505092915050565b600060208284031215610b2257600080fd5b5035919050565b80356001600160a01b0381168114610b4057600080fd5b919050565b60008060408385031215610b5857600080fd5b610b6183610b29565b946020939093013593505050565b600080600060608486031215610b8457600080fd5b610b8d84610b29565b9250610b9b60208501610b29565b9150604084013590509250925092565b600060208284031215610bbd57600080fd5b610aba82610b29565b60008060408385031215610bd957600080fd5b610be283610b29565b915060208301358015158114610bf757600080fd5b809150509250929050565b600080600080600060808688031215610c1a57600080fd5b610c2386610b29565b9450610c3160208701610b29565b935060408601359250606086013567ffffffffffffffff80821115610c5557600080fd5b818801915088601f830112610c6957600080fd5b813581811115610c7857600080fd5b896020828501011115610c8a57600080fd5b9699959850939650602001949392505050565b60008060408385031215610cb057600080fd5b610cb983610b29565b9150610cc760208401610b29565b9050925092905056fea2646970667358221220d164aa7c97618ddfb9c0f46239b4956f5d26b5f665f51fb61aa1253813f199a264736f6c63430008180033

Deployed Bytecode

0x60806040526004361061010d5760003560e01c80636cef16e61161009557806397e5311c1161006457806397e5311c146104f1578063a22cb46514610506578063b88d4fde14610526578063c87b56dd14610546578063e985e9c5146105665761011f565b80636cef16e61461048157806370a08231146104965780638da5cb5b146104b657806395d89b41146104dc5761011f565b806318160ddd116100dc57806318160ddd146103eb57806323b872dd1461040e578063243598791461042e57806342842e0e1461044e5780636352211e146104615761011f565b806301ffc9a71461031f57806306fdde0314610371578063081812fc14610393578063095ea7b3146103cb5761011f565b3661011f57341561011d57600080fd5b005b683602298b8c10b0123060003560e01c63263c69d68190036101d55781546001600160a01b0316331461016557604051631b1e598960e11b815260040160405180910390fd5b600435602401602081033560051b81015b8082146101c85781358060601c816001168260a01b60a81c811583028284027fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600038a4505050816020019150610176565b5050600160005260206000f35b8063144027d30361026b5781546001600160a01b0316331461020a57604051631b1e598960e11b815260040160405180910390fd5b600435602435604435602401602081033560051b81015b80821461025c57813583857fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600038a4816020019150610221565b50505050600160005260206000f35b80630f4599e5036103065760018201546001600160a01b0316156102c15760018201546001600160a01b03166004356001600160a01b0316146102c1576040516362cf623d60e11b815260040160405180910390fd5b81546001600160a01b0316156102ea57604051635fb2b52360e11b815260040160405180910390fd5b81546001600160a01b0319163317825560016000908152602090f35b604051631e085ca760e11b815260040160405180910390fd5b34801561032b57600080fd5b5061035c61033a366004610a90565b6301ffc9a760e09190911c9081146380ac58cd821417635b5e139f9091141790565b60405190151581526020015b60405180910390f35b34801561037d57600080fd5b50610386610586565b6040516103689190610ac1565b34801561039f57600080fd5b506103b36103ae366004610b10565b61059c565b6040516001600160a01b039091168152602001610368565b3480156103d757600080fd5b5061011d6103e6366004610b45565b6105b4565b3480156103f757600080fd5b5061040061063a565b604051908152602001610368565b34801561041a57600080fd5b5061011d610429366004610b6f565b61064c565b34801561043a57600080fd5b506103b3610449366004610b10565b6106db565b61011d61045c366004610b6f565b6106ed565b34801561046d57600080fd5b506103b361047c366004610b10565b61071f565b34801561048d57600080fd5b5061011d610731565b3480156104a257600080fd5b506104006104b1366004610bab565b6107e4565b3480156104c257600080fd5b50683602298b8c10b01232546001600160a01b03166103b3565b3480156104e857600080fd5b506103866107ff565b3480156104fd57600080fd5b506103b3610810565b34801561051257600080fd5b5061011d610521366004610bc6565b610845565b34801561053257600080fd5b5061011d610541366004610c02565b6108c8565b34801561055257600080fd5b50610386610561366004610b10565b610923565b34801561057257600080fd5b5061035c610581366004610c9d565b610933565b60606105976306fdde03600061095f565b905090565b60006105ae63081812fc8360006109bc565b92915050565b60006105be610810565b90508260601b60601c925060405163d10b6e0c600052836020528260405233606052602060006064601c34865af1601f3d11166105fe573d6000823e3d81fd5b806040525060006060528183600c5160601c7f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600038a4505050565b600061059763e2c792816000806109bc565b6000610656610810565b90508360601b60601c93508260601b60601c925060405163e5eb36c881528460208201528360408201528260608201523360808201526020816084601c840134865af16001825114166106ac573d6000823e3d81fd5b508183857fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600038a450505050565b60006105ae63243598798360006109bc565b6106f883838361064c565b813b1561071a5761071a83838360405180602001604052806000815250610a04565b505050565b60006105ae636352211e8360006109bc565b60008061073c610810565b9050638da5cb5b600052602060006004601c845afa601f3d11161561076457600c5160601c91505b683602298b8c10b0123254683602298b8c10b01230906001600160a01b0390811690841681146107de576002820180546001600160a01b0319166001600160a01b0386811691821790925560405190918316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35b50505050565b60006105ae63f5b100ea836001600160a01b031660006109bc565b60606105976395d89b41600061095f565b683602298b8c10b01230546001600160a01b03168061084257604051632d9523d760e11b815260040160405180910390fd5b90565b600061084f610810565b90508260601b60601c925060405163813500fc6000528360205282151560405233606052602060006064601c34865af160016000511416610893573d6000823e3d81fd5b83337f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160206040a36040525050600060605250565b6108d385858561064c565b833b1561091c5761091c85858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a0492505050565b5050505050565b60606105ae63c87b56dd8361095f565b600061095663e985e9c5846001600160a01b0316846001600160a01b03166109bc565b15159392505050565b6060600061096b610810565b9050604051915083600052826020526000806024601c845afa610991573d6000833e3d82fd5b60206000803e6020600051833e8151602060005101602084013e815160208301016040525092915050565b6000806109c7610810565b9050604051856000528460205283604052602060006044601c855afa601f3d11166109f5573d6000823e3d81fd5b60405250506000519392505050565b60405163150b7a028082523360208301528560601b60601c604083015283606083015260808083015282518060a08401528015610a4b578060c08401826020870160045afa505b60208360a48301601c860160008a5af1610a6e573d15610a6e573d6000843e3d83fd5b508060e01b825114610a885763d1a57ed66000526004601cfd5b505050505050565b600060208284031215610aa257600080fd5b81356001600160e01b031981168114610aba57600080fd5b9392505050565b60006020808352835180602085015260005b81811015610aef57858101830151858201604001528201610ad3565b506000604082860101526040601f19601f8301168501019250505092915050565b600060208284031215610b2257600080fd5b5035919050565b80356001600160a01b0381168114610b4057600080fd5b919050565b60008060408385031215610b5857600080fd5b610b6183610b29565b946020939093013593505050565b600080600060608486031215610b8457600080fd5b610b8d84610b29565b9250610b9b60208501610b29565b9150604084013590509250925092565b600060208284031215610bbd57600080fd5b610aba82610b29565b60008060408385031215610bd957600080fd5b610be283610b29565b915060208301358015158114610bf757600080fd5b809150509250929050565b600080600080600060808688031215610c1a57600080fd5b610c2386610b29565b9450610c3160208701610b29565b935060408601359250606086013567ffffffffffffffff80821115610c5557600080fd5b818801915088601f830112610c6957600080fd5b813581811115610c7857600080fd5b896020828501011115610c8a57600080fd5b9699959850939650602001949392505050565b60008060408385031215610cb057600080fd5b610cb983610b29565b9150610cc760208401610b29565b9050925092905056fea2646970667358221220d164aa7c97618ddfb9c0f46239b4956f5d26b5f665f51fb61aa1253813f199a264736f6c63430008180033

Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.