ETH Price: $2,950.06 (-0.19%)

Contract

0x126d2beb87E4d0F46bec03cCf7896B34012Ea849

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
297030612025-12-09 16:14:4646 days ago1765296886  Contract Creation0 ETH
Cross-Chain Transactions
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0xa832AFc5...3BF98BDB7
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
Raffle

Compiler Version
v0.8.28+commit.7893614a

ZkSolc Version
v1.5.15

Optimization Enabled:
Yes with Mode 3

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

import {IEntropyConsumer} from "@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol";
import {IEntropyV2} from "@pythnetwork/entropy-sdk-solidity/IEntropyV2.sol";

import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

import {IRaffle, RaffleEntry} from "./interfaces/IRaffle.sol";

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

uint32 constant ENTROPY_CALLBACK_GAS = 50_000;

contract Raffle is EthFundable, Ownable2Step, IEntropyConsumer, IRaffle {
    IEntropyV2 public entropyProvider;
    uint128 public maxFee;

    mapping(uint64 sequenceNumber => bytes32 commitment) internal commitedRaffles;
    mapping(bytes32 commitment => uint256 randomNumber) internal providedRandomNumbers;

    constructor(address _entropyProvider, uint128 _maxFee, address _owner) Ownable(_owner) {
        require(_entropyProvider != address(0), InvalidAddress());
        require(_owner != address(0), InvalidAddress());

        _setEntropyProvider(_entropyProvider);
        _setMaxFee(_maxFee);
    }

    // ----- core -----

    function commitRaffle(bytes32 commitment) external onlyOwner {
        uint128 fee = entropyProvider.getFeeV2(ENTROPY_CALLBACK_GAS);
        require(fee <= maxFee, FeeExceedsMax(maxFee, fee));

        uint256 balance = address(this).balance;
        require(balance >= fee, InsufficientBalance(balance, fee));

        uint64 sequenceNumber = entropyProvider.requestV2{value: fee}(ENTROPY_CALLBACK_GAS);
        require(commitedRaffles[sequenceNumber] == bytes32(0), DuplicateSequenceNumber(sequenceNumber));

        commitedRaffles[sequenceNumber] = commitment;
        emit RaffleCommited(commitment);
    }

    function selectWinners(RaffleEntry[] calldata entries, uint8 winnersCount, uint256 raffleId) external onlyOwner {
        // Precompute
        bytes32 dataHash = bytes32(raffleId);
        uint256 entriesLength = entries.length;
        uint256[] memory prefixSumArray = new uint256[](entriesLength + 1); // Starts at index 1
        for (uint256 i = 0; i < entriesLength; ++i) {
            RaffleEntry calldata entry = entries[i];

            dataHash = keccak256(abi.encodePacked(dataHash, entry.user, entry.tickets));
            prefixSumArray[i + 1] = prefixSumArray[i] + entry.tickets;
        }

        uint256 randomNumber = providedRandomNumbers[dataHash];
        require(randomNumber != 0, CommitmentNotFound(dataHash));

        // Select winners
        uint256 totalTicketsCount = prefixSumArray[entriesLength];
        address[] memory winners = new address[](winnersCount);
        for (uint256 i = 0; i < winnersCount; ++i) {
            uint256 winningTicketIdx = randomNumber % totalTicketsCount;
            winners[i] = _findWinner(entries, prefixSumArray, winningTicketIdx);

            randomNumber = uint256(keccak256(abi.encodePacked(randomNumber, i)));
        }

        emit WinnersSelected(raffleId, winners);
    }

    // ----- setters -----

    function setEntropyProvider(address newEntropyProvider) external onlyOwner {
        require(newEntropyProvider != address(0), InvalidAddress());
        _setEntropyProvider(newEntropyProvider);
    }

    function setMaxFee(uint128 newMaxFee) external onlyOwner {
        _setMaxFee(newMaxFee);
    }

    // ----- entropy consumer -----

    function entropyCallback(uint64 sequenceNumber, address /* provider */, bytes32 randomNumber) internal override {
        bytes32 commitment = commitedRaffles[sequenceNumber];
        providedRandomNumbers[commitment] = uint256(randomNumber);
        emit RafflePrepared(commitment, sequenceNumber, uint256(randomNumber));
    }

    function getEntropy() internal view override returns (address) {
        return address(entropyProvider);
    }

    // ----- eth fundable -----

    function canWithdrawEth(address user) internal view override returns (bool) {
        return user == owner();
    }

    // ----- internal -----

    function _findWinner(
        RaffleEntry[] calldata entries,
        uint256[] memory prefixSumArray,
        uint256 winningTicketIdx
    ) internal pure returns (address) {
        uint256 left = 0;
        uint256 right = entries.length - 1;

        while (left < right) {
            uint256 middle = (left + right) / 2;

            if (prefixSumArray[middle + 1] <= winningTicketIdx) {
                left = middle + 1;
            } else {
                right = middle;
            }
        }

        return entries[left].user;
    }

    function _setMaxFee(uint128 newMaxFee) internal {
        maxFee = newMaxFee;
        emit MaxFeeSet(newMaxFee);
    }

    function _setEntropyProvider(address newEntropyProvider) internal {
        entropyProvider = IEntropyV2(newEntropyProvider);
        emit EntropyProviderSet(newEntropyProvider);
    }
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

import {IEthFundable} from "./interfaces/IEthFundable.sol";

abstract contract EthFundable is IEthFundable {
    receive() external payable {}

    function withdraw(uint256 amount) external {
        require(canWithdrawEth(msg.sender), EthFundableUnauthorized(msg.sender));

        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, TransferFailed(msg.sender, amount));
    }

    function canWithdrawEth(address user) internal view virtual returns (bool);
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

struct RaffleEntry {
    address user;
    uint64 tickets;
}

interface IRaffleErrors {
    error CommitmentNotFound(bytes32 commitment);
    error DuplicateSequenceNumber(uint64 sequenceNumber);
    error FeeExceedsMax(uint128 maxAcceptableFee, uint128 fee);
    error InsufficientBalance(uint256 balance, uint256 valueToTransfer);
    error InvalidAddress();
    error WinnersCountMustBePositive();
}

interface IRaffle is IRaffleErrors {
    event RaffleCommited(bytes32 commitment);
    event RafflePrepared(bytes32 commitment, uint64 sequenceNumber, uint256 randomNumber);
    event WinnersSelected(uint256 raffleId, address[] winners);
    event EntropyProviderSet(address entropyProvider);
    event MaxFeeSet(uint128 maxFee);

    function commitRaffle(bytes32 commitment) external;

    function selectWinners(RaffleEntry[] calldata entries, uint8 winnersCount, uint256 raffleId) external;

    function setEntropyProvider(address newEntropyProvider) external;

    function setMaxFee(uint128 newMaxFee) external;
}

// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;

abstract contract IEntropyConsumer {
    // This method is called by Entropy to provide the random number to the consumer.
    // It asserts that the msg.sender is the Entropy contract. It is not meant to be
    // override by the consumer.
    function _entropyCallback(
        uint64 sequence,
        address provider,
        bytes32 randomNumber
    ) external {
        address entropy = getEntropy();
        require(entropy != address(0), "Entropy address not set");
        require(msg.sender == entropy, "Only Entropy can call this function");

        entropyCallback(sequence, provider, randomNumber);
    }

    // getEntropy returns Entropy contract address. The method is being used to check that the
    // callback is indeed from Entropy contract. The consumer is expected to implement this method.
    // Entropy address can be found here - https://docs.pyth.network/entropy/contract-addresses
    function getEntropy() internal view virtual returns (address);

    // This method is expected to be implemented by the consumer to handle the random number.
    // It will be called by _entropyCallback after _entropyCallback ensures that the call is
    // indeed from Entropy contract.
    function entropyCallback(
        uint64 sequence,
        address provider,
        bytes32 randomNumber
    ) internal virtual;
}

// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;

import "./EntropyEvents.sol";
import "./EntropyEventsV2.sol";
import "./EntropyStructsV2.sol";

interface IEntropyV2 is EntropyEventsV2 {
    /// @notice Request a random number using the default provider with default gas limit
    /// @return assignedSequenceNumber A unique identifier for this request
    /// @dev The address calling this function should be a contract that inherits from the IEntropyConsumer interface.
    /// The `entropyCallback` method on that interface will receive a callback with the returned sequence number and
    /// the generated random number.
    ///
    /// `entropyCallback` will be run with the provider's configured default gas limit.
    ///
    /// This method will revert unless the caller provides a sufficient fee (at least `getFeeV2()`) as msg.value.
    /// Note that the fee can change over time. Callers of this method should explicitly compute `getFeeV2()`
    /// prior to each invocation (as opposed to hardcoding a value). Further note that excess value is *not* refunded to the caller.
    ///
    /// Note that this method uses an in-contract PRNG to generate the user's contribution to the random number.
    /// This approach modifies the security guarantees such that a dishonest validator and provider can
    /// collude to manipulate the result (as opposed to a malicious user and provider). That is, the user
    /// now trusts the validator honestly draw a random number. If you wish to avoid this trust assumption,
    /// call a variant of `requestV2` that accepts a `userRandomNumber` parameter.
    function requestV2()
        external
        payable
        returns (uint64 assignedSequenceNumber);

    /// @notice Request a random number using the default provider with specified gas limit
    /// @param gasLimit The gas limit for the callback function.
    /// @return assignedSequenceNumber A unique identifier for this request
    /// @dev The address calling this function should be a contract that inherits from the IEntropyConsumer interface.
    /// The `entropyCallback` method on that interface will receive a callback with the returned sequence number and
    /// the generated random number.
    ///
    /// `entropyCallback` will be run with the `gasLimit` provided to this function.
    /// The `gasLimit` will be rounded up to a multiple of 10k (e.g., 19000 -> 20000), and furthermore is lower bounded
    /// by the provider's configured default limit.
    ///
    /// This method will revert unless the caller provides a sufficient fee (at least `getFeeV2(gasLimit)`) as msg.value.
    /// Note that the fee can change over time. Callers of this method should explicitly compute `getFeeV2(gasLimit)`
    /// prior to each invocation (as opposed to hardcoding a value). Further note that excess value is *not* refunded to the caller.
    ///
    /// Note that this method uses an in-contract PRNG to generate the user's contribution to the random number.
    /// This approach modifies the security guarantees such that a dishonest validator and provider can
    /// collude to manipulate the result (as opposed to a malicious user and provider). That is, the user
    /// now trusts the validator honestly draw a random number. If you wish to avoid this trust assumption,
    /// call a variant of `requestV2` that accepts a `userRandomNumber` parameter.
    function requestV2(
        uint32 gasLimit
    ) external payable returns (uint64 assignedSequenceNumber);

    /// @notice Request a random number from a specific provider with specified gas limit
    /// @param provider The address of the provider to request from
    /// @param gasLimit The gas limit for the callback function
    /// @return assignedSequenceNumber A unique identifier for this request
    /// @dev The address calling this function should be a contract that inherits from the IEntropyConsumer interface.
    /// The `entropyCallback` method on that interface will receive a callback with the returned sequence number and
    /// the generated random number.
    ///
    /// `entropyCallback` will be run with the `gasLimit` provided to this function.
    /// The `gasLimit` will be rounded up to a multiple of 10k (e.g., 19000 -> 20000), and furthermore is lower bounded
    /// by the provider's configured default limit.
    ///
    /// This method will revert unless the caller provides a sufficient fee (at least `getFeeV2(provider, gasLimit)`) as msg.value.
    /// Note that provider fees can change over time. Callers of this method should explicitly compute `getFeeV2(provider, gasLimit)`
    /// prior to each invocation (as opposed to hardcoding a value). Further note that excess value is *not* refunded to the caller.
    ///
    /// Note that this method uses an in-contract PRNG to generate the user's contribution to the random number.
    /// This approach modifies the security guarantees such that a dishonest validator and provider can
    /// collude to manipulate the result (as opposed to a malicious user and provider). That is, the user
    /// now trusts the validator honestly draw a random number. If you wish to avoid this trust assumption,
    /// call a variant of `requestV2` that accepts a `userRandomNumber` parameter.
    function requestV2(
        address provider,
        uint32 gasLimit
    ) external payable returns (uint64 assignedSequenceNumber);

    /// @notice Request a random number from a specific provider with a user-provided random number and gas limit
    /// @param provider The address of the provider to request from
    /// @param userRandomNumber A random number provided by the user for additional entropy
    /// @param gasLimit The gas limit for the callback function. Pass 0 to get a sane default value -- see note below.
    /// @return assignedSequenceNumber A unique identifier for this request
    /// @dev The address calling this function should be a contract that inherits from the IEntropyConsumer interface.
    /// The `entropyCallback` method on that interface will receive a callback with the returned sequence number and
    /// the generated random number.
    ///
    /// `entropyCallback` will be run with the `gasLimit` provided to this function.
    /// The `gasLimit` will be rounded up to a multiple of 10k (e.g., 19000 -> 20000), and furthermore is lower bounded
    /// by the provider's configured default limit.
    ///
    /// This method will revert unless the caller provides a sufficient fee (at least `getFeeV2(provider, gasLimit)`) as msg.value.
    /// Note that provider fees can change over time. Callers of this method should explicitly compute `getFeeV2(provider, gasLimit)`
    /// prior to each invocation (as opposed to hardcoding a value). Further note that excess value is *not* refunded to the caller.
    function requestV2(
        address provider,
        bytes32 userRandomNumber,
        uint32 gasLimit
    ) external payable returns (uint64 assignedSequenceNumber);

    /// @notice Get information about a specific entropy provider
    /// @param provider The address of the provider to query
    /// @return info The provider information including configuration, fees, and operational status
    /// @dev This method returns detailed information about a provider's configuration and capabilities.
    /// The returned ProviderInfo struct contains information such as the provider's fee structure and gas limits.
    function getProviderInfoV2(
        address provider
    ) external view returns (EntropyStructsV2.ProviderInfo memory info);

    /// @notice Get the address of the default entropy provider
    /// @return provider The address of the default provider
    /// @dev This method returns the address of the provider that will be used when no specific provider is specified
    /// in the requestV2 calls. The default provider can be used to get the base fee and gas limit information.
    function getDefaultProvider() external view returns (address provider);

    /// @notice Get information about a specific request
    /// @param provider The address of the provider that handled the request
    /// @param sequenceNumber The unique identifier of the request
    /// @return req The request information including status, random number, and other metadata
    /// @dev This method allows querying the state of a previously made request. The returned Request struct
    /// contains information about whether the request was fulfilled, the generated random number (if available),
    /// and other metadata about the request.
    function getRequestV2(
        address provider,
        uint64 sequenceNumber
    ) external view returns (EntropyStructsV2.Request memory req);

    /// @notice Get the fee charged by the default provider for the default gas limit
    /// @return feeAmount The fee amount in wei
    /// @dev This method returns the base fee required to make a request using the default provider with
    /// the default gas limit. This fee should be passed as msg.value when calling requestV2().
    /// The fee can change over time, so this method should be called before each request.
    function getFeeV2() external view returns (uint128 feeAmount);

    /// @notice Get the fee charged by the default provider for a specific gas limit
    /// @param gasLimit The gas limit for the callback function
    /// @return feeAmount The fee amount in wei
    /// @dev This method returns the fee required to make a request using the default provider with
    /// the specified gas limit. This fee should be passed as msg.value when calling requestV2(gasLimit).
    /// The fee can change over time, so this method should be called before each request.
    function getFeeV2(
        uint32 gasLimit
    ) external view returns (uint128 feeAmount);

    /// @notice Get the fee charged by a specific provider for a request with a given gas limit
    /// @param provider The address of the provider to query
    /// @param gasLimit The gas limit for the callback function
    /// @return feeAmount The fee amount in wei
    /// @dev This method returns the fee required to make a request using the specified provider with
    /// the given gas limit. This fee should be passed as msg.value when calling requestV2(provider, gasLimit)
    /// or requestV2(provider, userRandomNumber, gasLimit). The fee can change over time, so this method
    /// should be called before each request.
    function getFeeV2(
        address provider,
        uint32 gasLimit
    ) external view returns (uint128 feeAmount);
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

interface IEthFundableErrors {
    error EthFundableUnauthorized(address user);
    error TransferFailed(address to, uint256 value);
}

interface IEthFundable is IEthFundableErrors {
    function withdraw(uint256 amount) external;
}

// 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.1.0) (access/Ownable2Step.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Contract module which provides access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * This extension of the {Ownable} contract includes a two-step mechanism to transfer
 * ownership, where the new owner must call {acceptOwnership} in order to replace the
 * old one. This can help prevent common mistakes, such as transfers of ownership to
 * incorrect accounts, or to contracts that are unable to interact with the
 * permission system.
 *
 * The initial owner is specified at deployment time in the constructor for `Ownable`. This
 * can later be changed with {transferOwnership} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */
abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Returns the address of the pending owner.
     */
    function pendingOwner() public view virtual returns (address) {
        return _pendingOwner;
    }

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     *
     * Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer.
     */
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() public virtual {
        address sender = _msgSender();
        if (pendingOwner() != sender) {
            revert OwnableUnauthorizedAccount(sender);
        }
        _transferOwnership(sender);
    }
}

File 9 of 13 : EntropyEventsV2.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import "./EntropyStructs.sol";

/**
 * @title EntropyEventsV2
 * @notice Interface defining events for the Entropy V2 system, which handles random number generation
 * and provider management on Ethereum.
 * @dev This interface is used to emit events that track the lifecycle of random number requests,
 * provider registrations, and system configurations.
 */
interface EntropyEventsV2 {
    /**
     * @notice Emitted when a new provider registers with the Entropy system
     * @param provider The address of the registered provider
     * @param extraArgs A field for extra data for forward compatibility.
     */
    event Registered(address indexed provider, bytes extraArgs);

    /**
     * @notice Emitted when a user requests a random number from a provider
     * @param provider The address of the provider handling the request
     * @param caller The address of the user requesting the random number
     * @param sequenceNumber A unique identifier for this request
     * @param userContribution The user's contribution to the random number
     * @param gasLimit The gas limit for the callback.
     * @param extraArgs A field for extra data for forward compatibility.
     */
    event Requested(
        address indexed provider,
        address indexed caller,
        uint64 indexed sequenceNumber,
        bytes32 userContribution,
        uint32 gasLimit,
        bytes extraArgs
    );

    /**
     * @notice Emitted when a provider reveals the generated random number
     * @param provider The address of the provider that generated the random number
     * @param caller The address of the user who requested the random number (and who receives a callback)
     * @param sequenceNumber The unique identifier of the request
     * @param randomNumber The generated random number
     * @param userContribution The user's contribution to the random number
     * @param providerContribution The provider's contribution to the random number
     * @param callbackFailed Whether the callback to the caller failed
     * @param callbackReturnValue Return value from the callback. If the callback failed, this field contains
     * the error code and any additional returned data. Note that "" often indicates an out-of-gas error.
     * If the callback returns more than 256 bytes, only the first 256 bytes of the callback return value are included.
     * @param callbackGasUsed How much gas the callback used.
     * @param extraArgs A field for extra data for forward compatibility.
     */
    event Revealed(
        address indexed provider,
        address indexed caller,
        uint64 indexed sequenceNumber,
        bytes32 randomNumber,
        bytes32 userContribution,
        bytes32 providerContribution,
        bool callbackFailed,
        bytes callbackReturnValue,
        uint32 callbackGasUsed,
        bytes extraArgs
    );

    /**
     * @notice Emitted when a provider updates their fee
     * @param provider The address of the provider updating their fee
     * @param oldFee The previous fee amount
     * @param newFee The new fee amount
     * @param extraArgs A field for extra data for forward compatibility.
     */
    event ProviderFeeUpdated(
        address indexed provider,
        uint128 oldFee,
        uint128 newFee,
        bytes extraArgs
    );

    /**
     * @notice Emitted when a provider updates their default gas limit
     * @param provider The address of the provider updating their gas limit
     * @param oldDefaultGasLimit The previous default gas limit
     * @param newDefaultGasLimit The new default gas limit
     * @param extraArgs A field for extra data for forward compatibility.
     */
    event ProviderDefaultGasLimitUpdated(
        address indexed provider,
        uint32 oldDefaultGasLimit,
        uint32 newDefaultGasLimit,
        bytes extraArgs
    );

    /**
     * @notice Emitted when a provider updates their URI
     * @param provider The address of the provider updating their URI
     * @param oldUri The previous URI
     * @param newUri The new URI
     * @param extraArgs A field for extra data for forward compatibility.
     */
    event ProviderUriUpdated(
        address indexed provider,
        bytes oldUri,
        bytes newUri,
        bytes extraArgs
    );

    /**
     * @notice Emitted when a provider updates their fee manager address
     * @param provider The address of the provider updating their fee manager
     * @param oldFeeManager The previous fee manager address
     * @param newFeeManager The new fee manager address
     * @param extraArgs A field for extra data for forward compatibility.
     */
    event ProviderFeeManagerUpdated(
        address indexed provider,
        address oldFeeManager,
        address newFeeManager,
        bytes extraArgs
    );

    /**
     * @notice Emitted when a provider updates their maximum number of hashes that can be advanced
     * @param provider The address of the provider updating their max hashes
     * @param oldMaxNumHashes The previous maximum number of hashes
     * @param newMaxNumHashes The new maximum number of hashes
     * @param extraArgs A field for extra data for forward compatibility.
     */
    event ProviderMaxNumHashesAdvanced(
        address indexed provider,
        uint32 oldMaxNumHashes,
        uint32 newMaxNumHashes,
        bytes extraArgs
    );

    /**
     * @notice Emitted when a provider withdraws their accumulated fees
     * @param provider The address of the provider withdrawing fees
     * @param recipient The address receiving the withdrawn fees
     * @param withdrawnAmount The amount of fees withdrawn
     * @param extraArgs A field for extra data for forward compatibility.
     */
    event Withdrawal(
        address indexed provider,
        address indexed recipient,
        uint128 withdrawnAmount,
        bytes extraArgs
    );
}

File 10 of 13 : EntropyEvents.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import "./EntropyStructs.sol";

// Deprecated -- these events are still emitted, but the lack of indexing
// makes them hard to use.
interface EntropyEvents {
    event Registered(EntropyStructs.ProviderInfo provider);

    event Requested(EntropyStructs.Request request);
    event RequestedWithCallback(
        address indexed provider,
        address indexed requestor,
        uint64 indexed sequenceNumber,
        bytes32 userRandomNumber,
        EntropyStructs.Request request
    );

    event Revealed(
        EntropyStructs.Request request,
        bytes32 userRevelation,
        bytes32 providerRevelation,
        bytes32 blockHash,
        bytes32 randomNumber
    );
    event RevealedWithCallback(
        EntropyStructs.Request request,
        bytes32 userRandomNumber,
        bytes32 providerRevelation,
        bytes32 randomNumber
    );

    event CallbackFailed(
        address indexed provider,
        address indexed requestor,
        uint64 indexed sequenceNumber,
        bytes32 userRandomNumber,
        bytes32 providerRevelation,
        bytes32 randomNumber,
        bytes errorCode
    );

    event ProviderFeeUpdated(address provider, uint128 oldFee, uint128 newFee);

    event ProviderDefaultGasLimitUpdated(
        address indexed provider,
        uint32 oldDefaultGasLimit,
        uint32 newDefaultGasLimit
    );

    event ProviderUriUpdated(address provider, bytes oldUri, bytes newUri);

    event ProviderFeeManagerUpdated(
        address provider,
        address oldFeeManager,
        address newFeeManager
    );
    event ProviderMaxNumHashesAdvanced(
        address provider,
        uint32 oldMaxNumHashes,
        uint32 newMaxNumHashes
    );

    event Withdrawal(
        address provider,
        address recipient,
        uint128 withdrawnAmount
    );
}

File 11 of 13 : EntropyStructsV2.sol
// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

contract EntropyStructsV2 {
    struct ProviderInfo {
        uint128 feeInWei;
        uint128 accruedFeesInWei;
        // The commitment that the provider posted to the blockchain, and the sequence number
        // where they committed to this. This value is not advanced after the provider commits,
        // and instead is stored to help providers track where they are in the hash chain.
        bytes32 originalCommitment;
        uint64 originalCommitmentSequenceNumber;
        // Metadata for the current commitment. Providers may optionally use this field to help
        // manage rotations (i.e., to pick the sequence number from the correct hash chain).
        bytes commitmentMetadata;
        // Optional URI where clients can retrieve revelations for the provider.
        // Client SDKs can use this field to automatically determine how to retrieve random values for each provider.
        // TODO: specify the API that must be implemented at this URI
        bytes uri;
        // The first sequence number that is *not* included in the current commitment (i.e., an exclusive end index).
        // The contract maintains the invariant that sequenceNumber <= endSequenceNumber.
        // If sequenceNumber == endSequenceNumber, the provider must rotate their commitment to add additional random values.
        uint64 endSequenceNumber;
        // The sequence number that will be assigned to the next inbound user request.
        uint64 sequenceNumber;
        // The current commitment represents an index/value in the provider's hash chain.
        // These values are used to verify requests for future sequence numbers. Note that
        // currentCommitmentSequenceNumber < sequenceNumber.
        //
        // The currentCommitment advances forward through the provider's hash chain as values
        // are revealed on-chain.
        bytes32 currentCommitment;
        uint64 currentCommitmentSequenceNumber;
        // An address that is authorized to set / withdraw fees on behalf of this provider.
        address feeManager;
        // Maximum number of hashes to record in a request. This should be set according to the maximum gas limit
        // the provider supports for callbacks.
        uint32 maxNumHashes;
        // Default gas limit to use for callbacks.
        uint32 defaultGasLimit;
    }

    struct Request {
        // Storage slot 1 //
        address provider;
        uint64 sequenceNumber;
        // The number of hashes required to verify the provider revelation.
        uint32 numHashes;
        // Storage slot 2 //
        // The commitment is keccak256(userCommitment, providerCommitment). Storing the hash instead of both saves 20k gas by
        // eliminating 1 store.
        bytes32 commitment;
        // Storage slot 3 //
        // The number of the block where this request was created.
        // Note that we're using a uint64 such that we have an additional space for an address and other fields in
        // this storage slot. Although block.number returns a uint256, 64 bits should be plenty to index all of the
        // blocks ever generated.
        uint64 blockNumber;
        // The address that requested this random number.
        address requester;
        // If true, incorporate the blockhash of blockNumber into the generated random value.
        bool useBlockhash;
        // Status flag for requests with callbacks. See EntropyConstants for the possible values of this flag.
        uint8 callbackStatus;
        // The gasLimit in units of 10k gas. (i.e., 2 = 20k gas). We're using units of 10k in order to fit this
        // field into the remaining 2 bytes of this storage slot. The dynamic range here is 10k - 655M, which should
        // cover all real-world use cases.
        uint16 gasLimit10k;
    }
}

// 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 13 of 13 : EntropyStructs.sol
// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

// This contract holds old versions of the Entropy structs that are no longer used for contract storage.
// However, they are still used in EntropyEvents to maintain the public interface of prior versions of
// the Entropy contract.
//
// See EntropyStructsV2 for the struct definitions currently in use.
contract EntropyStructs {
    struct ProviderInfo {
        uint128 feeInWei;
        uint128 accruedFeesInWei;
        // The commitment that the provider posted to the blockchain, and the sequence number
        // where they committed to this. This value is not advanced after the provider commits,
        // and instead is stored to help providers track where they are in the hash chain.
        bytes32 originalCommitment;
        uint64 originalCommitmentSequenceNumber;
        // Metadata for the current commitment. Providers may optionally use this field to help
        // manage rotations (i.e., to pick the sequence number from the correct hash chain).
        bytes commitmentMetadata;
        // Optional URI where clients can retrieve revelations for the provider.
        // Client SDKs can use this field to automatically determine how to retrieve random values for each provider.
        // TODO: specify the API that must be implemented at this URI
        bytes uri;
        // The first sequence number that is *not* included in the current commitment (i.e., an exclusive end index).
        // The contract maintains the invariant that sequenceNumber <= endSequenceNumber.
        // If sequenceNumber == endSequenceNumber, the provider must rotate their commitment to add additional random values.
        uint64 endSequenceNumber;
        // The sequence number that will be assigned to the next inbound user request.
        uint64 sequenceNumber;
        // The current commitment represents an index/value in the provider's hash chain.
        // These values are used to verify requests for future sequence numbers. Note that
        // currentCommitmentSequenceNumber < sequenceNumber.
        //
        // The currentCommitment advances forward through the provider's hash chain as values
        // are revealed on-chain.
        bytes32 currentCommitment;
        uint64 currentCommitmentSequenceNumber;
        // An address that is authorized to set / withdraw fees on behalf of this provider.
        address feeManager;
        // Maximum number of hashes to record in a request. This should be set according to the maximum gas limit
        // the provider supports for callbacks.
        uint32 maxNumHashes;
    }

    struct Request {
        // Storage slot 1 //
        address provider;
        uint64 sequenceNumber;
        // The number of hashes required to verify the provider revelation.
        uint32 numHashes;
        // Storage slot 2 //
        // The commitment is keccak256(userCommitment, providerCommitment). Storing the hash instead of both saves 20k gas by
        // eliminating 1 store.
        bytes32 commitment;
        // Storage slot 3 //
        // The number of the block where this request was created.
        // Note that we're using a uint64 such that we have an additional space for an address and other fields in
        // this storage slot. Although block.number returns a uint256, 64 bits should be plenty to index all of the
        // blocks ever generated.
        uint64 blockNumber;
        // The address that requested this random number.
        address requester;
        // If true, incorporate the blockhash of blockNumber into the generated random value.
        bool useBlockhash;
        // True if this is a request that expects a callback.
        bool isRequestWithCallback;
    }
}

Settings
{
  "viaIR": true,
  "optimizer": {
    "enabled": true,
    "mode": "3"
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "abi"
      ]
    }
  },
  "detectMissingLibraries": false,
  "forceEVMLA": false,
  "enableEraVMExtensions": false,
  "codegen": "yul",
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_entropyProvider","type":"address"},{"internalType":"uint128","name":"_maxFee","type":"uint128"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bytes32","name":"commitment","type":"bytes32"}],"name":"CommitmentNotFound","type":"error"},{"inputs":[{"internalType":"uint64","name":"sequenceNumber","type":"uint64"}],"name":"DuplicateSequenceNumber","type":"error"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"EthFundableUnauthorized","type":"error"},{"inputs":[{"internalType":"uint128","name":"maxAcceptableFee","type":"uint128"},{"internalType":"uint128","name":"fee","type":"uint128"}],"name":"FeeExceedsMax","type":"error"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"valueToTransfer","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"WinnersCountMustBePositive","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"entropyProvider","type":"address"}],"name":"EntropyProviderSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"maxFee","type":"uint128"}],"name":"MaxFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"commitment","type":"bytes32"}],"name":"RaffleCommited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"commitment","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"sequenceNumber","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"randomNumber","type":"uint256"}],"name":"RafflePrepared","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"raffleId","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"winners","type":"address[]"}],"name":"WinnersSelected","type":"event"},{"inputs":[{"internalType":"uint64","name":"sequence","type":"uint64"},{"internalType":"address","name":"provider","type":"address"},{"internalType":"bytes32","name":"randomNumber","type":"bytes32"}],"name":"_entropyCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"commitment","type":"bytes32"}],"name":"commitRaffle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"entropyProvider","outputs":[{"internalType":"contract IEntropyV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxFee","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint64","name":"tickets","type":"uint64"}],"internalType":"struct RaffleEntry[]","name":"entries","type":"tuple[]"},{"internalType":"uint8","name":"winnersCount","type":"uint8"},{"internalType":"uint256","name":"raffleId","type":"uint256"}],"name":"selectWinners","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newEntropyProvider","type":"address"}],"name":"setEntropyProvider","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"newMaxFee","type":"uint128"}],"name":"setMaxFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

