ETH Price: $1,696.42 (-5.06%)

Contract

0xa50aB12246A8AaB7CD52811BF1F4F8AfF30e520e
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Purchase Market ...187863142023-12-14 18:58:59478 days ago1702580339IN
0xa50aB122...fF30e520e
0 ETH0.0051223151.51623736
Purchase Market ...187531052023-12-10 3:23:11483 days ago1702178591IN
0xa50aB122...fF30e520e
0 ETH0.0029765724.04013201
Purchase Market ...187375532023-12-07 23:03:47485 days ago1701990227IN
0xa50aB122...fF30e520e
0 ETH0.0063527354.51536501
Purchase Market ...187046462023-12-03 8:22:11490 days ago1701591731IN
0xa50aB122...fF30e520e
0 ETH0.0035918529.00941484
Purchase Market ...186965082023-12-02 5:03:59491 days ago1701493439IN
0xa50aB122...fF30e520e
0 ETH0.0048293427.12838121
Purchase Market ...186880612023-12-01 0:42:23492 days ago1701391343IN
0xa50aB122...fF30e520e
0 ETH0.0050442935.79929453
Purchase Market ...186789282023-11-29 18:02:47493 days ago1701280967IN
0xa50aB122...fF30e520e
0 ETH0.0055591438.73480091
Purchase Market ...186464772023-11-25 4:58:23498 days ago1700888303IN
0xa50aB122...fF30e520e
0 ETH0.0021005419.12494089
Purchase Market ...185586912023-11-12 22:03:59510 days ago1699826639IN
0xa50aB122...fF30e520e
0 ETH0.0021457829.59009461
Purchase Market ...185568992023-11-12 16:03:35511 days ago1699805015IN
0xa50aB122...fF30e520e
0 ETH0.0033443244.21777868
Purchase Market ...184606302023-10-30 4:35:23524 days ago1698640523IN
0xa50aB122...fF30e520e
0 ETH0.001863210.22940429
Purchase Market ...184596162023-10-30 1:10:59524 days ago1698628259IN
0xa50aB122...fF30e520e
0 ETH0.0020612411.59555727
Purchase Market ...184595482023-10-30 0:57:11524 days ago1698627431IN
0xa50aB122...fF30e520e
0 ETH0.0020263811.39941783
Purchase Market ...184569322023-10-29 16:07:59525 days ago1698595679IN
0xa50aB122...fF30e520e
0 ETH0.0025546614.3712813
Purchase Market ...184561012023-10-29 13:21:23525 days ago1698585683IN
0xa50aB122...fF30e520e
0 ETH0.001725717.35577506
Purchase Market ...184555872023-10-29 11:37:23525 days ago1698579443IN
0xa50aB122...fF30e520e
0 ETH0.0012983813.05977533
Purchase Market ...184550422023-10-29 9:46:59525 days ago1698572819IN
0xa50aB122...fF30e520e
0 ETH0.0012428911.64529266
Purchase Market ...184544092023-10-29 7:39:59525 days ago1698565199IN
0xa50aB122...fF30e520e
0 ETH0.0011450211.71415653
Purchase Market ...184538882023-10-29 5:53:59525 days ago1698558839IN
0xa50aB122...fF30e520e
0 ETH0.001604879.02820574
Purchase Market ...184536952023-10-29 5:15:23525 days ago1698556523IN
0xa50aB122...fF30e520e
0 ETH0.001802959.25248186
Purchase Market ...184121372023-10-23 9:40:47531 days ago1698054047IN
0xa50aB122...fF30e520e
0 ETH0.004116611.01462623
Purchase Market ...184051322023-10-22 10:06:23532 days ago1697969183IN
0xa50aB122...fF30e520e
0 ETH0.002231835.97163491
Purchase Market ...184050152023-10-22 9:42:23532 days ago1697967743IN
0xa50aB122...fF30e520e
0 ETH0.001703996.66878986
Purchase Market ...184036912023-10-22 5:15:35532 days ago1697951735IN
0xa50aB122...fF30e520e
0 ETH0.002283226.82515326
Purchase Market ...184007712023-10-21 19:28:47532 days ago1697916527IN
0xa50aB122...fF30e520e
0 ETH0.003520099.00649339
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Method Block
From
To
Transfer167557612023-03-04 14:46:47764 days ago1677941207
0xa50aB122...fF30e520e
0.002 ETH
Transfer167492682023-03-03 16:48:23765 days ago1677862103
0xa50aB122...fF30e520e
0.002 ETH
Transfer167484862023-03-03 14:10:47765 days ago1677852647
0xa50aB122...fF30e520e
0.002 ETH
Transfer167415322023-03-02 14:40:47766 days ago1677768047
0xa50aB122...fF30e520e
0.008 ETH
Transfer167415302023-03-02 14:40:23766 days ago1677768023
0xa50aB122...fF30e520e
0.002 ETH
Transfer167414452023-03-02 14:23:11766 days ago1677766991
0xa50aB122...fF30e520e
0.008 ETH
Transfer167414412023-03-02 14:22:23766 days ago1677766943
0xa50aB122...fF30e520e
0.008 ETH
Transfer167414342023-03-02 14:20:59766 days ago1677766859
0xa50aB122...fF30e520e
0.008 ETH
Transfer167414312023-03-02 14:20:23766 days ago1677766823
0xa50aB122...fF30e520e
0.002 ETH
Transfer167414222023-03-02 14:18:35766 days ago1677766715
0xa50aB122...fF30e520e
0.008 ETH
Transfer167414172023-03-02 14:17:35766 days ago1677766655
0xa50aB122...fF30e520e
0.012 ETH
Transfer167414142023-03-02 14:16:59766 days ago1677766619
0xa50aB122...fF30e520e
0.016 ETH
Transfer167413942023-03-02 14:12:59766 days ago1677766379
0xa50aB122...fF30e520e
0.002 ETH
Transfer167413922023-03-02 14:12:35766 days ago1677766355
0xa50aB122...fF30e520e
0.008 ETH
Transfer167413882023-03-02 14:11:47766 days ago1677766307
0xa50aB122...fF30e520e
0.002 ETH
Transfer167413882023-03-02 14:11:47766 days ago1677766307
0xa50aB122...fF30e520e
0.002 ETH
Transfer167413882023-03-02 14:11:47766 days ago1677766307
0xa50aB122...fF30e520e
0.002 ETH
Transfer167413862023-03-02 14:11:23766 days ago1677766283
0xa50aB122...fF30e520e
0.002 ETH
Transfer167413852023-03-02 14:11:11766 days ago1677766271
0xa50aB122...fF30e520e
0.002 ETH
Transfer167413842023-03-02 14:10:59766 days ago1677766259
0xa50aB122...fF30e520e
0.002 ETH
Transfer167413812023-03-02 14:10:23766 days ago1677766223
0xa50aB122...fF30e520e
0.008 ETH
Transfer167413792023-03-02 14:09:59766 days ago1677766199
0xa50aB122...fF30e520e
0.002 ETH
Transfer167413782023-03-02 14:09:35766 days ago1677766175
0xa50aB122...fF30e520e
0.008 ETH
Transfer167413762023-03-02 14:09:11766 days ago1677766151
0xa50aB122...fF30e520e
0.002 ETH
Transfer167413762023-03-02 14:09:11766 days ago1677766151
0xa50aB122...fF30e520e
0.002 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CRFTDMarketplace

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
Yes with 100000 runs

