Sonic Blaze Testnet

Contract Diff Checker

Contract Name:
sdeamon0xRandom

Contract Source Code:

// File: contracts\openzeppelin\contracts\utils\Context.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
/**
 * @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: contracts\openzeppelin\contracts\access\Ownable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.19;
/**
 * @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: contracts\openzeppelin\contracts\access\Ownable2Step.sol
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.19;
/**
 * @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.
     */
    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: contracts\openzeppelin\contracts\utils\Panic.sol
pragma solidity ^0.8.19;
/**
 * @dev Helper library for emitting standardized panic codes.
 *
 * ```solidity
 * contract Example {
 *      using Panic for uint256;
 *
 *      // Use any of the declared internal constants
 *      function foo() { Panic.GENERIC.panic(); }
 *
 *      // Alternatively
 *      function foo() { Panic.panic(Panic.GENERIC); }
 * }
 * ```
 *
 * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
 */
// slither-disable-next-line unused-state
library Panic {
    /// @dev generic / unspecified error
    uint256 internal constant GENERIC = 0x00;
    /// @dev used by the assert() builtin
    uint256 internal constant ASSERT = 0x01;
    /// @dev arithmetic underflow or overflow
    uint256 internal constant UNDER_OVERFLOW = 0x11;
    /// @dev division or modulo by zero
    uint256 internal constant DIVISION_BY_ZERO = 0x12;
    /// @dev enum conversion error
    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
    /// @dev invalid encoding in storage
    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
    /// @dev empty array pop
    uint256 internal constant EMPTY_ARRAY_POP = 0x31;
    /// @dev array out of bounds access
    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
    /// @dev resource error (too large allocation or too large array)
    uint256 internal constant RESOURCE_ERROR = 0x41;
    /// @dev calling invalid internal function
    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;
    /// @dev Reverts with a panic code. Recommended to use with
    /// the internal constants with predefined codes.
    function panic(uint256 code) internal pure {
        assembly ("memory-safe") {
            mstore(0x00, 0x4e487b71)
            mstore(0x20, code)
            revert(0x1c, 0x24)
        }
    }
}
// File: contracts/sdaemon0x/sdaemon0xRandomizer.sol
pragma solidity ^0.8.19;
// ------------------------------------------------------------
//
// DICE BY RND ASK COMMIT REVEAL (ACR)
//
// Constructed waiting Chainlink or good VRF on Sonic...
// and prevent double TX to create pseudo-random.
// Designed for sDeamon
// inspired by lib STL from C++ and openzeppelin double deque.
//
// -----------------------------------------------------------
interface sdeamon0xRandomCallback 
{
    function onRandomCallback(uint256 uid, uint256 res) external;
}
interface sdeamon0xRandomItf 
{
    function beginRandom(sdeamon0xRandomCallback CA) external returns (uint256);
}
contract sdeamon0xRandom is sdeamon0xRandomItf, Ownable2Step {
    constructor() Ownable(0x88524E752144C15dc1a12BA3978c2d700dc97498) {
        randomizer[0x88524E752144C15dc1a12BA3978c2d700dc97498] = true;
        nonceOne = uint256(keccak256(abi.encodePacked(block.prevrandao, msg.sender, block.timestamp, uint256(0x666))));
        nonceTwo = uint256(keccak256(abi.encodePacked(uint256(0x666), block.timestamp, block.prevrandao, msg.sender, uint256(69))));
        for(uint256 i=0; i<8; ++i)
            queues.push();
    }
    mapping(address => bool) public randomizer;
    function setRandomizer(address addr, bool b) external  onlyOwner {
        randomizer[addr] = b;
    }
    modifier onlyRandomizer() {
        require(randomizer[msg.sender] == true);
        _;
    }
    mapping(address => sdeamon0xRandomCallback) public registrars;
    mapping(sdeamon0xRandomCallback => bool)    public registereds;  
    function registerCA(sdeamon0xRandomCallback CA) payable public {
        if (msg.sender != owner()) {
            require(msg.value >= 500_000 ether, "No sufficient fund"); //price to buy my validator
        }
        registrars[msg.sender] = CA;
        registereds[CA] = true;
    }
    function unregisterCA(sdeamon0xRandomCallback CA) public {
        require(registrars[msg.sender] == CA, "not your CA");
        registereds[CA] = false;
        registrars[msg.sender] = sdeamon0xRandomCallback(address(0));
    }
    uint256 private nonceOne;
    uint256 private nonceTwo;
    uint256 public uniqueId = 0x666;
    struct Commit {
        uint256                     uniqueId;
        sdeamon0xRandomCallback     addr;
        uint256                     salt;
    }
    struct CommitQueue {
        uint128 _begin;
        uint128 _end;
        mapping(uint128 index => Commit) _data;
    }
    CommitQueue[] private queues;
    // return the number of canal
    function canal_length() public view returns (uint256) {
        return queues.length;
    }
    function pushFront(uint256 canal, Commit memory value) internal {
        require(canal < queues.length);
        unchecked {
            CommitQueue storage queue = queues[canal];
            uint128 frontIndex = queue._begin - 1;
            if (frontIndex == queue._end) Panic.panic(Panic.RESOURCE_ERROR);
            queue._data[frontIndex] = value;
            queue._begin = frontIndex;
        }
    }
    function popBack(uint256 canal) internal returns (Commit memory value) {
        require(canal < queues.length);
        unchecked {
            CommitQueue storage queue = queues[canal];
            uint128 backIndex = queue._end;
            if (backIndex == queue._begin) Panic.panic(Panic.EMPTY_ARRAY_POP);
            --backIndex;
            value = queue._data[backIndex];
            delete queue._data[backIndex];
            queue._end = backIndex;
        }
    }
    function queueLen(uint256 canal) public view returns (uint256) {
        require(canal < queues.length);
        unchecked {
            CommitQueue storage queue = queues[canal];
            return uint256(queue._end - queue._begin);
        }
    }
    uint256 canal_counter = 0;
    // Ask.
    function beginRandom(sdeamon0xRandomCallback CA) public returns (uint256) {
        require(registereds[CA] == true, "contract not registered");
        unchecked {
            nonceOne += 13;
            nonceTwo += 7;
        }
        ++uniqueId;
        uint256 salt = uint256(keccak256(abi.encodePacked(nonceOne, block.timestamp, block.prevrandao, msg.sender, nonceTwo)));
        pushFront(canal_counter, Commit(uniqueId, CA, salt));
        canal_counter++;
        canal_counter %= queues.length; 
        return uniqueId;
    }
    // Reveal.
    function fireRandom(uint256 canal) public onlyRandomizer {
        require(queueLen(canal) > 0, 'nothing to launch');
        Commit memory c = popBack(canal);
        uint256 random = uint256(keccak256(abi.encodePacked(c.salt, nonceOne, c.uniqueId, uniqueId, block.prevrandao, msg.sender, nonceTwo)));
        c.addr.onRandomCallback(c.uniqueId, random);
    }
    // clean to debug if onRandomCallback failed !
    function cleanQueue(uint256 canal) public onlyRandomizer {
        while(queueLen(canal) > 0) {
            popBack(canal);
        }
    }
    // withdraw to buy a validator "Sonic"
    function withdraw(uint256 amount) external onlyOwner {
        (bool success,) = payable(msg.sender).call{value: amount}("");
        require(success);
    }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):