0x9c4d535b0000000000000000000000000000000000000000000000000000000000000000010001712b5d0d9deee897ab3eb66f403a2a83f3a57cacbf2cdad5fe13a11e9c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000600000000000000000000000005a4a369f4db5df2054994af031b7b23949b98c0e00000000000000000000000000000000000000000000000000005af3107a4000000000000000000000000000005bbafdea28bfbb574ca2ea10f0c84a9f517188

Deployed Bytecode

0x00020000000000020009000000000002000000600310027000010000000103550000012a0030019d0000012a033001970000000100200190000000370000c13d0000008002000039000000400020043f000000040030008c000000670000413d000000000201043b000000e002200270000001390020009c0000006b0000a13d0000013a0020009c000000890000a13d0000013b0020009c000000e70000213d0000013e0020009c000001070000613d0000013f0020009c0000048c0000c13d0000000002000416000000000002004b0000048c0000c13d000000240030008c0000048c0000413d0000000401100370000000000101043b0000012d0010009c0000048c0000213d000000000200041a0000012d032001970000000002000411000000000023004b000001e40000c13d000000000001004b000002040000613d0000000202000039000000000302041a0000012f03300197000000000313019f000000000032041b000000800010043f00000000010004140000012a0010009c0000012a01008041000000c0011002100000014d011001c70000800d0200003900000001030000390000013304000041000001a10000013d0000000002000416000000000002004b0000048c0000c13d0000001f023000390000012b022001970000008002200039000000400020043f0000001f0430018f0000012c053001980000008002500039000000480000613d0000008006000039000000000701034f000000007807043c0000000006860436000000000026004b000000440000c13d000000000004004b000000550000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000000600030008c0000048c0000413d000000800400043d0000012d0040009c0000048c0000213d000000a00700043d0000012e0070009c0000048c0000213d000000c00600043d0000012d0060009c0000048c0000213d000000000006004b000001e90000c13d0000013701000041000000000010043f000000040000043f0000013801000041000004a700010430000000000003004b0000048c0000c13d0000000001000019000004a60001042e000001430020009c000000940000213d000001470020009c0000017b0000613d000001480020009c000001840000613d000001490020009c0000048c0000c13d0000000002000416000000000002004b0000048c0000c13d000000240030008c0000048c0000413d0000000401100370000000000301043b000000000100041a0000012d041001970000000001000411000000000041004b0000020a0000c13d00000000010004140000012a0010009c0000012a01008041000000c001100210000000000003004b000900000003001d000800000004001d000002140000c13d0000000002040019000002170000013d000001400020009c000001630000613d000001410020009c000001a20000613d000001420020009c0000048c0000c13d0000000001000416000000000001004b0000048c0000c13d000000000100041a000001e00000013d000001440020009c000001be0000613d000001450020009c000001db0000613d000001460020009c0000048c0000c13d0000000002000416000000000002004b0000048c0000c13d000000240030008c0000048c0000413d0000000401100370000000000301043b000000000100041a0000012d021001970000000001000411000000000012004b000002080000c13d000800000003001d0000000201000039000000000101041a0000015802000041000000800020043f0000c35002000039000000840020043f00000000030004140000012d021001970000012a0030009c0000012a03008041000000c00130021000000159011001c7000900000002001d04a504a00000040f000000800a00003900000060031002700000012a03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000000c40000613d000000000801034f000000008908043c000000000a9a043600000000005a004b000000c00000c13d000000000006004b000000d10000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f000000000065043500000001002001900000024a0000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200030008c0000048c0000413d000000800300043d0000012e0030009c0000048c0000213d0000000301000039000000000101041a0000012e01100197000000000013004b000002e00000a13d0000016202000041000000000020043f000000040010043f000000240030043f0000016101000041000004a7000104300000013c0020009c0000015e0000613d0000013d0020009c0000048c0000c13d0000000002000416000000000002004b0000048c0000c13d000000240030008c0000048c0000413d0000000401100370000000000601043b0000012d0060009c0000048c0000213d000000000100041a0000012d051001970000000001000411000000000015004b000002080000c13d0000000101000039000000000201041a0000012f02200197000000000262019f000000000021041b00000000010004140000012a0010009c0000012a01008041000000c00110021000000130011001c70000800d0200003900000003030000390000014b04000041000001ba0000013d0000000002000416000000000002004b0000048c0000c13d000000640030008c0000048c0000413d0000000402100370000000000202043b000001500020009c0000048c0000213d0000002304200039000000000034004b0000048c0000813d0000000404200039000000000441034f000000000404043b000700000004001d000001500040009c0000048c0000213d00000007040000290000000604400210000600240020003d0000000602400029000000000032004b0000048c0000213d0000002402100370000000000202043b000500000002001d000000ff0020008c0000048c0000213d0000004402100370000000000502043b000000000200041a0000012d042001970000000002000411000000000024004b000001e40000c13d000100000005001d0000000702000029000001500020009c0000048e0000613d0000000702000029000000010220003900000005042002100000003f054000390000015105500197000001520050009c0000048e0000213d0000008005500039000000400050043f000000800020043f0000001f0240018f000000000004004b000001430000613d000000000331034f000000a004400039000000a005000039000000003603043c0000000005650436000000000045004b0000013f0000c13d000000000002004b000000070000006b00000001060000290000030e0000c13d000900000006001d000000000060043f0000000501000039000000200010043f00000000010004140000012a0010009c0000012a01008041000000c00110021000000154011001c7000080100200003904a504a00000040f00000001002001900000048c0000613d000000000101043b000000000101041a000000000001004b000003d90000c13d0000015701000041000000000010043f0000000901000029000000040010043f0000013801000041000004a7000104300000000001000416000000000001004b0000048c0000c13d0000000101000039000001df0000013d0000000001000416000000000001004b0000048c0000c13d000000000100041a0000012d051001970000000002000411000000000025004b000001e40000c13d0000000102000039000000000302041a0000012f03300197000000000032041b0000012f01100197000000000010041b00000000010004140000012a0010009c0000012a01008041000000c00110021000000130011001c70000800d02000039000000030300003900000131040000410000000006000019000001ba0000013d0000000001000416000000000001004b0000048c0000c13d0000000301000039000000000101041a0000012e01100197000000800010043f0000014c01000041000004a60001042e0000000002000416000000000002004b0000048c0000c13d000000240030008c0000048c0000413d0000000401100370000000000101043b0000012e0010009c0000048c0000213d000000000200041a0000012d032001970000000002000411000000000023004b000001e40000c13d0000012e021001970000000303000039000000000403041a0000013404400197000000000114019f000000000013041b000000800020043f00000000010004140000012a0010009c0000012a01008041000000c0011002100000014d011001c70000800d0200003900000001030000390000013504000041000001ba0000013d0000000001000416000000000001004b0000048c0000c13d0000000101000039000000000201041a0000012d032001970000000006000411000000000063004b0000020f0000c13d0000012f02200197000000000021041b000000000100041a0000012f02100197000000000262019f000000000020041b00000000020004140000012d051001970000012a0020009c0000012a02008041000000c00120021000000130011001c70000800d020000390000000303000039000001310400004104a5049b0000040f0000000100200190000000690000c13d0000048c0000013d0000000002000416000000000002004b0000048c0000c13d000000640030008c0000048c0000413d0000000402100370000000000202043b000001500020009c0000048c0000213d0000002403100370000000000303043b0000012d0030009c0000048c0000213d0000004401100370000000000401043b0000000201000039000000000101041a0000012d011001980000029b0000c13d0000016301000041000000800010043f0000002001000039000000840010043f0000001701000039000000a40010043f0000016901000041000000c40010043f0000016a01000041000004a7000104300000000001000416000000000001004b0000048c0000c13d0000000201000039000000000101041a0000012d01100197000000800010043f0000014c01000041000004a60001042e0000014a01000041000000000010043f000000040020043f0000013801000041000004a7000104300000000101000039000000000201041a0000012f02200197000000000021041b000000000100041a0000012f02100197000000000262019f000000000020041b000000400200043d000700000002001d00000000020004140000012d051001970000012a0020009c0000012a02008041000000c00120021000000130011001c70000800d020000390000000303000039000800000007001d000900000004001d000001310400004104a5049b0000040f000000090300002900000001002001900000048c0000613d000000000003004b000002680000c13d0000014e01000041000000000010043f0000014f01000041000004a7000104300000014a020000410000020b0000013d0000016b02000041000000000020043f000000040010043f0000013801000041000004a7000104300000014a01000041000000000010043f000000040060043f0000013801000041000004a70001043000000130011001c70000800902000039000000000500001904a5049b0000040f00000060031002700000012a03300198000002400000613d0000001f043000390000012b044001970000003f044000390000016c04400197000000400500043d0000000004450019000000000054004b00000000060000390000000106004039000001500040009c0000048e0000213d00000001006001900000048e0000c13d000000400040043f0000001f0430018f00000000063504360000012c053001980000000003560019000002330000613d000000000701034f000000007807043c0000000006860436000000000036004b0000022f0000c13d000000000004004b000002400000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001304350000000100200190000000690000c13d0000016d01000041000000000010043f0000000801000029000000040010043f0000000901000029000000240010043f0000016101000041000004a7000104300000001f0530018f0000012c06300198000000400200043d0000000004620019000002550000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000002510000c13d000000000005004b000002620000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500000060013002100000012a0020009c0000012a020080410000004002200210000000000112019f000004a7000104300000000201000039000000000201041a0000012f02200197000000000232019f000000000021041b000000070100002900000000003104350000012a0010009c0000012a01008041000000400110021000000000020004140000012a0020009c0000012a02008041000000c002200210000000000112019f00000132011001c70000800d020000390000000103000039000001330400004104a5049b0000040f000000080300002900000001002001900000048c0000613d0000012e013001970000000304000039000000000204041a0000013402200197000000000232019f000000000024041b000000400200043d00000000001204350000012a0020009c0000012a02008041000000400120021000000000020004140000012a0020009c0000012a02008041000000c002200210000000000112019f00000132011001c70000800d020000390000000103000039000001350400004104a5049b0000040f00000001002001900000048c0000613d0000002001000039000001000010044300000120000004430000013601000041000004a60001042e0000000003000411000000000013004b000002d40000c13d000900000004001d0000015001200197000800000001001d000000000010043f0000000401000039000000200010043f00000000010004140000012a0010009c0000012a01008041000000c00110021000000154011001c7000080100200003904a504a00000040f00000001002001900000048c0000613d000000000101043b000000000101041a000700000001001d000000000010043f0000000501000039000000200010043f00000000010004140000012a0010009c0000012a01008041000000c00110021000000154011001c7000080100200003904a504a00000040f00000001002001900000048c0000613d000000000101043b0000000903000029000000000031041b000000400100043d00000040021000390000000000320435000000200210003900000008030000290000000000320435000000070200002900000000002104350000012a0010009c0000012a01008041000000400110021000000000020004140000012a0020009c0000012a02008041000000c002200210000000000112019f00000167011001c70000800d0200003900000001030000390000016804000041000001a10000013d0000016301000041000000800010043f0000002001000039000000840010043f0000002301000039000000a40010043f0000016401000041000000c40010043f0000016501000041000000e40010043f0000016601000041000004a700010430000700000003001d0000015a0100004100000000001004430000000001000410000000040010044300000000010004140000012a0010009c0000012a01008041000000c0011002100000015b011001c70000800a0200003904a504a00000040f0000000100200190000002f80000613d000000000101043b0000000704000029000000000041004b000002f90000813d0000016002000041000000000020043f000000040010043f000000240040043f0000016101000041000004a700010430000000000001042f000000400200043d0000015c01000041000000000012043500000004012000390000c3500300003900000000003104350000012a0020009c000600000002001d0000012a010000410000000001024019000000400110021000000000020004140000012a0020009c0000012a02008041000000c002200210000000000112019f000000000004004b000003550000c13d00000138011001c700000009020000290000035a0000013d0000000005000019000000010600002900000006025002100000000603200029000000000231034f000000000202043b0000012d0020009c0000048c0000213d000800200030003d0000000801100360000000000301043b000001500030009c0000048c0000213d000900000005001d0000006002200210000000400100043d00000040041000390000000000240435000000c002300210000000540310003900000000002304350000003c0200003900000000022104360000000000620435000001530010009c0000048e0000213d0000006003100039000000400030043f0000012a0020009c0000012a02008041000000400220021000000000010104330000012a0010009c0000012a010080410000006001100210000000000121019f00000000020004140000012a0020009c0000012a02008041000000c002200210000000000112019f00000130011001c7000080100200003904a504a00000040f000000010020019000000009050000290000048c0000613d000000000601043b000000800200043d000000000052004b000004940000a13d00000001010003670000000803100360000000000303043b000001500030009c0000048c0000213d0000000504500210000000a0044000390000000004040433000000000034001a000004370000413d0000000105500039000000000052004b000004940000a13d00000000023400190000000503500210000000a0033000390000000000230435000000070050006c000003100000413d000001470000013d0000015d011001c7000080090200003900000007030000290000000904000029000000000500001904a5049b0000040f00000060031002700000012a03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000006057000290000036a0000613d000000000801034f0000000609000029000000008a08043c0000000009a90436000000000059004b000003660000c13d000000000006004b000003770000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000003bb0000613d0000001f01400039000000600210018f0000000601200029000000000021004b00000000020000390000000102004039000001500010009c0000048e0000213d00000001002001900000048e0000c13d000000400010043f000000200030008c0000048c0000413d00000006010000290000000001010433000900000001001d000001500010009c0000048c0000213d0000000901000029000000000010043f0000000401000039000000200010043f00000000010004140000012a0010009c0000012a01008041000000c00110021000000154011001c7000080100200003904a504a00000040f00000001002001900000048c0000613d000000000101043b000000000101041a000000000001004b000004330000c13d0000000901000029000000000010043f0000000401000039000000200010043f00000000010004140000012a0010009c0000012a01008041000000c00110021000000154011001c7000080100200003904a504a00000040f00000001002001900000048c0000613d000000000101043b0000000802000029000000000021041b000000400100043d00000000002104350000012a0010009c0000012a01008041000000400110021000000000020004140000012a0020009c0000012a02008041000000c002200210000000000112019f00000132011001c70000800d0200003900000001030000390000015f04000041000001a10000013d0000001f0530018f0000012c06300198000000400200043d0000000004620019000003c60000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000003c20000c13d000000000005004b000003d30000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500000060013002100000012a0020009c0000012a020080410000004002200210000000000121019f000004a700010430000000800200043d000000070020006c000004940000a13d000000050200002900000005022002100000003f0320003900003fe00330018f000000400400043d0000000003340019000800000004001d000000000043004b00000000040000390000000104004039000001500030009c0000048e0000213d00000001004001900000048e0000c13d0000000504000029000000ff0540018f00000007040000290000000504400210000000a0044000390000000004040433000200000004001d000000400030043f0000000803000029000500000005001d0000000003530436000400000003001d0000001f0320018f000000000002004b000004010000613d0000000405000029000000000225001900000000040000310000000104400367000000004604043c0000000005650436000000000025004b000003fd0000c13d000000000003004b000000050000006b0000042b0000c13d000000400100043d0000002002100039000000400300003900000000003204350000000102000029000000000021043500000008020000290000000003020433000000400210003900000000003204350000006002100039000000000003004b000004190000613d0000000004000019000000040600002900000000650604340000012d0550019700000000025204360000000104400039000000000034004b000004130000413d00000000021200490000012a0020009c0000012a0200804100000060022002100000012a0010009c0000012a010080410000004001100210000000000112019f00000000020004140000012a0020009c0000012a02008041000000c002200210000000000121019f00000130011001c70000800d0200003900000001030000390000015604000041000001a10000013d000000020000006b000004350000c13d0000015501000041000000000010043f0000001201000039000000040010043f0000013801000041000004a7000104300000015e01000041000001590000013d000000070000006b0000043d0000c13d0000015501000041000000000010043f0000001101000039000000040010043f0000013801000041000004a7000104300000000702000029000000010820008a0000000009000019000300000008001d000000000008004b000004580000613d00000002301000fa00000000040800190000000002000019000000000042001a000004370000413d000000000542001900000001055002700000000106500039000000800700043d000000000067004b000004940000a13d0000000507600210000000a0077000390000000007070433000000000037004b000000000504a019000000000206a019000000000052004b0000000004050019000004460000413d000004590000013d0000000002000019000000070020006c000004940000813d000000060220021000000006022000290000000102200367000000000202043b0000012d0020009c0000048c0000213d00000008030000290000000003030433000000000093004b000004940000a13d000000050390021000000004033000290000000000230435000000400200043d0000004003200039000900000009001d0000000000930435000000400300003900000000033204360000000000130435000001530020009c0000048e0000213d0000006001200039000000400010043f0000012a0030009c0000012a03008041000000400130021000000000020204330000012a0020009c0000012a020080410000006002200210000000000112019f00000000020004140000012a0020009c0000012a02008041000000c002200210000000000112019f00000130011001c7000080100200003904a504a00000040f0000000100200190000000030800002900000009090000290000048c0000613d000000000101043b0000000109900039000000050090006c000004410000413d000004040000013d0000000001000019000004a7000104300000015501000041000000000010043f0000004101000039000000040010043f0000013801000041000004a7000104300000015501000041000000000010043f0000003201000039000000040010043f0000013801000041000004a700010430000000000001042f0000049e002104210000000102000039000000000001042d0000000002000019000000000001042d000004a3002104230000000102000039000000000001042d0000000002000019000000000001042d000004a500000432000004a60001042e000004a70001043000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e002000000000000000000000000000000000000200000000000000000000000000e38ca1a8dfdc33992e65af8ea63e21eed85591a8f2878b8e067c62a274b6f4affffffffffffffffffffffffffffffff000000000000000000000000000000008622bf175396424c91b6188fbe782daafe45b5972e14f9389682bd20966db52c00000002000000000000000000000000000000400000010000000000000000001e4fbdf700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000000000000000000000715018a5000000000000000000000000000000000000000000000000000000009f32e3cc00000000000000000000000000000000000000000000000000000000e30c397700000000000000000000000000000000000000000000000000000000e30c397800000000000000000000000000000000000000000000000000000000f2fde38b000000000000000000000000000000000000000000000000000000009f32e3cd00000000000000000000000000000000000000000000000000000000a13cf38600000000000000000000000000000000000000000000000000000000715018a60000000000000000000000000000000000000000000000000000000079ba5097000000000000000000000000000000000000000000000000000000008da5cb5b0000000000000000000000000000000000000000000000000000000052a5f1f70000000000000000000000000000000000000000000000000000000052a5f1f8000000000000000000000000000000000000000000000000000000005bf414ac000000000000000000000000000000000000000000000000000000006e6714280000000000000000000000000000000000000000000000000000000001f59d160000000000000000000000000000000000000000000000000000000026105246000000000000000000000000000000000000000000000000000000002e1a7d4d118cdaa70000000000000000000000000000000000000000000000000000000038d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270000000000000000000000000000000000000000200000008000000000000000000200000000000000000000000000000000000020000000800000000000000000e6c4247b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff00000000000000000000000000000000000000000000007fffffffffffffffe0000000000000000000000000000000000000000000000000ffffffffffffff7f000000000000000000000000000000000000000000000000ffffffffffffff9f02000000000000000000000000000000000000400000000000000000000000004e487b71000000000000000000000000000000000000000000000000000000005fa006001f7473b386c7bb4db093cb973ce5c895e51c3813bdbd723097d0349e836588c900000000000000000000000000000000000000000000000000000000ca1642e10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000008000000000000000009cc7f708afc65944829bd487b90b72536b1951864fbfc14e125fc972a6507f3902000002000000000000000000000000000000240000000000000000000000000bed189f000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000024000000000000000000000000c117c63700000000000000000000000000000000000000000000000000000000d7800ccb8e24f7dac0649f9f6452217340a7445661b1f4dc274538b9c4b16f32cf47918100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000000000000000000000001a430930000000000000000000000000000000000000000000000000000000008c379a0000000000000000000000000000000000000000000000000000000004f6e6c7920456e74726f70792063616e2063616c6c20746869732066756e6374696f6e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000840000008000000000000000000200000000000000000000000000000000000060000000000000000000000000b972cfe63ba59dfe9e545ff54afa066237c90648adca7b6c995e06ec1164afd0456e74726f70792061646472657373206e6f742073657400000000000000000000000000000000000000000000000000000000640000008000000000000000006f6213850000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffe01c43b97600000000000000000000000000000000000000000000000000000000000000000000000000a2646970667358221220ae41044d557e5b953b5f2f1078f13c285e49926a49b6b23fcf50e571f86f42f764736f6c6378247a6b736f6c633a312e352e31353b736f6c633a302e382e32383b6c6c766d3a312e302e320055

Block Transaction 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  ]

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.