Other Settings:
default evmVersion
File 1 of 7 : CRFTDMarketplace.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {utils} from "./utils/utils.sol";
import {choice} from "./utils/choice.sol";
import {ERC20} from "solmate/tokens/ERC20.sol";
import {Owned} from "solmate/auth/Owned.sol";
import {ERC721} from "solmate/tokens/ERC721.sol";
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol";

error NotActive();
error NoSupplyLeft();
error NotAuthorized();
error InvalidReceiver();
error InvalidEthAmount();
error InsufficientValue();
error InvalidPaymentToken();
error MaxPurchasesReached();
error ContractCallNotAllowed();
error RandomSeedAlreadyChosen();

//       ___           ___           ___                    _____
//      /  /\         /  /\         /  /\       ___        /  /::\
//     /  /:/        /  /::\       /  /:/_     /__/\      /  /:/\:\
//    /  /:/        /  /:/\:\     /  /:/ /\    \  \:\    /  /:/  \:\
//   /  /:/  ___   /  /::\ \:\   /  /:/ /:/     \__\:\  /__/:/ \__\:|
//  /__/:/  /  /\ /__/:/\:\_\:\ /__/:/ /:/      /  /::\ \  \:\ /  /:/
//  \  \:\ /  /:/ \__\/~|::\/:/ \  \:\/:/      /  /:/\:\ \  \:\  /:/
//   \  \:\  /:/     |  |:|::/   \  \::/      /  /:/__\/  \  \:\/:/
//    \  \:\/:/      |  |:|\/     \  \:\     /__/:/        \  \::/
//     \  \::/       |__|:|        \  \:\    \__\/          \__\/
//      \__\/         \__\|         \__\/

