ETH Price: $2,855.32 (-2.92%)

Contract

0x9bb24B151fb2AF89790603F35e2082c129bC463B

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Set Players Elim...115976942025-03-19 1:00:53313 days ago1742346053IN
0x9bb24B15...129bC463B
0 ETH0.000002050.00100025
Set Players Elim...115673662025-03-18 16:35:25313 days ago1742315725IN
0x9bb24B15...129bC463B
0 ETH0.000000160.00100158
Set Players Elim...114248912025-03-17 1:00:50315 days ago1742173250IN
0x9bb24B15...129bC463B
0 ETH0.000002090.00100026
Set Players Elim...114176622025-03-16 23:00:21315 days ago1742166021IN
0x9bb24B15...129bC463B
0 ETH0.000000950.00100026
Set Players Elim...112290582025-03-14 18:36:57317 days ago1741977417IN
0x9bb24B15...129bC463B
0 ETH0.000003440.00100025
Set Players Elim...110792552025-03-13 1:00:14319 days ago1741827614IN
0x9bb24B15...129bC463B
0 ETH0.000002180.00100025
Set Players Elim...110721502025-03-12 23:01:49319 days ago1741820509IN
0x9bb24B15...129bC463B
0 ETH0.00000110.00100025
Set Players Elim...109714592025-03-11 19:03:38320 days ago1741719818IN
0x9bb24B15...129bC463B
0 ETH0.000002260.00100025

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
104535342025-03-05 19:11:33326 days ago1741201893  Contract Creation0 ETH

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TransferPauserExtension

Compiler Version
v0.8.26+commit.8a97fa7a

Optimization Enabled:
Yes with 100 runs

Other Settings:
cancun EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {ITransferHookExtension} from "../interfaces/ITransferHookExtension.sol";
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";


contract TransferPauserExtension is ITransferHookExtension, ERC165 {
    bytes32 immutable public GAME_CONTROLLER_ROLE = keccak256("GAME_CONTROLLER_ROLE");
    IAccessControl public immutable baseNFT;

    error GameControllerRoleNeeded();
    error JuryNFTsCannotBeTransferred(uint256 tokenId);
    event PlayersSetEliminatedAt(address indexed by, uint256[] indexed players, uint256 timestamp);

    mapping(uint256 => uint256) playerBecameJuryAt;

    constructor(address baseNFT_) {
        baseNFT = IAccessControl(baseNFT_);
    }

    function playersBecameJuryAt(uint256[] memory playerIds) external view returns (uint256[] memory playersResult) {
        playersResult = new uint256[](playerIds.length);
        for (uint256 i = 0; i < playerIds.length; i++) {
            playersResult[i] = playerBecameJuryAt[playerIds[i]];
        }
    }

    function singlePlayerBecameJuryAt(uint256 playerId) external view returns (uint256) {
        return playerBecameJuryAt[playerId];
    }

    function _requireGameControllerRole() internal view {
        if (!baseNFT.hasRole(GAME_CONTROLLER_ROLE, msg.sender)) {
            revert GameControllerRoleNeeded();
        }
    }

    function setPlayersEliminated(uint256[] memory players) external {
        _requireGameControllerRole();
        emit PlayersSetEliminatedAt(msg.sender, players, block.timestamp);
        for (uint256 i = 0; i < players.length; i++) {
            playerBecameJuryAt[players[i]] = block.timestamp;
        }
    }

    function setPlayerBackInGame(uint256[] memory players) external {
        _requireGameControllerRole();
        emit PlayersSetEliminatedAt(msg.sender, players, 0);
        for (uint256 i = 0; i < players.length; i++) {
            playerBecameJuryAt[players[i]] = 0;
        }
    }

    function canTransfer(uint256 tokenId) public view returns (bool) {
        if (playerBecameJuryAt[tokenId] == 0) {
            return true;
        }
        return false;
    }

    function _requireCanTransfer(uint256 tokenId) internal view {
        if (!canTransfer(tokenId)) {
            revert JuryNFTsCannotBeTransferred(tokenId);
        }
    }

    function beforeTokenTransfers(address /* from */, address /* to */, address /* operator */, uint256 startTokenId, uint256 quantity) external view {
        for (uint256 i = startTokenId; i < startTokenId + quantity; i++) {
            _requireCanTransfer(i);
        }
    }

    function supportsInterface(bytes4 interfaceId) public view override(ERC165, ITransferHookExtension) returns (bool) {
        return (interfaceId == type(ITransferHookExtension).interfaceId || super.supportsInterface(interfaceId));
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

/// @dev ITransferHookExtension – optional extension to add custom behavior to 721 NFT on Transfer
/// @notice Used for custom functionality and improvements
interface ITransferHookExtension {
    /// @param from Address transfer from
    /// @param to Address transfer to
    /// @param operator Address operating (calling) the transfer
    /// @param startTokenId transfer start token id
    /// @param quantity Transfer quantity (from ERC721A)
    function beforeTokenTransfers(address from, address to, address operator, uint256 startTokenId, uint256 quantity) external;
    /// @notice Used for supportsInterface IERC165
    function supportsInterface(bytes4 interfaceId) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC-165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).
     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/",
    "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
    "erc721a-upgradeable/=node_modules/erc721a-upgradeable/contracts/",
    "solady/=node_modules/solady/src/",
    "base64/=lib/base64/",
    "ds-test/=node_modules/ds-test/src/",
    "forge-std/=node_modules/forge-std/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 100
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"baseNFT_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"GameControllerRoleNeeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"JuryNFTsCannotBeTransferred","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":true,"internalType":"uint256[]","name":"players","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"PlayersSetEliminatedAt","type":"event"},{"inputs":[],"name":"GAME_CONTROLLER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseNFT","outputs":[{"internalType":"contract IAccessControl","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"startTokenId","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"beforeTokenTransfers","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"canTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"playerIds","type":"uint256[]"}],"name":"playersBecameJuryAt","outputs":[{"internalType":"uint256[]","name":"playersResult","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"players","type":"uint256[]"}],"name":"setPlayerBackInGame","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"players","type":"uint256[]"}],"name":"setPlayersEliminated","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"playerId","type":"uint256"}],"name":"singlePlayerBecameJuryAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

