ETH Price: $1,908.19 (-2.32%)

Transaction Decoder

Block:
19830560 at May-09-2024 06:01:11 AM +UTC
Transaction Fee:
0.000305015031279168 ETH $0.58
Gas Used:
59,808 Gas / 5.099903546 Gwei

Emitted Events:

406 CoolmanAirdrop.AirdropVerified( account=2F3676AA7D67BF2C3805980EB2193F2EB3954BDE2EDFDBA97934E7DB6F33B342, nft=0xa5c0bd78d1667c13bfb403e2a3336871396713c5, tokenId=1782 )

Account State Difference:

  Address   Before After State Difference Code
0x22560ABD...6E64eb806
0x8210268C...909daF08a
0.001137270868512505 Eth
Nonce: 244
0.000832255837233337 Eth
Nonce: 245
0.000305015031279168
(beaverbuild)
18.963653576102038679 Eth18.963655650968232023 Eth0.000002074866193344

Execution Trace

CoolmanAirdrop.verifyAirdrops( airdropInfos= )
  • Coolman Universe: COOLMAN Token.6352211e( )
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
    pragma solidity ^0.8.20;
    import {Context} from "../utils/Context.sol";
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * The initial owner is set to the address provided by the deployer. This can
     * later be changed with {transferOwnership}.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be applied to your functions to restrict their use to
     * the owner.
     */
    abstract contract Ownable is Context {
        address private _owner;
        /**
         * @dev The caller account is not authorized to perform an operation.
         */
        error OwnableUnauthorizedAccount(address account);
        /**
         * @dev The owner is not a valid owner account. (eg. `address(0)`)
         */
        error OwnableInvalidOwner(address owner);
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
        /**
         * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
         */
        constructor(address initialOwner) {
            if (initialOwner == address(0)) {
                revert OwnableInvalidOwner(address(0));
            }
            _transferOwnership(initialOwner);
        }
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            _checkOwner();
            _;
        }
        /**
         * @dev Returns the address of the current owner.
         */
        function owner() public view virtual returns (address) {
            return _owner;
        }
        /**
         * @dev Throws if the sender is not the owner.
         */
        function _checkOwner() internal view virtual {
            if (owner() != _msgSender()) {
                revert OwnableUnauthorizedAccount(_msgSender());
            }
        }
        /**
         * @dev Leaves the contract without owner. It will not be possible to call
         * `onlyOwner` functions. Can only be called by the current owner.
         *
         * NOTE: Renouncing ownership will leave the contract without an owner,
         * thereby disabling any functionality that is only available to the owner.
         */
        function renounceOwnership() public virtual onlyOwner {
            _transferOwnership(address(0));
        }
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         * Can only be called by the current owner.
         */
        function transferOwnership(address newOwner) public virtual onlyOwner {
            if (newOwner == address(0)) {
                revert OwnableInvalidOwner(address(0));
            }
            _transferOwnership(newOwner);
        }
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         * Internal function without access restriction.
         */
        function _transferOwnership(address newOwner) internal virtual {
            address oldOwner = _owner;
            _owner = newOwner;
            emit OwnershipTransferred(oldOwner, newOwner);
        }
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
    pragma solidity ^0.8.20;
    /**
     * @dev Provides information about the current execution context, including the
     * sender of the transaction and its data. While these are generally available
     * via msg.sender and msg.data, they should not be accessed in such a direct
     * manner, since when dealing with meta-transactions the account sending and
     * paying for execution may not be the actual sender (as far as an application
     * is concerned).
     *
     * This contract is only required for intermediate, library-like contracts.
     */
    abstract contract Context {
        function _msgSender() internal view virtual returns (address) {
            return msg.sender;
        }
        function _msgData() internal view virtual returns (bytes calldata) {
            return msg.data;
        }
        function _contextSuffixLength() internal view virtual returns (uint256) {
            return 0;
        }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity 0.8.24;
    import { IERC721 } from "./IERC721.sol";
    import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
    /*
    I see you nerd! ⌐⊙_⊙
    */
    contract CoolmanAirdrop is Ownable {
        address public nft1;
        address public nft2;
        bool public isLive;
        struct AirdropInfo {
            bytes32 account;
            address nft;
            uint256 tokenId;
        }
        struct NFTToken {
            address nft;
            uint256 tokenId;
        }
        mapping (address => mapping(uint256 => bool)) public claimed;
        // errors
        error AlreadyClaimed();
        error InvalidNft();
        error NotLive();
        error NotOwner();
        event AirdropVerified(bytes32 account, address nft, uint256 tokenId);
        event AirdropDeleted(address nft, uint256 tokenId);
        constructor(address _nft1, address _nft2) Ownable(msg.sender) {
            nft1 = _nft1;
            nft2 = _nft2;
        }
        function _verifyAirdrop(AirdropInfo memory airdropInfo) internal {
            if (airdropInfo.nft != nft1 && airdropInfo.nft != nft2) {
                revert InvalidNft();
            }
            if (claimed[airdropInfo.nft][airdropInfo.tokenId]) {
                revert AlreadyClaimed();
            }
            if (IERC721(airdropInfo.nft).ownerOf(airdropInfo.tokenId) != msg.sender) {
                revert NotOwner();
            }
            claimed[airdropInfo.nft][airdropInfo.tokenId] = true;
            emit AirdropVerified(airdropInfo.account, airdropInfo.nft, airdropInfo.tokenId);
        }
        function verifyAirdrop(AirdropInfo memory airdropInfo) public {
            if (!isLive) {
                revert NotLive();
            }
            _verifyAirdrop(airdropInfo);
        }
        function verifyAirdrops(AirdropInfo[] memory airdropInfos) public {
            if (!isLive) {
                revert NotLive();
            }
            unchecked {
                for (uint256 i = 0; i < airdropInfos.length; ++i) {
                    _verifyAirdrop(airdropInfos[i]);
                }
            }
        }
        function deleteAirdrops(NFTToken[] memory nftTokens) public onlyOwner {
            unchecked {
                for (uint256 i = 0; i < nftTokens.length; ++i) {
                    claimed[nftTokens[i].nft][nftTokens[i].tokenId] = false;
                    emit AirdropDeleted(nftTokens[i].nft, nftTokens[i].tokenId);
                }
            }
        }
        function goLive() public onlyOwner {
            isLive = true;
        }
        function pause() public onlyOwner {
            isLive = false;
        }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity 0.8.24;
    interface IERC721 {
        function ownerOf(uint256 tokenId) external view returns (address owner);
    }