/// @title CRFTDMarketplace
/// @author phaze (https://github.com/0xPhaze)
/// @notice Marketplace that supports purchasing limited off-chain items
contract CRFTDMarketplace is Owned(msg.sender) {
    using SafeTransferLib for ERC20;

    /* ------------- events ------------- */

    event MarketItemPurchased(
        uint256 indexed marketId,
        bytes32 indexed itemHash,
        address indexed account,
        bytes32 userHash,
        address paymentToken,
        uint256 price
    );

    /* ------------- structs ------------- */

    struct MarketItem {
        uint256 marketId;
        uint256 start;
        uint256 end;
        uint256 expiry;
        uint256 maxPurchases;
        uint256 maxSupply;
        uint256 raffleNumPrizes;
        address[] raffleControllers;
        address receiver;
        bytes32 dataHash;
        address[] acceptedPaymentTokens;
        uint256[] tokenPricesStart;
        uint256[] tokenPricesEnd;
    }

    /* ------------- storage ------------- */

    /// @dev (bytes32 itemHash) => (uint256 totalSupply)
    mapping(bytes32 => uint256) public totalSupply;
    /// @dev (bytes32 itemHash) => (address user) => (uint256 numPurchases)
    mapping(bytes32 => mapping(address => uint256)) public numPurchases;
    /// @dev (bytes32 itemHash) => (uint256 tokenId) => (address user)
    mapping(bytes32 => mapping(uint256 => address)) public raffleEntries;
    /// @dev (bytes32 itemHash) => (uint256 seed)
    mapping(bytes32 => uint256) public raffleRandomSeeds;

    /* ------------- external ------------- */

    function purchaseMarketItems(
        MarketItem[] calldata items,
        address[] calldata paymentTokens,
        bytes32 userHash
    ) external payable {
        uint256 msgValue = msg.value;

        for (uint256 i; i < items.length; ++i) {
            MarketItem calldata item = items[i];

            bytes32 itemHash = keccak256(abi.encode(item));

            uint256 supply = ++totalSupply[itemHash];

            unchecked {
                if (block.timestamp < item.start || item.expiry < block.timestamp) revert NotActive();
                if (++numPurchases[itemHash][msg.sender] > item.maxPurchases) revert MaxPurchasesReached();
                if (supply > item.maxSupply) revert NoSupplyLeft();
            }

            address paymentToken = paymentTokens[i];

            (bool found, uint256 tokenIndex) = utils.indexOf(item.acceptedPaymentTokens, paymentToken);
            if (!found) revert InvalidPaymentToken();

            uint256 tokenPrice = item.tokenPricesStart[tokenIndex];

            // dutch auction item
            if (item.end != 0) {
                uint256 timestamp = block.timestamp > item.end ? item.end : block.timestamp;

                tokenPrice -=
                    ((item.tokenPricesStart[tokenIndex] - item.tokenPricesEnd[tokenIndex]) * (timestamp - item.start)) /
                    (item.end - item.start);
            }

            // raffle item; store id ownership
            if (item.raffleNumPrizes != 0) {
                raffleEntries[itemHash][supply] = msg.sender;
            }

            if (paymentToken == address(0)) {
                msgValue -= tokenPrice;

                payable(item.receiver).transfer(tokenPrice);
            } else {
                require(paymentToken.code.length != 0);

                ERC20(paymentToken).safeTransferFrom(msg.sender, item.receiver, tokenPrice);
            }

            emit MarketItemPurchased(item.marketId, itemHash, msg.sender, userHash, paymentToken, tokenPrice);
        }

        if (msgValue != 0) payable(msg.sender).transfer(msgValue);
    }

    /* ------------- view (off-chain) ------------- */

    function getRaffleEntrants(bytes32 itemHash) external view returns (address[] memory entrants) {
        uint256 supply = totalSupply[itemHash];

        entrants = new address[](supply);

        for (uint256 i; i < supply; ++i) entrants[i] = raffleEntries[itemHash][i + 1];
    }

    function getRaffleWinners(bytes32 itemHash, uint256 numPrizes) public view returns (address[] memory winners) {
        uint256 randomSeed = raffleRandomSeeds[itemHash];

        if (randomSeed == 0) return winners;

        uint256[] memory winnerIds = choice.selectNOfM(numPrizes, totalSupply[itemHash], randomSeed);

        uint256 numWinners = winnerIds.length;

        winners = new address[](numWinners);

        for (uint256 i; i < numWinners; ++i) winners[i] = raffleEntries[itemHash][winnerIds[i] + 1];
    }

    /* ------------- restricted ------------- */

    function revealRaffle(MarketItem calldata item) external {
        bytes32 itemHash = keccak256(abi.encode(item));

        if (block.timestamp < item.expiry) revert NotActive();

        (bool found, ) = utils.indexOf(item.raffleControllers, msg.sender);

        if (!found) revert NotAuthorized();

        if (raffleRandomSeeds[itemHash] != 0) revert RandomSeedAlreadyChosen();

        raffleRandomSeeds[itemHash] = uint256(keccak256(abi.encode(blockhash(block.number - 1), itemHash)));
    }

    /* ------------- owner ------------- */

    function recoverToken(ERC20 token) external onlyOwner {
        token.transfer(msg.sender, token.balanceOf(address(this)));
    }

    function recoverNFT(ERC721 token, uint256 id) external onlyOwner {
        token.transferFrom(address(this), msg.sender, id);
    }
}

File 2 of 7 : utils.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library utils {
    function getOwnedIds(
        mapping(uint256 => address) storage ownerOf,
        address user,
        uint256 collectionSize
    ) internal view returns (uint256[] memory ids) {
        uint256 memPtr;
        uint256 idsLength;

        assembly {
            ids := mload(0x40)
            memPtr := add(ids, 32)
        }

        unchecked {
            uint256 end = collectionSize + 1;
            for (uint256 id = 0; id < end; ++id) {
                if (ownerOf[id] == user) {
                    assembly {
                        mstore(memPtr, id)
                        memPtr := add(memPtr, 32)
                        idsLength := add(idsLength, 1)
                    }
                }
            }
        }

        assembly {
            mstore(ids, idsLength)
            mstore(0x40, memPtr)
        }
    }

    function indexOf(address[] calldata arr, address addr) internal pure returns (bool found, uint256 index) {
        unchecked {
            for (uint256 i; i < arr.length; ++i) if (arr[i] == addr) return (true, i);
        }
        return (false, 0);
    }
}

File 3 of 7 : choice.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

// author: phaze

