Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0x4C0b9B7b3e290B793474c533C7AC90262bb69971
Balance 0 ETH
Nonce 1
Code Size 5191 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

5191 bytes
0x6080604052600436106101445760003560e01c80638456cb59116100b6578063b79fba271161006f578063b79fba2714610365578063bf4c1d1e14610392578063c465e49f146103c8578063e9bf95a2146103dd578063ec5ae157146103fd578063f2fde38b146104135761014b565b80638456cb59146102b65780638da5cb5b146102cb57806391b7f5ed146102fd57806393e84cd91461031d578063aa3bf60e14610325578063acec338a146103455761014b565b80633f4ba83a116101085780633f4ba83a146102225780634ec18db9146102375780635c975abb1461024c5780635cad65a11461026b57806369c1a7ed1461028b578063715018a6146102a15761014b565b806302fb0c5e1461016657806312065fe01461019557806336118b52146101b25780633b98d8e6146101d25780633c042fb2146102025761014b565b3661014b57005b34801561015757600080fd5b5061016433600036610433565b005b34801561017257600080fd5b506004546101809060ff1681565b60405190151581526020015b60405180910390f35b3480156101a157600080fd5b50475b60405190815260200161018c565b3480156101be57600080fd5b506101646101cd3660046111ba565b610658565b3480156101de57600080fd5b506101806101ed3660046111ea565b60066020526000908152604090205460ff1681565b34801561020e57600080fd5b5061016461021d3660046111ea565b61079a565b34801561022e57600080fd5b50610164610901565b34801561024357600080fd5b506005546101a4565b34801561025857600080fd5b50600054600160a01b900460ff16610180565b34801561027757600080fd5b50610180610286366004611203565b610913565b34801561029757600080fd5b506101a460025481565b3480156102ad57600080fd5b50610164610929565b3480156102c257600080fd5b5061016461093b565b3480156102d757600080fd5b506000546001600160a01b03165b6040516001600160a01b03909116815260200161018c565b34801561030957600080fd5b506101646103183660046111ea565b61094b565b61016461098f565b34801561033157600080fd5b50610180610340366004611203565b610cfe565b34801561035157600080fd5b5061016461036036600461122f565b610d34565b34801561037157600080fd5b50610385610380366004611258565b610d7d565b60405161018c919061127a565b34801561039e57600080fd5b506102e56103ad3660046111ea565b6007602052600090815260409020546001600160a01b031681565b3480156103d457600080fd5b506101a4600581565b3480156103e957600080fd5b506101a46103f8366004611203565b610e77565b34801561040957600080fd5b506101a460035481565b34801561041f57600080fd5b5061016461042e3660046112be565b610ef9565b6000546001600160a01b0384811691161461048e5760405162461bcd60e51b815260206004820152601660248201527513db9b1e481bdddb995c8818d85b8819195c1bdcda5d60521b60448201526064015b60405180910390fd5b80158015906104a557506104a36020826112f1565b155b6104e25760405162461bcd60e51b815260206004820152600e60248201526d092dcecc2d8d2c840d8cadccee8d60931b6044820152606401610485565b60005b6104f060208361131b565b811015610652576000838361050684602061132f565b90610512856001611346565b61051d90602061132f565b9261052a93929190611359565b81019061053791906111ea565b60008181526006602052604090205490915060ff161561058b5760405162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e481a5b881c1bdbdb608a1b6044820152606401610485565b6001600160a01b03851660008181526000805160206113f28339815191526020908152604080832085845282528083204390556005805460018082019092557f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00186905560068352818420805460ff19169091179055600790915280822080546001600160a01b031916841790555183917f2afc8e88f530f9a4d426e1d9aa85c29ec6e38951a150424846f9b0415b15f33b91a3508061064a81611383565b9150506104e5565b50505050565b610660610f37565b610668610f64565b6001600160a01b0381166106b05760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610485565b478211156106f75760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610485565b6000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114610744576040519150601f19603f3d011682016040523d82523d6000602084013e610749565b606091505b505090508061078c5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610485565b5061079660018055565b5050565b6107a2610f37565b60008181526006602052604090205460ff166107ee5760405162461bcd60e51b815260206004820152600b60248201526a139bdd081a5b881c1bdbdb60aa1b6044820152606401610485565b60005b6005548110156108a757816005828154811061080f5761080f61139c565b906000526020600020015403610895576005805461082f906001906113b2565b8154811061083f5761083f61139c565b90600052602060002001546005828154811061085d5761085d61139c565b600091825260209091200155600580548061087a5761087a6113c5565b600190038181906000526020600020016000905590556108a7565b8061089f81611383565b9150506107f1565b506000818152600660205260408120805460ff19169055546108d3906001600160a01b03168083610f8e565b60405181907f1dd020ab4e46cb183ee32c514b343e9a803ba5ce0fabf281f39c0f0a37071bd690600090a250565b610909610f37565b610911611010565b565b600061091f8383610cfe565b1590505b92915050565b610931610f37565b6109116000611065565b610943610f37565b6109116110b5565b610953610f37565b60028190556040518181527f6bfd5e75539a9d2626425a2e2922675256b219fe546d63dad56011759b9a2f66906020015b60405180910390a150565b610997610f64565b61099f6110f8565b60045460ff166109e45760405162461bcd60e51b815260206004820152601060248201526f4c6f747465727920696e61637469766560801b6044820152606401610485565b600254341015610a2d5760405162461bcd60e51b8152602060048201526014602482015273125b9cdd59999a58da595b9d081c185e5b595b9d60621b6044820152606401610485565b600554610a725760405162461bcd60e51b81526020600482015260136024820152724e6f207072697a657320617661696c61626c6560681b6044820152606401610485565b60038054906000610a8283611383565b91905055506000444260035433604051602001610acb949392919093845260208401929092526040830152606090811b6bffffffffffffffffffffffff19169082015260740190565b60408051601f198184030181529190528051602090910120600554909150600090610af690836112f1565b9050600060058281548110610b0d57610b0d61139c565b60009182526020808320909101548083526007909152604090912054600580549293506001600160a01b0390911691610b48906001906113b2565b81548110610b5857610b5861139c565b906000526020600020015460058481548110610b7657610b7661139c565b6000918252602090912001556005805480610b9357610b936113c5565b600082815260208082208301600019908101839055909201909255838252600681526040808320805460ff191690556007909152902080546001600160a01b0319169055610be2813384610f8e565b60035460408051348152602081018790523392917f4011fff102fa79e54900316bba9ba8fa8bcdc15e023292edd636c727dfe3c87d910160405180910390a3600354604051839133917f435d496d95c2fa344731362e4067994acb8cb72a4aa34b318e70f31c41da5d5e90600090a4600254341115610cf1576002546000903390610c6d90346113b2565b604051600081818185875af1925050503d8060008114610ca9576040519150601f19603f3d011682016040523d82523d6000602084013e610cae565b606091505b5050905080610cef5760405162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b6044820152606401610485565b505b5050505061091160018055565b6001600160a01b039190911660009081526000805160206113f28339815191526020908152604080832093835292905220541590565b610d3c610f37565b6004805460ff19168215159081179091556040519081527f18480802bce25a27d61b6c3a1c5a3d200820627e87b0c2b385c763edd2531cd190602001610984565b60606000610d8b8385611346565b600554909150811115610d9d57506005545b6005548410610dbc575050604080516000815260208101909152610923565b6000610dc885836113b2565b67ffffffffffffffff811115610de057610de06113db565b604051908082528060200260200182016040528015610e09578160200160208202803683370190505b509050845b82811015610e6e5760058181548110610e2957610e2961139c565b9060005260206000200154828783610e4191906113b2565b81518110610e5157610e5161139c565b602090810291909101015280610e6681611383565b915050610e0e565b50949350505050565b6001600160a01b03821660009081526000805160206113f283398151915260209081526040808320848452909152812054808203610ec8576040516362ef5a1960e01b815260040160405180910390fd5b6000610ed482436113b2565b905060058110610ee5576000610ef0565b610ef08160056113b2565b95945050505050565b610f01610f37565b6001600160a01b038116610f2b57604051631e4fbdf760e01b815260006004820152602401610485565b610f3481611065565b50565b6000546001600160a01b031633146109115760405163118cdaa760e01b8152336004820152602401610485565b600260015403610f8757604051633ee5aeb560e01b815260040160405180910390fd5b6002600155565b610f99838383611123565b80826001600160a01b0316846001600160a01b03167ff1d95ed4d1680e6f665104f19c296ae52c1f64cd8114e84d55dc6349dbdafea360405160405180910390a46001600160a01b03831660009081526000805160206113f283398151915260209081526040808320848452909152812055505050565b61101861117b565b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6110bd6110f8565b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586110483390565b600054600160a01b900460ff16156109115760405163d93c066560e01b815260040160405180910390fd5b61112d8382610cfe565b1561114b576040516362ef5a1960e01b815260040160405180910390fd5b60006111578483610e77565b9050801561065257604051633247baf960e21b815260048101829052602401610485565b600054600160a01b900460ff1661091157604051638dfc202b60e01b815260040160405180910390fd5b6001600160a01b0381168114610f3457600080fd5b600080604083850312156111cd57600080fd5b8235915060208301356111df816111a5565b809150509250929050565b6000602082840312156111fc57600080fd5b5035919050565b6000806040838503121561121657600080fd5b8235611221816111a5565b946020939093013593505050565b60006020828403121561124157600080fd5b8135801515811461125157600080fd5b9392505050565b6000806040838503121561126b57600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b818110156112b257835183529284019291840191600101611296565b50909695505050505050565b6000602082840312156112d057600080fd5b8135611251816111a5565b634e487b7160e01b600052601260045260246000fd5b600082611300576113006112db565b500690565b634e487b7160e01b600052601160045260246000fd5b60008261132a5761132a6112db565b500490565b808202811582820484141761092357610923611305565b8082018082111561092357610923611305565b6000808585111561136957600080fd5b8386111561137657600080fd5b5050820193919092039150565b60006001820161139557611395611305565b5060010190565b634e487b7160e01b600052603260045260246000fd5b8181038181111561092357610923611305565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052604160045260246000fdfea282d38759ca2a57f8989aea0c5822bcfbf65ad49415379bdbc35dbb78efd8daa264697066735822122067d8e71726fbe7e08d16031f1b97af7b278846dc2ecb9c0bfca636071cf882b264736f6c63430008140033