60c03460a357601f61072238819003918201601f19168301916001600160401b0383118484101760a75780849260209460405283398101031260a357516001600160a01b0381169081900360a3577f5245c884765f598386b104eddc4b9179437165bef12b695749d575c8493d71a360805260a05260405161066690816100bc82396080518181816102ee0152610569015260a051818181610326015261059b0152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a71461037d575080634d4f6ea914610355578063687fff22146103115780636e00ffd2146102d75780636eb6526f146102ae5780638eb8f4511461022b578063a949fdb014610171578063c1308e64146100fb5763d2f6d2561461007f575f80fd5b346100f75761008d36610460565b61009561055a565b61009e81610520565b6040514281527f35ea45ac7c567c7af88337c8fdd94e3eee9fd42e4588566fc992b146a1e30cf660203392a35f5b81518110156100f557806100e2600192846104f8565b515f525f6020524260405f2055016100cc565b005b5f80fd5b346100f75761010936610460565b61011161055a565b61011a81610520565b6040515f81527f35ea45ac7c567c7af88337c8fdd94e3eee9fd42e4588566fc992b146a1e30cf660203392a35f5b81518110156100f5578061015e600192846104f8565b515f525f6020525f604081205501610148565b346100f75761017f36610460565b8051906101a461018e83610448565b9261019c6040519485610412565b808452610448565b602083019190601f19013683375f5b81518110156101e657806101c9600192846104f8565b515f525f60205260405f20546101df82876104f8565b52016101b3565b505090604051918291602083019060208452518091526040830191905f5b818110610212575050500390f35b8251845285945060209384019390920191600101610204565b346100f75760a03660031901126100f7576102446103d0565b5061024d6103e6565b506102566103fc565b50606435608435810180821191825b61029a57818110156100f55761027a816104df565b156102885760010182610265565b631696eb8560e21b5f5260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b346100f75760203660031901126100f7576004355f525f602052602060405f2054604051908152f35b346100f7575f3660031901126100f75760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346100f7575f3660031901126100f7576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346100f75760203660031901126100f75760206103736004356104df565b6040519015158152f35b346100f75760203660031901126100f7576004359063ffffffff60e01b82168092036100f7576020916347a39efb60e11b81149081156103bf575b5015158152f35b6301ffc9a760e01b149050836103b8565b600435906001600160a01b03821682036100f757565b602435906001600160a01b03821682036100f757565b604435906001600160a01b03821682036100f757565b90601f8019910116810190811067ffffffffffffffff82111761043457604052565b634e487b7160e01b5f52604160045260245ffd5b67ffffffffffffffff81116104345760051b60200190565b60206003198201126100f7576004359067ffffffffffffffff82116100f757806023830112156100f757816004013561049881610448565b926104a66040519485610412565b8184526024602085019260051b8201019283116100f757602401905b8282106104cf5750505090565b81358152602091820191016104c2565b5f525f60205260405f2054156104f3575f90565b600190565b805182101561050c5760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b6040518091829160208251919201905f5b8181106105415750505003902090565b8251845285945060209384019390920191600101610531565b604051632474521560e21b81527f000000000000000000000000000000000000000000000000000000000000000060048201523360248201526020816044817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610625575f916105ea575b50156105db57565b63e590d16f60e01b5f5260045ffd5b90506020813d60201161061d575b8161060560209383610412565b810103126100f7575180151581036100f7575f6105d3565b3d91506105f8565b6040513d5f823e3d90fdfea2646970667358221220fc2594c54ded6d057ea15ea654b1ff80a8908c9e4c70b6cc19743fad5a621c6364736f6c634300081a003300000000000000000000000087239d9cf8a95adaea78c5b4678b6398d115f140