// assumption: n << m
// caveats: splits random number into 16 parts for efficiency
// this means that 65536 is the highest random number
// (can skew uniform distributions when m is hight)
library choice {
    function selectNOfM(
        uint256 n,
        uint256 m,
        uint256 r
    ) internal pure returns (uint256[] memory selected) {
        if (n > m) n = m;

        selected = new uint256[](n);

        uint256 s;
        uint256 slot;

        uint256 j;
        uint256 c;

        bool invalidChoice;

        unchecked {
            for (uint256 i; i < n; ++i) {
                do {
                    slot = (s & 0xF) << 4;
                    if (slot == 0 && i != 0) r = uint256(keccak256(abi.encode(r, s)));
                    c = ((r >> slot) & 0xFFFF) % m;
                    invalidChoice = false;
                    for (j = 0; j < i && !invalidChoice; ++j) invalidChoice = selected[j] == c;
                    ++s;
                } while (invalidChoice);

                selected[i] = c;
            }
        }
    }
}

File 4 of 7 : ERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*//////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*//////////////////////////////////////////////////////////////
                            EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*//////////////////////////////////////////////////////////////
                               ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*//////////////////////////////////////////////////////////////
                             EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                keccak256(
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
                                ),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}

File 5 of 7 : Owned.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event OwnerUpdated(address indexed user, address indexed newOwner);

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _owner) {
        owner = _owner;

        emit OwnerUpdated(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function setOwner(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnerUpdated(msg.sender, newOwner);
    }
}

File 6 of 7 : ERC721.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*//////////////////////////////////////////////////////////////
                         METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                      ERC721 BALANCE/OWNER STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) internal _ownerOf;

    mapping(address => uint256) internal _balanceOf;

    function ownerOf(uint256 id) public view virtual returns (address owner) {
        require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
    }

    function balanceOf(address owner) public view virtual returns (uint256) {
        require(owner != address(0), "ZERO_ADDRESS");

        return _balanceOf[owner];
    }

    /*//////////////////////////////////////////////////////////////
                         ERC721 APPROVAL STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*//////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) public virtual {
        address owner = _ownerOf[id];

        require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        require(from == _ownerOf[id], "WRONG_FROM");

        require(to != address(0), "INVALID_RECIPIENT");

        require(
            msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],
            "NOT_AUTHORIZED"
        );

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        unchecked {
            _balanceOf[from]--;

            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        delete getApproved[id];

        emit Transfer(from, to, id);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        transferFrom(from, to, id);

        if (to.code.length != 0)
            require(
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
                    ERC721TokenReceiver.onERC721Received.selector,
                "UNSAFE_RECIPIENT"
            );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes calldata data
    ) public virtual {
        transferFrom(from, to, id);

        if (to.code.length != 0)
            require(
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
                    ERC721TokenReceiver.onERC721Received.selector,
                "UNSAFE_RECIPIENT"
            );
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id) internal virtual {
        require(to != address(0), "INVALID_RECIPIENT");

        require(_ownerOf[id] == address(0), "ALREADY_MINTED");

        // Counter overflow is incredibly unrealistic.
        unchecked {
            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        emit Transfer(address(0), to, id);
    }

    function _burn(uint256 id) internal virtual {
        address owner = _ownerOf[id];

        require(owner != address(0), "NOT_MINTED");

        // Ownership check above ensures no underflow.
        unchecked {
            _balanceOf[owner]--;
        }

        delete _ownerOf[id];

        delete getApproved[id];

        emit Transfer(owner, address(0), id);
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL SAFE MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _safeMint(address to, uint256 id) internal virtual {
        _mint(to, id);

        if (to.code.length != 0)
            require(
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
                    ERC721TokenReceiver.onERC721Received.selector,
                "UNSAFE_RECIPIENT"
            );
    }

    function _safeMint(
        address to,
        uint256 id,
        bytes memory data
    ) internal virtual {
        _mint(to, id);

        if (to.code.length != 0)
            require(
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
                    ERC721TokenReceiver.onERC721Received.selector,
                "UNSAFE_RECIPIENT"
            );
    }
}

/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721TokenReceiver {
    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC721TokenReceiver.onERC721Received.selector;
    }
}

File 7 of 7 : SafeTransferLib.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import {ERC20} from "../tokens/ERC20.sol";

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Caution! This library won't check that a token has code, responsibility is delegated to the caller.
library SafeTransferLib {
    /*//////////////////////////////////////////////////////////////
                             ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool success;

        assembly {
            // Transfer the ETH and store if it succeeded or not.
            success := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(success, "ETH_TRANSFER_FAILED");
    }

    /*//////////////////////////////////////////////////////////////
                            ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(
        ERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // We'll write our calldata to this slot below, but restore it later.
            let memPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(0, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
            mstore(4, from) // Append the "from" argument.
            mstore(36, to) // Append the "to" argument.
            mstore(68, amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 100 because that's the total length of our calldata (4 + 32 * 3)
                // Counterintuitively, this call() must be positioned after the or() in the
                // surrounding and() because and() evaluates its arguments from right to left.
                call(gas(), token, 0, 0, 100, 0, 32)
            )

            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, memPointer) // Restore the memPointer.
        }

        require(success, "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // We'll write our calldata to this slot below, but restore it later.
            let memPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(0, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
            mstore(4, to) // Append the "to" argument.
            mstore(36, amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because that's the total length of our calldata (4 + 32 * 2)
                // Counterintuitively, this call() must be positioned after the or() in the
                // surrounding and() because and() evaluates its arguments from right to left.
                call(gas(), token, 0, 0, 68, 0, 32)
            )

            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, memPointer) // Restore the memPointer.
        }

        require(success, "TRANSFER_FAILED");
    }

    function safeApprove(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // We'll write our calldata to this slot below, but restore it later.
            let memPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(0, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
            mstore(4, to) // Append the "to" argument.
            mstore(36, amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because that's the total length of our calldata (4 + 32 * 2)
                // Counterintuitively, this call() must be positioned after the or() in the
                // surrounding and() because and() evaluates its arguments from right to left.
                call(gas(), token, 0, 0, 68, 0, 32)
            )

            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, memPointer) // Restore the memPointer.
        }

        require(success, "APPROVE_FAILED");
    }
}