Verified Source Code Partial Match

Compiler: v0.8.20+commit.a1b79de6 EVM: paris Optimization: Yes (200 runs)
PhilipLotteryV67.sol 712 lines
// Sources flattened with hardhat v2.22.5 https://hardhat.org

// SPDX-License-Identifier: MIT AND PHUNKY

// File @openzeppelin/contracts/utils/[email protected]

// Original license: 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;
    }
}


// File @openzeppelin/contracts/access/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

/**
 * @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);
    }
}


// File @openzeppelin/contracts/utils/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    bool private _paused;

    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    /**
     * @dev The operation failed because the contract is paused.
     */
    error EnforcedPause();

    /**
     * @dev The operation failed because the contract is not paused.
     */
    error ExpectedPause();

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        if (paused()) {
            revert EnforcedPause();
        }
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        if (!paused()) {
            revert ExpectedPause();
        }
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}


// File @openzeppelin/contracts/utils/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}


// File contracts/V2MainnetUpgrade/EthscriptionsEscrower.sol

// Original license: SPDX_License_Identifier: MIT
pragma solidity 0.8.20;

library EthscriptionsEscrowerStorage {
    struct Layout {
        mapping(address => mapping(bytes32 => uint256)) ethscriptionReceivedOnBlockNumber;
    }

    bytes32 internal constant STORAGE_SLOT =
        keccak256(
            "ethscriptions.contracts.storage.EthscriptionsEscrowerStorage"
        );

    function s() internal pure returns (Layout storage l) {
        bytes32 slot = STORAGE_SLOT;
        assembly {
            l.slot := slot
        }
    }
}

