Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
5775426 | 220 days ago | Contract Creation | 0 ETH |
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 Name:
DisputeGameFactory
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 999999 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import { LibClone } from "@solady/utils/LibClone.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { ISemver } from "src/universal/ISemver.sol"; import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; import { LibGameId } from "src/dispute/lib/LibGameId.sol"; import "src/libraries/DisputeTypes.sol"; import "src/libraries/DisputeErrors.sol"; /// @title DisputeGameFactory /// @notice A factory contract for creating `IDisputeGame` contracts. All created dispute games are stored in both a /// mapping and an append only array. The timestamp of the creation time of the dispute game is packed tightly /// into the storage slot with the address of the dispute game to make offchain discoverability of playable /// dispute games easier. contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver { /// @dev Allows for the creation of clone proxies with immutable arguments. using LibClone for address; /// @notice Semantic version. /// @custom:semver 0.6.0 string public constant version = "0.6.0"; /// @inheritdoc IDisputeGameFactory mapping(GameType => IDisputeGame) public gameImpls; /// @inheritdoc IDisputeGameFactory mapping(GameType => uint256) public initBonds; /// @notice Mapping of a hash of `gameType || rootClaim || extraData` to the deployed `IDisputeGame` clone (where // `||` denotes concatenation). mapping(Hash => GameId) internal _disputeGames; /// @notice An append-only array of disputeGames that have been created. Used by offchain game solvers to /// efficiently track dispute games. GameId[] internal _disputeGameList; /// @notice Constructs a new DisputeGameFactory contract. constructor() OwnableUpgradeable() { initialize(address(0)); } /// @notice Initializes the contract. /// @param _owner The owner of the contract. function initialize(address _owner) public initializer { __Ownable_init(); _transferOwnership(_owner); } /// @inheritdoc IDisputeGameFactory function gameCount() external view returns (uint256 gameCount_) { gameCount_ = _disputeGameList.length; } /// @inheritdoc IDisputeGameFactory function games( GameType _gameType, Claim _rootClaim, bytes calldata _extraData ) external view returns (IDisputeGame proxy_, Timestamp timestamp_) { Hash uuid = getGameUUID(_gameType, _rootClaim, _extraData); (, timestamp_, proxy_) = _disputeGames[uuid].unpack(); } /// @inheritdoc IDisputeGameFactory function gameAtIndex(uint256 _index) external view returns (GameType gameType_, Timestamp timestamp_, IDisputeGame proxy_) { (gameType_, timestamp_, proxy_) = _disputeGameList[_index].unpack(); } /// @inheritdoc IDisputeGameFactory function create( GameType _gameType, Claim _rootClaim, bytes calldata _extraData ) external payable returns (IDisputeGame proxy_) { // Grab the implementation contract for the given `GameType`. IDisputeGame impl = gameImpls[_gameType]; // If there is no implementation to clone for the given `GameType`, revert. if (address(impl) == address(0)) revert NoImplementation(_gameType); // If the required initialization bond is not met, revert. if (msg.value != initBonds[_gameType]) revert IncorrectBondAmount(); // Get the hash of the parent block. bytes32 parentHash = blockhash(block.number - 1); // Clone the implementation contract and initialize it with the given parameters. // // CWIA Calldata Layout: // ┌──────────────┬────────────────────────────────────┐ // │ Bytes │ Description │ // ├──────────────┼────────────────────────────────────┤ // │ [0, 20) │ Game creator address │ // │ [20, 52) │ Root claim │ // │ [52, 84) │ Parent block hash at creation time │ // │ [84, 84 + n) │ Extra data (opaque) │ // └──────────────┴────────────────────────────────────┘ proxy_ = IDisputeGame(address(impl).clone(abi.encodePacked(msg.sender, _rootClaim, parentHash, _extraData))); proxy_.initialize{ value: msg.value }(); // Compute the unique identifier for the dispute game. Hash uuid = getGameUUID(_gameType, _rootClaim, _extraData); // If a dispute game with the same UUID already exists, revert. if (GameId.unwrap(_disputeGames[uuid]) != bytes32(0)) revert GameAlreadyExists(uuid); // Pack the game ID. GameId id = LibGameId.pack(_gameType, Timestamp.wrap(uint64(block.timestamp)), proxy_); // Store the dispute game id in the mapping & emit the `DisputeGameCreated` event. _disputeGames[uuid] = id; _disputeGameList.push(id); emit DisputeGameCreated(address(proxy_), _gameType, _rootClaim); } /// @inheritdoc IDisputeGameFactory function getGameUUID( GameType _gameType, Claim _rootClaim, bytes calldata _extraData ) public pure returns (Hash uuid_) { uuid_ = Hash.wrap(keccak256(abi.encode(_gameType, _rootClaim, _extraData))); } /// @inheritdoc IDisputeGameFactory function findLatestGames( GameType _gameType, uint256 _start, uint256 _n ) external view returns (GameSearchResult[] memory games_) { // If the `_start` index is greater than or equal to the game array length or `_n == 0`, return an empty array. if (_start >= _disputeGameList.length || _n == 0) return games_; // Allocate enough memory for the full array, but start the array's length at `0`. We may not use all of the // memory allocated, but we don't know ahead of time the final size of the array. assembly { games_ := mload(0x40) mstore(0x40, add(games_, add(0x20, shl(0x05, _n)))) } // Perform a reverse linear search for the `_n` most recent games of type `_gameType`. for (uint256 i = _start; i >= 0 && i <= _start;) { GameId id = _disputeGameList[i]; (GameType gameType, Timestamp timestamp, IDisputeGame proxy) = id.unpack(); if (gameType.raw() == _gameType.raw()) { // Increase the size of the `games_` array by 1. // SAFETY: We can safely lazily allocate memory here because we pre-allocated enough memory for the max // possible size of the array. assembly { mstore(games_, add(mload(games_), 0x01)) } bytes memory extraData = proxy.extraData(); Claim rootClaim = proxy.rootClaim(); games_[games_.length - 1] = GameSearchResult({ index: i, metadata: id, timestamp: timestamp, rootClaim: rootClaim, extraData: extraData }); if (games_.length >= _n) break; } unchecked { i--; } } } /// @inheritdoc IDisputeGameFactory function setImplementation(GameType _gameType, IDisputeGame _impl) external onlyOwner { gameImpls[_gameType] = _impl; emit ImplementationSet(address(_impl), _gameType); } /// @inheritdoc IDisputeGameFactory function setInitBond(GameType _gameType, uint256 _initBond) external onlyOwner { initBonds[_gameType] = _initBond; emit InitBondUpdated(_gameType, _initBond); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Minimal proxy library. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol) /// @author Minimal proxy by 0age (https://github.com/0age) /// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie /// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args) /// @author Minimal ERC1967 proxy by jtriley-eth (https://github.com/jtriley-eth/minimum-viable-proxy) /// /// @dev Minimal proxy: /// Although the sw0nt pattern saves 5 gas over the erc-1167 pattern during runtime, /// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern, /// which saves 4 gas over the erc-1167 pattern during runtime, and has the smallest bytecode. /// /// @dev Minimal proxy (PUSH0 variant): /// This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai. /// It is optimized first for minimal runtime gas, then for minimal bytecode. /// The PUSH0 clone functions are intentionally postfixed with a jarring "_PUSH0" as /// many EVM chains may not support the PUSH0 opcode in the early months after Shanghai. /// Please use with caution. /// /// @dev Clones with immutable args (CWIA): /// The implementation of CWIA here implements a `receive()` method that emits the /// `ReceiveETH(uint256)` event. This skips the `DELEGATECALL` when there is no calldata, /// enabling us to accept hard gas-capped `sends` & `transfers` for maximum backwards /// composability. The minimal proxy implementation does not offer this feature. /// /// @dev Minimal ERC1967 proxy: /// An minimal ERC1967 proxy, intended to be upgraded with UUPS. /// This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic. library LibClone { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Unable to deploy the clone. error DeploymentFailed(); /// @dev The salt must start with either the zero address or `by`. error SaltDoesNotStartWith(); /// @dev The ETH transfer has failed. error ETHTransferFailed(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MINIMAL PROXY OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Deploys a clone of `implementation`. function clone(address implementation) internal returns (address instance) { instance = clone(0, implementation); } /// @dev Deploys a clone of `implementation`. function clone(uint256 value, address implementation) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { /** * --------------------------------------------------------------------------+ * CREATION (9 bytes) | * --------------------------------------------------------------------------| * Opcode | Mnemonic | Stack | Memory | * --------------------------------------------------------------------------| * 60 runSize | PUSH1 runSize | r | | * 3d | RETURNDATASIZE | 0 r | | * 81 | DUP2 | r 0 r | | * 60 offset | PUSH1 offset | o r 0 r | | * 3d | RETURNDATASIZE | 0 o r 0 r | | * 39 | CODECOPY | 0 r | [0..runSize): runtime code | * f3 | RETURN | | [0..runSize): runtime code | * --------------------------------------------------------------------------| * RUNTIME (44 bytes) | * --------------------------------------------------------------------------| * Opcode | Mnemonic | Stack | Memory | * --------------------------------------------------------------------------| * | * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: | * 3d | RETURNDATASIZE | 0 | | * 3d | RETURNDATASIZE | 0 0 | | * 3d | RETURNDATASIZE | 0 0 0 | | * 3d | RETURNDATASIZE | 0 0 0 0 | | * | * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: | * 36 | CALLDATASIZE | cds 0 0 0 0 | | * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | | * 3d | RETURNDATASIZE | 0 0 cds 0 0 0 0 | | * 37 | CALLDATACOPY | 0 0 0 0 | [0..cds): calldata | * | * ::: delegate call to the implementation contract :::::::::::::::::::::::: | * 36 | CALLDATASIZE | cds 0 0 0 0 | [0..cds): calldata | * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | [0..cds): calldata | * 73 addr | PUSH20 addr | addr 0 cds 0 0 0 0 | [0..cds): calldata | * 5a | GAS | gas addr 0 cds 0 0 0 0 | [0..cds): calldata | * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata | * | * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: | * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata | * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata | * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata | * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata | * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata | * | * 60 0x2a | PUSH1 0x2a | 0x2a success 0 rds | [0..rds): returndata | * 57 | JUMPI | 0 rds | [0..rds): returndata | * | * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * fd | REVERT | | [0..rds): returndata | * | * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 5b | JUMPDEST | 0 rds | [0..rds): returndata | * f3 | RETURN | | [0..rds): returndata | * --------------------------------------------------------------------------+ */ mstore(0x21, 0x5af43d3d93803e602a57fd5bf3) mstore(0x14, implementation) mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73) instance := create(value, 0x0c, 0x35) if iszero(instance) { mstore(0x00, 0x30116425) // `DeploymentFailed()`. revert(0x1c, 0x04) } mstore(0x21, 0) // Restore the overwritten part of the free memory pointer. } } /// @dev Deploys a deterministic clone of `implementation` with `salt`. function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) { instance = cloneDeterministic(0, implementation, salt); } /// @dev Deploys a deterministic clone of `implementation` with `salt`. function cloneDeterministic(uint256 value, address implementation, bytes32 salt) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { mstore(0x21, 0x5af43d3d93803e602a57fd5bf3) mstore(0x14, implementation) mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73) instance := create2(value, 0x0c, 0x35, salt) if iszero(instance) { mstore(0x00, 0x30116425) // `DeploymentFailed()`. revert(0x1c, 0x04) } mstore(0x21, 0) // Restore the overwritten part of the free memory pointer. } } /// @dev Returns the initialization code hash of the clone of `implementation`. /// Used for mining vanity addresses with create2crunch. function initCodeHash(address implementation) internal pure returns (bytes32 hash) { /// @solidity memory-safe-assembly assembly { mstore(0x21, 0x5af43d3d93803e602a57fd5bf3) mstore(0x14, implementation) mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73) hash := keccak256(0x0c, 0x35) mstore(0x21, 0) // Restore the overwritten part of the free memory pointer. } } /// @dev Returns the address of the deterministic clone of `implementation`, /// with `salt` by `deployer`. /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. function predictDeterministicAddress(address implementation, bytes32 salt, address deployer) internal pure returns (address predicted) { bytes32 hash = initCodeHash(implementation); predicted = predictDeterministicAddress(hash, salt, deployer); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MINIMAL PROXY OPERATIONS (PUSH0 VARIANT) */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Deploys a PUSH0 clone of `implementation`. function clone_PUSH0(address implementation) internal returns (address instance) { instance = clone_PUSH0(0, implementation); } /// @dev Deploys a PUSH0 clone of `implementation`. function clone_PUSH0(uint256 value, address implementation) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { /** * --------------------------------------------------------------------------+ * CREATION (9 bytes) | * --------------------------------------------------------------------------| * Opcode | Mnemonic | Stack | Memory | * --------------------------------------------------------------------------| * 60 runSize | PUSH1 runSize | r | | * 5f | PUSH0 | 0 r | | * 81 | DUP2 | r 0 r | | * 60 offset | PUSH1 offset | o r 0 r | | * 5f | PUSH0 | 0 o r 0 r | | * 39 | CODECOPY | 0 r | [0..runSize): runtime code | * f3 | RETURN | | [0..runSize): runtime code | * --------------------------------------------------------------------------| * RUNTIME (45 bytes) | * --------------------------------------------------------------------------| * Opcode | Mnemonic | Stack | Memory | * --------------------------------------------------------------------------| * | * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: | * 5f | PUSH0 | 0 | | * 5f | PUSH0 | 0 0 | | * | * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: | * 36 | CALLDATASIZE | cds 0 0 | | * 5f | PUSH0 | 0 cds 0 0 | | * 5f | PUSH0 | 0 0 cds 0 0 | | * 37 | CALLDATACOPY | 0 0 | [0..cds): calldata | * | * ::: delegate call to the implementation contract :::::::::::::::::::::::: | * 36 | CALLDATASIZE | cds 0 0 | [0..cds): calldata | * 5f | PUSH0 | 0 cds 0 0 | [0..cds): calldata | * 73 addr | PUSH20 addr | addr 0 cds 0 0 | [0..cds): calldata | * 5a | GAS | gas addr 0 cds 0 0 | [0..cds): calldata | * f4 | DELEGATECALL | success | [0..cds): calldata | * | * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: | * 3d | RETURNDATASIZE | rds success | [0..cds): calldata | * 5f | PUSH0 | 0 rds success | [0..cds): calldata | * 5f | PUSH0 | 0 0 rds success | [0..cds): calldata | * 3e | RETURNDATACOPY | success | [0..rds): returndata | * | * 60 0x29 | PUSH1 0x29 | 0x29 success | [0..rds): returndata | * 57 | JUMPI | | [0..rds): returndata | * | * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 3d | RETURNDATASIZE | rds | [0..rds): returndata | * 5f | PUSH0 | 0 rds | [0..rds): returndata | * fd | REVERT | | [0..rds): returndata | * | * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 5b | JUMPDEST | | [0..rds): returndata | * 3d | RETURNDATASIZE | rds | [0..rds): returndata | * 5f | PUSH0 | 0 rds | [0..rds): returndata | * f3 | RETURN | | [0..rds): returndata | * --------------------------------------------------------------------------+ */ mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16 mstore(0x14, implementation) // 20 mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9 instance := create(value, 0x0e, 0x36) if iszero(instance) { mstore(0x00, 0x30116425) // `DeploymentFailed()`. revert(0x1c, 0x04) } mstore(0x24, 0) // Restore the overwritten part of the free memory pointer. } } /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`. function cloneDeterministic_PUSH0(address implementation, bytes32 salt) internal returns (address instance) { instance = cloneDeterministic_PUSH0(0, implementation, salt); } /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`. function cloneDeterministic_PUSH0(uint256 value, address implementation, bytes32 salt) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16 mstore(0x14, implementation) // 20 mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9 instance := create2(value, 0x0e, 0x36, salt) if iszero(instance) { mstore(0x00, 0x30116425) // `DeploymentFailed()`. revert(0x1c, 0x04) } mstore(0x24, 0) // Restore the overwritten part of the free memory pointer. } } /// @dev Returns the initialization code hash of the PUSH0 clone of `implementation`. /// Used for mining vanity addresses with create2crunch. function initCodeHash_PUSH0(address implementation) internal pure returns (bytes32 hash) { /// @solidity memory-safe-assembly assembly { mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16 mstore(0x14, implementation) // 20 mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9 hash := keccak256(0x0e, 0x36) mstore(0x24, 0) // Restore the overwritten part of the free memory pointer. } } /// @dev Returns the address of the deterministic PUSH0 clone of `implementation`, /// with `salt` by `deployer`. /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. function predictDeterministicAddress_PUSH0( address implementation, bytes32 salt, address deployer ) internal pure returns (address predicted) { bytes32 hash = initCodeHash_PUSH0(implementation); predicted = predictDeterministicAddress(hash, salt, deployer); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CLONES WITH IMMUTABLE ARGS OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // Note: This implementation of CWIA differs from the original implementation. // If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`. /// @dev Deploys a clone of `implementation` with immutable arguments encoded in `data`. function clone(address implementation, bytes memory data) internal returns (address instance) { instance = clone(0, implementation, data); } /// @dev Deploys a clone of `implementation` with immutable arguments encoded in `data`. function clone(uint256 value, address implementation, bytes memory data) internal returns (address instance) { assembly { // Compute the boundaries of the data and cache the memory slots around it. let mBefore3 := mload(sub(data, 0x60)) let mBefore2 := mload(sub(data, 0x40)) let mBefore1 := mload(sub(data, 0x20)) let dataLength := mload(data) let dataEnd := add(add(data, 0x20), dataLength) let mAfter1 := mload(dataEnd) // +2 bytes for telling how much data there is appended to the call. let extraLength := add(dataLength, 2) // The `creationSize` is `extraLength + 108` // The `runSize` is `creationSize - 10`. /** * ---------------------------------------------------------------------------------------------------+ * CREATION (10 bytes) | * ---------------------------------------------------------------------------------------------------| * Opcode | Mnemonic | Stack | Memory | * ---------------------------------------------------------------------------------------------------| * 61 runSize | PUSH2 runSize | r | | * 3d | RETURNDATASIZE | 0 r | | * 81 | DUP2 | r 0 r | | * 60 offset | PUSH1 offset | o r 0 r | | * 3d | RETURNDATASIZE | 0 o r 0 r | | * 39 | CODECOPY | 0 r | [0..runSize): runtime code | * f3 | RETURN | | [0..runSize): runtime code | * ---------------------------------------------------------------------------------------------------| * RUNTIME (98 bytes + extraLength) | * ---------------------------------------------------------------------------------------------------| * Opcode | Mnemonic | Stack | Memory | * ---------------------------------------------------------------------------------------------------| * | * ::: if no calldata, emit event & return w/o `DELEGATECALL` ::::::::::::::::::::::::::::::::::::::: | * 36 | CALLDATASIZE | cds | | * 60 0x2c | PUSH1 0x2c | 0x2c cds | | * 57 | JUMPI | | | * 34 | CALLVALUE | cv | | * 3d | RETURNDATASIZE | 0 cv | | * 52 | MSTORE | | [0..0x20): callvalue | * 7f sig | PUSH32 0x9e.. | sig | [0..0x20): callvalue | * 59 | MSIZE | 0x20 sig | [0..0x20): callvalue | * 3d | RETURNDATASIZE | 0 0x20 sig | [0..0x20): callvalue | * a1 | LOG1 | | [0..0x20): callvalue | * 00 | STOP | | [0..0x20): callvalue | * 5b | JUMPDEST | | | * | * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 36 | CALLDATASIZE | cds | | * 3d | RETURNDATASIZE | 0 cds | | * 3d | RETURNDATASIZE | 0 0 cds | | * 37 | CALLDATACOPY | | [0..cds): calldata | * | * ::: keep some values in stack :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 3d | RETURNDATASIZE | 0 | [0..cds): calldata | * 3d | RETURNDATASIZE | 0 0 | [0..cds): calldata | * 3d | RETURNDATASIZE | 0 0 0 | [0..cds): calldata | * 3d | RETURNDATASIZE | 0 0 0 0 | [0..cds): calldata | * 61 extra | PUSH2 extra | e 0 0 0 0 | [0..cds): calldata | * | * ::: copy extra data to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 80 | DUP1 | e e 0 0 0 0 | [0..cds): calldata | * 60 0x62 | PUSH1 0x62 | 0x62 e e 0 0 0 0 | [0..cds): calldata | * 36 | CALLDATASIZE | cds 0x62 e e 0 0 0 0 | [0..cds): calldata | * 39 | CODECOPY | e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * | * ::: delegate call to the implementation contract ::::::::::::::::::::::::::::::::::::::::::::::::: | * 36 | CALLDATASIZE | cds e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 01 | ADD | cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 3d | RETURNDATASIZE | 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 73 addr | PUSH20 addr | addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 5a | GAS | gas addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * | * ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData | * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData | * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata | * | * 60 0x60 | PUSH1 0x60 | 0x60 success 0 rds | [0..rds): returndata | * 57 | JUMPI | 0 rds | [0..rds): returndata | * | * ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * fd | REVERT | | [0..rds): returndata | * | * ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 5b | JUMPDEST | 0 rds | [0..rds): returndata | * f3 | RETURN | | [0..rds): returndata | * ---------------------------------------------------------------------------------------------------+ */ mstore(data, 0x5af43d3d93803e606057fd5bf3) // Write the bytecode before the data. mstore(sub(data, 0x0d), implementation) // Write the address of the implementation. // Write the rest of the bytecode. mstore( sub(data, 0x21), or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73) ) // `keccak256("ReceiveETH(uint256)")` mstore( sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff ) mstore( // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e. // The actual EVM limit may be smaller and may change over time. sub(data, add(0x59, lt(extraLength, 0xff9e))), or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f) ) mstore(dataEnd, shl(0xf0, extraLength)) instance := create(value, sub(data, 0x4c), add(extraLength, 0x6c)) if iszero(instance) { mstore(0x00, 0x30116425) // `DeploymentFailed()`. revert(0x1c, 0x04) } // Restore the overwritten memory surrounding `data`. mstore(dataEnd, mAfter1) mstore(data, dataLength) mstore(sub(data, 0x20), mBefore1) mstore(sub(data, 0x40), mBefore2) mstore(sub(data, 0x60), mBefore3) } } /// @dev Deploys a deterministic clone of `implementation` /// with immutable arguments encoded in `data` and `salt`. function cloneDeterministic(address implementation, bytes memory data, bytes32 salt) internal returns (address instance) { instance = cloneDeterministic(0, implementation, data, salt); } /// @dev Deploys a deterministic clone of `implementation` /// with immutable arguments encoded in `data` and `salt`. function cloneDeterministic( uint256 value, address implementation, bytes memory data, bytes32 salt ) internal returns (address instance) { assembly { // Compute the boundaries of the data and cache the memory slots around it. let mBefore3 := mload(sub(data, 0x60)) let mBefore2 := mload(sub(data, 0x40)) let mBefore1 := mload(sub(data, 0x20)) let dataLength := mload(data) let dataEnd := add(add(data, 0x20), dataLength) let mAfter1 := mload(dataEnd) // +2 bytes for telling how much data there is appended to the call. let extraLength := add(dataLength, 2) mstore(data, 0x5af43d3d93803e606057fd5bf3) // Write the bytecode before the data. mstore(sub(data, 0x0d), implementation) // Write the address of the implementation. // Write the rest of the bytecode. mstore( sub(data, 0x21), or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73) ) // `keccak256("ReceiveETH(uint256)")` mstore( sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff ) mstore( // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e. // The actual EVM limit may be smaller and may change over time. sub(data, add(0x59, lt(extraLength, 0xff9e))), or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f) ) mstore(dataEnd, shl(0xf0, extraLength)) instance := create2(value, sub(data, 0x4c), add(extraLength, 0x6c), salt) if iszero(instance) { mstore(0x00, 0x30116425) // `DeploymentFailed()`. revert(0x1c, 0x04) } // Restore the overwritten memory surrounding `data`. mstore(dataEnd, mAfter1) mstore(data, dataLength) mstore(sub(data, 0x20), mBefore1) mstore(sub(data, 0x40), mBefore2) mstore(sub(data, 0x60), mBefore3) } } /// @dev Returns the initialization code hash of the clone of `implementation` /// using immutable arguments encoded in `data`. /// Used for mining vanity addresses with create2crunch. function initCodeHash(address implementation, bytes memory data) internal pure returns (bytes32 hash) { assembly { // Compute the boundaries of the data and cache the memory slots around it. let mBefore3 := mload(sub(data, 0x60)) let mBefore2 := mload(sub(data, 0x40)) let mBefore1 := mload(sub(data, 0x20)) let dataLength := mload(data) let dataEnd := add(add(data, 0x20), dataLength) let mAfter1 := mload(dataEnd) // Do a out-of-gas revert if `dataLength` is too big. 0xffff - 0x02 - 0x62 = 0xff9b. // The actual EVM limit may be smaller and may change over time. returndatacopy(returndatasize(), returndatasize(), gt(dataLength, 0xff9b)) // +2 bytes for telling how much data there is appended to the call. let extraLength := add(dataLength, 2) mstore(data, 0x5af43d3d93803e606057fd5bf3) // Write the bytecode before the data. mstore(sub(data, 0x0d), implementation) // Write the address of the implementation. // Write the rest of the bytecode. mstore( sub(data, 0x21), or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73) ) // `keccak256("ReceiveETH(uint256)")` mstore( sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff ) mstore( sub(data, 0x5a), or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f) ) mstore(dataEnd, shl(0xf0, extraLength)) hash := keccak256(sub(data, 0x4c), add(extraLength, 0x6c)) // Restore the overwritten memory surrounding `data`. mstore(dataEnd, mAfter1) mstore(data, dataLength) mstore(sub(data, 0x20), mBefore1) mstore(sub(data, 0x40), mBefore2) mstore(sub(data, 0x60), mBefore3) } } /// @dev Returns the address of the deterministic clone of /// `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`. /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. function predictDeterministicAddress( address implementation, bytes memory data, bytes32 salt, address deployer ) internal pure returns (address predicted) { bytes32 hash = initCodeHash(implementation, data); predicted = predictDeterministicAddress(hash, salt, deployer); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MINIMAL ERC1967 PROXY OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // Note: The ERC1967 proxy here is intended to be upgraded with UUPS. // This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic. /// @dev Deploys a minimal ERC1967 proxy with `implementation`. function deployERC1967(address implementation) internal returns (address instance) { instance = deployERC1967(0, implementation); } /// @dev Deploys a minimal ERC1967 proxy with `implementation`. function deployERC1967(uint256 value, address implementation) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { /** * ---------------------------------------------------------------------------------+ * CREATION (34 bytes) | * ---------------------------------------------------------------------------------| * Opcode | Mnemonic | Stack | Memory | * ---------------------------------------------------------------------------------| * 60 runSize | PUSH1 runSize | r | | * 3d | RETURNDATASIZE | 0 r | | * 81 | DUP2 | r 0 r | | * 60 offset | PUSH1 offset | o r 0 r | | * 3d | RETURNDATASIZE | 0 o r 0 r | | * 39 | CODECOPY | 0 r | [0..runSize): runtime code | * 73 impl | PUSH20 impl | impl 0 r | [0..runSize): runtime code | * 60 slotPos | PUSH1 slotPos | slotPos impl 0 r | [0..runSize): runtime code | * 51 | MLOAD | slot impl 0 r | [0..runSize): runtime code | * 55 | SSTORE | 0 r | [0..runSize): runtime code | * f3 | RETURN | | [0..runSize): runtime code | * ---------------------------------------------------------------------------------| * RUNTIME (62 bytes) | * ---------------------------------------------------------------------------------| * Opcode | Mnemonic | Stack | Memory | * ---------------------------------------------------------------------------------| * | * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: | * 36 | CALLDATASIZE | cds | | * 3d | RETURNDATASIZE | 0 cds | | * 3d | RETURNDATASIZE | 0 0 cds | | * 37 | CALLDATACOPY | | [0..calldatasize): calldata | * | * ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: | * 3d | RETURNDATASIZE | 0 | | * 3d | RETURNDATASIZE | 0 0 | | * 36 | CALLDATASIZE | cds 0 0 | [0..calldatasize): calldata | * 3d | RETURNDATASIZE | 0 cds 0 0 | [0..calldatasize): calldata | * 7f slot | PUSH32 slot | s 0 cds 0 0 | [0..calldatasize): calldata | * 54 | SLOAD | i 0 cds 0 0 | [0..calldatasize): calldata | * 5a | GAS | g i 0 cds 0 0 | [0..calldatasize): calldata | * f4 | DELEGATECALL | succ | [0..calldatasize): calldata | * | * ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: | * 3d | RETURNDATASIZE | rds succ | [0..calldatasize): calldata | * 60 0x00 | PUSH1 0x00 | 0 rds succ | [0..calldatasize): calldata | * 80 | DUP1 | 0 0 rds succ | [0..calldatasize): calldata | * 3e | RETURNDATACOPY | succ | [0..returndatasize): returndata | * | * ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: | * 60 0x38 | PUSH1 0x38 | dest succ | [0..returndatasize): returndata | * 57 | JUMPI | | [0..returndatasize): returndata | * | * ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: | * 3d | RETURNDATASIZE | rds | [0..returndatasize): returndata | * 60 0x00 | PUSH1 0x00 | 0 rds | [0..returndatasize): returndata | * fd | REVERT | | [0..returndatasize): returndata | * | * ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: | * 5b | JUMPDEST | | [0..returndatasize): returndata | * 3d | RETURNDATASIZE | rds | [0..returndatasize): returndata | * 60 0x00 | PUSH1 0x00 | 0 rds | [0..returndatasize): returndata | * f3 | RETURN | | [0..returndatasize): returndata | * ---------------------------------------------------------------------------------+ */ let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3) mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076) mstore(0x20, 0x6009) mstore(0x1e, implementation) mstore(0x0a, 0x603d3d8160223d3973) instance := create(value, 0x21, 0x5f) if iszero(instance) { mstore(0x00, 0x30116425) // `DeploymentFailed()`. revert(0x1c, 0x04) } mstore(0x40, m) // Restore the free memory pointer. mstore(0x60, 0) // Restore the zero slot. } } /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`. function deployDeterministicERC1967(address implementation, bytes32 salt) internal returns (address instance) { instance = deployDeterministicERC1967(0, implementation, salt); } /// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`. function deployDeterministicERC1967(uint256 value, address implementation, bytes32 salt) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3) mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076) mstore(0x20, 0x6009) mstore(0x1e, implementation) mstore(0x0a, 0x603d3d8160223d3973) instance := create2(value, 0x21, 0x5f, salt) if iszero(instance) { mstore(0x00, 0x30116425) // `DeploymentFailed()`. revert(0x1c, 0x04) } mstore(0x40, m) // Restore the free memory pointer. mstore(0x60, 0) // Restore the zero slot. } } /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`. /// Note: This method is intended for use in ERC4337 factories, /// which are expected to NOT revert if the proxy is already deployed. function createDeterministicERC1967(address implementation, bytes32 salt) internal returns (bool alreadyDeployed, address instance) { return createDeterministicERC1967(0, implementation, salt); } /// @dev Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`. /// Note: This method is intended for use in ERC4337 factories, /// which are expected to NOT revert if the proxy is already deployed. function createDeterministicERC1967(uint256 value, address implementation, bytes32 salt) internal returns (bool alreadyDeployed, address instance) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3) mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076) mstore(0x20, 0x6009) mstore(0x1e, implementation) mstore(0x0a, 0x603d3d8160223d3973) // Compute and store the bytecode hash. mstore(add(m, 0x35), keccak256(0x21, 0x5f)) mstore(m, shl(88, address())) mstore8(m, 0xff) // Write the prefix. mstore(add(m, 0x15), salt) instance := keccak256(m, 0x55) for {} 1 {} { if iszero(extcodesize(instance)) { instance := create2(value, 0x21, 0x5f, salt) if iszero(instance) { mstore(0x00, 0x30116425) // `DeploymentFailed()`. revert(0x1c, 0x04) } break } alreadyDeployed := 1 if iszero(value) { break } if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } break } mstore(0x40, m) // Restore the free memory pointer. mstore(0x60, 0) // Restore the zero slot. } } /// @dev Returns the initialization code hash of the clone of `implementation` /// using immutable arguments encoded in `data`. /// Used for mining vanity addresses with create2crunch. function initCodeHashERC1967(address implementation) internal pure returns (bytes32 hash) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3) mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076) mstore(0x20, 0x6009) mstore(0x1e, implementation) mstore(0x0a, 0x603d3d8160223d3973) hash := keccak256(0x21, 0x5f) mstore(0x40, m) // Restore the free memory pointer. mstore(0x60, 0) // Restore the zero slot. } } /// @dev Returns the address of the deterministic clone of /// `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`. /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. function predictDeterministicAddressERC1967( address implementation, bytes32 salt, address deployer ) internal pure returns (address predicted) { bytes32 hash = initCodeHashERC1967(implementation); predicted = predictDeterministicAddress(hash, salt, deployer); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* OTHER OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the address when a contract with initialization code hash, /// `hash`, is deployed with `salt`, by `deployer`. /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer) internal pure returns (address predicted) { /// @solidity memory-safe-assembly assembly { // Compute and store the bytecode hash. mstore8(0x00, 0xff) // Write the prefix. mstore(0x35, hash) mstore(0x01, shl(96, deployer)) mstore(0x15, salt) predicted := keccak256(0x00, 0x55) mstore(0x35, 0) // Restore the overwritten part of the free memory pointer. } } /// @dev Requires that `salt` starts with either the zero address or `by`. function checkStartsWith(bytes32 salt, address by) internal pure { /// @solidity memory-safe-assembly assembly { // If the salt does not start with the zero address or `by`. if iszero(or(iszero(shr(96, salt)), eq(shr(96, shl(96, by)), shr(96, salt)))) { mstore(0x00, 0x0c4549ef) // `SaltDoesNotStartWith()`. revert(0x1c, 0x04) } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title ISemver /// @notice ISemver is a simple contract for ensuring that contracts are /// versioned using semantic versioning. interface ISemver { /// @notice Getter for the semantic version of the contract. This is not /// meant to be used onchain but instead meant to be used by offchain /// tooling. /// @return Semver contract version as a string. function version() external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IInitializable } from "src/dispute/interfaces/IInitializable.sol"; import "src/libraries/DisputeTypes.sol"; /// @title IDisputeGame /// @notice The generic interface for a DisputeGame contract. interface IDisputeGame is IInitializable { /// @notice Emitted when the game is resolved. /// @param status The status of the game after resolution. event Resolved(GameStatus indexed status); /// @notice Returns the timestamp that the DisputeGame contract was created at. /// @return createdAt_ The timestamp that the DisputeGame contract was created at. function createdAt() external view returns (Timestamp createdAt_); /// @notice Returns the timestamp that the DisputeGame contract was resolved at. /// @return resolvedAt_ The timestamp that the DisputeGame contract was resolved at. function resolvedAt() external view returns (Timestamp resolvedAt_); /// @notice Returns the current status of the game. /// @return status_ The current status of the game. function status() external view returns (GameStatus status_); /// @notice Getter for the game type. /// @dev The reference impl should be entirely different depending on the type (fault, validity) /// i.e. The game type should indicate the security model. /// @return gameType_ The type of proof system being used. function gameType() external view returns (GameType gameType_); /// @notice Getter for the creator of the dispute game. /// @dev `clones-with-immutable-args` argument #1 /// @return creator_ The creator of the dispute game. function gameCreator() external pure returns (address creator_); /// @notice Getter for the root claim. /// @dev `clones-with-immutable-args` argument #2 /// @return rootClaim_ The root claim of the DisputeGame. function rootClaim() external pure returns (Claim rootClaim_); /// @notice Getter for the parent hash of the L1 block when the dispute game was created. /// @dev `clones-with-immutable-args` argument #3 /// @return l1Head_ The parent hash of the L1 block when the dispute game was created. function l1Head() external pure returns (Hash l1Head_); /// @notice Getter for the extra data. /// @dev `clones-with-immutable-args` argument #4 /// @return extraData_ Any extra data supplied to the dispute game contract by the creator. function extraData() external pure returns (bytes memory extraData_); /// @notice If all necessary information has been gathered, this function should mark the game /// status as either `CHALLENGER_WINS` or `DEFENDER_WINS` and return the status of /// the resolved game. It is at this stage that the bonds should be awarded to the /// necessary parties. /// @dev May only be called if the `status` is `IN_PROGRESS`. /// @return status_ The status of the game after resolution. function resolve() external returns (GameStatus status_); /// @notice A compliant implementation of this interface should return the components of the /// game UUID's preimage provided in the cwia payload. The preimage of the UUID is /// constructed as `keccak256(gameType . rootClaim . extraData)` where `.` denotes /// concatenation. /// @return gameType_ The type of proof system being used. /// @return rootClaim_ The root claim of the DisputeGame. /// @return extraData_ Any extra data supplied to the dispute game contract by the creator. function gameData() external view returns (GameType gameType_, Claim rootClaim_, bytes memory extraData_); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IDisputeGame } from "./IDisputeGame.sol"; import "src/libraries/DisputeTypes.sol"; /// @title IDisputeGameFactory /// @notice The interface for a DisputeGameFactory contract. interface IDisputeGameFactory { /// @notice Emitted when a new dispute game is created /// @param disputeProxy The address of the dispute game proxy /// @param gameType The type of the dispute game proxy's implementation /// @param rootClaim The root claim of the dispute game event DisputeGameCreated(address indexed disputeProxy, GameType indexed gameType, Claim indexed rootClaim); /// @notice Emitted when a new game implementation added to the factory /// @param impl The implementation contract for the given `GameType`. /// @param gameType The type of the DisputeGame. event ImplementationSet(address indexed impl, GameType indexed gameType); /// @notice Emitted when a game type's initialization bond is updated /// @param gameType The type of the DisputeGame. /// @param newBond The new bond (in wei) for initializing the game type. event InitBondUpdated(GameType indexed gameType, uint256 indexed newBond); /// @notice Information about a dispute game found in a `findLatestGames` search. struct GameSearchResult { uint256 index; GameId metadata; Timestamp timestamp; Claim rootClaim; bytes extraData; } /// @notice The total number of dispute games created by this factory. /// @return gameCount_ The total number of dispute games created by this factory. function gameCount() external view returns (uint256 gameCount_); /// @notice `games` queries an internal mapping that maps the hash of /// `gameType ++ rootClaim ++ extraData` to the deployed `DisputeGame` clone. /// @dev `++` equates to concatenation. /// @param _gameType The type of the DisputeGame - used to decide the proxy implementation /// @param _rootClaim The root claim of the DisputeGame. /// @param _extraData Any extra data that should be provided to the created dispute game. /// @return proxy_ The clone of the `DisputeGame` created with the given parameters. /// Returns `address(0)` if nonexistent. /// @return timestamp_ The timestamp of the creation of the dispute game. function games( GameType _gameType, Claim _rootClaim, bytes calldata _extraData ) external view returns (IDisputeGame proxy_, Timestamp timestamp_); /// @notice `gameAtIndex` returns the dispute game contract address and its creation timestamp /// at the given index. Each created dispute game increments the underlying index. /// @param _index The index of the dispute game. /// @return gameType_ The type of the DisputeGame - used to decide the proxy implementation. /// @return timestamp_ The timestamp of the creation of the dispute game. /// @return proxy_ The clone of the `DisputeGame` created with the given parameters. /// Returns `address(0)` if nonexistent. function gameAtIndex(uint256 _index) external view returns (GameType gameType_, Timestamp timestamp_, IDisputeGame proxy_); /// @notice `gameImpls` is a mapping that maps `GameType`s to their respective /// `IDisputeGame` implementations. /// @param _gameType The type of the dispute game. /// @return impl_ The address of the implementation of the game type. /// Will be cloned on creation of a new dispute game with the given `gameType`. function gameImpls(GameType _gameType) external view returns (IDisputeGame impl_); /// @notice Returns the required bonds for initializing a dispute game of the given type. /// @param _gameType The type of the dispute game. /// @return bond_ The required bond for initializing a dispute game of the given type. function initBonds(GameType _gameType) external view returns (uint256 bond_); /// @notice Creates a new DisputeGame proxy contract. /// @param _gameType The type of the DisputeGame - used to decide the proxy implementation. /// @param _rootClaim The root claim of the DisputeGame. /// @param _extraData Any extra data that should be provided to the created dispute game. /// @return proxy_ The address of the created DisputeGame proxy. function create( GameType _gameType, Claim _rootClaim, bytes calldata _extraData ) external payable returns (IDisputeGame proxy_); /// @notice Sets the implementation contract for a specific `GameType`. /// @dev May only be called by the `owner`. /// @param _gameType The type of the DisputeGame. /// @param _impl The implementation contract for the given `GameType`. function setImplementation(GameType _gameType, IDisputeGame _impl) external; /// @notice Sets the bond (in wei) for initializing a game type. /// @dev May only be called by the `owner`. /// @param _gameType The type of the DisputeGame. /// @param _initBond The bond (in wei) for initializing a game type. function setInitBond(GameType _gameType, uint256 _initBond) external; /// @notice Returns a unique identifier for the given dispute game parameters. /// @dev Hashes the concatenation of `gameType . rootClaim . extraData` /// without expanding memory. /// @param _gameType The type of the DisputeGame. /// @param _rootClaim The root claim of the DisputeGame. /// @param _extraData Any extra data that should be provided to the created dispute game. /// @return uuid_ The unique identifier for the given dispute game parameters. function getGameUUID( GameType _gameType, Claim _rootClaim, bytes memory _extraData ) external pure returns (Hash uuid_); /// @notice Finds the `_n` most recent `GameId`'s of type `_gameType` starting at `_start`. If there are less than /// `_n` games of type `_gameType` starting at `_start`, then the returned array will be shorter than `_n`. /// @param _gameType The type of game to find. /// @param _start The index to start the reverse search from. /// @param _n The number of games to find. function findLatestGames( GameType _gameType, uint256 _start, uint256 _n ) external view returns (GameSearchResult[] memory games_); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; import "src/libraries/DisputeTypes.sol"; import "src/dispute/interfaces/IDisputeGame.sol"; /// @title LibGameId /// @notice Utility functions for packing and unpacking GameIds. library LibGameId { /// @notice Packs values into a 32 byte GameId type. /// @param _gameType The game type. /// @param _timestamp The timestamp of the game's creation. /// @param _gameProxy The game proxy address. /// @return gameId_ The packed GameId. function pack( GameType _gameType, Timestamp _timestamp, IDisputeGame _gameProxy ) internal pure returns (GameId gameId_) { assembly { gameId_ := or(or(shl(224, _gameType), shl(160, _timestamp)), _gameProxy) } } /// @notice Unpacks values from a 32 byte GameId type. /// @param _gameId The packed GameId. /// @return gameType_ The game type. /// @return timestamp_ The timestamp of the game's creation. /// @return gameProxy_ The game proxy address. function unpack(GameId _gameId) internal pure returns (GameType gameType_, Timestamp timestamp_, IDisputeGame gameProxy_) { assembly { gameType_ := shr(224, _gameId) timestamp_ := and(shr(160, _gameId), 0xFFFFFFFFFFFFFFFF) gameProxy_ := and(_gameId, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; import { LibHashing } from "src/dispute/lib/LibHashing.sol"; import { LibClaim, LibHash, LibDuration, LibClock, LibTimestamp, LibVMStatus, LibGameType } from "src/dispute/lib/LibUDT.sol"; import { LibPosition } from "src/dispute/lib/LibPosition.sol"; import { LibGameId } from "src/dispute/lib/LibGameId.sol"; using LibClaim for Claim global; using LibHashing for Claim global; using LibHash for Hash global; using LibPosition for Position global; using LibDuration for Duration global; using LibClock for Clock global; using LibGameId for GameId global; using LibTimestamp for Timestamp global; using LibVMStatus for VMStatus global; using LibGameType for GameType global; /// @notice A custom type for a generic hash. type Hash is bytes32; /// @notice A claim represents an MPT root representing the state of the fault proof program. type Claim is bytes32; /// @notice A claim hash represents a hash of a claim and a position within the game tree. /// @dev Keccak hash of abi.encodePacked(Claim, Position); type ClaimHash is bytes32; /// @notice A bondamount represents the amount of collateral that a user has locked up in a claim. type BondAmount is uint256; /// @notice A dedicated timestamp type. type Timestamp is uint64; /// @notice A dedicated duration type. /// @dev Unit: seconds type Duration is uint64; /// @notice A `GameId` represents a packed 4 byte game ID, a 8 byte timestamp, and a 20 byte address. /// @dev The packed layout of this type is as follows: /// ┌───────────┬───────────┐ /// │ Bits │ Value │ /// ├───────────┼───────────┤ /// │ [0, 32) │ Game Type │ /// │ [32, 96) │ Timestamp │ /// │ [96, 256) │ Address │ /// └───────────┴───────────┘ type GameId is bytes32; /// @notice A `Clock` represents a packed `Duration` and `Timestamp` /// @dev The packed layout of this type is as follows: /// ┌────────────┬────────────────┐ /// │ Bits │ Value │ /// ├────────────┼────────────────┤ /// │ [0, 64) │ Duration │ /// │ [64, 128) │ Timestamp │ /// └────────────┴────────────────┘ type Clock is uint128; /// @notice A `Position` represents a position of a claim within the game tree. /// @dev This is represented as a "generalized index" where the high-order bit /// is the level in the tree and the remaining bits is a unique bit pattern, allowing /// a unique identifier for each node in the tree. Mathematically, it is calculated /// as 2^{depth} + indexAtDepth. type Position is uint128; /// @notice A `GameType` represents the type of game being played. type GameType is uint32; /// @notice A `VMStatus` represents the status of a VM execution. type VMStatus is uint8; /// @notice The current status of the dispute game. enum GameStatus { // The game is currently in progress, and has not been resolved. IN_PROGRESS, // The game has concluded, and the `rootClaim` was challenged successfully. CHALLENGER_WINS, // The game has concluded, and the `rootClaim` could not be contested. DEFENDER_WINS } /// @notice Represents an L2 output root and the L2 block number at which it was generated. /// @custom:field root The output root. /// @custom:field l2BlockNumber The L2 block number at which the output root was generated. struct OutputRoot { Hash root; uint256 l2BlockNumber; } /// @title GameTypes /// @notice A library that defines the IDs of games that can be played. library GameTypes { /// @dev A dispute game type the uses the cannon vm. GameType internal constant CANNON = GameType.wrap(0); /// @dev A permissioned dispute game type the uses the cannon vm. GameType internal constant PERMISSIONED_CANNON = GameType.wrap(1); /// @notice A dispute game type the uses the asterisc VM GameType internal constant ASTERISC = GameType.wrap(2); /// @notice A dispute game type that uses an alphabet vm. /// Not intended for production use. GameType internal constant ALPHABET = GameType.wrap(255); } /// @title VMStatuses /// @notice Named type aliases for the various valid VM status bytes. library VMStatuses { /// @notice The VM has executed successfully and the outcome is valid. VMStatus internal constant VALID = VMStatus.wrap(0); /// @notice The VM has executed successfully and the outcome is invalid. VMStatus internal constant INVALID = VMStatus.wrap(1); /// @notice The VM has paniced. VMStatus internal constant PANIC = VMStatus.wrap(2); /// @notice The VM execution is still in progress. VMStatus internal constant UNFINISHED = VMStatus.wrap(3); } /// @title LocalPreimageKey /// @notice Named type aliases for local `PreimageOracle` key identifiers. library LocalPreimageKey { /// @notice The identifier for the L1 head hash. uint256 internal constant L1_HEAD_HASH = 0x01; /// @notice The identifier for the starting output root. uint256 internal constant STARTING_OUTPUT_ROOT = 0x02; /// @notice The identifier for the disputed output root. uint256 internal constant DISPUTED_OUTPUT_ROOT = 0x03; /// @notice The identifier for the disputed L2 block number. uint256 internal constant DISPUTED_L2_BLOCK_NUMBER = 0x04; /// @notice The identifier for the chain ID. uint256 internal constant CHAIN_ID = 0x05; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; import "src/libraries/DisputeTypes.sol"; //////////////////////////////////////////////////////////////// // `DisputeGameFactory` Errors // //////////////////////////////////////////////////////////////// /// @notice Thrown when a dispute game is attempted to be created with an unsupported game type. /// @param gameType The unsupported game type. error NoImplementation(GameType gameType); /// @notice Thrown when a dispute game that already exists is attempted to be created. /// @param uuid The UUID of the dispute game that already exists. error GameAlreadyExists(Hash uuid); /// @notice Thrown when the root claim has an unexpected VM status. /// Some games can only start with a root-claim with a specific status. /// @param rootClaim is the claim that was unexpected. error UnexpectedRootClaim(Claim rootClaim); //////////////////////////////////////////////////////////////// // `FaultDisputeGame` Errors // //////////////////////////////////////////////////////////////// /// @notice Thrown when a dispute game has already been initialized. error AlreadyInitialized(); /// @notice Thrown when a supplied bond is not equal to the required bond amount to cover the cost of the interaction. error IncorrectBondAmount(); /// @notice Thrown when a credit claim is attempted for a value of 0. error NoCreditToClaim(); /// @notice Thrown when the transfer of credit to a recipient account reverts. error BondTransferFailed(); /// @notice Thrown when the `extraData` passed to the CWIA proxy is of improper length, or contains invalid information. error BadExtraData(); /// @notice Thrown when a defense against the root claim is attempted. error CannotDefendRootClaim(); /// @notice Thrown when a claim is attempting to be made that already exists. error ClaimAlreadyExists(); /// @notice Thrown when a given claim is invalid (0). error InvalidClaim(); /// @notice Thrown when an action that requires the game to be `IN_PROGRESS` is invoked when /// the game is not in progress. error GameNotInProgress(); /// @notice Thrown when a move is attempted to be made after the clock has timed out. error ClockTimeExceeded(); /// @notice Thrown when the game is attempted to be resolved too early. error ClockNotExpired(); /// @notice Thrown when a move is attempted to be made at or greater than the max depth of the game. error GameDepthExceeded(); /// @notice Thrown when a step is attempted above the maximum game depth. error InvalidParent(); /// @notice Thrown when an invalid prestate is supplied to `step`. error InvalidPrestate(); /// @notice Thrown when a step is made that computes the expected post state correctly. error ValidStep(); /// @notice Thrown when a game is attempted to be initialized with an L1 head that does /// not contain the disputed output root. error L1HeadTooOld(); /// @notice Thrown when an invalid local identifier is passed to the `addLocalData` function. error InvalidLocalIdent(); /// @notice Thrown when resolving claims out of order. error OutOfOrderResolution(); /// @notice Thrown when resolving a claim that has already been resolved. error ClaimAlreadyResolved(); /// @notice Thrown when a parent output root is attempted to be found on a claim that is in /// the output root portion of the tree. error ClaimAboveSplit(); /// @notice Thrown on deployment if the split depth is greater than or equal to the max /// depth of the game. error InvalidSplitDepth(); /// @notice Thrown on deployment if the max clock duration is less than or equal to the clock extension. error InvalidClockExtension(); /// @notice Thrown on deployment if the max depth is greater than `LibPosition.` error MaxDepthTooLarge(); /// @notice Thrown when trying to step against a claim for a second time, after it has already been countered with /// an instruction step. error DuplicateStep(); /// @notice Thrown when an anchor root is not found for a given game type. error AnchorRootNotFound(); //////////////////////////////////////////////////////////////// // `PermissionedDisputeGame` Errors // //////////////////////////////////////////////////////////////// /// @notice Thrown when an unauthorized address attempts to interact with the game. error BadAuth();
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title IInitializable /// @notice An interface for initializable contracts. interface IInitializable { /// @notice Initializes the contract. /// @dev This function may only be called once. function initialize() external payable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; import "src/libraries/DisputeTypes.sol"; /// @title Hashing /// @notice This library contains all of the hashing utilities used in the Cannon contracts. library LibHashing { /// @notice Hashes a claim and a position together. /// @param _claim A Claim type. /// @param _position The position of `claim`. /// @param _challengeIndex The index of the claim being moved against. /// @return claimHash_ A hash of abi.encodePacked(claim, position|challengeIndex); function hashClaimPos( Claim _claim, Position _position, uint256 _challengeIndex ) internal pure returns (ClaimHash claimHash_) { assembly { mstore(0x00, _claim) mstore(0x20, or(shl(128, _position), and(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, _challengeIndex))) claimHash_ := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; import "src/libraries/DisputeTypes.sol"; /// @title LibClock /// @notice This library contains helper functions for working with the `Clock` type. library LibClock { /// @notice Packs a `Duration` and `Timestamp` into a `Clock` type. /// @param _duration The `Duration` to pack into the `Clock` type. /// @param _timestamp The `Timestamp` to pack into the `Clock` type. /// @return clock_ The `Clock` containing the `_duration` and `_timestamp`. function wrap(Duration _duration, Timestamp _timestamp) internal pure returns (Clock clock_) { assembly { clock_ := or(shl(0x40, _duration), _timestamp) } } /// @notice Pull the `Duration` out of a `Clock` type. /// @param _clock The `Clock` type to pull the `Duration` out of. /// @return duration_ The `Duration` pulled out of `_clock`. function duration(Clock _clock) internal pure returns (Duration duration_) { // Shift the high-order 64 bits into the low-order 64 bits, leaving only the `duration`. assembly { duration_ := shr(0x40, _clock) } } /// @notice Pull the `Timestamp` out of a `Clock` type. /// @param _clock The `Clock` type to pull the `Timestamp` out of. /// @return timestamp_ The `Timestamp` pulled out of `_clock`. function timestamp(Clock _clock) internal pure returns (Timestamp timestamp_) { // Clean the high-order 192 bits by shifting the clock left and then right again, leaving // only the `timestamp`. assembly { timestamp_ := shr(0xC0, shl(0xC0, _clock)) } } /// @notice Get the value of a `Clock` type in the form of the underlying uint128. /// @param _clock The `Clock` type to get the value of. /// @return clock_ The value of the `Clock` type as a uint128 type. function raw(Clock _clock) internal pure returns (uint128 clock_) { assembly { clock_ := _clock } } } /// @title LibClaim /// @notice This library contains helper functions for working with the `Claim` type. library LibClaim { /// @notice Get the value of a `Claim` type in the form of the underlying bytes32. /// @param _claim The `Claim` type to get the value of. /// @return claim_ The value of the `Claim` type as a bytes32 type. function raw(Claim _claim) internal pure returns (bytes32 claim_) { assembly { claim_ := _claim } } } /// @title LibDuration /// @notice This library contains helper functions for working with the `Duration` type. library LibDuration { /// @notice Get the value of a `Duration` type in the form of the underlying uint64. /// @param _duration The `Duration` type to get the value of. /// @return duration_ The value of the `Duration` type as a uint64 type. function raw(Duration _duration) internal pure returns (uint64 duration_) { assembly { duration_ := _duration } } } /// @title LibHash /// @notice This library contains helper functions for working with the `Hash` type. library LibHash { /// @notice Get the value of a `Hash` type in the form of the underlying bytes32. /// @param _hash The `Hash` type to get the value of. /// @return hash_ The value of the `Hash` type as a bytes32 type. function raw(Hash _hash) internal pure returns (bytes32 hash_) { assembly { hash_ := _hash } } } /// @title LibTimestamp /// @notice This library contains helper functions for working with the `Timestamp` type. library LibTimestamp { /// @notice Get the value of a `Timestamp` type in the form of the underlying uint64. /// @param _timestamp The `Timestamp` type to get the value of. /// @return timestamp_ The value of the `Timestamp` type as a uint64 type. function raw(Timestamp _timestamp) internal pure returns (uint64 timestamp_) { assembly { timestamp_ := _timestamp } } } /// @title LibVMStatus /// @notice This library contains helper functions for working with the `VMStatus` type. library LibVMStatus { /// @notice Get the value of a `VMStatus` type in the form of the underlying uint8. /// @param _vmstatus The `VMStatus` type to get the value of. /// @return vmstatus_ The value of the `VMStatus` type as a uint8 type. function raw(VMStatus _vmstatus) internal pure returns (uint8 vmstatus_) { assembly { vmstatus_ := _vmstatus } } } /// @title LibGameType /// @notice This library contains helper functions for working with the `GameType` type. library LibGameType { /// @notice Get the value of a `GameType` type in the form of the underlying uint32. /// @param _gametype The `GameType` type to get the value of. /// @return gametype_ The value of the `GameType` type as a uint32 type. function raw(GameType _gametype) internal pure returns (uint32 gametype_) { assembly { gametype_ := _gametype } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; import "src/libraries/DisputeTypes.sol"; import "src/libraries/DisputeErrors.sol"; /// @title LibPosition /// @notice This library contains helper functions for working with the `Position` type. library LibPosition { /// @notice the `MAX_POSITION_BITLEN` is the number of bits that the `Position` type, and the implementation of /// its behavior within this library, can safely support. uint8 internal constant MAX_POSITION_BITLEN = 126; /// @notice Computes a generalized index (2^{depth} + indexAtDepth). /// @param _depth The depth of the position. /// @param _indexAtDepth The index at the depth of the position. /// @return position_ The computed generalized index. function wrap(uint8 _depth, uint128 _indexAtDepth) internal pure returns (Position position_) { assembly { // gindex = 2^{_depth} + _indexAtDepth position_ := add(shl(_depth, 1), _indexAtDepth) } } /// @notice Pulls the `depth` out of a `Position` type. /// @param _position The generalized index to get the `depth` of. /// @return depth_ The `depth` of the `position` gindex. /// @custom:attribution Solady <https://github.com/Vectorized/Solady> function depth(Position _position) internal pure returns (uint8 depth_) { // Return the most significant bit offset, which signifies the depth of the gindex. assembly { depth_ := or(depth_, shl(6, lt(0xffffffffffffffff, shr(depth_, _position)))) depth_ := or(depth_, shl(5, lt(0xffffffff, shr(depth_, _position)))) // For the remaining 32 bits, use a De Bruijn lookup. _position := shr(depth_, _position) _position := or(_position, shr(1, _position)) _position := or(_position, shr(2, _position)) _position := or(_position, shr(4, _position)) _position := or(_position, shr(8, _position)) _position := or(_position, shr(16, _position)) depth_ := or( depth_, byte( shr(251, mul(_position, shl(224, 0x07c4acdd))), 0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f ) ) } } /// @notice Pulls the `indexAtDepth` out of a `Position` type. /// The `indexAtDepth` is the left/right index of a position at a specific depth within /// the binary tree, starting from index 0. For example, at gindex 2, the `depth` = 1 /// and the `indexAtDepth` = 0. /// @param _position The generalized index to get the `indexAtDepth` of. /// @return indexAtDepth_ The `indexAtDepth` of the `position` gindex. function indexAtDepth(Position _position) internal pure returns (uint128 indexAtDepth_) { // Return bits p_{msb-1}...p_{0}. This effectively pulls the 2^{depth} out of the gindex, // leaving only the `indexAtDepth`. uint256 msb = depth(_position); assembly { indexAtDepth_ := sub(_position, shl(msb, 1)) } } /// @notice Get the left child of `_position`. /// @param _position The position to get the left position of. /// @return left_ The position to the left of `position`. function left(Position _position) internal pure returns (Position left_) { assembly { left_ := shl(1, _position) } } /// @notice Get the right child of `_position` /// @param _position The position to get the right position of. /// @return right_ The position to the right of `position`. function right(Position _position) internal pure returns (Position right_) { assembly { right_ := or(1, shl(1, _position)) } } /// @notice Get the parent position of `_position`. /// @param _position The position to get the parent position of. /// @return parent_ The parent position of `position`. function parent(Position _position) internal pure returns (Position parent_) { assembly { parent_ := shr(1, _position) } } /// @notice Get the deepest, right most gindex relative to the `position`. This is equivalent to /// calling `right` on a position until the maximum depth is reached. /// @param _position The position to get the relative deepest, right most gindex of. /// @param _maxDepth The maximum depth of the game. /// @return rightIndex_ The deepest, right most gindex relative to the `position`. function rightIndex(Position _position, uint256 _maxDepth) internal pure returns (Position rightIndex_) { uint256 msb = depth(_position); assembly { let remaining := sub(_maxDepth, msb) rightIndex_ := or(shl(remaining, _position), sub(shl(remaining, 1), 1)) } } /// @notice Get the deepest, right most trace index relative to the `position`. This is /// equivalent to calling `right` on a position until the maximum depth is reached and /// then finding its index at depth. /// @param _position The position to get the relative trace index of. /// @param _maxDepth The maximum depth of the game. /// @return traceIndex_ The trace index relative to the `position`. function traceIndex(Position _position, uint256 _maxDepth) internal pure returns (uint256 traceIndex_) { uint256 msb = depth(_position); assembly { let remaining := sub(_maxDepth, msb) traceIndex_ := sub(or(shl(remaining, _position), sub(shl(remaining, 1), 1)), shl(_maxDepth, 1)) } } /// @notice Gets the position of the highest ancestor of `_position` that commits to the same /// trace index. /// @param _position The position to get the highest ancestor of. /// @return ancestor_ The highest ancestor of `position` that commits to the same trace index. function traceAncestor(Position _position) internal pure returns (Position ancestor_) { // Create a field with only the lowest unset bit of `_position` set. Position lsb; assembly { lsb := and(not(_position), add(_position, 1)) } // Find the index of the lowest unset bit within the field. uint256 msb = depth(lsb); // The highest ancestor that commits to the same trace index is the original position // shifted right by the index of the lowest unset bit. assembly { let a := shr(msb, _position) // Bound the ancestor to the minimum gindex, 1. ancestor_ := or(a, iszero(a)) } } /// @notice Gets the position of the highest ancestor of `_position` that commits to the same /// trace index, while still being below `_upperBoundExclusive`. /// @param _position The position to get the highest ancestor of. /// @param _upperBoundExclusive The exclusive upper depth bound, used to inform where to stop in order /// to not escape a sub-tree. /// @return ancestor_ The highest ancestor of `position` that commits to the same trace index. function traceAncestorBounded( Position _position, uint256 _upperBoundExclusive ) internal pure returns (Position ancestor_) { // This function only works for positions that are below the upper bound. if (_position.depth() <= _upperBoundExclusive) revert ClaimAboveSplit(); // Grab the global trace ancestor. ancestor_ = traceAncestor(_position); // If the ancestor is above or at the upper bound, shift it to be below the upper bound. // This should be a special case that only covers positions that commit to the final leaf // in a sub-tree. if (ancestor_.depth() <= _upperBoundExclusive) { ancestor_ = ancestor_.rightIndex(_upperBoundExclusive + 1); } } /// @notice Get the move position of `_position`, which is the left child of: /// 1. `_position` if `_isAttack` is true. /// 2. `_position | 1` if `_isAttack` is false. /// @param _position The position to get the relative attack/defense position of. /// @param _isAttack Whether or not the move is an attack move. /// @return move_ The move position relative to `position`. function move(Position _position, bool _isAttack) internal pure returns (Position move_) { assembly { move_ := shl(1, or(iszero(_isAttack), _position)) } } /// @notice Get the value of a `Position` type in the form of the underlying uint128. /// @param _position The position to get the value of. /// @return raw_ The value of the `position` as a uint128 type. function raw(Position _position) internal pure returns (uint128 raw_) { assembly { raw_ := _position } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
{ "remappings": [ "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@rari-capital/solmate/=lib/solmate/", "@lib-keccak/=lib/lib-keccak/contracts/lib/", "@solady/=lib/solady/src/", "forge-std/=lib/forge-std/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "safe-contracts/=lib/safe-contracts/contracts/", "kontrol-cheatcodes/=lib/kontrol-cheatcodes/src/", "@solady-test/=lib/lib-keccak/lib/solady/test/", "lib-keccak/=lib/lib-keccak/contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solady/=lib/solady/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 999999 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": false, "libraries": {} }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"Hash","name":"uuid","type":"bytes32"}],"name":"GameAlreadyExists","type":"error"},{"inputs":[],"name":"IncorrectBondAmount","type":"error"},{"inputs":[{"internalType":"GameType","name":"gameType","type":"uint32"}],"name":"NoImplementation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"disputeProxy","type":"address"},{"indexed":true,"internalType":"GameType","name":"gameType","type":"uint32"},{"indexed":true,"internalType":"Claim","name":"rootClaim","type":"bytes32"}],"name":"DisputeGameCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"impl","type":"address"},{"indexed":true,"internalType":"GameType","name":"gameType","type":"uint32"}],"name":"ImplementationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"GameType","name":"gameType","type":"uint32"},{"indexed":true,"internalType":"uint256","name":"newBond","type":"uint256"}],"name":"InitBondUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint32"},{"internalType":"Claim","name":"_rootClaim","type":"bytes32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"create","outputs":[{"internalType":"contract IDisputeGame","name":"proxy_","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint32"},{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_n","type":"uint256"}],"name":"findLatestGames","outputs":[{"components":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"GameId","name":"metadata","type":"bytes32"},{"internalType":"Timestamp","name":"timestamp","type":"uint64"},{"internalType":"Claim","name":"rootClaim","type":"bytes32"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct IDisputeGameFactory.GameSearchResult[]","name":"games_","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"gameAtIndex","outputs":[{"internalType":"GameType","name":"gameType_","type":"uint32"},{"internalType":"Timestamp","name":"timestamp_","type":"uint64"},{"internalType":"contract IDisputeGame","name":"proxy_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gameCount","outputs":[{"internalType":"uint256","name":"gameCount_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"GameType","name":"","type":"uint32"}],"name":"gameImpls","outputs":[{"internalType":"contract IDisputeGame","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint32"},{"internalType":"Claim","name":"_rootClaim","type":"bytes32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"games","outputs":[{"internalType":"contract IDisputeGame","name":"proxy_","type":"address"},{"internalType":"Timestamp","name":"timestamp_","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint32"},{"internalType":"Claim","name":"_rootClaim","type":"bytes32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"getGameUUID","outputs":[{"internalType":"Hash","name":"uuid_","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"GameType","name":"","type":"uint32"}],"name":"initBonds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint32"},{"internalType":"contract IDisputeGame","name":"_impl","type":"address"}],"name":"setImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint32"},{"internalType":"uint256","name":"_initBond","type":"uint256"}],"name":"setInitBond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506200001e600062000024565b62000292565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016260201b62000cdd1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b6200010c62000171565b6200011782620001d9565b80156200015e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001cd5760405162461bcd60e51b815260206004820152602b60248201526000805160206200185283398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d76200022b565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620002875760405162461bcd60e51b815260206004820152602b60248201526000805160206200185283398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d733620001d9565b6115b080620002a26000396000f3fe6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d6101083660046110bf565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110f6565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d610197366004611111565b61045e565b3480156101a857600080fd5b506101bc6101b736600461113b565b6104aa565b60405161017391906111e8565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600581526020017f302e362e3000000000000000000000000000000000000000000000000000000081525081565b60405161017391906112a5565b34801561024a57600080fd5b5061025e6102593660046112b8565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110f6565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e33660046112b8565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e3660046112b8565b6109ef565b34801561033f57600080fd5b5061035361034e36600461133f565b610a28565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af366004611358565b610a8a565b3480156103c057600080fd5b5061010d6103cf366004611358565b610c26565b6103dc610cf9565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610cf9565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f0611375565b600091825260209091200154905060e081901c60a082901c67ffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff831663ffffffff891683036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113d3565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610643919061149e565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a5161068591906114b7565b8151811061069557610695611375565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ef565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610cf9565b6107536000610d7a565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff86166000908152606660205260409020543414610813576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108206001436114b7565b40905061088a338783888860405160200161083f9594939291906114f5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df1565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d457600080fd5b505af11580156108e8573d6000803e3d6000fd5b505050505060006108fb888888886109ef565b60008181526067602052604090205490915015610947576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a089493929190611542565b604051602081830303815290604052805190602001209050949350505050565b6000806000610a7d60688581548110610a4357610a43611375565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9196909550909350915050565b600054610100900460ff1615808015610aaa5750600054600160ff909116105b80610ac45750303b158015610ac4575060005460ff166001145b610b50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bae57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bb6610dff565b610bbf82610d7a565b8015610c2257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c2e610cf9565b73ffffffffffffffffffffffffffffffffffffffff8116610cd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610cda81610d7a565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006106e760008484610e9e565b600054610100900460ff16610e96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753610fe4565b600060608203516040830351602084035184518060208701018051600283016c5af43d3d93803e606057fd5bf3895289600d8a035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218a03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8a035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018a03528060f01b8352606c8101604c8a038cf097505086610f6a5763301164256000526004601cfd5b905285527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09092019190915292915050565b600054610100900460ff1661107b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d7a565b803563ffffffff8116811461109857600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cda57600080fd5b600080604083850312156110d257600080fd5b6110db83611084565b915060208301356110eb8161109d565b809150509250929050565b60006020828403121561110857600080fd5b6106e782611084565b6000806040838503121561112457600080fd5b61112d83611084565b946020939093013593505050565b60008060006060848603121561115057600080fd5b61115984611084565b95602085013595506040909401359392505050565b60005b83811015611189578181015183820152602001611171565b83811115611198576000848401525b50505050565b600081518084526111b681602086016020860161116e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611297578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a0918501829052906112838186018361119e565b96890196945050509086019060010161120f565b509098975050505050505050565b6020815260006106e7602083018461119e565b600080600080606085870312156112ce57600080fd5b6112d785611084565b935060208501359250604085013567ffffffffffffffff808211156112fb57600080fd5b818701915087601f83011261130f57600080fd5b81358181111561131e57600080fd5b88602082850101111561133057600080fd5b95989497505060200194505050565b60006020828403121561135157600080fd5b5035919050565b60006020828403121561136a57600080fd5b81356106e78161109d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113e557600080fd5b815167ffffffffffffffff808211156113fd57600080fd5b818401915084601f83011261141157600080fd5b815181811115611423576114236113a4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611469576114696113a4565b8160405282815287602084870101111561148257600080fd5b61149383602083016020880161116e565b979650505050505050565b6000602082840312156114b057600080fd5b5051919050565b6000828210156114f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008660601b1681528460148201528360348201528183605483013760009101605401908152949350505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069
Deployed Bytecode
0x6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d6101083660046110bf565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110f6565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d610197366004611111565b61045e565b3480156101a857600080fd5b506101bc6101b736600461113b565b6104aa565b60405161017391906111e8565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600581526020017f302e362e3000000000000000000000000000000000000000000000000000000081525081565b60405161017391906112a5565b34801561024a57600080fd5b5061025e6102593660046112b8565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110f6565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e33660046112b8565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e3660046112b8565b6109ef565b34801561033f57600080fd5b5061035361034e36600461133f565b610a28565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af366004611358565b610a8a565b3480156103c057600080fd5b5061010d6103cf366004611358565b610c26565b6103dc610cf9565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610cf9565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f0611375565b600091825260209091200154905060e081901c60a082901c67ffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff831663ffffffff891683036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113d3565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610643919061149e565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a5161068591906114b7565b8151811061069557610695611375565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ef565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610cf9565b6107536000610d7a565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff86166000908152606660205260409020543414610813576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108206001436114b7565b40905061088a338783888860405160200161083f9594939291906114f5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df1565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d457600080fd5b505af11580156108e8573d6000803e3d6000fd5b505050505060006108fb888888886109ef565b60008181526067602052604090205490915015610947576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a089493929190611542565b604051602081830303815290604052805190602001209050949350505050565b6000806000610a7d60688581548110610a4357610a43611375565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9196909550909350915050565b600054610100900460ff1615808015610aaa5750600054600160ff909116105b80610ac45750303b158015610ac4575060005460ff166001145b610b50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bae57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bb6610dff565b610bbf82610d7a565b8015610c2257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c2e610cf9565b73ffffffffffffffffffffffffffffffffffffffff8116610cd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610cda81610d7a565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006106e760008484610e9e565b600054610100900460ff16610e96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753610fe4565b600060608203516040830351602084035184518060208701018051600283016c5af43d3d93803e606057fd5bf3895289600d8a035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218a03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8a035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018a03528060f01b8352606c8101604c8a038cf097505086610f6a5763301164256000526004601cfd5b905285527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09092019190915292915050565b600054610100900460ff1661107b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d7a565b803563ffffffff8116811461109857600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cda57600080fd5b600080604083850312156110d257600080fd5b6110db83611084565b915060208301356110eb8161109d565b809150509250929050565b60006020828403121561110857600080fd5b6106e782611084565b6000806040838503121561112457600080fd5b61112d83611084565b946020939093013593505050565b60008060006060848603121561115057600080fd5b61115984611084565b95602085013595506040909401359392505050565b60005b83811015611189578181015183820152602001611171565b83811115611198576000848401525b50505050565b600081518084526111b681602086016020860161116e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611297578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a0918501829052906112838186018361119e565b96890196945050509086019060010161120f565b509098975050505050505050565b6020815260006106e7602083018461119e565b600080600080606085870312156112ce57600080fd5b6112d785611084565b935060208501359250604085013567ffffffffffffffff808211156112fb57600080fd5b818701915087601f83011261130f57600080fd5b81358181111561131e57600080fd5b88602082850101111561133057600080fd5b95989497505060200194505050565b60006020828403121561135157600080fd5b5035919050565b60006020828403121561136a57600080fd5b81356106e78161109d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113e557600080fd5b815167ffffffffffffffff808211156113fd57600080fd5b818401915084601f83011261141157600080fd5b815181811115611423576114236113a4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611469576114696113a4565b8160405282815287602084870101111561148257600080fd5b61149383602083016020880161116e565b979650505050505050565b6000602082840312156114b057600080fd5b5051919050565b6000828210156114f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008660601b1681528460148201528360348201528183605483013760009101605401908152949350505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a
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.