Settings
{
  "remappings": [
    "ArrayUtils/=lib/ArrayUtils/src/",
    "CRFTD/=src/",
    "UDS/=lib/UDS/src/",
    "ds-test/=lib/solmate/lib/ds-test/src/",
    "f-utils/=lib/f-utils/src/",
    "forge-std/=lib/forge-std/src/",
    "script/=script/",
    "solmate/=lib/solmate/src/",
    "src/=src/",
    "test/=test/",
    "src/=src/",
    "test/=test/",
    "script/=script/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 100000
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"name":"InvalidPaymentToken","type":"error"},{"inputs":[],"name":"MaxPurchasesReached","type":"error"},{"inputs":[],"name":"NoSupplyLeft","type":"error"},{"inputs":[],"name":"NotActive","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"RandomSeedAlreadyChosen","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"itemHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bytes32","name":"userHash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"paymentToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"MarketItemPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"inputs":[{"internalType":"bytes32","name":"itemHash","type":"bytes32"}],"name":"getRaffleEntrants","outputs":[{"internalType":"address[]","name":"entrants","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"itemHash","type":"bytes32"},{"internalType":"uint256","name":"numPrizes","type":"uint256"}],"name":"getRaffleWinners","outputs":[{"internalType":"address[]","name":"winners","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"}],"name":"numPurchases","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"maxPurchases","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"raffleNumPrizes","type":"uint256"},{"internalType":"address[]","name":"raffleControllers","type":"address[]"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"address[]","name":"acceptedPaymentTokens","type":"address[]"},{"internalType":"uint256[]","name":"tokenPricesStart","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenPricesEnd","type":"uint256[]"}],"internalType":"struct CRFTDMarketplace.MarketItem[]","name":"items","type":"tuple[]"},{"internalType":"address[]","name":"paymentTokens","type":"address[]"},{"internalType":"bytes32","name":"userHash","type":"bytes32"}],"name":"purchaseMarketItems","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"raffleEntries","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"raffleRandomSeeds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ERC721","name":"token","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"recoverNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"token","type":"address"}],"name":"recoverToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"maxPurchases","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"raffleNumPrizes","type":"uint256"},{"internalType":"address[]","name":"raffleControllers","type":"address[]"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"address[]","name":"acceptedPaymentTokens","type":"address[]"},{"internalType":"uint256[]","name":"tokenPricesStart","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenPricesEnd","type":"uint256[]"}],"internalType":"struct CRFTDMarketplace.MarketItem","name":"item","type":"tuple"}],"name":"revealRaffle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50600080546001600160a01b031916339081178255604051909182917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a35061190b806100616000396000f3fe6080604052600436106100c75760003560e01c80639be65a6011610074578063bcd4d8a11161004e578063bcd4d8a114610251578063d878385514610289578063ef82783a146102d757600080fd5b80639be65a60146101e4578063b524abcf14610204578063b7cb4b551461023157600080fd5b80636c281806116100a55780636c281806146101445780638da5cb5b1461017f5780638e9769fb146101d157600080fd5b806313af4035146100cc578063243f3428146100ee5780633319a00d14610124575b600080fd5b3480156100d857600080fd5b506100ec6100e73660046111e7565b6102f7565b005b3480156100fa57600080fd5b5061010e61010936600461120b565b6103ed565b60405161011b9190611224565b60405180910390f35b34801561013057600080fd5b506100ec61013f36600461127e565b6104e6565b34801561015057600080fd5b5061017161015f36600461120b565b60046020526000908152604090205481565b60405190815260200161011b565b34801561018b57600080fd5b506000546101ac9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161011b565b6100ec6101df3660046112f6565b6105f7565b3480156101f057600080fd5b506100ec6101ff3660046111e7565b610aab565b34801561021057600080fd5b5061017161021f36600461120b565b60016020526000908152604090205481565b34801561023d57600080fd5b506100ec61024c36600461136a565b610c5c565b34801561025d57600080fd5b5061017161026c3660046113a6565b600260209081526000928352604080842090915290825290205481565b34801561029557600080fd5b506101ac6102a43660046113d6565b600360209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff1681565b3480156102e357600080fd5b5061010e6102f23660046113d6565b610dc6565b60005473ffffffffffffffffffffffffffffffffffffffff16331461037d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b6000818152600160205260409020546060908067ffffffffffffffff811115610418576104186113f8565b604051908082528060200260200182016040528015610441578160200160208202803683370190505b50915060005b818110156104df57600084815260036020526040812090610469836001611456565b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168382815181106104aa576104aa61146e565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526104d88161149d565b9050610447565b5050919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610567576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610374565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201523360248201526044810182905273ffffffffffffffffffffffffffffffffffffffff8316906323b872dd90606401600060405180830381600087803b1580156105db57600080fd5b505af11580156105ef573d6000803e3d6000fd5b505050505050565b3460005b85811015610a6e57368787838181106106165761061661146e565b905060200281019061062891906114d5565b905060008160405160200161063d919061161f565b604051602081830303815290604052805190602001209050600060016000838152602001908152602001600020600081546106779061149d565b9182905550905060208301354210806106935750428360600135105b156106ca576040517f80cb55e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600260209081526040808320338452909152902080546001019081905560808401351015610729576040517f05bd282700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260a00135811115610767576040517f800113cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600088888681811061077b5761077b61146e565b905060200201602081019061079091906111e7565b90506000806107ac6107a6610140880188611774565b85610f11565b91509150816107e7576040517f56e7ec5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006107f7610160880188611774565b838181106108075761080761146e565b90506020020135905086604001356000146108d05760008760400135421161082f5742610835565b87604001355b9050610849602089013560408a01356117dc565b61085760208a0135836117dc565b6108656101808b018b611774565b868181106108755761087561146e565b905060200201358a80610160019061088d9190611774565b8781811061089d5761089d61146e565b905060200201356108ae91906117dc565b6108b891906117f3565b6108c2919061185f565b6108cc90836117dc565b9150505b60c08701351561091c576000868152600360209081526040808320888452909152902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555b73ffffffffffffffffffffffffffffffffffffffff84166109a057610941818a6117dc565b9850610955610120880161010089016111e7565b73ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015801561099a573d6000803e3d6000fd5b506109f9565b8373ffffffffffffffffffffffffffffffffffffffff163b6000036109c457600080fd5b6109f9336109da6101208a016101008b016111e7565b73ffffffffffffffffffffffffffffffffffffffff8716919084610f9c565b604080518b815273ffffffffffffffffffffffffffffffffffffffff86166020820152908101829052339087908935907ffa5895e43f290edbd4b57005f70df6eb9a23c25c8913d394b59c6026137373239060600160405180910390a45050505050505080610a679061149d565b90506105fb565b5080156105ef57604051339082156108fc029083906000818181858888f19350505050158015610aa2573d6000803e3d6000fd5b50505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610374565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063a9059cbb90339083906370a0823190602401602060405180830381865afa158015610ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc4919061189a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044016020604051808303816000875af1158015610c34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5891906118b3565b5050565b600081604051602001610c6f919061161f565b6040516020818303038152906040528051906020012090508160600135421015610cc5576040517f80cb55e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610cdd610cd760e0850185611774565b33610f11565b50905080610d17576040517fea8e4eb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526004602052604090205415610d5d576040517f7745801a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d686001436117dc565b60408051914060208301528101839052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009485526004909252909220919091555050565b600082815260046020526040812054606091819003610de55750610f0b565b600084815260016020526040812054610e0090859084611066565b80519091508067ffffffffffffffff811115610e1e57610e1e6113f8565b604051908082528060200260200182016040528015610e47578160200160208202803683370190505b50935060005b81811015610f0657600360008881526020019081526020016000206000848381518110610e7c57610e7c61146e565b60200260200101516001610e909190611456565b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16858281518110610ed157610ed161146e565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152610eff8161149d565b9050610e4d565b505050505b92915050565b60008060005b84811015610f8b578373ffffffffffffffffffffffffffffffffffffffff16868683818110610f4857610f4861146e565b9050602002016020810190610f5d91906111e7565b73ffffffffffffffffffffffffffffffffffffffff1603610f8357600192509050610f94565b600101610f17565b50600080915091505b935093915050565b60006040517f23b872dd000000000000000000000000000000000000000000000000000000006000528460045283602452826044526020600060646000808a5af13d15601f3d116001600051141617169150600060605280604052508061105f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610374565b5050505050565b606082841115611074578293505b8367ffffffffffffffff81111561108d5761108d6113f8565b6040519080825280602002602001820160405280156110b6578160200160208202803683370190505b5090506000806000806000805b898110156111a5575b60f0600487901b169450841580156110e357508015155b156111185760408051602081018a90529081018790526060016040516020818303038152906040528051906020012060001c97505b8861ffff89871c168161112d5761112d611830565b06925060009150600093505b8084108015611146575081155b15611174578287858151811061115e5761115e61146e565b6020026020010151149150836001019350611139565b856001019550816110cc57828782815181106111925761119261146e565b60209081029190910101526001016110c3565b5050505050509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146111d457600080fd5b50565b80356111e2816111b2565b919050565b6000602082840312156111f957600080fd5b8135611204816111b2565b9392505050565b60006020828403121561121d57600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b8181101561127257835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611240565b50909695505050505050565b6000806040838503121561129157600080fd5b823561129c816111b2565b946020939093013593505050565b60008083601f8401126112bc57600080fd5b50813567ffffffffffffffff8111156112d457600080fd5b6020830191508360208260051b85010111156112ef57600080fd5b9250929050565b60008060008060006060868803121561130e57600080fd5b853567ffffffffffffffff8082111561132657600080fd5b61133289838a016112aa565b9097509550602088013591508082111561134b57600080fd5b50611358888289016112aa565b96999598509660400135949350505050565b60006020828403121561137c57600080fd5b813567ffffffffffffffff81111561139357600080fd5b82016101a0818503121561120457600080fd5b600080604083850312156113b957600080fd5b8235915060208301356113cb816111b2565b809150509250929050565b600080604083850312156113e957600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561146957611469611427565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036114ce576114ce611427565b5060010190565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6183360301811261150957600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261154857600080fd5b830160208101925035905067ffffffffffffffff81111561156857600080fd5b8060051b36038213156112ef57600080fd5b8183526000602080850194508260005b858110156115c557813561159d816111b2565b73ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161158a565b509495945050505050565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561160257600080fd5b8260051b8083602087013760009401602001938452509192915050565b6020815281356020820152602082013560408201526040820135606082015260608201356080820152608082013560a082015260a082013560c082015260c082013560e0820152600061167560e0840184611513565b6101a0610100818187015261168f6101c08701848661157a565b935061169c8188016111d7565b9250506101206116c38187018473ffffffffffffffffffffffffffffffffffffffff169052565b61014092508087013583870152506116dd82870187611513565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061016081888703018189015261171786868561157a565b9550611725818a018a611513565b95509250506101808188870301818901526117418686856115d0565b955061174f818a018a611513565b9550925050808786030183880152506117698484836115d0565b979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126117a957600080fd5b83018035915067ffffffffffffffff8211156117c457600080fd5b6020019150600581901b36038213156112ef57600080fd5b6000828210156117ee576117ee611427565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561182b5761182b611427565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611895577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000602082840312156118ac57600080fd5b5051919050565b6000602082840312156118c557600080fd5b8151801515811461120457600080fdfea2646970667358221220e606f9eec46bc457ff04c52da1ef1ec40cfc613543754766b57fc331b1ff4ad964736f6c634300080f0033