Deployed Bytecode

0x6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a71461037d575080634d4f6ea914610355578063687fff22146103115780636e00ffd2146102d75780636eb6526f146102ae5780638eb8f4511461022b578063a949fdb014610171578063c1308e64146100fb5763d2f6d2561461007f575f80fd5b346100f75761008d36610460565b61009561055a565b61009e81610520565b6040514281527f35ea45ac7c567c7af88337c8fdd94e3eee9fd42e4588566fc992b146a1e30cf660203392a35f5b81518110156100f557806100e2600192846104f8565b515f525f6020524260405f2055016100cc565b005b5f80fd5b346100f75761010936610460565b61011161055a565b61011a81610520565b6040515f81527f35ea45ac7c567c7af88337c8fdd94e3eee9fd42e4588566fc992b146a1e30cf660203392a35f5b81518110156100f5578061015e600192846104f8565b515f525f6020525f604081205501610148565b346100f75761017f36610460565b8051906101a461018e83610448565b9261019c6040519485610412565b808452610448565b602083019190601f19013683375f5b81518110156101e657806101c9600192846104f8565b515f525f60205260405f20546101df82876104f8565b52016101b3565b505090604051918291602083019060208452518091526040830191905f5b818110610212575050500390f35b8251845285945060209384019390920191600101610204565b346100f75760a03660031901126100f7576102446103d0565b5061024d6103e6565b506102566103fc565b50606435608435810180821191825b61029a57818110156100f55761027a816104df565b156102885760010182610265565b631696eb8560e21b5f5260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b346100f75760203660031901126100f7576004355f525f602052602060405f2054604051908152f35b346100f7575f3660031901126100f75760206040517f5245c884765f598386b104eddc4b9179437165bef12b695749d575c8493d71a38152f35b346100f7575f3660031901126100f7576040517f00000000000000000000000087239d9cf8a95adaea78c5b4678b6398d115f1406001600160a01b03168152602090f35b346100f75760203660031901126100f75760206103736004356104df565b6040519015158152f35b346100f75760203660031901126100f7576004359063ffffffff60e01b82168092036100f7576020916347a39efb60e11b81149081156103bf575b5015158152f35b6301ffc9a760e01b149050836103b8565b600435906001600160a01b03821682036100f757565b602435906001600160a01b03821682036100f757565b604435906001600160a01b03821682036100f757565b90601f8019910116810190811067ffffffffffffffff82111761043457604052565b634e487b7160e01b5f52604160045260245ffd5b67ffffffffffffffff81116104345760051b60200190565b60206003198201126100f7576004359067ffffffffffffffff82116100f757806023830112156100f757816004013561049881610448565b926104a66040519485610412565b8184526024602085019260051b8201019283116100f757602401905b8282106104cf5750505090565b81358152602091820191016104c2565b5f525f60205260405f2054156104f3575f90565b600190565b805182101561050c5760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b6040518091829160208251919201905f5b8181106105415750505003902090565b8251845285945060209384019390920191600101610531565b604051632474521560e21b81527f5245c884765f598386b104eddc4b9179437165bef12b695749d575c8493d71a360048201523360248201526020816044817f00000000000000000000000087239d9cf8a95adaea78c5b4678b6398d115f1406001600160a01b03165afa908115610625575f916105ea575b50156105db57565b63e590d16f60e01b5f5260045ffd5b90506020813d60201161061d575b8161060560209383610412565b810103126100f7575180151581036100f7575f6105d3565b3d91506105f8565b6040513d5f823e3d90fdfea2646970667358221220fc2594c54ded6d057ea15ea654b1ff80a8908c9e4c70b6cc19743fad5a621c6364736f6c634300081a0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000087239d9cf8a95adaea78c5b4678b6398d115f140

-----Decoded View---------------
Arg [0] : baseNFT_ (address): 0x87239d9CF8A95adAea78c5b4678B6398d115F140

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000087239d9cf8a95adaea78c5b4678b6398d115f140


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
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.