contract EthscriptionsEscrower {
    error EthscriptionNotDeposited();
    error EthscriptionAlreadyReceivedFromSender();
    error InvalidEthscriptionLength();
    error AdditionalCooldownRequired(uint256 additionalBlocksNeeded);

    event ethscriptions_protocol_TransferEthscriptionForPreviousOwner(
        address indexed previousOwner,
        address indexed recipient,
        bytes32 indexed id
    );

    event PotentialEthscriptionDeposited(
        address indexed owner,
        bytes32 indexed potentialEthscriptionId
    );

    event PotentialEthscriptionWithdrawn(
        address indexed owner,
        bytes32 indexed potentialEthscriptionId
    );

    uint256 public constant ETHSCRIPTION_TRANSFER_COOLDOWN_BLOCKS = 5;

    function _transferEthscription(
        address previousOwner,
        address to,
        bytes32 ethscriptionId
    ) internal virtual {
        _validateTransferEthscription(previousOwner, to, ethscriptionId);

        emit ethscriptions_protocol_TransferEthscriptionForPreviousOwner(
            previousOwner,
            to,
            ethscriptionId
        );

        _afterTransferEthscription(previousOwner, to, ethscriptionId);
    }

    function withdrawEthscription(bytes32 ethscriptionId) internal virtual {
        _transferEthscription(msg.sender, msg.sender, ethscriptionId);

        // emit PotentialEthscriptionWithdrawn(msg.sender, ethscriptionId);
    }

    function _onPotentialEthscriptionDeposit(
        address previousOwner,
        bytes calldata userCalldata
    ) internal virtual {
        if (userCalldata.length != 32) revert InvalidEthscriptionLength();

        bytes32 potentialEthscriptionId = abi.decode(userCalldata, (bytes32));

        if (
            userEthscriptionPossiblyStored(
                previousOwner,
                potentialEthscriptionId
            )
        ) {
            revert EthscriptionAlreadyReceivedFromSender();
        }

        EthscriptionsEscrowerStorage.s().ethscriptionReceivedOnBlockNumber[
            previousOwner
        ][potentialEthscriptionId] = block.number;

        // emit PotentialEthscriptionDeposited(previousOwner, potentialEthscriptionId);
    }

    function _validateTransferEthscription(
        address previousOwner,
        address to,
        bytes32 ethscriptionId
    ) internal view virtual {
        if (
            userEthscriptionDefinitelyNotStored(previousOwner, ethscriptionId)
        ) {
            revert EthscriptionNotDeposited();
        }

        uint256 blocksRemaining = blocksRemainingUntilValidTransfer(
            previousOwner,
            ethscriptionId
        );

        if (blocksRemaining != 0) {
            revert AdditionalCooldownRequired(blocksRemaining);
        }
    }

    function _afterTransferEthscription(
        address previousOwner,
        address to,
        bytes32 ethscriptionId
    ) internal virtual {
        delete EthscriptionsEscrowerStorage
            .s()
            .ethscriptionReceivedOnBlockNumber[previousOwner][ethscriptionId];
    }

    function blocksRemainingUntilValidTransfer(
        address previousOwner,
        bytes32 ethscriptionId
    ) public view virtual returns (uint256) {
        uint256 receivedBlockNumber = EthscriptionsEscrowerStorage
            .s()
            .ethscriptionReceivedOnBlockNumber[previousOwner][ethscriptionId];

        if (receivedBlockNumber == 0) {
            revert EthscriptionNotDeposited();
        }

        uint256 blocksPassed = block.number - receivedBlockNumber;

        return
            blocksPassed < ETHSCRIPTION_TRANSFER_COOLDOWN_BLOCKS
                ? ETHSCRIPTION_TRANSFER_COOLDOWN_BLOCKS - blocksPassed
                : 0;
    }

    function userEthscriptionDefinitelyNotStored(
        address owner,
        bytes32 ethscriptionId
    ) public view virtual returns (bool) {
        return
            EthscriptionsEscrowerStorage.s().ethscriptionReceivedOnBlockNumber[
                owner
            ][ethscriptionId] == 0;
    }

    function userEthscriptionPossiblyStored(
        address owner,
        bytes32 ethscriptionId
    ) public view virtual returns (bool) {
        return !userEthscriptionDefinitelyNotStored(owner, ethscriptionId);
    }
}