Deployed Bytecode

0x6080604052600436106100c75760003560e01c80639be65a6011610074578063bcd4d8a11161004e578063bcd4d8a114610251578063d878385514610289578063ef82783a146102d757600080fd5b80639be65a60146101e4578063b524abcf14610204578063b7cb4b551461023157600080fd5b80636c281806116100a55780636c281806146101445780638da5cb5b1461017f5780638e9769fb146101d157600080fd5b806313af4035146100cc578063243f3428146100ee5780633319a00d14610124575b600080fd5b3480156100d857600080fd5b506100ec6100e73660046111e7565b6102f7565b005b3480156100fa57600080fd5b5061010e61010936600461120b565b6103ed565b60405161011b9190611224565b60405180910390f35b34801561013057600080fd5b506100ec61013f36600461127e565b6104e6565b34801561015057600080fd5b5061017161015f36600461120b565b60046020526000908152604090205481565b60405190815260200161011b565b34801561018b57600080fd5b506000546101ac9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161011b565b6100ec6101df3660046112f6565b6105f7565b3480156101f057600080fd5b506100ec6101ff3660046111e7565b610aab565b34801561021057600080fd5b5061017161021f36600461120b565b60016020526000908152604090205481565b34801561023d57600080fd5b506100ec61024c36600461136a565b610c5c565b34801561025d57600080fd5b5061017161026c3660046113a6565b600260209081526000928352604080842090915290825290205481565b34801561029557600080fd5b506101ac6102a43660046113d6565b600360209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff1681565b3480156102e357600080fd5b5061010e6102f23660046113d6565b610dc6565b60005473ffffffffffffffffffffffffffffffffffffffff16331461037d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b6000818152600160205260409020546060908067ffffffffffffffff811115610418576104186113f8565b604051908082528060200260200182016040528015610441578160200160208202803683370190505b50915060005b818110156104df57600084815260036020526040812090610469836001611456565b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168382815181106104aa576104aa61146e565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526104d88161149d565b9050610447565b5050919050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610567576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610374565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201523360248201526044810182905273ffffffffffffffffffffffffffffffffffffffff8316906323b872dd90606401600060405180830381600087803b1580156105db57600080fd5b505af11580156105ef573d6000803e3d6000fd5b505050505050565b3460005b85811015610a6e57368787838181106106165761061661146e565b905060200281019061062891906114d5565b905060008160405160200161063d919061161f565b604051602081830303815290604052805190602001209050600060016000838152602001908152602001600020600081546106779061149d565b9182905550905060208301354210806106935750428360600135105b156106ca576040517f80cb55e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600260209081526040808320338452909152902080546001019081905560808401351015610729576040517f05bd282700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260a00135811115610767576040517f800113cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600088888681811061077b5761077b61146e565b905060200201602081019061079091906111e7565b90506000806107ac6107a6610140880188611774565b85610f11565b91509150816107e7576040517f56e7ec5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006107f7610160880188611774565b838181106108075761080761146e565b90506020020135905086604001356000146108d05760008760400135421161082f5742610835565b87604001355b9050610849602089013560408a01356117dc565b61085760208a0135836117dc565b6108656101808b018b611774565b868181106108755761087561146e565b905060200201358a80610160019061088d9190611774565b8781811061089d5761089d61146e565b905060200201356108ae91906117dc565b6108b891906117f3565b6108c2919061185f565b6108cc90836117dc565b9150505b60c08701351561091c576000868152600360209081526040808320888452909152902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555b73ffffffffffffffffffffffffffffffffffffffff84166109a057610941818a6117dc565b9850610955610120880161010089016111e7565b73ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015801561099a573d6000803e3d6000fd5b506109f9565b8373ffffffffffffffffffffffffffffffffffffffff163b6000036109c457600080fd5b6109f9336109da6101208a016101008b016111e7565b73ffffffffffffffffffffffffffffffffffffffff8716919084610f9c565b604080518b815273ffffffffffffffffffffffffffffffffffffffff86166020820152908101829052339087908935907ffa5895e43f290edbd4b57005f70df6eb9a23c25c8913d394b59c6026137373239060600160405180910390a45050505050505080610a679061149d565b90506105fb565b5080156105ef57604051339082156108fc029083906000818181858888f19350505050158015610aa2573d6000803e3d6000fd5b50505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610374565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff82169063a9059cbb90339083906370a0823190602401602060405180830381865afa158015610ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc4919061189a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044016020604051808303816000875af1158015610c34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5891906118b3565b5050565b600081604051602001610c6f919061161f565b6040516020818303038152906040528051906020012090508160600135421015610cc5576040517f80cb55e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610cdd610cd760e0850185611774565b33610f11565b50905080610d17576040517fea8e4eb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526004602052604090205415610d5d576040517f7745801a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d686001436117dc565b60408051914060208301528101839052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009485526004909252909220919091555050565b600082815260046020526040812054606091819003610de55750610f0b565b600084815260016020526040812054610e0090859084611066565b80519091508067ffffffffffffffff811115610e1e57610e1e6113f8565b604051908082528060200260200182016040528015610e47578160200160208202803683370190505b50935060005b81811015610f0657600360008881526020019081526020016000206000848381518110610e7c57610e7c61146e565b60200260200101516001610e909190611456565b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16858281518110610ed157610ed161146e565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152610eff8161149d565b9050610e4d565b505050505b92915050565b60008060005b84811015610f8b578373ffffffffffffffffffffffffffffffffffffffff16868683818110610f4857610f4861146e565b9050602002016020810190610f5d91906111e7565b73ffffffffffffffffffffffffffffffffffffffff1603610f8357600192509050610f94565b600101610f17565b50600080915091505b935093915050565b60006040517f23b872dd000000000000000000000000000000000000000000000000000000006000528460045283602452826044526020600060646000808a5af13d15601f3d116001600051141617169150600060605280604052508061105f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610374565b5050505050565b606082841115611074578293505b8367ffffffffffffffff81111561108d5761108d6113f8565b6040519080825280602002602001820160405280156110b6578160200160208202803683370190505b5090506000806000806000805b898110156111a5575b60f0600487901b169450841580156110e357508015155b156111185760408051602081018a90529081018790526060016040516020818303038152906040528051906020012060001c97505b8861ffff89871c168161112d5761112d611830565b06925060009150600093505b8084108015611146575081155b15611174578287858151811061115e5761115e61146e565b6020026020010151149150836001019350611139565b856001019550816110cc57828782815181106111925761119261146e565b60209081029190910101526001016110c3565b5050505050509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146111d457600080fd5b50565b80356111e2816111b2565b919050565b6000602082840312156111f957600080fd5b8135611204816111b2565b9392505050565b60006020828403121561121d57600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b8181101561127257835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611240565b50909695505050505050565b6000806040838503121561129157600080fd5b823561129c816111b2565b946020939093013593505050565b60008083601f8401126112bc57600080fd5b50813567ffffffffffffffff8111156112d457600080fd5b6020830191508360208260051b85010111156112ef57600080fd5b9250929050565b60008060008060006060868803121561130e57600080fd5b853567ffffffffffffffff8082111561132657600080fd5b61133289838a016112aa565b9097509550602088013591508082111561134b57600080fd5b50611358888289016112aa565b96999598509660400135949350505050565b60006020828403121561137c57600080fd5b813567ffffffffffffffff81111561139357600080fd5b82016101a0818503121561120457600080fd5b600080604083850312156113b957600080fd5b8235915060208301356113cb816111b2565b809150509250929050565b600080604083850312156113e957600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561146957611469611427565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036114ce576114ce611427565b5060010190565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6183360301811261150957600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261154857600080fd5b830160208101925035905067ffffffffffffffff81111561156857600080fd5b8060051b36038213156112ef57600080fd5b8183526000602080850194508260005b858110156115c557813561159d816111b2565b73ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161158a565b509495945050505050565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561160257600080fd5b8260051b8083602087013760009401602001938452509192915050565b6020815281356020820152602082013560408201526040820135606082015260608201356080820152608082013560a082015260a082013560c082015260c082013560e0820152600061167560e0840184611513565b6101a0610100818187015261168f6101c08701848661157a565b935061169c8188016111d7565b9250506101206116c38187018473ffffffffffffffffffffffffffffffffffffffff169052565b61014092508087013583870152506116dd82870187611513565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061016081888703018189015261171786868561157a565b9550611725818a018a611513565b95509250506101808188870301818901526117418686856115d0565b955061174f818a018a611513565b9550925050808786030183880152506117698484836115d0565b979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126117a957600080fd5b83018035915067ffffffffffffffff8211156117c457600080fd5b6020019150600581901b36038213156112ef57600080fd5b6000828210156117ee576117ee611427565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561182b5761182b611427565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611895577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000602082840312156118ac57600080fd5b5051919050565b6000602082840312156118c557600080fd5b8151801515811461120457600080fdfea2646970667358221220e606f9eec46bc457ff04c52da1ef1ec40cfc613543754766b57fc331b1ff4ad964736f6c634300080f0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ 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.