Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
KhugaBash
Compiler Version
v0.8.28+commit.7893614a
ZkSolc Version
v1.5.11
Optimization Enabled:
Yes with Mode 3
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import "solady/utils/Initializable.sol"; import "solady/auth/Ownable.sol"; import "solady/utils/ReentrancyGuard.sol"; import "solady/utils/UUPSUpgradeable.sol"; import "solady/utils/SignatureCheckerLib.sol"; import "solady/utils/EIP712.sol"; /** * @title KhugaBash * @dev Main contract for the Khuga Bash game, implementing score system, stat upgrades, and leaderboard * @notice This is the zkSync version of the contract, optimized for L2 execution and upgradeable */ contract KhugaBash is Initializable, Ownable, ReentrancyGuard, UUPSUpgradeable, EIP712 { // Structs struct Player { uint256 score; bool isRegistered; } struct LeaderboardEntry { address player; uint256 score; } // State variables mapping(address => Player) private players; mapping(address => uint256) private playerNonce; address public backendSigner; address[] private playerAddresses; uint256 private constant MAX_LEADERBOARD_SIZE = 100; uint256 private constant SCORE_PER_GAME = 10; bytes32 private constant SCORE_UPDATED_TYPE_HASH = keccak256("ScoreUpdated(uint256 score,uint256 nonce)"); // Events event PlayerRegistered(address indexed player, uint256 nonce); event ScoreEarned(address indexed player, uint256 score); event ScoreUpdated(uint256 score, uint256 nonce); event LeaderboardUpdated(address indexed player, uint256 score); event Debug(bytes32 messageHash, address signer, bytes signature); error PlayerAlreadyRegistered(); error InvalidSignature(); error InvalidNonce(); error PlayerNotRegistered(); /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize() public initializer { _initializeOwner(msg.sender); } // Player Registration function registerPlayer(uint256 nonce) external { require(!players[msg.sender].isRegistered, PlayerAlreadyRegistered()); players[msg.sender] = Player({score: 0, isRegistered: true}); playerNonce[msg.sender] = nonce; playerAddresses.push(msg.sender); emit PlayerRegistered(msg.sender, nonce); } // Game score System function awardScore(address player, uint256 multiplier) external onlyOwner { require(players[player].isRegistered, PlayerNotRegistered()); uint256 scoreToAward = SCORE_PER_GAME * multiplier; players[player].score += scoreToAward; emit ScoreEarned(player, scoreToAward); emit LeaderboardUpdated(player, players[player].score); } function updateScore( uint256 score, uint256 nonce, bytes calldata signature ) external { require(nonce == playerNonce[msg.sender] + 1, InvalidNonce()); bytes32 messageHash = _hashTypedData( keccak256(abi.encode(SCORE_UPDATED_TYPE_HASH, score, nonce)) ); if ( !SignatureCheckerLib.isValidSignatureNowCalldata( backendSigner, messageHash, signature ) ) { revert InvalidSignature(); } players[msg.sender].score += score; playerNonce[msg.sender]++; emit ScoreUpdated(score, nonce); } // Leaderboard Functions function getTopPlayers( uint256 limit ) external view returns (LeaderboardEntry[] memory) { uint256 size = playerAddresses.length; uint256 resultSize = size < limit ? size : limit; resultSize = resultSize < MAX_LEADERBOARD_SIZE ? resultSize : MAX_LEADERBOARD_SIZE; LeaderboardEntry[] memory topPlayers = new LeaderboardEntry[]( resultSize ); // Create initial array for (uint256 i = 0; i < resultSize; i++) { topPlayers[i] = LeaderboardEntry({ player: playerAddresses[i], score: players[playerAddresses[i]].score }); } // Simple bubble sort (can be optimized for production) for (uint256 i = 0; i < resultSize - 1; i++) { for (uint256 j = 0; j < resultSize - i - 1; j++) { if (topPlayers[j].score < topPlayers[j + 1].score) { LeaderboardEntry memory temp = topPlayers[j]; topPlayers[j] = topPlayers[j + 1]; topPlayers[j + 1] = temp; } } } return topPlayers; } // Player Stats function getPlayerStats( address player ) external view returns (Player memory) { require(players[player].isRegistered, PlayerNotRegistered()); return players[player]; } // Admin Functions function setBackendSigner(address _backendSigner) external onlyOwner { backendSigner = _backendSigner; } function setPlayerNonce(address player, uint256 nonce) external onlyOwner { playerNonce[player] = nonce; } // Required override for UUPS proxy pattern function _authorizeUpgrade( address newImplementation ) internal override onlyOwner {} function _domainNameAndVersion() internal pure virtual override returns (string memory, string memory) { return ("KhugaBash", "1"); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Initializable mixin for the upgradeable contracts. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Initializable.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/proxy/utils/Initializable.sol) abstract contract Initializable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The contract is already initialized. error InvalidInitialization(); /// @dev The contract is not initializing. error NotInitializing(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Triggered when the contract has been initialized. event Initialized(uint64 version); /// @dev `keccak256(bytes("Initialized(uint64)"))`. bytes32 private constant _INTIALIZED_EVENT_SIGNATURE = 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The default initializable slot is given by: /// `bytes32(~uint256(uint32(bytes4(keccak256("_INITIALIZABLE_SLOT")))))`. /// /// Bits Layout: /// - [0] `initializing` /// - [1..64] `initializedVersion` bytes32 private constant _INITIALIZABLE_SLOT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffbf601132; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTRUCTOR */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ constructor() { // Construction time check to ensure that `_initializableSlot()` is not // overridden to zero. Will be optimized away if there is no revert. require(_initializableSlot() != bytes32(0)); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Override to return a non-zero custom storage slot if required. function _initializableSlot() internal pure virtual returns (bytes32) { return _INITIALIZABLE_SLOT; } /// @dev Guards an initializer function so that it can be invoked at most once. /// /// You can guard a function with `onlyInitializing` such that it can be called /// through a function guarded with `initializer`. /// /// This is similar to `reinitializer(1)`, except that in the context of a constructor, /// an `initializer` guarded function can be invoked multiple times. /// This can be useful during testing and is not expected to be used in production. /// /// Emits an {Initialized} event. modifier initializer() virtual { bytes32 s = _initializableSlot(); /// @solidity memory-safe-assembly assembly { let i := sload(s) // Set `initializing` to 1, `initializedVersion` to 1. sstore(s, 3) // If `!(initializing == 0 && initializedVersion == 0)`. if i { // If `!(address(this).code.length == 0 && initializedVersion == 1)`. if iszero(lt(extcodesize(address()), eq(shr(1, i), 1))) { mstore(0x00, 0xf92ee8a9) // `InvalidInitialization()`. revert(0x1c, 0x04) } s := shl(shl(255, i), s) // Skip initializing if `initializing == 1`. } } _; /// @solidity memory-safe-assembly assembly { if s { // Set `initializing` to 0, `initializedVersion` to 1. sstore(s, 2) // Emit the {Initialized} event. mstore(0x20, 1) log1(0x20, 0x20, _INTIALIZED_EVENT_SIGNATURE) } } } /// @dev Guards an reinitialzer function so that it can be invoked at most once. /// /// You can guard a function with `onlyInitializing` such that it can be called /// through a function guarded with `reinitializer`. /// /// Emits an {Initialized} event. modifier reinitializer(uint64 version) virtual { bytes32 s = _initializableSlot(); /// @solidity memory-safe-assembly assembly { // Clean upper bits, and shift left by 1 to make space for the initializing bit. version := shl(1, and(version, 0xffffffffffffffff)) let i := sload(s) // If `initializing == 1 || initializedVersion >= version`. if iszero(lt(and(i, 1), lt(i, version))) { mstore(0x00, 0xf92ee8a9) // `InvalidInitialization()`. revert(0x1c, 0x04) } // Set `initializing` to 1, `initializedVersion` to `version`. sstore(s, or(1, version)) } _; /// @solidity memory-safe-assembly assembly { // Set `initializing` to 0, `initializedVersion` to `version`. sstore(s, version) // Emit the {Initialized} event. mstore(0x20, shr(1, version)) log1(0x20, 0x20, _INTIALIZED_EVENT_SIGNATURE) } } /// @dev Guards a function such that it can only be called in the scope /// of a function guarded with `initializer` or `reinitializer`. modifier onlyInitializing() virtual { _checkInitializing(); _; } /// @dev Reverts if the contract is not initializing. function _checkInitializing() internal view virtual { bytes32 s = _initializableSlot(); /// @solidity memory-safe-assembly assembly { if iszero(and(1, sload(s))) { mstore(0x00, 0xd7e6bcf8) // `NotInitializing()`. revert(0x1c, 0x04) } } } /// @dev Locks any future initializations by setting the initialized version to `2**64 - 1`. /// /// Calling this in the constructor will prevent the contract from being initialized /// or reinitialized. It is recommended to use this to lock implementation contracts /// that are designed to be called through proxies. /// /// Emits an {Initialized} event the first time it is successfully called. function _disableInitializers() internal virtual { bytes32 s = _initializableSlot(); /// @solidity memory-safe-assembly assembly { let i := sload(s) if and(i, 1) { mstore(0x00, 0xf92ee8a9) // `InvalidInitialization()`. revert(0x1c, 0x04) } let uint64max := 0xffffffffffffffff if iszero(eq(shr(1, i), uint64max)) { // Set `initializing` to 0, `initializedVersion` to `2**64 - 1`. sstore(s, shl(1, uint64max)) // Emit the {Initialized} event. mstore(0x20, uint64max) log1(0x20, 0x20, _INTIALIZED_EVENT_SIGNATURE) } } } /// @dev Returns the highest version that has been initialized. function _getInitializedVersion() internal view virtual returns (uint64 version) { bytes32 s = _initializableSlot(); /// @solidity memory-safe-assembly assembly { version := shr(1, sload(s)) } } /// @dev Returns whether the contract is currently initializing. function _isInitializing() internal view virtual returns (bool result) { bytes32 s = _initializableSlot(); /// @solidity memory-safe-assembly assembly { result := and(1, sload(s)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple single owner authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol) /// /// @dev Note: /// This implementation does NOT auto-initialize the owner to `msg.sender`. /// You MUST call the `_initializeOwner` in the constructor / initializer. /// /// While the ownable portion follows /// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility, /// the nomenclature for the 2-step ownership handover may be unique to this codebase. abstract contract Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The caller is not authorized to call the function. error Unauthorized(); /// @dev The `newOwner` cannot be the zero address. error NewOwnerIsZeroAddress(); /// @dev The `pendingOwner` does not have a valid handover request. error NoHandoverRequest(); /// @dev Cannot double-initialize. error AlreadyInitialized(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ownership is transferred from `oldOwner` to `newOwner`. /// This event is intentionally kept the same as OpenZeppelin's Ownable to be /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173), /// despite it not being as lightweight as a single argument event. event OwnershipTransferred(address indexed oldOwner, address indexed newOwner); /// @dev An ownership handover to `pendingOwner` has been requested. event OwnershipHandoverRequested(address indexed pendingOwner); /// @dev The ownership handover to `pendingOwner` has been canceled. event OwnershipHandoverCanceled(address indexed pendingOwner); /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`. uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE = 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0; /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE = 0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d; /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE = 0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The owner slot is given by: /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`. /// It is intentionally chosen to be a high value /// to avoid collision with lower slots. /// The choice of manual storage layout is to enable compatibility /// with both regular and upgradeable contracts. bytes32 internal constant _OWNER_SLOT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927; /// The ownership handover slot of `newOwner` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED)) /// let handoverSlot := keccak256(0x00, 0x20) /// ``` /// It stores the expiry timestamp of the two-step ownership handover. uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Override to return true to make `_initializeOwner` prevent double-initialization. function _guardInitializeOwner() internal pure virtual returns (bool guard) {} /// @dev Initializes the owner directly without authorization guard. /// This function must be called upon initialization, /// regardless of whether the contract is upgradeable or not. /// This is to enable generalization to both regular and upgradeable contracts, /// and to save gas in case the initial owner is not the caller. /// For performance reasons, this function will not check if there /// is an existing owner. function _initializeOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT if sload(ownerSlot) { mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`. revert(0x1c, 0x04) } // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } else { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(_OWNER_SLOT, newOwner) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } } /// @dev Sets the owner directly without authorization guard. function _setOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) } } else { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, newOwner) } } } /// @dev Throws if the sender is not the owner. function _checkOwner() internal view virtual { /// @solidity memory-safe-assembly assembly { // If the caller is not the stored owner, revert. if iszero(eq(caller(), sload(_OWNER_SLOT))) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } /// @dev Returns how long a two-step ownership handover is valid for in seconds. /// Override to return a different value if needed. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _ownershipHandoverValidFor() internal view virtual returns (uint64) { return 48 * 3600; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to transfer the ownership to `newOwner`. function transferOwnership(address newOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { if iszero(shl(96, newOwner)) { mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`. revert(0x1c, 0x04) } } _setOwner(newOwner); } /// @dev Allows the owner to renounce their ownership. function renounceOwnership() public payable virtual onlyOwner { _setOwner(address(0)); } /// @dev Request a two-step ownership handover to the caller. /// The request will automatically expire in 48 hours (172800 seconds) by default. function requestOwnershipHandover() public payable virtual { unchecked { uint256 expires = block.timestamp + _ownershipHandoverValidFor(); /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to `expires`. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), expires) // Emit the {OwnershipHandoverRequested} event. log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller()) } } } /// @dev Cancels the two-step ownership handover to the caller, if any. function cancelOwnershipHandover() public payable virtual { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), 0) // Emit the {OwnershipHandoverCanceled} event. log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller()) } } /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`. /// Reverts if there is no existing ownership handover requested by `pendingOwner`. function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) let handoverSlot := keccak256(0x0c, 0x20) // If the handover does not exist, or has expired. if gt(timestamp(), sload(handoverSlot)) { mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`. revert(0x1c, 0x04) } // Set the handover slot to 0. sstore(handoverSlot, 0) } _setOwner(pendingOwner); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the owner of the contract. function owner() public view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { result := sload(_OWNER_SLOT) } } /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`. function ownershipHandoverExpiresAt(address pendingOwner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // Compute the handover slot. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) // Load the handover slot. result := sload(keccak256(0x0c, 0x20)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by the owner. modifier onlyOwner() virtual { _checkOwner(); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Reentrancy guard mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ReentrancyGuard.sol) abstract contract ReentrancyGuard { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Unauthorized reentrant call. error Reentrancy(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Equivalent to: `uint72(bytes9(keccak256("_REENTRANCY_GUARD_SLOT")))`. /// 9 bytes is large enough to avoid collisions with lower slots, /// but not too large to result in excessive bytecode bloat. uint256 private constant _REENTRANCY_GUARD_SLOT = 0x929eee149b4bd21268; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* REENTRANCY GUARD */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Guards a function from reentrancy. modifier nonReentrant() virtual { /// @solidity memory-safe-assembly assembly { if eq(sload(_REENTRANCY_GUARD_SLOT), address()) { mstore(0x00, 0xab143c06) // `Reentrancy()`. revert(0x1c, 0x04) } sstore(_REENTRANCY_GUARD_SLOT, address()) } _; /// @solidity memory-safe-assembly assembly { sstore(_REENTRANCY_GUARD_SLOT, codesize()) } } /// @dev Guards a view function from read-only reentrancy. modifier nonReadReentrant() virtual { /// @solidity memory-safe-assembly assembly { if eq(sload(_REENTRANCY_GUARD_SLOT), address()) { mstore(0x00, 0xab143c06) // `Reentrancy()`. revert(0x1c, 0x04) } } _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {CallContextChecker} from "./CallContextChecker.sol"; /// @notice UUPS proxy mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/UUPSUpgradeable.sol) /// @author Modified from OpenZeppelin /// (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/utils/UUPSUpgradeable.sol) /// /// @dev Note: /// - This implementation is intended to be used with ERC1967 proxies. /// See: `LibClone.deployERC1967` and related functions. /// - This implementation is NOT compatible with legacy OpenZeppelin proxies /// which do not store the implementation at `_ERC1967_IMPLEMENTATION_SLOT`. abstract contract UUPSUpgradeable is CallContextChecker { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The upgrade failed. error UpgradeFailed(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Emitted when the proxy's implementation is upgraded. event Upgraded(address indexed implementation); /// @dev `keccak256(bytes("Upgraded(address)"))`. uint256 private constant _UPGRADED_EVENT_SIGNATURE = 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ERC-1967 storage slot for the implementation in the proxy. /// `uint256(keccak256("eip1967.proxy.implementation")) - 1`. bytes32 internal constant _ERC1967_IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* UUPS OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Please override this function to check if `msg.sender` is authorized /// to upgrade the proxy to `newImplementation`, reverting if not. /// ``` /// function _authorizeUpgrade(address) internal override onlyOwner {} /// ``` function _authorizeUpgrade(address newImplementation) internal virtual; /// @dev Returns the storage slot used by the implementation, /// as specified in [ERC1822](https://eips.ethereum.org/EIPS/eip-1822). /// /// Note: The `notDelegated` modifier prevents accidental upgrades to /// an implementation that is a proxy contract. function proxiableUUID() public view virtual notDelegated returns (bytes32) { // This function must always return `_ERC1967_IMPLEMENTATION_SLOT` to comply with ERC1967. return _ERC1967_IMPLEMENTATION_SLOT; } /// @dev Upgrades the proxy's implementation to `newImplementation`. /// Emits a {Upgraded} event. /// /// Note: Passing in empty `data` skips the delegatecall to `newImplementation`. function upgradeToAndCall(address newImplementation, bytes calldata data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); /// @solidity memory-safe-assembly assembly { newImplementation := shr(96, shl(96, newImplementation)) // Clears upper 96 bits. mstore(0x00, returndatasize()) mstore(0x01, 0x52d1902d) // `proxiableUUID()`. let s := _ERC1967_IMPLEMENTATION_SLOT // Check if `newImplementation` implements `proxiableUUID` correctly. if iszero(eq(mload(staticcall(gas(), newImplementation, 0x1d, 0x04, 0x01, 0x20)), s)) { mstore(0x01, 0x55299b49) // `UpgradeFailed()`. revert(0x1d, 0x04) } // Emit the {Upgraded} event. log2(codesize(), 0x00, _UPGRADED_EVENT_SIGNATURE, newImplementation) sstore(s, newImplementation) // Updates the implementation. // Perform a delegatecall to `newImplementation` if `data` is non-empty. if data.length { // Forwards the `data` to `newImplementation` via delegatecall. let m := mload(0x40) calldatacopy(m, data.offset, data.length) if iszero(delegatecall(gas(), newImplementation, m, data.length, codesize(), 0x00)) { // Bubble up the revert if the call reverts. returndatacopy(m, 0x00, returndatasize()) revert(m, returndatasize()) } } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Signature verification helper that supports both ECDSA signatures from EOAs /// and ERC1271 signatures from smart contract wallets like Argent and Gnosis safe. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SignatureCheckerLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/SignatureChecker.sol) /// /// @dev Note: /// - The signature checking functions use the ecrecover precompile (0x1). /// - The `bytes memory signature` variants use the identity precompile (0x4) /// to copy memory internally. /// - Unlike ECDSA signatures, contract signatures are revocable. /// - As of Solady version 0.0.134, all `bytes signature` variants accept both /// regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures. /// See: https://eips.ethereum.org/EIPS/eip-2098 /// This is for calldata efficiency on smart accounts prevalent on L2s. /// /// WARNING! Do NOT use signatures as unique identifiers: /// - Use a nonce in the digest to prevent replay attacks on the same contract. /// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts. /// EIP-712 also enables readable signing of typed data for better user safety. /// This implementation does NOT check if a signature is non-malleable. library SignatureCheckerLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* SIGNATURE CHECKING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `signature` is valid for `signer` and `hash`. /// If `signer.code.length == 0`, then validate with `ecrecover`, else /// it will validate with ERC1271 on `signer`. function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool isValid) { if (signer == address(0)) return isValid; /// @solidity memory-safe-assembly assembly { let m := mload(0x40) for {} 1 {} { if iszero(extcodesize(signer)) { switch mload(signature) case 64 { let vs := mload(add(signature, 0x40)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x60, shr(1, shl(1, vs))) // `s`. } case 65 { mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x60, mload(add(signature, 0x40))) // `s`. } default { break } mstore(0x00, hash) mstore(0x40, mload(add(signature, 0x20))) // `r`. let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20)) isValid := gt(returndatasize(), shl(96, xor(signer, recovered))) mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. // Copy the `signature` over. let n := add(0x20, mload(signature)) let copied := staticcall(gas(), 4, signature, n, add(m, 0x44), n) isValid := staticcall(gas(), signer, m, add(returndatasize(), 0x44), d, 0x20) isValid := and(eq(mload(d), f), and(isValid, copied)) break } } } /// @dev Returns whether `signature` is valid for `signer` and `hash`. /// If `signer.code.length == 0`, then validate with `ecrecover`, else /// it will validate with ERC1271 on `signer`. function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature) internal view returns (bool isValid) { if (signer == address(0)) return isValid; /// @solidity memory-safe-assembly assembly { let m := mload(0x40) for {} 1 {} { if iszero(extcodesize(signer)) { switch signature.length case 64 { let vs := calldataload(add(signature.offset, 0x20)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, calldataload(signature.offset)) // `r`. mstore(0x60, shr(1, shl(1, vs))) // `s`. } case 65 { mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. calldatacopy(0x40, signature.offset, 0x40) // `r`, `s`. } default { break } mstore(0x00, hash) let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20)) isValid := gt(returndatasize(), shl(96, xor(signer, recovered))) mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), signature.length) // Copy the `signature` over. calldatacopy(add(m, 0x64), signature.offset, signature.length) isValid := staticcall(gas(), signer, m, add(signature.length, 0x64), d, 0x20) isValid := and(eq(mload(d), f), isValid) break } } } /// @dev Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`. /// If `signer.code.length == 0`, then validate with `ecrecover`, else /// it will validate with ERC1271 on `signer`. function isValidSignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs) internal view returns (bool isValid) { if (signer == address(0)) return isValid; /// @solidity memory-safe-assembly assembly { let m := mload(0x40) for {} 1 {} { if iszero(extcodesize(signer)) { mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, r) // `r`. mstore(0x60, shr(1, shl(1, vs))) // `s`. let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20)) isValid := gt(returndatasize(), shl(96, xor(signer, recovered))) mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), shr(1, shl(1, vs))) // `s`. mstore8(add(m, 0xa4), add(shr(255, vs), 27)) // `v`. isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20) isValid := and(eq(mload(d), f), isValid) break } } } /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`. /// If `signer.code.length == 0`, then validate with `ecrecover`, else /// it will validate with ERC1271 on `signer`. function isValidSignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (bool isValid) { if (signer == address(0)) return isValid; /// @solidity memory-safe-assembly assembly { let m := mload(0x40) for {} 1 {} { if iszero(extcodesize(signer)) { mstore(0x00, hash) mstore(0x20, and(v, 0xff)) // `v`. mstore(0x40, r) // `r`. mstore(0x60, s) // `s`. let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20)) isValid := gt(returndatasize(), shl(96, xor(signer, recovered))) mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), s) // `s`. mstore8(add(m, 0xa4), v) // `v`. isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20) isValid := and(eq(mload(d), f), isValid) break } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC1271 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // Note: These ERC1271 operations do NOT have an ECDSA fallback. /// @dev Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. // Copy the `signature` over. let n := add(0x20, mload(signature)) let copied := staticcall(gas(), 4, signature, n, add(m, 0x44), n) isValid := staticcall(gas(), signer, m, add(returndatasize(), 0x44), d, 0x20) isValid := and(eq(mload(d), f), and(isValid, copied)) } } /// @dev Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract. function isValidERC1271SignatureNowCalldata( address signer, bytes32 hash, bytes calldata signature ) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), signature.length) // Copy the `signature` over. calldatacopy(add(m, 0x64), signature.offset, signature.length) isValid := staticcall(gas(), signer, m, add(signature.length, 0x64), d, 0x20) isValid := and(eq(mload(d), f), isValid) } } /// @dev Returns whether the signature (`r`, `vs`) is valid for `hash` /// for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), shr(1, shl(1, vs))) // `s`. mstore8(add(m, 0xa4), add(shr(255, vs), 27)) // `v`. isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20) isValid := and(eq(mload(d), f), isValid) } } /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `hash` /// for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), s) // `s`. mstore8(add(m, 0xa4), v) // `v`. isValid := staticcall(gas(), signer, m, 0xa5, d, 0x20) isValid := and(eq(mload(d), f), isValid) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC6492 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // Note: These ERC6492 operations now include an ECDSA fallback at the very end. // The calldata variants are excluded for brevity. /// @dev Returns whether `signature` is valid for `hash`. /// If the signature is postfixed with the ERC6492 magic number, it will attempt to /// deploy / prepare the `signer` smart account before doing a regular ERC1271 check. /// Note: This function is NOT reentrancy safe. /// The verifier must be deployed. /// Otherwise, the function will return false if `signer` is not yet deployed / prepared. /// See: https://gist.github.com/Vectorized/011d6becff6e0a73e42fe100f8d7ef04 /// With a dedicated verifier, this function is safe to use in contracts /// that have been granted special permissions. function isValidERC6492SignatureNowAllowSideEffects( address signer, bytes32 hash, bytes memory signature ) internal returns (bool isValid) { /// @solidity memory-safe-assembly assembly { function callIsValidSignature(signer_, hash_, signature_) -> _isValid { let m_ := mload(0x40) let f_ := shl(224, 0x1626ba7e) mstore(m_, f_) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m_, 0x04), hash_) let d_ := add(m_, 0x24) mstore(d_, 0x40) // The offset of the `signature` in the calldata. let n_ := add(0x20, mload(signature_)) let copied_ := staticcall(gas(), 4, signature_, n_, add(m_, 0x44), n_) _isValid := staticcall(gas(), signer_, m_, add(returndatasize(), 0x44), d_, 0x20) _isValid := and(eq(mload(d_), f_), and(_isValid, copied_)) } let noCode := iszero(extcodesize(signer)) let n := mload(signature) for {} 1 {} { if iszero(eq(mload(add(signature, n)), mul(0x6492, div(not(isValid), 0xffff)))) { if iszero(noCode) { isValid := callIsValidSignature(signer, hash, signature) } break } if iszero(noCode) { let o := add(signature, 0x20) // Signature bytes. isValid := callIsValidSignature(signer, hash, add(o, mload(add(o, 0x40)))) if isValid { break } } let m := mload(0x40) mstore(m, signer) mstore(add(m, 0x20), hash) pop( call( gas(), // Remaining gas. 0x0000bc370E4DC924F427d84e2f4B9Ec81626ba7E, // Non-reverting verifier. 0, // Send zero ETH. m, // Start of memory. add(returndatasize(), 0x40), // Length of calldata in memory. staticcall(gas(), 4, add(signature, 0x20), n, add(m, 0x40), n), // 1. 0x00 // Length of returndata to write. ) ) isValid := returndatasize() break } // Do `ecrecover` fallback if `noCode && !isValid`. for {} gt(noCode, isValid) {} { switch n case 64 { let vs := mload(add(signature, 0x40)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x60, shr(1, shl(1, vs))) // `s`. } case 65 { mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x60, mload(add(signature, 0x40))) // `s`. } default { break } let m := mload(0x40) mstore(0x00, hash) mstore(0x40, mload(add(signature, 0x20))) // `r`. let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20)) isValid := gt(returndatasize(), shl(96, xor(signer, recovered))) mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } } /// @dev Returns whether `signature` is valid for `hash`. /// If the signature is postfixed with the ERC6492 magic number, it will attempt /// to use a reverting verifier to deploy / prepare the `signer` smart account /// and do a `isValidSignature` check via the reverting verifier. /// Note: This function is reentrancy safe. /// The reverting verifier must be deployed. /// Otherwise, the function will return false if `signer` is not yet deployed / prepared. /// See: https://gist.github.com/Vectorized/846a474c855eee9e441506676800a9ad function isValidERC6492SignatureNow(address signer, bytes32 hash, bytes memory signature) internal returns (bool isValid) { /// @solidity memory-safe-assembly assembly { function callIsValidSignature(signer_, hash_, signature_) -> _isValid { let m_ := mload(0x40) let f_ := shl(224, 0x1626ba7e) mstore(m_, f_) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m_, 0x04), hash_) let d_ := add(m_, 0x24) mstore(d_, 0x40) // The offset of the `signature` in the calldata. let n_ := add(0x20, mload(signature_)) let copied_ := staticcall(gas(), 4, signature_, n_, add(m_, 0x44), n_) _isValid := staticcall(gas(), signer_, m_, add(returndatasize(), 0x44), d_, 0x20) _isValid := and(eq(mload(d_), f_), and(_isValid, copied_)) } let noCode := iszero(extcodesize(signer)) let n := mload(signature) for {} 1 {} { if iszero(eq(mload(add(signature, n)), mul(0x6492, div(not(isValid), 0xffff)))) { if iszero(noCode) { isValid := callIsValidSignature(signer, hash, signature) } break } if iszero(noCode) { let o := add(signature, 0x20) // Signature bytes. isValid := callIsValidSignature(signer, hash, add(o, mload(add(o, 0x40)))) if isValid { break } } let m := mload(0x40) mstore(m, signer) mstore(add(m, 0x20), hash) let willBeZeroIfRevertingVerifierExists := call( gas(), // Remaining gas. 0x00007bd799e4A591FeA53f8A8a3E9f931626Ba7e, // Reverting verifier. 0, // Send zero ETH. m, // Start of memory. add(returndatasize(), 0x40), // Length of calldata in memory. staticcall(gas(), 4, add(signature, 0x20), n, add(m, 0x40), n), // 1. 0x00 // Length of returndata to write. ) isValid := gt(returndatasize(), willBeZeroIfRevertingVerifierExists) break } // Do `ecrecover` fallback if `noCode && !isValid`. for {} gt(noCode, isValid) {} { switch n case 64 { let vs := mload(add(signature, 0x40)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x60, shr(1, shl(1, vs))) // `s`. } case 65 { mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x60, mload(add(signature, 0x40))) // `s`. } default { break } let m := mload(0x40) mstore(0x00, hash) mstore(0x40, mload(add(signature, 0x20))) // `r`. let recovered := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20)) isValid := gt(returndatasize(), shl(96, xor(signer, recovered))) mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HASHING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an Ethereum Signed Message, created from a `hash`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, hash) // Store into scratch space for keccak256. mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes. result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`. } } /// @dev Returns an Ethereum Signed Message, created from `s`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. /// Note: Supports lengths of `s` up to 999999 bytes. function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let sLength := mload(s) let o := 0x20 mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded. mstore(0x00, 0x00) // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`. for { let temp := sLength } 1 {} { o := sub(o, 1) mstore8(o, add(48, mod(temp, 10))) temp := div(temp, 10) if iszero(temp) { break } } let n := sub(0x3a, o) // Header length: `26 + 32 - o`. // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes. returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20)) mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header. result := keccak256(add(s, sub(0x20, n)), add(n, sLength)) mstore(s, sLength) // Restore the length. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EMPTY CALLDATA HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an empty calldata bytes. function emptySignature() internal pure returns (bytes calldata signature) { /// @solidity memory-safe-assembly assembly { signature.length := 0 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Contract for EIP-712 typed structured data hashing and signing. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EIP712.sol) /// @author Modified from Solbase (https://github.com/Sol-DAO/solbase/blob/main/src/utils/EIP712.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol) /// /// @dev Note, this implementation: /// - Uses `address(this)` for the `verifyingContract` field. /// - Does NOT use the optional EIP-712 salt. /// - Does NOT use any EIP-712 extensions. /// This is for simplicity and to save gas. /// If you need to customize, please fork / modify accordingly. abstract contract EIP712 { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS AND IMMUTABLES */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`. bytes32 internal constant _DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f; /// @dev `keccak256("EIP712Domain(string name,string version,address verifyingContract)")`. /// This is only used in `_hashTypedDataSansChainId`. bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID = 0x91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a2766; uint256 private immutable _cachedThis; uint256 private immutable _cachedChainId; bytes32 private immutable _cachedNameHash; bytes32 private immutable _cachedVersionHash; bytes32 private immutable _cachedDomainSeparator; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTRUCTOR */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Cache the hashes for cheaper runtime gas costs. /// In the case of upgradeable contracts (i.e. proxies), /// or if the chain id changes due to a hard fork, /// the domain separator will be seamlessly calculated on-the-fly. constructor() { _cachedThis = uint256(uint160(address(this))); _cachedChainId = block.chainid; string memory name; string memory version; if (!_domainNameAndVersionMayChange()) (name, version) = _domainNameAndVersion(); bytes32 nameHash = _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(name)); bytes32 versionHash = _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(version)); _cachedNameHash = nameHash; _cachedVersionHash = versionHash; bytes32 separator; if (!_domainNameAndVersionMayChange()) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Load the free memory pointer. mstore(m, _DOMAIN_TYPEHASH) mstore(add(m, 0x20), nameHash) mstore(add(m, 0x40), versionHash) mstore(add(m, 0x60), chainid()) mstore(add(m, 0x80), address()) separator := keccak256(m, 0xa0) } } _cachedDomainSeparator = separator; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* FUNCTIONS TO OVERRIDE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Please override this function to return the domain name and version. /// ``` /// function _domainNameAndVersion() /// internal /// pure /// virtual /// returns (string memory name, string memory version) /// { /// name = "Solady"; /// version = "1"; /// } /// ``` /// /// Note: If the returned result may change after the contract has been deployed, /// you must override `_domainNameAndVersionMayChange()` to return true. function _domainNameAndVersion() internal view virtual returns (string memory name, string memory version); /// @dev Returns if `_domainNameAndVersion()` may change /// after the contract has been deployed (i.e. after the constructor). /// Default: false. function _domainNameAndVersionMayChange() internal pure virtual returns (bool result) {} /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HASHING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the EIP-712 domain separator. function _domainSeparator() internal view virtual returns (bytes32 separator) { if (_domainNameAndVersionMayChange()) { separator = _buildDomainSeparator(); } else { separator = _cachedDomainSeparator; if (_cachedDomainSeparatorInvalidated()) separator = _buildDomainSeparator(); } } /// @dev Returns the hash of the fully encoded EIP-712 message for this domain, /// given `structHash`, as defined in /// https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct. /// /// The hash can be used together with {ECDSA-recover} to obtain the signer of a message: /// ``` /// bytes32 digest = _hashTypedData(keccak256(abi.encode( /// keccak256("Mail(address to,string contents)"), /// mailTo, /// keccak256(bytes(mailContents)) /// ))); /// address signer = ECDSA.recover(digest, signature); /// ``` function _hashTypedData(bytes32 structHash) internal view virtual returns (bytes32 digest) { // We will use `digest` to store the domain separator to save a bit of gas. if (_domainNameAndVersionMayChange()) { digest = _buildDomainSeparator(); } else { digest = _cachedDomainSeparator; if (_cachedDomainSeparatorInvalidated()) digest = _buildDomainSeparator(); } /// @solidity memory-safe-assembly assembly { // Compute the digest. mstore(0x00, 0x1901000000000000) // Store "\x19\x01". mstore(0x1a, digest) // Store the domain separator. mstore(0x3a, structHash) // Store the struct hash. digest := keccak256(0x18, 0x42) // Restore the part of the free memory slot that was overwritten. mstore(0x3a, 0) } } /// @dev Variant of `_hashTypedData` that excludes the chain ID. /// We expect that most contracts will use `_hashTypedData` as the main hash, /// and `_hashTypedDataSansChainId` only occasionally for cross-chain workflows. /// Thus this is optimized for smaller bytecode size over runtime gas. function _hashTypedDataSansChainId(bytes32 structHash) internal view virtual returns (bytes32 digest) { (string memory name, string memory version) = _domainNameAndVersion(); /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Load the free memory pointer. mstore(0x00, _DOMAIN_TYPEHASH_SANS_CHAIN_ID) mstore(0x20, keccak256(add(name, 0x20), mload(name))) mstore(0x40, keccak256(add(version, 0x20), mload(version))) mstore(0x60, address()) // Compute the digest. mstore(0x20, keccak256(0x00, 0x80)) // Store the domain separator. mstore(0x00, 0x1901) // Store "\x19\x01". mstore(0x40, structHash) // Store the struct hash. digest := keccak256(0x1e, 0x42) mstore(0x40, m) // Restore the free memory pointer. mstore(0x60, 0) // Restore the zero pointer. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EIP-5267 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev See: https://eips.ethereum.org/EIPS/eip-5267 function eip712Domain() public view virtual returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { fields = hex"0f"; // `0b01111`. (name, version) = _domainNameAndVersion(); chainId = block.chainid; verifyingContract = address(this); salt = salt; // `bytes32(0)`. extensions = extensions; // `new uint256[](0)`. } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the EIP-712 domain separator. function _buildDomainSeparator() private view returns (bytes32 separator) { // We will use `separator` to store the name hash to save a bit of gas. bytes32 versionHash; if (_domainNameAndVersionMayChange()) { (string memory name, string memory version) = _domainNameAndVersion(); separator = keccak256(bytes(name)); versionHash = keccak256(bytes(version)); } else { separator = _cachedNameHash; versionHash = _cachedVersionHash; } /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Load the free memory pointer. mstore(m, _DOMAIN_TYPEHASH) mstore(add(m, 0x20), separator) // Name hash. mstore(add(m, 0x40), versionHash) mstore(add(m, 0x60), chainid()) mstore(add(m, 0x80), address()) separator := keccak256(m, 0xa0) } } /// @dev Returns if the cached domain separator has been invalidated. function _cachedDomainSeparatorInvalidated() private view returns (bool result) { uint256 cachedChainId = _cachedChainId; uint256 cachedThis = _cachedThis; /// @solidity memory-safe-assembly assembly { result := iszero(and(eq(chainid(), cachedChainId), eq(address(), cachedThis))) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Call context checker mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/CallContextChecker.sol) contract CallContextChecker { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The call is from an unauthorized call context. error UnauthorizedCallContext(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* IMMUTABLES */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev For checking if the context is a delegate call. /// /// Note: To enable use cases with an immutable default implementation in the bytecode, /// (see: ERC6551Proxy), we don't require that the proxy address must match the /// value stored in the implementation slot, which may not be initialized. uint256 private immutable __self = uint256(uint160(address(this))); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CALL CONTEXT CHECKS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // A proxy call can be either via a `delegatecall` to an implementation, // or a 7702 call on an authority that points to a delegation. /// @dev Returns whether the current call context is on a EIP7702 authority /// (i.e. externally owned account). function _onEIP7702Authority() internal view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { extcodecopy(address(), 0x00, 0x00, 0x20) result := and(eq(0xef0100, shr(232, mload(0x00))), lt(sub(extcodesize(address()), 1), 23)) } } /// @dev Returns whether the current call context is on the implementation itself. function _onImplementation() internal view virtual returns (bool) { return __self == uint160(address(this)); } /// @dev Requires that the current call context is performed via a EIP7702 authority. function _checkOnlyEIP7702Authority() internal view virtual { if (!_onEIP7702Authority()) _revertUnauthorizedCallContext(); } /// @dev Requires that the current call context is performed via a proxy. function _checkOnlyProxy() internal view virtual { if (_onImplementation()) _revertUnauthorizedCallContext(); } /// @dev Requires that the current call context is NOT performed via a proxy. /// This is the opposite of `checkOnlyProxy`. function _checkNotDelegated() internal view virtual { if (!_onImplementation()) _revertUnauthorizedCallContext(); } /// @dev Requires that the current call context is performed via a EIP7702 authority. modifier onlyEIP7702Authority() virtual { _checkOnlyEIP7702Authority(); _; } /// @dev Requires that the current call context is performed via a proxy. modifier onlyProxy() virtual { _checkOnlyProxy(); _; } /// @dev Requires that the current call context is NOT performed via a proxy. /// This is the opposite of `onlyProxy`. modifier notDelegated() virtual { _checkNotDelegated(); _; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function _revertUnauthorizedCallContext() private pure { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x9f03a026) // `UnauthorizedCallContext()`. revert(0x1c, 0x04) } } }
{ "viaIR": false, "codegen": "yul", "remappings": [ "solady/=lib/solady/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/" ], "evmVersion": "cancun", "outputSelection": { "*": { "*": [ "abi" ] } }, "optimizer": { "enabled": true, "mode": "3", "fallback_to_optimizing_for_size": false, "disable_system_request_memoization": true }, "metadata": {}, "libraries": {}, "enableEraVMExtensions": false, "forceEVMLA": false }
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"PlayerAlreadyRegistered","type":"error"},{"inputs":[],"name":"PlayerNotRegistered","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnauthorizedCallContext","type":"error"},{"inputs":[],"name":"UpgradeFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"messageHash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"signer","type":"address"},{"indexed":false,"internalType":"bytes","name":"signature","type":"bytes"}],"name":"Debug","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":false,"internalType":"uint256","name":"score","type":"uint256"}],"name":"LeaderboardUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"PlayerRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":false,"internalType":"uint256","name":"score","type":"uint256"}],"name":"ScoreEarned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"score","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"ScoreUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"internalType":"address","name":"player","type":"address"},{"internalType":"uint256","name":"multiplier","type":"uint256"}],"name":"awardScore","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"backendSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"getPlayerStats","outputs":[{"components":[{"internalType":"uint256","name":"score","type":"uint256"},{"internalType":"bool","name":"isRegistered","type":"bool"}],"internalType":"struct KhugaBash.Player","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"getTopPlayers","outputs":[{"components":[{"internalType":"address","name":"player","type":"address"},{"internalType":"uint256","name":"score","type":"uint256"}],"internalType":"struct KhugaBash.LeaderboardEntry[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"registerPlayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_backendSigner","type":"address"}],"name":"setBackendSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"setPlayerNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"score","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"updateScore","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
9c4d535b00000000000000000000000000000000000000000000000000000000000000000100023d41834b12ae7dd726d485d28f3b0f05c02a010ef4e3baea79742c7d3900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x0002000000000002000b00000000000200010000000103550000000100200190000000500000c13d0000006002100270000001d7022001970000008003000039000000400030043f000000040020008c0000042e0000413d000000000301043b000000e003300270000001e70030009c000000770000a13d000001e80030009c000000860000213d000001ef0030009c000001520000a13d000001f00030009c0000028e0000613d000001f10030009c000002ce0000613d000001f20030009c0000042e0000c13d0000000001000416000000000001004b0000042e0000c13d0000000901000039000000800010043f000001db02000041000000a00020043f0000010002000039000000400020043f0000000102000039000000c00020043f000001dd03000041000000e00030043f0000020e03000041000001000030043f000000e003000039000001200030043f000001e00010043f000002000100043d0000020f01100197000001db011001c7000002000010043f000002090000043f0000012001000039000001400010043f000002200020043f000002400100043d0000021001100197000001dd011001c7000002400010043f000002410000043f000001d80100004100000000001004430000000001000414000001d70010009c000001d701008041000000c001100210000001d9011001c70000800b020000390757074d0000040f0000000100200190000006360000613d000000000101043b000001600010043f0000000001000410000001800010043f000001a00000043f0000016001000039000001c00010043f000000600100043d000002600010043f000000000001004b000004990000c13d0000018001000039000004a30000013d0000014001000039000000400010043f0000000001000416000000000001004b0000042e0000c13d0000000001000410000000800010043f000000a00010043f000001d80100004100000000001004430000000001000414000001d70010009c000001d701008041000000c001100210000001d9011001c70000800b020000390757074d0000040f0000000100200190000006360000613d000000000401043b000000c00040043f000000400100043d000001da0010009c000000710000813d0000004002100039000000400020043f00000009020000390000000002210436000001db030000410000000000320435000000400500043d000001dc0050009c000000ce0000a13d0000020c01000041000000000010043f0000004101000039000000040010043f0000020d010000410000075900010430000001f50030009c000000a10000a13d000001f60030009c000001700000a13d000001f70030009c000003370000613d000001f80030009c000003540000613d000001f90030009c0000042e0000c13d0000000001000416000000000001004b0000042e0000c13d00000002010000390000041f0000013d000001e90030009c000001b30000a13d000001ea0030009c000003710000613d000001eb0030009c000003a00000613d000001ec0030009c0000042e0000c13d000000240020008c0000042e0000413d0000000002000416000000000002004b0000042e0000c13d0000000401100370000000000101043b000002010010009c0000042e0000213d00000202020000410000000c0020043f000000000010043f0000000c010000390000002002000039075707330000040f000000000101041a000000800010043f0000020301000041000007580001042e000001fc0030009c000001d20000213d000001ff0030009c000003b10000613d000002000030009c0000042e0000c13d00000202010000410000000c0010043f0000000001000411000000000010043f000002080100004100000000001004430000000001000414000001d70010009c000001d701008041000000c001100210000001d9011001c70000800b020000390757074d0000040f0000000100200190000006360000613d000000000101043b000b00000001001d0000000001000414000001d70010009c000001d701008041000000c00110021000000207011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b0000000b02000029000002320220009a000000000021041b0000000001000414000001d70010009c000001d701008041000000c001100210000001de011001c70000800d02000039000000020300003900000233040000410000036b0000013d000900000004001d0000004003500039000000400030043f0000000103000039000b00000005001d0000000004350436000001dd03000041000a00000004001d0000000000340435000001d70020009c000001d70200804100000040022002100000000001010433000001d70010009c000001d7010080410000006001100210000000000121019f0000000002000414000001d70020009c000001d702008041000000c002200210000000000112019f000001de011001c700008010020000390757074d0000040f00000001002001900000042e0000613d0000000a02000029000001d70020009c000001d70200804100000040022002100000000b030000290000000003030433000001d70030009c000001d7030080410000006003300210000000000223019f000000000101043b000b00000001001d0000000001000414000001d70010009c000001d701008041000000c001100210000000000121019f000001de011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b0000000b05000029000000e00050043f000001000010043f000000400200043d0000008003200039000000000400041000000000004304350000006003200039000000090400002900000000004304350000004003200039000000000013043500000020012000390000000000510435000001df010000410000000000120435000001d70020009c000001d70200804100000040012002100000000002000414000001d70020009c000001d702008041000000c002200210000000000121019f000001e0011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b000001200010043f000001e102000041000000000202041a0000000100200190000004470000c13d0000023802200197000001e20020009c000001370000613d000001e201000041000001e102000041000000000012041b000001e301000041000000200010043f0000000001000414000001d70010009c000001d701008041000000c001100210000001e4011001c70000800d020000390000000103000039000001e504000041075707480000040f00000001002001900000042e0000613d000001200100043d000000800200043d00000140000004430000016000200443000000a00200043d00000020030000390000018000300443000001a000200443000000c00200043d0000004004000039000001c000400443000001e0002004430000006002000039000000e00400043d000002000020044300000220004004430000008002000039000001000400043d00000240002004430000026000400443000000a0020000390000028000200443000002a000100443000001000030044300000006010000390000012000100443000001e601000041000007580001042e000001f30030009c000003d80000613d000001f40030009c0000042e0000c13d000000440020008c0000042e0000413d0000000002000416000000000002004b0000042e0000c13d0000000401100370000000000101043b000b00000001001d000002010010009c0000042e0000213d075707120000040f0000000b01000029000000000010043f0000000101000039000000200010043f00000024010000390000000101100367000000000101043b000b00000001001d00000040020000390000000001000019075707330000040f0000000b02000029000000000021041b0000000001000019000007580001042e000001fa0030009c000003ed0000613d000001fb0030009c0000042e0000c13d000000240020008c0000042e0000413d0000000002000416000000000002004b0000042e0000c13d0000000401100370000000000101043b000b00000001001d000002010010009c0000042e0000213d000000c001000039000000400010043f000000800000043f000000a00000043f0000000b01000029000000000010043f000000200000043f0000000001000414000001d70010009c000001d701008041000000c0011002100000020b011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b0000000101100039000000000101041a000000ff00100190000003d40000613d0000000b01000029000000000010043f000000200000043f00000040020000390000000001000019075707330000040f000b00000001001d000000400100043d000a00000001001d075707070000040f0000000b03000029000000000103041a0000000a0200002900000000021204360000000103300039000000000303041a000000ff003001900000000003000039000000010300c0390000000000320435000000400300043d00000000011304360000000002020433000000000002004b0000000002000039000000010200c0390000000000210435000001d70030009c000001d703008041000000400130021000000220011001c7000007580001042e000001ed0030009c0000041b0000613d000001ee0030009c0000042e0000c13d000000240020008c0000042e0000413d0000000002000416000000000002004b0000042e0000c13d0000000302000039000000000d02041a0000000401100370000000000101043b00000000001d004b000000000d0180190000006400d0008c000000640d0080390000000501d002100000003f0210003900001fe00220018f0000008002200039000000400020043f0000008000d0043f00000000000d004b000004300000c13d0000020c01000041000000000010043f0000001101000039000000040010043f0000020d010000410000075900010430000001fd0030009c000004240000613d000001fe0030009c0000042e0000c13d000000640020008c0000042e0000413d0000000003000416000000000003004b0000042e0000c13d0000002403100370000000000303043b000a00000003001d0000000403100370000000000303043b000900000003001d0000004403100370000000000303043b000b00000003001d000001e30030009c0000042e0000213d0000000b030000290000002303300039000000000023004b0000042e0000813d0000000b03000029000700040030003d0000000701100360000000000101043b000800000001001d000001e30010009c0000042e0000213d0000000b010000290000002403100039000600000003001d0000000801300029000000000021004b0000042e0000213d0000000001000411000000000010043f0000000101000039000000200010043f0000000001000414000001d70010009c000001d701008041000000c0011002100000020b011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b000000000101041a000000010110003a000001cc0000613d0000000a03000029000000000013004b000005290000c13d000000400100043d000000600210003900000000003204350000004002100039000000090300002900000000003204350000006002000039000000000221043600000227030000410000000000320435000002280010009c000000710000213d0000008003100039000000400030043f000001d70020009c000001d70200804100000040022002100000000001010433000001d70010009c000001d7010080410000006001100210000000000121019f0000000002000414000001d70020009c000001d702008041000000c002200210000000000112019f000001de011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b000500000001001d0000021c01000041000000000010044300000000010004120000000400100443000000a00100003900000024001004430000000001000414000001d70010009c000001d701008041000000c0011002100000021d011001c700008005020000390757074d0000040f0000000100200190000006360000613d000000000101043b000400000001001d0000021c01000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000001d70010009c000001d701008041000000c0011002100000021d011001c700008005020000390757074d0000040f0000000100200190000006360000613d000000000101043b000300000001001d0000021c01000041000000000010044300000000010004120000000400100443000000400100003900000024001004430000000001000414000001d70010009c000001d701008041000000c0011002100000021d011001c700008005020000390757074d0000040f0000000100200190000006360000613d000000000101043b000200000001001d000001d80100004100000000001004430000000001000414000001d70010009c000001d701008041000000c001100210000001d9011001c70000800b020000390757074d0000040f0000000100200190000006360000613d0000000002000410000000000101043b000100000001001d000000030020006c000005d00000c13d0000000202000029000000010020006b000005d00000c13d0000022901000041000000000010043f00000004010000290000001a0010043f00000005010000290000003a0010043f0000000001000414000001d70010009c000001d701008041000000c0011002100000022a011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b000400000001001d0000003a0000043f0000000201000039000000000101041a000300000001001d000502010010019c000006100000c13d0000023101000041000000000010043f000002130100004100000759000104300000000001000416000000000001004b0000042e0000c13d000001e102000041000000000302041a0000000301000039000000000012041b000000000003004b000002af0000613d000b00000003001d00000217010000410000000000100443000000000100041000000004001004430000000001000414000001d70010009c000001d701008041000000c00110021000000218011001c700008002020000390757074d0000040f0000000100200190000006360000613d0000000b030000290000023802300197000000000101043b000000020020008c000004470000c13d000000000001004b000004470000c13d00000001003001900000000002000019000001e102006041000b00000002001d00000000060004110000020401000041000000000061041b0000000001000414000001d70010009c000001d701008041000000c001100210000001de011001c70000800d0200003900000003030000390000021a040000410000000005000019075707480000040f00000001002001900000042e0000613d0000000b0000006b0000036f0000613d00000002010000390000000b02000029000000000012041b0000000103000039000000200030043f0000000001000414000001d70010009c000001d701008041000000c001100210000001e4011001c70000800d02000039000001e5040000410000036c0000013d000000240020008c0000042e0000413d0000000002000416000000000002004b0000042e0000c13d0000000401100370000000000101043b000b00000001001d0000000001000411000000000010043f000000200000043f0000000001000414000001d70010009c000001d701008041000000c0011002100000020b011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b0000000101100039000000000101041a000000ff00100190000004a80000c13d000000400200043d000001dc0020009c000000710000213d0000004001200039000000400010043f00000020032000390000000101000039000900000003001d0000000000130435000a00000002001d00000000000204350000000001000411000000000010043f000000200000043f0000000001000414000001d70010009c000001d701008041000000c0011002100000020b011001c700008010020000390757074d0000040f00000001002001900000042e0000613d0000000a020000290000000002020433000000000101043b000000000021041b0000000101100039000000000201041a000002390220019700000009030000290000000003030433000000000003004b000000010220c1bf000000000021041b0000000001000411000000000010043f0000000101000039000000200010043f0000000001000414000001d70010009c000001d701008041000000c0011002100000020b011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b0000000b02000029000000000021041b0000000302000039000000000102041a000001e30010009c000000710000213d0000000103100039000000000032041b000000000020043f0000020a0110009a000000000201041a00000214022001970000000005000411000000000252019f000000000021041b000000400100043d0000000b020000290000000000210435000001d70010009c000001d70100804100000040011002100000000002000414000001d70020009c000001d702008041000000c002200210000000000112019f00000215011001c70000800d02000039000000020300003900000216040000410000036c0000013d0000000001000416000000000001004b0000042e0000c13d0000021c0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000001d70010009c000001d701008041000000c0011002100000021d011001c700008005020000390757074d0000040f0000000100200190000006360000613d000000000101043b0000000002000410000000000021004b000004170000c13d000000400100043d0000021e020000410000000000210435000001d70010009c000001d70100804100000040011002100000021f011001c7000007580001042e00000202010000410000000c0010043f0000000001000411000000000010043f0000000001000414000001d70010009c000001d701008041000000c00110021000000207011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b000000000001041b0000000001000414000001d70010009c000001d701008041000000c001100210000001de011001c70000800d0200003900000002030000390000021b040000410000000005000411075707480000040f00000001002001900000042e0000613d0000000001000019000007580001042e000000240020008c0000042e0000413d0000000401100370000000000101043b000b00000001001d000002010010009c0000042e0000213d0000020401000041000000000101041a0000000002000411000000000012004b000005c80000c13d00000202010000410000000c0010043f0000000b01000029000000000010043f0000000001000414000001d70010009c000001d701008041000000c00110021000000207011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b000900000001001d000000000101041a000a00000001001d000002080100004100000000001004430000000001000414000001d70010009c000001d701008041000000c001100210000001d9011001c70000800b020000390757074d0000040f0000000100200190000006360000613d000000000101043b0000000a0010006c000004f50000a13d0000020901000041000000000010043f00000206010000410000075900010430000000240020008c0000042e0000413d0000000401100370000000000101043b000002010010009c0000042e0000213d0000020402000041000000000202041a0000000003000411000000000023004b000005c80000c13d000000000001004b000004f80000c13d0000020501000041000000000010043f00000206010000410000075900010430000000440020008c0000042e0000413d0000000002000416000000000002004b0000042e0000c13d0000000402100370000000000202043b000b00000002001d000002010020009c0000042e0000213d0000002401100370000000000301043b0000020401000041000000000101041a0000000002000411000000000012004b000005c80000c13d000a00000003001d0000000b01000029000000000010043f000000200000043f0000000001000414000001d70010009c000001d701008041000000c0011002100000020b011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b0000000101100039000000000101041a000000ff00100190000004ac0000c13d0000023701000041000000000010043f000002130100004100000759000104300000020401000041000000000501041a0000000001000411000000000051004b000005c80000c13d0000000001000414000001d70010009c000001d701008041000000c001100210000001de011001c70000800d0200003900000003030000390000021a040000410000000006000019075707480000040f00000001002001900000042e0000613d0000020401000041000000000001041b0000000001000019000007580001042e000000440020008c0000042e0000413d0000000403100370000000000303043b000b00000003001d000002010030009c0000042e0000213d0000002403100370000000000303043b000001e30030009c0000042e0000213d0000002304300039000000000024004b0000042e0000813d000900040030003d0000000901100360000000000101043b000a00000001001d000001e30010009c0000042e0000213d0000000a013000290000002401100039000000000021004b0000042e0000213d0000021c0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000001d70010009c000001d701008041000000c0011002100000021d011001c700008005020000390757074d0000040f0000000100200190000006360000613d000000000101043b0000000002000410000000000021004b0000052d0000c13d0000022501000041000000000010043f000002060100004100000759000104300000000001000416000000000001004b0000042e0000c13d0000020401000041000000000101041a0000020101100197000000800010043f0000020301000041000007580001042e000000240020008c0000042e0000413d0000000002000416000000000002004b0000042e0000c13d0000000401100370000000000101043b000b00000001001d000002010010009c0000043f0000a13d0000000001000019000007590001043000000000030000190000004004200039000000400040043f000000200420003900000000000404350000000000020435000000a00430003900000000002404350000002003300039000000000013004b0000044b0000813d000000400200043d000001dc0020009c000004310000a13d000000710000013d075707120000040f0000000201000039000000000201041a00000214022001970000000b022001af000000000021041b0000000001000019000007580001042e0000021901000041000000000010043f00000206010000410000075900010430000000000300001900090000000d001d0000000301000039000000000101041a000000000031004b000005230000a13d000b00000003001d0000020a0130009a000000000101041a0000020101100197000a00000001001d000000000010043f000000200000043f0000000001000414000001d70010009c000001d701008041000000c0011002100000020b011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000400200043d000001dc0020009c000000090d000029000000710000213d000000000101043b000000000101041a0000004003200039000000400030043f000000200320003900000000001304350000000a010000290000000000120435000000800100043d0000000b03000029000000000031004b000005230000a13d0000000501300210000000a0011000390000000000210435000000800100043d000000000031004b000005230000a13d00000001033000390000000000d3004b0000044d0000413d0000000102d0008c000004fb0000c13d000000400100043d00000020020000390000000002210436000000800300043d00000000003204350000004002100039000000000003004b000004900000613d000000a004000039000000000500001900000000460404340000000076060434000002010660019700000000066204360000000007070433000000000076043500000040022000390000000105500039000000000035004b000004860000413d0000000002120049000001d70020009c000001d7020080410000006002200210000001d70010009c000001d7010080410000004001100210000000000112019f000007580001042e0000028003000039000000000200001900000080050000390000000004030019000000005305043400000000033404360000000102200039000000000012004b0000049c0000413d000000e00140008a000001d70010009c000001d701008041000000600110021000000211011001c7000007580001042e0000021201000041000000000010043f000002130100004100000759000104300000000a020000290000000a032000c90000000a0130011a000000000012004b000001cc0000c13d000a00000003001d0000000b01000029000000000010043f000000200000043f0000000001000414000001d70010009c000001d701008041000000c0011002100000020b011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b000000000201041a0000000a03000029000000000032001a000001cc0000413d0000000002320019000000000021041b000000400100043d0000000000310435000001d70010009c000001d70100804100000040011002100000000002000414000001d70020009c000001d702008041000000c002200210000000000112019f00000215011001c70000800d02000039000000020300003900000235040000410000000b05000029075707480000040f00000001002001900000042e0000613d0000000b01000029000000000010043f000000200000043f0000000001000414000001d70010009c000001d701008041000000c0011002100000020b011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b000000000101041a000000400200043d0000000000120435000001d70020009c000001d70200804100000040012002100000000002000414000001d70020009c000001d702008041000000c002200210000000000112019f00000215011001c70000800d02000039000000020300003900000236040000410000000b050000290000036c0000013d0000000901000029000000000001041b0000000b010000290757071c0000040f0000000001000019000007580001042e0000000004000019000005000000013d0000000104400039000000000024004b0000047c0000813d0000000000d4004b000001cc0000213d0000023a0540016700000000055d001a000004fd0000613d00000000070000190000050a0000013d000000000056004b0000000007060019000004fd0000813d000000000071004b000005230000a13d0000000106700039000000000061004b000005230000a13d0000000507700210000000a00970003900000000070904330000000508600210000000200a700039000000000b0a0433000000a008800039000000000a080433000000200ca00039000000000c0c04330000000000cb004b000005070000813d0000000000a90435000000800100043d000000000061004b000005230000a13d0000000000780435000000800100043d000000000061004b000005070000213d0000020c01000041000000000010043f0000003201000039000000040010043f0000020d0100004100000759000104300000022601000041000000000010043f000002130100004100000759000104300000020401000041000000000101041a0000000002000411000000000012004b000005c80000c13d0000000001000031000000000010043f000001f701000041000000010010043f0000000001000414000001d70010009c000001d701008041000000c00110021000000221011001c70000000b020000290757074d0000040f0000006003100270000001d703300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf0000054c0000613d0000000107000039000000000801034f000000008908043c0000000007970436000000000047004b000005480000c13d000000010220018f000000000005004b0000055a0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000000003001f00000000010204330000021e0010009c000005cc0000c13d0000000001000414000001d70010009c000001d701008041000000c001100210000001de011001c70000800d02000039000000020300003900000223040000410000000b05000029075707480000040f00000001002001900000042e0000613d0000021e010000410000000b02000029000000000021041b0000000a0000006b0000036f0000613d0000000a030000290000023b023001980000001f0330018f000000400100043d000800000001001d00000000012100190000000904000029000000200440003900000001044003670000057f0000613d000000000504034f0000000806000029000000005705043c0000000006760436000000000016004b0000057b0000c13d000000000003004b0000058c0000613d000000000224034f0000000303300210000000000401043300000000043401cf000000000434022f000000000202043b0000010003300089000000000232022f00000000023201cf000000000242019f000000000021043500000217010000410000000000100443000000000100041200000004001004430000000001000414000001d70010009c000001d701008041000000c00110021000000218011001c700008002020000390757074d0000040f0000000100200190000006360000613d0000000a01000029000001d70010009c000001d70100804100000060011002100000000002000414000001d70020009c000001d702008041000000c002200210000000000112019f0000000802000029000001d70020009c000001d702008041000a0040002002180000000a011001af0000000b02000029075707520000040f0000006003100270000001d70030019d00000001002001900000036f0000c13d000001d7023001970000001f0420018f000002240520019800000008080000290000000003580019000005b80000613d000000000601034f000000006706043c0000000008780436000000000038004b000005b40000c13d000000000004004b000005c50000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000013043500000060012002100000000a011001af00000759000104300000023401000041000000000010043f000002060100004100000759000104300000022201000041000000010010043f00000221010000410000075900010430000000400200043d000001df01000041000300000002001d0000000001120436000400000001001d0000021c01000041000000000010044300000000010004120000000400100443000000600100003900000024001004430000000001000414000001d70010009c000001d701008041000000c0011002100000021d011001c700008005020000390757074d0000040f0000000100200190000006360000613d000000000101043b000000040200002900000000001204350000021c01000041000000000010044300000000010004120000000400100443000000800100003900000024001004430000000001000414000001d70010009c000001d701008041000000c0011002100000021d011001c700008005020000390757074d0000040f0000000100200190000006360000613d000000000101043b000000030400002900000080024000390000000003000410000000000032043500000060024000390000000103000029000000000032043500000040024000390000000000120435000001d70040009c000001d70400804100000040014002100000000002000414000001d70020009c000001d702008041000000c002200210000000000121019f000001e0011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b000400000001001d000002730000013d000000400100043d000200000001001d00000217010000410000000000100443000000050100002900000004001004430000000001000414000001d70010009c000001d701008041000000c00110021000000218011001c700008002020000390757074d0000040f0000000100200190000006360000613d000000000101043b000000000001004b000006370000c13d0000000801000029000000400010008c000006940000613d0000000801000029000000410010008c0000028a0000c13d0000000b0100002900000064011000390000000101100367000000000101043b000000f801100270000000200010043f000000060100002900000001011003670000004003000039000000001201043c0000000003230436000000800030008c000006310000c13d000006a10000013d000000000001042f000000020500002900000064025000390000004401500039000000240650003900000004035000390000022b040000410000000000450435000000040400002900000000004304350000004003000039000b00000006001d0000000000360435000000080400002900000000004104350000023b034001980000001f0440018f000000000132001900000006050000290000000105500367000006500000613d000000000605034f000000006706043c0000000002720436000000000012004b0000064c0000c13d000000000004004b0000065d0000613d000000000235034f0000000303400210000000000401043300000000043401cf000000000434022f000000000202043b0000010003300089000000000232022f00000000023201cf000000000242019f00000000002104350000000201000029000001d70010009c000001d701008041000000400110021000000008020000290000022c0020009c0000022c020080410000006002200210000000000112019f0000000002000414000001d70020009c000001d702008041000000c002200210000000000121019f0000022d0110009a00000005020000290757074d0000040f0000006003100270000001d703300197000000200030008c000000200400003900000000040340190000001f0540018f00000020064001900000000b046000290000067d0000613d000000000701034f0000000b08000029000000007907043c0000000008980436000000000048004b000006790000c13d000000000005004b0000068a0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000000003001f0000000b0100002900000000010104330000022b0010009c00000000010000390000000101006039000000000112016f00000001001001900000028a0000613d000006d00000013d000000070400002900000040014000390000000101100367000000000101043b000000ff031002700000001b03300039000000200030043f00000020034000390000000102300367000000000202043b000000400020043f0000022e01100197000000600010043f0000000401000029000000000010043f0000000001000414000001d70010009c000001d701008041000000c0011002100000022f011001c700000001020000390757074d0000040f00000001090000390000006003100270000001d703300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf000006b90000613d000000000701034f000000007807043c0000000009890436000000000049004b000006b50000c13d000000010220018f000000000005004b000006c70000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000000003001f0000000001020433000000600000043f0000000202000029000000400020043f000000030110014f0000006001100210000000000013004b0000028a0000a13d0000000001000411000000000010043f000000200000043f0000000001000414000001d70010009c000001d701008041000000c0011002100000020b011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b000000000201041a000000090020002a000001cc0000413d0000000902200029000000000021041b0000000001000411000000000010043f0000000101000039000000200010043f0000000001000414000001d70010009c000001d701008041000000c0011002100000020b011001c700008010020000390757074d0000040f00000001002001900000042e0000613d000000000101043b000000000201041a000000010220003a000001cc0000613d000000000021041b000000400100043d00000020021000390000000a03000029000000000032043500000009020000290000000000210435000001d70010009c000001d70100804100000040011002100000000002000414000001d70020009c000001d702008041000000c002200210000000000112019f0000020b011001c70000800d02000039000000010300003900000230040000410000036c0000013d000001da0010009c0000070c0000813d0000004001100039000000400010043f000000000001042d0000020c01000041000000000010043f0000004101000039000000040010043f0000020d0100004100000759000104300000020401000041000000000101041a0000000002000411000000000012004b000007180000c13d000000000001042d0000023401000041000000000010043f0000020601000041000007590001043000010000000000020000020402000041000000000502041a00000000020004140000020106100197000001d70020009c000001d702008041000000c001200210000001de011001c70000800d0200003900000003030000390000021a04000041000100000006001d075707480000040f0000000100200190000007300000613d00000204010000410000000102000029000000000021041b000000000001042d00000000010000190000075900010430000000000001042f000001d70010009c000001d7010080410000004001100210000001d70020009c000001d7020080410000006002200210000000000112019f0000000002000414000001d70020009c000001d702008041000000c002200210000000000112019f000001de011001c700008010020000390757074d0000040f0000000100200190000007460000613d000000000101043b000000000001042d000000000100001900000759000104300000074b002104210000000102000039000000000001042d0000000002000019000000000001042d00000750002104230000000102000039000000000001042d0000000002000019000000000001042d00000755002104250000000102000039000000000001042d0000000002000019000000000001042d0000075700000432000007580001042e00000759000104300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff9a8a0592ac89c5ad3bc6df8224c17b485976f597df104ee20d0df415241f670b0200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc04b68756761426173680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf310000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f02000000000000000000000000000000000000a0000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffbf601132000000000000000000000000000000000000000000000001fffffffffffffffe000000000000000000000000000000000000000000000000ffffffffffffffff0200000000000000000000000000000000000020000000200000000000000000c7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d200000002000000000000000000000000000001c000000100000000000000000000000000000000000000000000000000000000000000000000000000715018a5000000000000000000000000000000000000000000000000000000008da5cb5a00000000000000000000000000000000000000000000000000000000f04e283d00000000000000000000000000000000000000000000000000000000f04e283e00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000fee81cf4000000000000000000000000000000000000000000000000000000008da5cb5b00000000000000000000000000000000000000000000000000000000ba3c0067000000000000000000000000000000000000000000000000000000008129fc1b000000000000000000000000000000000000000000000000000000008129fc1c00000000000000000000000000000000000000000000000000000000821644e60000000000000000000000000000000000000000000000000000000084b0196e00000000000000000000000000000000000000000000000000000000715018a6000000000000000000000000000000000000000000000000000000007271bd7a000000000000000000000000000000000000000000000000000000004f1ef2850000000000000000000000000000000000000000000000000000000052d1902c0000000000000000000000000000000000000000000000000000000052d1902d0000000000000000000000000000000000000000000000000000000054d1f13d0000000000000000000000000000000000000000000000000000000065d65e86000000000000000000000000000000000000000000000000000000004f1ef286000000000000000000000000000000000000000000000000000000004fd66eae0000000000000000000000000000000000000000000000000000000036f9566f0000000000000000000000000000000000000000000000000000000036f9567000000000000000000000000000000000000000000000000000000000385aa0d70000000000000000000000000000000000000000000000000000000019d29beb0000000000000000000000000000000000000000000000000000000025692962000000000000000000000000ffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000389a75e10000000000000000000000000000000000000020000000800000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927000000000000000000000000000000000000000000000000000000007448fbae00000000000000000000000000000000000000040000001c000000000000000002000000000000000000000000000000000000200000000c0000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d95539132000000000000000000000000000000000000000000000000000000006f5e88183da8a5f161a6c3ff06a60736d0ed24d7963cc6a5c4fafd2fa1dae9bb908e07a502000000000000000000000000000000000000400000000000000000000000004e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000001000000000000000000ab5ac72b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000200000000000000000000000000000000000020000000000000000000000000324cb0062138d65997c86cd3012489ceb351d602f2f55c7408306e8040c79f3f1806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b83020000020000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000000000000000000000f92ee8a98be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0fa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0200000200000000000000000000000000000044000000000000000000000000360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc0000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000040000001d00000000000000000000000000000000000000000000000000000000000000000000000055299b49bc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b00000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000000000000000000000000000000000009f03a026756688fe000000000000000000000000000000000000000000000000000000002490220cb91f83014ac0d727e13dce8b176302e0fd4bd96c9f4c381942269f0e000000000000000000000000000000000000000000000000ffffffffffffff7f000000000000000000000000000000000000000000000000190100000000000002000000000000000000000000000000000000420000001800000000000000001626ba7e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffff9bffffffffffffffffffffffffffffffffffffff9c0000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000080000000000000000000000000efd5a7f141ae02cd40bc84ffe6ebb58811cb61dfd017746842a005c78bfed8528baa579f00000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d00dbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d0000000000000000000000000000000000000000000000000000000082b42900869fbbabf77b40949a507fa060ce28ba380b0f168fc23838320938f6910926a624e225604268d6416871b32db1be8e49f497caf8360393b31d71a34a4ce2669337ae9e4c00000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0d53de5f6d84c9f92a6ed229cb46a010b85b6d6bc6417f1db910a011322424d62
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.