// File contracts/V2MainnetUpgrade/PhilipLotteryV67.sol

// Original license: SPDX_License_Identifier: PHUNKY

/*********** PhilipLotteryV67 *
* ░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░▓▓▓▓░░░░░░▓▓▓▓░░░░░░ *
* ░░░░░▒▒██░░░░░░▒▒██░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░████░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░██░░░░░░░░ *
* ░░░░░░░░░██████░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░ *
* ░░░░░░░░░░░░░░░░░░░░░░░░░ *
****************************/

pragma solidity 0.8.20;
contract PhilipLotteryV67 is EthscriptionsEscrower, Ownable, Pausable, ReentrancyGuard {

    uint256 public playPrice;
    uint256 public totalPlays;
    bool public active;

    bytes32[] private _prizePool;
    mapping(bytes32 => bool) public inPool;
    mapping(bytes32 => address) public depositor;

    event LotteryPlayed(
        uint256 indexed playId,
        address indexed player,
        uint256 price,
        uint256 randomSeed
    );

    event PrizeAwarded(
        uint256 indexed playId,
        address indexed winner,
        bytes32 indexed hashId
    );

    event PrizeDeposited(bytes32 indexed hashId, address indexed depositor);
    event PrizeWithdrawn(bytes32 indexed hashId);
    event PriceSet(uint256 newPrice);
    event ActiveToggled(bool active);

    constructor(uint256 _playPrice) Ownable(msg.sender) {
        playPrice = _playPrice;
        active = true;
    }

    // =========================================================
    // Ethscription Deposits (owner sends ethscriptions here)
    // =========================================================

    fallback() external {
        _onPotentialEthscriptionDeposit(msg.sender, msg.data);
    }

    function _onPotentialEthscriptionDeposit(
        address previousOwner,
        bytes calldata userCalldata
    ) internal override {
        require(previousOwner == owner(), "Only owner can deposit");
        require(userCalldata.length > 0 && userCalldata.length % 32 == 0, "Invalid length");

        for (uint256 i = 0; i < userCalldata.length / 32; i++) {
            bytes32 hashId = abi.decode(userCalldata[i * 32 : (i + 1) * 32], (bytes32));

            require(!inPool[hashId], "Already in pool");

            // Record in escrow storage (tracks block number for cooldown)
            EthscriptionsEscrowerStorage.s().ethscriptionReceivedOnBlockNumber[
                previousOwner
            ][hashId] = block.number;

            // Add to prize pool
            _prizePool.push(hashId);
            inPool[hashId] = true;
            depositor[hashId] = previousOwner;

            emit PrizeDeposited(hashId, previousOwner);
        }
    }

    // =========================================================
    // Play (pay fee, win random ethscription)
    // =========================================================

    function play() external payable nonReentrant whenNotPaused {
        require(active, "Lottery inactive");
        require(msg.value >= playPrice, "Insufficient payment");
        require(_prizePool.length > 0, "No prizes available");

        totalPlays++;

        uint256 randomSeed = uint256(keccak256(abi.encodePacked(
            block.prevrandao,
            block.timestamp,
            totalPlays,
            msg.sender
        )));

        uint256 winIndex = randomSeed % _prizePool.length;
        bytes32 wonHashId = _prizePool[winIndex];
        address dep = depositor[wonHashId];

        // Remove from pool (swap with last, then pop)
        _prizePool[winIndex] = _prizePool[_prizePool.length - 1];
        _prizePool.pop();
        inPool[wonHashId] = false;
        delete depositor[wonHashId];

        // Transfer ethscription to winner via escrower protocol event
        _transferEthscription(dep, msg.sender, wonHashId);

        emit LotteryPlayed(totalPlays, msg.sender, msg.value, randomSeed);
        emit PrizeAwarded(totalPlays, msg.sender, wonHashId);

        // Refund excess payment
        if (msg.value > playPrice) {
            (bool sent, ) = payable(msg.sender).call{value: msg.value - playPrice}("");
            require(sent, "Refund failed");
        }
    }

    // =========================================================
    // View Functions
    // =========================================================

    function poolSize() external view returns (uint256) {
        return _prizePool.length;
    }

    function getPoolItems(uint256 offset, uint256 limit) external view returns (bytes32[] memory) {
        uint256 end = offset + limit;
        if (end > _prizePool.length) end = _prizePool.length;
        if (offset >= _prizePool.length) return new bytes32[](0);

        bytes32[] memory items = new bytes32[](end - offset);
        for (uint256 i = offset; i < end; i++) {
            items[i - offset] = _prizePool[i];
        }
        return items;
    }

    function getBalance() external view returns (uint256) {
        return address(this).balance;
    }

    // =========================================================
    // Owner Functions
    // =========================================================

    function setPrice(uint256 _price) external onlyOwner {
        playPrice = _price;
        emit PriceSet(_price);
    }

    function setActive(bool _active) external onlyOwner {
        active = _active;
        emit ActiveToggled(_active);
    }

    function withdrawETH(uint256 amount, address payable to) external onlyOwner nonReentrant {
        require(to != address(0), "Invalid address");
        require(amount <= address(this).balance, "Insufficient balance");
        (bool sent, ) = to.call{value: amount}("");
        require(sent, "Transfer failed");
    }

    function withdrawPrize(bytes32 hashId) external onlyOwner {
        require(inPool[hashId], "Not in pool");

        // Find and remove from array
        for (uint256 i = 0; i < _prizePool.length; i++) {
            if (_prizePool[i] == hashId) {
                _prizePool[i] = _prizePool[_prizePool.length - 1];
                _prizePool.pop();
                break;
            }
        }
        inPool[hashId] = false;

        // Transfer back to owner
        _transferEthscription(owner(), owner(), hashId);

        emit PrizeWithdrawn(hashId);
    }

    function pause() external onlyOwner {
        _pause();
    }

    function unpause() external onlyOwner {
        _unpause();
    }

    receive() external payable {}
}

Read Contract

ETHSCRIPTION_TRANSFER_COOLDOWN_BLOCKS 0xc465e49f → uint256
active 0x02fb0c5e → bool
blocksRemainingUntilValidTransfer 0xe9bf95a2 → uint256
depositor 0xbf4c1d1e → address
getBalance 0x12065fe0 → uint256
getPoolItems 0xb79fba27 → bytes32[]
inPool 0x3b98d8e6 → bool
owner 0x8da5cb5b → address
paused 0x5c975abb → bool
playPrice 0x69c1a7ed → uint256
poolSize 0x4ec18db9 → uint256
totalPlays 0xec5ae157 → uint256
userEthscriptionDefinitelyNotStored 0xaa3bf60e → bool
userEthscriptionPossiblyStored 0x5cad65a1 → bool

Write Contract 9 functions

These functions modify contract state and require a wallet transaction to execute.

pause 0x8456cb59
No parameters
play 0x93e84cd9
No parameters
renounceOwnership 0x715018a6
No parameters
setActive 0xacec338a
bool _active
setPrice 0x91b7f5ed
uint256 _price
transferOwnership 0xf2fde38b
address newOwner
unpause 0x3f4ba83a
No parameters
withdrawETH 0x36118b52
uint256 amount
address to
withdrawPrize 0x3c042fb2
bytes32 hashId

Recent Transactions

No transactions found for this address