Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Loading...
Loading
Contract Name:
FaultDisputeGame
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 { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; import { IInitializable } from "src/dispute/interfaces/IInitializable.sol"; import { IBigStepper, IPreimageOracle } from "src/dispute/interfaces/IBigStepper.sol"; import { Clone } from "src/libraries/Clone.sol"; import { Types } from "src/libraries/Types.sol"; import { ISemver } from "src/universal/ISemver.sol"; import { LibClock } from "src/dispute/lib/LibUDT.sol"; import "src/libraries/DisputeTypes.sol"; import "src/libraries/DisputeErrors.sol"; /// @title FaultDisputeGame /// @notice An implementation of the `IFaultDisputeGame` interface. contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { //////////////////////////////////////////////////////////////// // State Vars // //////////////////////////////////////////////////////////////// /// @notice The absolute prestate of the instruction trace. This is a constant that is defined /// by the program that is being used to execute the trace. Claim internal immutable ABSOLUTE_PRESTATE; /// @notice The max depth of the game. uint256 internal immutable MAX_GAME_DEPTH; /// @notice The max depth of the output bisection portion of the position tree. Immediately beneath /// this depth, execution trace bisection begins. uint256 internal immutable SPLIT_DEPTH; /// @notice The duration of the game. Duration internal immutable GAME_DURATION; /// @notice An onchain VM that performs single instruction steps on a fault proof program trace. IBigStepper internal immutable VM; /// @notice The genesis block number uint256 internal immutable GENESIS_BLOCK_NUMBER; /// @notice The genesis output root Hash internal immutable GENESIS_OUTPUT_ROOT; /// @notice The game type ID GameType internal immutable GAME_TYPE; /// @notice The global root claim's position is always at gindex 1. Position internal constant ROOT_POSITION = Position.wrap(1); /// @notice The starting timestamp of the game Timestamp public createdAt; /// @notice The timestamp of the game's global resolution. Timestamp public resolvedAt; /// @inheritdoc IDisputeGame GameStatus public status; /// @inheritdoc IFaultDisputeGame Hash public l1Head; /// @notice An append-only array of all claims made during the dispute game. ClaimData[] public claimData; /// @notice Credited balances for winning participants. mapping(address => uint256) public credit; /// @notice An internal mapping to allow for constant-time lookups of existing claims. mapping(ClaimHash => bool) internal claims; /// @notice An internal mapping of subgames rooted at a claim index to other claim indices in the subgame. mapping(uint256 => uint256[]) internal subgames; /// @notice Indicates whether the subgame rooted at the root claim has been resolved. bool internal subgameAtRootResolved; /// @notice Flag for the `initialize` function to prevent re-initialization. bool internal initialized; /// @notice Semantic version. /// @custom:semver 0.0.24 string public constant version = "0.0.24"; /// @param _gameType The type ID of the game. /// @param _absolutePrestate The absolute prestate of the instruction trace. /// @param _genesisBlockNumber The block number of the genesis block. /// @param _genesisOutputRoot The output root of the genesis block. /// @param _maxGameDepth The maximum depth of bisection. /// @param _splitDepth The final depth of the output bisection portion of the game. /// @param _gameDuration The duration of the game. /// @param _vm An onchain VM that performs single instruction steps on a fault proof program /// trace. constructor( GameType _gameType, Claim _absolutePrestate, uint256 _genesisBlockNumber, Hash _genesisOutputRoot, uint256 _maxGameDepth, uint256 _splitDepth, Duration _gameDuration, IBigStepper _vm ) { // The split depth cannot be greater than or equal to the max game depth. if (_splitDepth >= _maxGameDepth) revert InvalidSplitDepth(); GAME_TYPE = _gameType; ABSOLUTE_PRESTATE = _absolutePrestate; GENESIS_BLOCK_NUMBER = _genesisBlockNumber; GENESIS_OUTPUT_ROOT = _genesisOutputRoot; MAX_GAME_DEPTH = _maxGameDepth; SPLIT_DEPTH = _splitDepth; GAME_DURATION = _gameDuration; VM = _vm; } //////////////////////////////////////////////////////////////// // `IFaultDisputeGame` impl // //////////////////////////////////////////////////////////////// /// @inheritdoc IFaultDisputeGame function step(uint256 _claimIndex, bool _isAttack, bytes calldata _stateData, bytes calldata _proof) external { // INVARIANT: Steps cannot be made unless the game is currently in progress. if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress(); // Get the parent. If it does not exist, the call will revert with OOB. ClaimData storage parent = claimData[_claimIndex]; // Pull the parent position out of storage. Position parentPos = parent.position; // Determine the position of the step. Position stepPos = parentPos.move(_isAttack); // INVARIANT: A step cannot be made unless the move position is 1 below the `MAX_GAME_DEPTH` if (stepPos.depth() != MAX_GAME_DEPTH + 1) revert InvalidParent(); // Determine the expected pre & post states of the step. Claim preStateClaim; ClaimData storage postState; if (_isAttack) { // If the step position's index at depth is 0, the prestate is the absolute // prestate. // If the step is an attack at a trace index > 0, the prestate exists elsewhere in // the game state. // NOTE: We localize the `indexAtDepth` for the current execution trace subgame by finding // the remainder of the index at depth divided by 2 ** (MAX_GAME_DEPTH - SPLIT_DEPTH), // which is the number of leaves in each execution trace subgame. This is so that we can // determine whether or not the step position is represents the `ABSOLUTE_PRESTATE`. preStateClaim = (stepPos.indexAtDepth() % (1 << (MAX_GAME_DEPTH - SPLIT_DEPTH))) == 0 ? ABSOLUTE_PRESTATE : _findTraceAncestor(Position.wrap(parentPos.raw() - 1), parent.parentIndex, false).claim; // For all attacks, the poststate is the parent claim. postState = parent; } else { // If the step is a defense, the poststate exists elsewhere in the game state, // and the parent claim is the expected pre-state. preStateClaim = parent.claim; postState = _findTraceAncestor(Position.wrap(parentPos.raw() + 1), parent.parentIndex, false); } // INVARIANT: The prestate is always invalid if the passed `_stateData` is not the // preimage of the prestate claim hash. // We ignore the highest order byte of the digest because it is used to // indicate the VM Status and is added after the digest is computed. if (keccak256(_stateData) << 8 != preStateClaim.raw() << 8) revert InvalidPrestate(); // Compute the local preimage context for the step. Hash uuid = _findLocalContext(_claimIndex); // INVARIANT: If a step is an attack, the poststate is valid if the step produces // the same poststate hash as the parent claim's value. // If a step is a defense: // 1. If the parent claim and the found post state agree with each other // (depth diff % 2 == 0), the step is valid if it produces the same // state hash as the post state's claim. // 2. If the parent claim and the found post state disagree with each other // (depth diff % 2 != 0), the parent cannot be countered unless the step // produces the same state hash as `postState.claim`. // SAFETY: While the `attack` path does not need an extra check for the post // state's depth in relation to the parent, we don't need another // branch because (n - n) % 2 == 0. bool validStep = VM.step(_stateData, _proof, uuid.raw()) == postState.claim.raw(); bool parentPostAgree = (parentPos.depth() - postState.position.depth()) % 2 == 0; if (parentPostAgree == validStep) revert ValidStep(); // Set the parent claim as countered. We do not need to append a new claim to the game; // instead, we can just set the existing parent as countered. parent.counteredBy = msg.sender; } /// @notice Generic move function, used for both `attack` and `defend` moves. /// @param _challengeIndex The index of the claim being moved against. /// @param _claim The claim at the next logical position in the game. /// @param _isAttack Whether or not the move is an attack or defense. function move(uint256 _challengeIndex, Claim _claim, bool _isAttack) public payable { // INVARIANT: Moves cannot be made unless the game is currently in progress. if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress(); // Get the parent. If it does not exist, the call will revert with OOB. ClaimData memory parent = claimData[_challengeIndex]; // Compute the position that the claim commits to. Because the parent's position is already // known, we can compute the next position by moving left or right depending on whether // or not the move is an attack or defense. Position parentPos = parent.position; Position nextPosition = parentPos.move(_isAttack); uint256 nextPositionDepth = nextPosition.depth(); // INVARIANT: A defense can never be made against the root claim of either the output root game or any // of the execution trace bisection subgames. This is because the root claim commits to the // entire state. Therefore, the only valid defense is to do nothing if it is agreed with. if ((_challengeIndex == 0 || nextPositionDepth == SPLIT_DEPTH + 2) && !_isAttack) { revert CannotDefendRootClaim(); } // INVARIANT: A move can never surpass the `MAX_GAME_DEPTH`. The only option to counter a // claim at this depth is to perform a single instruction step on-chain via // the `step` function to prove that the state transition produces an unexpected // post-state. if (nextPositionDepth > MAX_GAME_DEPTH) revert GameDepthExceeded(); // When the next position surpasses the split depth (i.e., it is the root claim of an execution // trace bisection sub-game), we need to perform some extra verification steps. if (nextPositionDepth == SPLIT_DEPTH + 1) { _verifyExecBisectionRoot(_claim, _challengeIndex, parentPos, _isAttack); } // INVARIANT: The `msg.value` must be sufficient to cover the required bond. if (getRequiredBond(nextPosition) > msg.value) revert InsufficientBond(); // Fetch the grandparent clock, if it exists. // The grandparent clock should always exist unless the parent is the root claim. Clock grandparentClock; if (parent.parentIndex != type(uint32).max) { grandparentClock = claimData[parent.parentIndex].clock; } // Compute the duration of the next clock. This is done by adding the duration of the // grandparent claim to the difference between the current block timestamp and the // parent's clock timestamp. Duration nextDuration = Duration.wrap( uint64( // First, fetch the duration of the grandparent claim. grandparentClock.duration().raw() // Second, add the difference between the current block timestamp and the // parent's clock timestamp. + block.timestamp - parent.clock.timestamp().raw() ) ); // INVARIANT: A move can never be made once its clock has exceeded `GAME_DURATION / 2` // seconds of time. if (nextDuration.raw() > GAME_DURATION.raw() >> 1) revert ClockTimeExceeded(); // Construct the next clock with the new duration and the current block timestamp. Clock nextClock = LibClock.wrap(nextDuration, Timestamp.wrap(uint64(block.timestamp))); // INVARIANT: There cannot be multiple identical claims with identical moves on the same challengeIndex. Multiple // claims at the same position may dispute the same challengeIndex. However, they must have different // values. ClaimHash claimHash = _claim.hashClaimPos(nextPosition, _challengeIndex); if (claims[claimHash]) revert ClaimAlreadyExists(); claims[claimHash] = true; // Create the new claim. claimData.push( ClaimData({ parentIndex: uint32(_challengeIndex), counteredBy: address(0), claimant: msg.sender, bond: uint128(msg.value), claim: _claim, position: nextPosition, clock: nextClock }) ); // Set the parent claim as countered. claimData[_challengeIndex].counteredBy = msg.sender; // Update the subgame rooted at the parent claim. subgames[_challengeIndex].push(claimData.length - 1); // Emit the appropriate event for the attack or defense. emit Move(_challengeIndex, _claim, msg.sender); } /// @inheritdoc IFaultDisputeGame function attack(uint256 _parentIndex, Claim _claim) external payable { move(_parentIndex, _claim, true); } /// @inheritdoc IFaultDisputeGame function defend(uint256 _parentIndex, Claim _claim) external payable { move(_parentIndex, _claim, false); } /// @inheritdoc IFaultDisputeGame function addLocalData(uint256 _ident, uint256 _execLeafIdx, uint256 _partOffset) external { // INVARIANT: Local data can only be added if the game is currently in progress. if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress(); (Claim starting, Position startingPos, Claim disputed, Position disputedPos) = _findStartingAndDisputedOutputs(_execLeafIdx); Hash uuid = _computeLocalContext(starting, startingPos, disputed, disputedPos); IPreimageOracle oracle = VM.oracle(); if (_ident == LocalPreimageKey.L1_HEAD_HASH) { // Load the L1 head hash oracle.loadLocalData(_ident, uuid.raw(), l1Head.raw(), 32, _partOffset); } else if (_ident == LocalPreimageKey.STARTING_OUTPUT_ROOT) { // Load the starting proposal's output root. oracle.loadLocalData(_ident, uuid.raw(), starting.raw(), 32, _partOffset); } else if (_ident == LocalPreimageKey.DISPUTED_OUTPUT_ROOT) { // Load the disputed proposal's output root oracle.loadLocalData(_ident, uuid.raw(), disputed.raw(), 32, _partOffset); } else if (_ident == LocalPreimageKey.STARTING_L2_BLOCK_NUMBER) { // Load the starting proposal's L2 block number as a big-endian uint64 in the // high order 8 bytes of the word. // If the starting position is 0 (invalid), the starting output root is genesis. Otherwise, // we add the index at depth + 1 to the genesis block number to get the L2 block number. uint256 l2Number = startingPos.raw() == 0 ? GENESIS_BLOCK_NUMBER : GENESIS_BLOCK_NUMBER + startingPos.traceIndex(SPLIT_DEPTH) + 1; oracle.loadLocalData(_ident, uuid.raw(), bytes32(l2Number << 0xC0), 8, _partOffset); } else if (_ident == LocalPreimageKey.CHAIN_ID) { // Load the chain ID as a big-endian uint64 in the high order 8 bytes of the word. oracle.loadLocalData(_ident, uuid.raw(), bytes32(block.chainid << 0xC0), 8, _partOffset); } else { revert InvalidLocalIdent(); } } /// @inheritdoc IFaultDisputeGame function l2BlockNumber() public pure returns (uint256 l2BlockNumber_) { l2BlockNumber_ = _getArgUint256(0x20); } //////////////////////////////////////////////////////////////// // `IDisputeGame` impl // //////////////////////////////////////////////////////////////// /// @inheritdoc IDisputeGame function gameType() public view override returns (GameType gameType_) { gameType_ = GAME_TYPE; } /// @inheritdoc IDisputeGame function resolve() external returns (GameStatus status_) { // INVARIANT: Resolution cannot occur unless the game is currently in progress. if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress(); // INVARIANT: Resolution cannot occur unless the absolute root subgame has been resolved. if (!subgameAtRootResolved) revert OutOfOrderResolution(); // Update the global game status; The dispute has concluded. status_ = claimData[0].counteredBy == address(0) ? GameStatus.DEFENDER_WINS : GameStatus.CHALLENGER_WINS; resolvedAt = Timestamp.wrap(uint64(block.timestamp)); emit Resolved(status = status_); } /// @inheritdoc IFaultDisputeGame function resolveClaim(uint256 _claimIndex) external payable { // INVARIANT: Resolution cannot occur unless the game is currently in progress. if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress(); ClaimData storage parent = claimData[_claimIndex]; // INVARIANT: Cannot resolve a subgame unless the clock of its root has expired uint64 parentClockDuration = parent.clock.duration().raw(); uint64 timeSinceParentMove = uint64(block.timestamp) - parent.clock.timestamp().raw(); if (parentClockDuration + timeSinceParentMove <= GAME_DURATION.raw() >> 1) { revert ClockNotExpired(); } uint256[] storage challengeIndices = subgames[_claimIndex]; uint256 challengeIndicesLen = challengeIndices.length; // INVARIANT: Cannot resolve subgames twice if (_claimIndex == 0 && subgameAtRootResolved) { revert ClaimAlreadyResolved(); } // Uncontested claims are resolved implicitly unless they are the root claim. Pay out the bond to the claimant // and return early. if (challengeIndicesLen == 0 && _claimIndex != 0) { _distributeBond(parent.claimant, parent); return; } // Assume parent is honest until proven otherwise address countered = address(0); for (uint256 i = 0; i < challengeIndicesLen; ++i) { uint256 challengeIndex = challengeIndices[i]; // INVARIANT: Cannot resolve a subgame containing an unresolved claim if (subgames[challengeIndex].length != 0) revert OutOfOrderResolution(); ClaimData storage claim = claimData[challengeIndex]; // Ignore false claims if (claim.counteredBy == address(0)) { countered = msg.sender; break; } } // If the parent was not successfully countered, pay out the parent's bond to the claimant. // If the parent was successfully countered, pay out the parent's bond to the challenger. _distributeBond(countered == address(0) ? parent.claimant : countered, parent); // Once a subgame is resolved, we percolate the result up the DAG so subsequent calls to // resolveClaim will not need to traverse this subgame. parent.counteredBy = countered; // Resolved subgames have no entries delete subgames[_claimIndex]; // Indicate the game is ready to be resolved globally. if (_claimIndex == 0) { subgameAtRootResolved = true; } } /// @inheritdoc IDisputeGame function rootClaim() public pure returns (Claim rootClaim_) { rootClaim_ = Claim.wrap(_getArgFixedBytes(0x00)); } /// @inheritdoc IDisputeGame function extraData() public pure returns (bytes memory extraData_) { // The extra data starts at the second word within the cwia calldata and // is 32 bytes long. extraData_ = _getArgDynBytes(0x20, 0x20); } /// @inheritdoc IDisputeGame function gameData() external view returns (GameType gameType_, Claim rootClaim_, bytes memory extraData_) { gameType_ = gameType(); rootClaim_ = rootClaim(); extraData_ = extraData(); } //////////////////////////////////////////////////////////////// // MISC EXTERNAL // //////////////////////////////////////////////////////////////// /// @inheritdoc IInitializable function initialize() external payable { // SAFETY: Any revert in this function will bubble up to the DisputeGameFactory and // prevent the game from being created. // // Implicit assumptions: // - The `gameStatus` state variable defaults to 0, which is `GameStatus.IN_PROGRESS` // - The dispute game factory will enforce the required bond to initialize the game. // // Explicit checks: // - The game must not have already been initialized. // - An output root cannot be proposed at or before the genesis block. // INVARIANT: The game must not have already been initialized. if (initialized) revert AlreadyInitialized(); // Do not allow the game to be initialized if the root claim corresponds to a block at or before the // configured genesis block number. if (l2BlockNumber() <= GENESIS_BLOCK_NUMBER) revert UnexpectedRootClaim(rootClaim()); // Revert if the calldata size is too large, which signals that the `extraData` contains more than expected. // This is to prevent adding extra bytes to the `extraData` that result in a different game UUID in the factory, // but are not used by the game, which would allow for multiple dispute games for the same output proposal to // be created. // Expected length: 0x46 (0x04 selector + 0x20 root claim + 0x20 extraData + 0x02 CWIA bytes) assembly { if gt(calldatasize(), 0x46) { // Store the selector for `ExtraDataTooLong()` & revert mstore(0x00, 0xc407e025) revert(0x1C, 0x04) } } // Set the root claim claimData.push( ClaimData({ parentIndex: type(uint32).max, counteredBy: address(0), claimant: tx.origin, bond: uint128(msg.value), claim: rootClaim(), position: ROOT_POSITION, clock: LibClock.wrap(Duration.wrap(0), Timestamp.wrap(uint64(block.timestamp))) }) ); // Set the game's starting timestamp createdAt = Timestamp.wrap(uint64(block.timestamp)); // Persist the blockhash of the parent block. l1Head = Hash.wrap(blockhash(block.number - 1)); // Set the game as initialized. initialized = true; } /// @notice Returns the length of the `claimData` array. function claimDataLen() external view returns (uint256 len_) { len_ = claimData.length; } /// @notice Returns the required bond for a given move kind. /// @param _position The position of the bonded interaction. /// @return requiredBond_ The required ETH bond for the given move, in wei. function getRequiredBond(Position _position) public pure returns (uint256 requiredBond_) { // TODO _position; requiredBond_ = 0; } /// @notice Claim the credit belonging to the recipient address. /// @param _recipient The owner and recipient of the credit. function claimCredit(address _recipient) external { // Remove the credit from the recipient prior to performing the external call. uint256 recipientCredit = credit[_recipient]; credit[_recipient] = 0; // Transfer the credit to the recipient. (bool success,) = _recipient.call{ value: recipientCredit }(hex""); if (!success) revert BondTransferFailed(); } //////////////////////////////////////////////////////////////// // IMMUTABLE GETTERS // //////////////////////////////////////////////////////////////// /// @notice Returns the absolute prestate of the instruction trace. function absolutePrestate() external view returns (Claim absolutePrestate_) { absolutePrestate_ = ABSOLUTE_PRESTATE; } /// @notice Returns the max game depth. function maxGameDepth() external view returns (uint256 maxGameDepth_) { maxGameDepth_ = MAX_GAME_DEPTH; } /// @notice Returns the split depth. function splitDepth() external view returns (uint256 splitDepth_) { splitDepth_ = SPLIT_DEPTH; } /// @notice Returns the game duration. function gameDuration() external view returns (Duration gameDuration_) { gameDuration_ = GAME_DURATION; } /// @notice Returns the address of the VM. function vm() external view returns (IBigStepper vm_) { vm_ = VM; } /// @notice Returns the genesis block number. function genesisBlockNumber() external view returns (uint256 genesisBlockNumber_) { genesisBlockNumber_ = GENESIS_BLOCK_NUMBER; } /// @notice Returns the genesis output root. function genesisOutputRoot() external view returns (Hash genesisOutputRoot_) { genesisOutputRoot_ = GENESIS_OUTPUT_ROOT; } //////////////////////////////////////////////////////////////// // HELPERS // //////////////////////////////////////////////////////////////// /// @notice Pays out the bond of a claim to a given recipient. /// @param _recipient The recipient of the bond. /// @param _bonded The claim to pay out the bond of. function _distributeBond(address _recipient, ClaimData storage _bonded) internal { // Set all bits in the bond value to indicate that the bond has been paid out. uint256 bond = _bonded.bond; if (bond == type(uint128).max) revert ClaimAlreadyResolved(); _bonded.bond = type(uint128).max; // Increase the recipient's credit. credit[_recipient] += bond; } /// @notice Verifies the integrity of an execution bisection subgame's root claim. Reverts if the claim /// is invalid. /// @param _rootClaim The root claim of the execution bisection subgame. function _verifyExecBisectionRoot( Claim _rootClaim, uint256 _parentIdx, Position _parentPos, bool _isAttack ) internal view { // The root claim of an execution trace bisection sub-game must: // 1. Signal that the VM panicked or resulted in an invalid transition if the disputed output root // was made by the opposing party. // 2. Signal that the VM resulted in a valid transition if the disputed output root was made by the same party. // If the move is a defense, the disputed output could have been made by either party. In this case, we // need to search for the parent output to determine what the expected status byte should be. Position disputedLeafPos = Position.wrap(_parentPos.raw() + 1); ClaimData storage disputed = _findTraceAncestor({ _pos: disputedLeafPos, _start: _parentIdx, _global: true }); uint8 vmStatus = uint8(_rootClaim.raw()[0]); if (_isAttack || disputed.position.depth() % 2 == SPLIT_DEPTH % 2) { // If the move is an attack, the parent output is always deemed to be disputed. In this case, we only need // to check that the root claim signals that the VM panicked or resulted in an invalid transition. // If the move is a defense, and the disputed output and creator of the execution trace subgame disagree, // the root claim should also signal that the VM panicked or resulted in an invalid transition. if (!(vmStatus == VMStatuses.INVALID.raw() || vmStatus == VMStatuses.PANIC.raw())) { revert UnexpectedRootClaim(_rootClaim); } } else if (vmStatus != VMStatuses.VALID.raw()) { // The disputed output and the creator of the execution trace subgame agree. The status byte should // have signaled that the VM succeeded. revert UnexpectedRootClaim(_rootClaim); } } /// @notice Finds the trace ancestor of a given position within the DAG. /// @param _pos The position to find the trace ancestor claim of. /// @param _start The index to start searching from. /// @param _global Whether or not to search the entire dag or just within an execution trace subgame. If set to /// `true`, and `_pos` is at or above the split depth, this function will revert. /// @return ancestor_ The ancestor claim that commits to the same trace index as `_pos`. function _findTraceAncestor( Position _pos, uint256 _start, bool _global ) internal view returns (ClaimData storage ancestor_) { // Grab the trace ancestor's expected position. Position traceAncestorPos = _global ? _pos.traceAncestor() : _pos.traceAncestorBounded(SPLIT_DEPTH); // Walk up the DAG to find a claim that commits to the same trace index as `_pos`. It is // guaranteed that such a claim exists. ancestor_ = claimData[_start]; while (ancestor_.position.raw() != traceAncestorPos.raw()) { ancestor_ = claimData[ancestor_.parentIndex]; } } /// @notice Finds the starting and disputed output root for a given `ClaimData` within the DAG. This /// `ClaimData` must be below the `SPLIT_DEPTH`. /// @param _start The index within `claimData` of the claim to start searching from. /// @return startingClaim_ The starting output root claim. /// @return startingPos_ The starting output root position. /// @return disputedClaim_ The disputed output root claim. /// @return disputedPos_ The disputed output root position. function _findStartingAndDisputedOutputs(uint256 _start) internal view returns (Claim startingClaim_, Position startingPos_, Claim disputedClaim_, Position disputedPos_) { // Fatch the starting claim. uint256 claimIdx = _start; ClaimData storage claim = claimData[claimIdx]; // If the starting claim's depth is less than or equal to the split depth, we revert as this is UB. if (claim.position.depth() <= SPLIT_DEPTH) revert ClaimAboveSplit(); // We want to: // 1. Find the first claim at the split depth. // 2. Determine whether it was the starting or disputed output for the exec game. // 3. Find the complimentary claim depending on the info from #2 (pre or post). // Walk up the DAG until the ancestor's depth is equal to the split depth. uint256 currentDepth; ClaimData storage execRootClaim = claim; while ((currentDepth = claim.position.depth()) > SPLIT_DEPTH) { uint256 parentIndex = claim.parentIndex; // If we're currently at the split depth + 1, we're at the root of the execution sub-game. // We need to keep track of the root claim here to determine whether the execution sub-game was // started with an attack or defense against the output leaf claim. if (currentDepth == SPLIT_DEPTH + 1) execRootClaim = claim; claim = claimData[parentIndex]; claimIdx = parentIndex; } // Determine whether the start of the execution sub-game was an attack or defense to the output root // above. This is important because it determines which claim is the starting output root and which // is the disputed output root. (Position execRootPos, Position outputPos) = (execRootClaim.position, claim.position); bool wasAttack = execRootPos.parent().raw() == outputPos.raw(); // Determine the starting and disputed output root indices. // 1. If it was an attack, the disputed output root is `claim`, and the starting output root is // elsewhere in the DAG (it must commit to the block # index at depth of `outputPos - 1`). // 2. If it was a defense, the starting output root is `claim`, and the disputed output root is // elsewhere in the DAG (it must commit to the block # index at depth of `outputPos + 1`). if (wasAttack) { // If this is an attack on the first output root (the block directly after genesis), the // starting claim nor position exists in the tree. We leave these as 0, which can be easily // identified due to 0 being an invalid Gindex. if (outputPos.indexAtDepth() > 0) { ClaimData storage starting = _findTraceAncestor(Position.wrap(outputPos.raw() - 1), claimIdx, true); (startingClaim_, startingPos_) = (starting.claim, starting.position); } else { startingClaim_ = Claim.wrap(GENESIS_OUTPUT_ROOT.raw()); } (disputedClaim_, disputedPos_) = (claim.claim, claim.position); } else { ClaimData storage disputed = _findTraceAncestor(Position.wrap(outputPos.raw() + 1), claimIdx, true); (startingClaim_, startingPos_) = (claim.claim, claim.position); (disputedClaim_, disputedPos_) = (disputed.claim, disputed.position); } } /// @notice Finds the local context hash for a given claim index that is present in an execution trace subgame. /// @param _claimIndex The index of the claim to find the local context hash for. /// @return uuid_ The local context hash. function _findLocalContext(uint256 _claimIndex) internal view returns (Hash uuid_) { (Claim starting, Position startingPos, Claim disputed, Position disputedPos) = _findStartingAndDisputedOutputs(_claimIndex); uuid_ = _computeLocalContext(starting, startingPos, disputed, disputedPos); } /// @notice Computes the local context hash for a set of starting/disputed claim values and positions. /// @param _starting The starting claim. /// @param _startingPos The starting claim's position. /// @param _disputed The disputed claim. /// @param _disputedPos The disputed claim's position. /// @return uuid_ The local context hash. function _computeLocalContext( Claim _starting, Position _startingPos, Claim _disputed, Position _disputedPos ) internal pure returns (Hash uuid_) { // A position of 0 indicates that the starting claim is the absolute prestate. In this special case, // we do not include the starting claim within the local context hash. if (_startingPos.raw() == 0) { uuid_ = Hash.wrap(keccak256(abi.encode(_disputed, _disputedPos))); } else { uuid_ = Hash.wrap(keccak256(abi.encode(_starting, _startingPos, _disputed, _disputedPos))); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; 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 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 root claim. /// @dev `clones-with-immutable-args` argument #1 /// @return rootClaim_ The root claim of the DisputeGame. function rootClaim() external pure returns (Claim rootClaim_); /// @notice Getter for the extra data. /// @dev `clones-with-immutable-args` argument #2 /// @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.15; import { IDisputeGame } from "./IDisputeGame.sol"; import "src/libraries/DisputeTypes.sol"; /// @title IFaultDisputeGame /// @notice The interface for a fault proof backed dispute game. interface IFaultDisputeGame is IDisputeGame { /// @notice The `ClaimData` struct represents the data associated with a Claim. struct ClaimData { uint32 parentIndex; address counteredBy; address claimant; uint128 bond; Claim claim; Position position; Clock clock; } /// @notice Emitted when a new claim is added to the DAG by `claimant` /// @param parentIndex The index within the `claimData` array of the parent claim /// @param claim The claim being added /// @param claimant The address of the claimant event Move(uint256 indexed parentIndex, Claim indexed claim, address indexed claimant); /// @notice Attack a disagreed upon `Claim`. /// @param _parentIndex Index of the `Claim` to attack in the `claimData` array. /// @param _claim The `Claim` at the relative attack position. function attack(uint256 _parentIndex, Claim _claim) external payable; /// @notice Defend an agreed upon `Claim`. /// @param _parentIndex Index of the claim to defend in the `claimData` array. /// @param _claim The `Claim` at the relative defense position. function defend(uint256 _parentIndex, Claim _claim) external payable; /// @notice Perform an instruction step via an on-chain fault proof processor. /// @dev This function should point to a fault proof processor in order to execute /// a step in the fault proof program on-chain. The interface of the fault proof /// processor contract should adhere to the `IBigStepper` interface. /// @param _claimIndex The index of the challenged claim within `claimData`. /// @param _isAttack Whether or not the step is an attack or a defense. /// @param _stateData The stateData of the step is the preimage of the claim at the given /// prestate, which is at `_stateIndex` if the move is an attack and `_claimIndex` if /// the move is a defense. If the step is an attack on the first instruction, it is /// the absolute prestate of the fault proof VM. /// @param _proof Proof to access memory nodes in the VM's merkle state tree. function step(uint256 _claimIndex, bool _isAttack, bytes calldata _stateData, bytes calldata _proof) external; /// @notice Posts the requested local data to the VM's `PreimageOralce`. /// @param _ident The local identifier of the data to post. /// @param _execLeafIdx The index of the leaf claim in an execution subgame that requires the local data for a step. /// @param _partOffset The offset of the data to post. function addLocalData(uint256 _ident, uint256 _execLeafIdx, uint256 _partOffset) external; /// @notice Resolves the subgame rooted at the given claim index. /// @dev This function must be called bottom-up in the DAG /// A subgame is a tree of claims that has a maximum depth of 1. /// A subgame root claims is valid if, and only if, all of its child claims are invalid. /// At the deepest level in the DAG, a claim is invalid if there's a successful step against it. /// @param _claimIndex The index of the subgame root claim to resolve. function resolveClaim(uint256 _claimIndex) external payable; /// @notice A block hash on the L1 that contains the disputed output root. function l1Head() external view returns (Hash l1Head_); /// @notice The l2BlockNumber of the disputed output root in the `L2OutputOracle`. function l2BlockNumber() external view returns (uint256 l2BlockNumber_); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; /// @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 { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; /// @title IBigStepper /// @notice Describes a state machine that can perform a single instruction step, provided a prestate and an optional /// proof. /// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ /// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⠶⢅⠒⢄⢔⣶⡦⣤⡤⠄⣀⠀⠀⠀⠀⠀⠀⠀ /// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠨⡏⠀⠀⠈⠢⣙⢯⣄⠀⢨⠯⡺⡘⢄⠀⠀⠀⠀⠀ /// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣶⡆⠀⠀⠀⠀⠈⠓⠬⡒⠡⣀⢙⡜⡀⠓⠄⠀⠀⠀ /// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡷⠿⣧⣀⡀⠀⠀⠀⠀⠀⠀⠉⠣⣞⠩⠥⠀⠼⢄⠀⠀ /// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀⠀⠉⢹⣶⠒⠒⠂⠈⠉⠁⠘⡆⠀⣿⣿⠫⡄⠀ /// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⢶⣤⣀⡀⠀⠀⢸⡿⠀⠀⠀⠀⠀⢀⠞⠀⠀⢡⢨⢀⡄⠀ /// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡒⣿⢿⡤⠝⡣⠉⠁⠚⠛⠀⠤⠤⣄⡰⠁⠀⠀⠀⠉⠙⢸⠀⠀ /// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡤⢯⡌⡿⡇⠘⡷⠀⠁⠀⠀⢀⣰⠢⠲⠛⣈⣸⠦⠤⠶⠴⢬⣐⣊⡂⠀ /// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⡪⡗⢫⠞⠀⠆⣀⠻⠤⠴⠐⠚⣉⢀⠦⠂⠋⠁⠀⠁⠀⠀⠀⠀⢋⠉⠇⠀ /// ⠀⠀⠀⠀⣀⡤⠐⠒⠘⡹⠉⢸⠇⠸⠀⠀⠀⠀⣀⣤⠴⠚⠉⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⠀⣾⠀ /// ⠀⠀⠀⡰⠀⠉⠉⠀⠁⠀⠀⠈⢇⠈⠒⠒⠘⠈⢀⢡⡂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠀⢸⡄ /// ⠀⠀⠸⣿⣆⠤⢀⡀⠀⠀⠀⠀⢘⡌⠀⠀⣀⣀⣀⡈⣤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⢸⡇ /// ⠀⠀⢸⣀⠀⠉⠒⠐⠛⠋⠭⠭⠍⠉⠛⠒⠒⠒⠀⠒⠚⠛⠛⠛⠩⠭⠭⠭⠭⠤⠤⠤⠤⠤⠭⠭⠉⠓⡆ /// ⠀⠀⠘⠿⣷⣶⣤⣤⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇ /// ⠀⠀⠀⠀⠀⠉⠙⠛⠛⠻⠿⢿⣿⣿⣷⣶⣶⣶⣤⣤⣀⣁⣛⣃⣒⠿⠿⠿⠤⠠⠄⠤⠤⢤⣛⣓⣂⣻⡇ /// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠙⠛⠻⠿⠿⠿⢿⣿⣿⣿⣷⣶⣶⣾⣿⣿⣿⣿⠿⠟⠁ /// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀ interface IBigStepper { /// @notice Performs the state transition from a given prestate and returns the hash of the post state witness. /// @param _stateData The raw opaque prestate data. /// @param _proof Opaque proof data, can be used to prove things about the prestate in relation to the state of the /// interface's implementation. /// @param _localContext The local key context for the preimage oracle. Optional, can be set as a constant if the /// implementation only requires one set of local keys. /// @return postState_ The hash of the post state witness after the state transition. function step( bytes calldata _stateData, bytes calldata _proof, bytes32 _localContext ) external returns (bytes32 postState_); /// @notice Returns the preimage oracle used by the state machine. function oracle() external view returns (IPreimageOracle oracle_); }
// SPDX-License-Identifier: BSD pragma solidity ^0.8.15; /// @title Clone /// @author zefram.eth, Saw-mon & Natalie, clabby /// @notice Provides helper functions for reading immutable args from calldata /// @dev Original: /// https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args/ /// blob/105efee1b9127ed7f6fedf139e1fc796ce8791f2/src/Clone.sol /// @dev MODIFICATIONS: /// - Added `_getArgDynBytes` function. contract Clone { uint256 private constant ONE_WORD = 0x20; /// @notice Reads an immutable arg with type address /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgAddress(uint256 argOffset) internal pure returns (address arg) { uint256 offset = _getImmutableArgsOffset(); assembly { arg := shr(0x60, calldataload(add(offset, argOffset))) } } /// @notice Reads an immutable arg with type uint256 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint256(uint256 argOffset) internal pure returns (uint256 arg) { uint256 offset = _getImmutableArgsOffset(); assembly { arg := calldataload(add(offset, argOffset)) } } /// @notice Reads an immutable arg with type bytes32 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgFixedBytes(uint256 argOffset) internal pure returns (bytes32 arg) { uint256 offset = _getImmutableArgsOffset(); assembly { arg := calldataload(add(offset, argOffset)) } } /// @notice Reads a uint256 array stored in the immutable args. /// @param argOffset The offset of the arg in the packed data /// @param arrLen Number of elements in the array /// @return arr The array function _getArgUint256Array(uint256 argOffset, uint64 arrLen) internal pure returns (uint256[] memory arr) { uint256 offset = _getImmutableArgsOffset() + argOffset; arr = new uint256[](arrLen); assembly { calldatacopy(add(arr, ONE_WORD), offset, shl(5, arrLen)) } } /// @notice Reads a dynamic bytes array stored in the immutable args. /// @param argOffset The offset of the arg in the packed data /// @param arrLen Number of elements in the array /// @return arr The array function _getArgDynBytes(uint256 argOffset, uint64 arrLen) internal pure returns (bytes memory arr) { uint256 offset = _getImmutableArgsOffset() + argOffset; arr = new bytes(arrLen); assembly { calldatacopy(add(arr, ONE_WORD), offset, arrLen) } } /// @notice Reads an immutable arg with type uint64 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint64(uint256 argOffset) internal pure returns (uint64 arg) { uint256 offset = _getImmutableArgsOffset(); assembly { arg := shr(0xc0, calldataload(add(offset, argOffset))) } } /// @notice Reads an immutable arg with type uint8 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint8(uint256 argOffset) internal pure returns (uint8 arg) { uint256 offset = _getImmutableArgsOffset(); assembly { arg := shr(0xf8, calldataload(add(offset, argOffset))) } } /// @return offset The offset of the packed immutable args in calldata function _getImmutableArgsOffset() internal pure returns (uint256 offset) { assembly { offset := sub(calldatasize(), shr(0xf0, calldataload(sub(calldatasize(), 2)))) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Types /// @notice Contains various types used throughout the Optimism contract system. library Types { /// @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1 /// timestamp that the output root is posted. This timestamp is used to verify that the /// finalization period has passed since the output root was submitted. /// @custom:field outputRoot Hash of the L2 output. /// @custom:field timestamp Timestamp of the L1 block that the output root was submitted in. /// @custom:field l2BlockNumber L2 block number that the output corresponds to. struct OutputProposal { bytes32 outputRoot; uint128 timestamp; uint128 l2BlockNumber; } /// @notice Struct representing the elements that are hashed together to generate an output root /// which itself represents a snapshot of the L2 state. /// @custom:field version Version of the output root. /// @custom:field stateRoot Root of the state trie at the block of this output. /// @custom:field messagePasserStorageRoot Root of the message passer storage trie. /// @custom:field latestBlockhash Hash of the block this output was generated from. struct OutputRootProof { bytes32 version; bytes32 stateRoot; bytes32 messagePasserStorageRoot; bytes32 latestBlockhash; } /// @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end /// user (as opposed to a system deposit transaction generated by the system). /// @custom:field from Address of the sender of the transaction. /// @custom:field to Address of the recipient of the transaction. /// @custom:field isCreation True if the transaction is a contract creation. /// @custom:field value Value to send to the recipient. /// @custom:field mint Amount of ETH to mint. /// @custom:field gasLimit Gas limit of the transaction. /// @custom:field data Data of the transaction. /// @custom:field l1BlockHash Hash of the block the transaction was submitted in. /// @custom:field logIndex Index of the log in the block the transaction was submitted in. struct UserDepositTransaction { address from; address to; bool isCreation; uint256 value; uint256 mint; uint64 gasLimit; bytes data; bytes32 l1BlockHash; uint256 logIndex; } /// @notice Struct representing a withdrawal transaction. /// @custom:field nonce Nonce of the withdrawal transaction /// @custom:field sender Address of the sender of the transaction. /// @custom:field target Address of the recipient of the transaction. /// @custom:field value Value to send to the recipient. /// @custom:field gasLimit Gas limit of the transaction. /// @custom:field data Data of the transaction. struct WithdrawalTransaction { uint256 nonce; address sender; address target; uint256 value; uint256 gasLimit; bytes data; } }
// 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.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 uint8. /// @param _gametype The `GameType` type to get the value of. /// @return gametype_ The value of the `GameType` type as a uint8 type. function raw(GameType _gametype) internal pure returns (uint8 gametype_) { assembly { gametype_ := _gametype } } }
// 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 1 byte game ID, an 11 byte timestamp, and a 20 byte address. /// @dev The packed layout of this type is as follows: /// ┌───────────┬───────────┐ /// │ Bits │ Value │ /// ├───────────┼───────────┤ /// │ [0, 8) │ Game Type │ /// │ [8, 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 uint8; /// @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 } /// @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); /// @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 starting L2 block number. uint256 internal constant STARTING_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 too low to cover the cost of the interaction. error InsufficientBond(); /// @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 too long for the `FaultDisputeGame`. error ExtraDataTooLong(); /// @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();
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; /// @title IPreimageOracle /// @notice Interface for a preimage oracle. interface IPreimageOracle { /// @notice Reads a preimage from the oracle. /// @param _key The key of the preimage to read. /// @param _offset The offset of the preimage to read. /// @return dat_ The preimage data. /// @return datLen_ The length of the preimage data. function readPreimage(bytes32 _key, uint256 _offset) external view returns (bytes32 dat_, uint256 datLen_); /// @notice Loads of local data part into the preimage oracle. /// @param _ident The identifier of the local data. /// @param _localContext The local key context for the preimage oracle. Optionally, can be set as a constant /// if the caller only requires one set of local keys. /// @param _word The local data word. /// @param _size The number of bytes in `_word` to load. /// @param _partOffset The offset of the local data part to write to the oracle. /// @dev The local data parts are loaded into the preimage oracle under the context /// of the caller - no other account can write to the caller's context /// specific data. /// /// There are 5 local data identifiers: /// ┌────────────┬────────────────────────┐ /// │ Identifier │ Data │ /// ├────────────┼────────────────────────┤ /// │ 1 │ L1 Head Hash (bytes32) │ /// │ 2 │ Output Root (bytes32) │ /// │ 3 │ Root Claim (bytes32) │ /// │ 4 │ L2 Block Number (u64) │ /// │ 5 │ Chain ID (u64) │ /// └────────────┴────────────────────────┘ function loadLocalData( uint256 _ident, bytes32 _localContext, bytes32 _word, uint256 _size, uint256 _partOffset ) external returns (bytes32 key_); /// @notice Prepares a preimage to be read by keccak256 key, starting at the given offset and up to 32 bytes /// (clipped at preimage length, if out of data). /// @param _partOffset The offset of the preimage to read. /// @param _preimage The preimage data. function loadKeccak256PreimagePart(uint256 _partOffset, bytes calldata _preimage) external; /// @notice Prepares a preimage to be read by sha256 key, starting at the given offset and up to 32 bytes /// (clipped at preimage length, if out of data). /// @param _partOffset The offset of the preimage to read. /// @param _preimage The preimage data. function loadSha256PreimagePart(uint256 _partOffset, bytes calldata _preimage) external; }
// 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"; import "src/libraries/DisputeErrors.sol"; /// @title LibPosition /// @notice This library contains helper functions for working with the `Position` type. library LibPosition { /// @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(uint64 _depth, uint64 _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 (uint64 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 (uint64 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 + 1` if `_isAttack` is true. /// 1. `_position` 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 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(248, _gameType), shl(184, _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(248, _gameId) timestamp_ := shr(184, and(_gameId, not(shl(248, 0xff)))) gameProxy_ := and(_gameId, 0xffffffffffffffffffffffffffffffffffffffff) } } }
{ "remappings": [ "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@rari-capital/solmate/=lib/solmate/", "@cwia/=lib/clones-with-immutable-args/src/", "@lib-keccak/=lib/lib-keccak/contracts/lib/", "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/=lib/solady/src/", "@eth-optimism/=node_modules/@eth-optimism/", "clones-with-immutable-args/=lib/clones-with-immutable-args/src/", "lib-keccak/=lib/lib-keccak/contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "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", "libraries": {} }
[{"inputs":[{"internalType":"GameType","name":"_gameType","type":"uint8"},{"internalType":"Claim","name":"_absolutePrestate","type":"bytes32"},{"internalType":"uint256","name":"_genesisBlockNumber","type":"uint256"},{"internalType":"Hash","name":"_genesisOutputRoot","type":"bytes32"},{"internalType":"uint256","name":"_maxGameDepth","type":"uint256"},{"internalType":"uint256","name":"_splitDepth","type":"uint256"},{"internalType":"Duration","name":"_gameDuration","type":"uint64"},{"internalType":"contract IBigStepper","name":"_vm","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"BondTransferFailed","type":"error"},{"inputs":[],"name":"CannotDefendRootClaim","type":"error"},{"inputs":[],"name":"ClaimAboveSplit","type":"error"},{"inputs":[],"name":"ClaimAlreadyExists","type":"error"},{"inputs":[],"name":"ClaimAlreadyResolved","type":"error"},{"inputs":[],"name":"ClockNotExpired","type":"error"},{"inputs":[],"name":"ClockTimeExceeded","type":"error"},{"inputs":[],"name":"GameDepthExceeded","type":"error"},{"inputs":[],"name":"GameNotInProgress","type":"error"},{"inputs":[],"name":"InsufficientBond","type":"error"},{"inputs":[],"name":"InvalidLocalIdent","type":"error"},{"inputs":[],"name":"InvalidParent","type":"error"},{"inputs":[],"name":"InvalidPrestate","type":"error"},{"inputs":[],"name":"InvalidSplitDepth","type":"error"},{"inputs":[],"name":"OutOfOrderResolution","type":"error"},{"inputs":[{"internalType":"Claim","name":"rootClaim","type":"bytes32"}],"name":"UnexpectedRootClaim","type":"error"},{"inputs":[],"name":"ValidStep","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"parentIndex","type":"uint256"},{"indexed":true,"internalType":"Claim","name":"claim","type":"bytes32"},{"indexed":true,"internalType":"address","name":"claimant","type":"address"}],"name":"Move","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum GameStatus","name":"status","type":"uint8"}],"name":"Resolved","type":"event"},{"inputs":[],"name":"absolutePrestate","outputs":[{"internalType":"Claim","name":"absolutePrestate_","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ident","type":"uint256"},{"internalType":"uint256","name":"_execLeafIdx","type":"uint256"},{"internalType":"uint256","name":"_partOffset","type":"uint256"}],"name":"addLocalData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_parentIndex","type":"uint256"},{"internalType":"Claim","name":"_claim","type":"bytes32"}],"name":"attack","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimCredit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"claimData","outputs":[{"internalType":"uint32","name":"parentIndex","type":"uint32"},{"internalType":"address","name":"counteredBy","type":"address"},{"internalType":"address","name":"claimant","type":"address"},{"internalType":"uint128","name":"bond","type":"uint128"},{"internalType":"Claim","name":"claim","type":"bytes32"},{"internalType":"Position","name":"position","type":"uint128"},{"internalType":"Clock","name":"clock","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimDataLen","outputs":[{"internalType":"uint256","name":"len_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"createdAt","outputs":[{"internalType":"Timestamp","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"credit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_parentIndex","type":"uint256"},{"internalType":"Claim","name":"_claim","type":"bytes32"}],"name":"defend","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"extraData","outputs":[{"internalType":"bytes","name":"extraData_","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"gameData","outputs":[{"internalType":"GameType","name":"gameType_","type":"uint8"},{"internalType":"Claim","name":"rootClaim_","type":"bytes32"},{"internalType":"bytes","name":"extraData_","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gameDuration","outputs":[{"internalType":"Duration","name":"gameDuration_","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gameType","outputs":[{"internalType":"GameType","name":"gameType_","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"genesisBlockNumber","outputs":[{"internalType":"uint256","name":"genesisBlockNumber_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"genesisOutputRoot","outputs":[{"internalType":"Hash","name":"genesisOutputRoot_","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"Position","name":"_position","type":"uint128"}],"name":"getRequiredBond","outputs":[{"internalType":"uint256","name":"requiredBond_","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"l1Head","outputs":[{"internalType":"Hash","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l2BlockNumber","outputs":[{"internalType":"uint256","name":"l2BlockNumber_","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"maxGameDepth","outputs":[{"internalType":"uint256","name":"maxGameDepth_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_challengeIndex","type":"uint256"},{"internalType":"Claim","name":"_claim","type":"bytes32"},{"internalType":"bool","name":"_isAttack","type":"bool"}],"name":"move","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"resolve","outputs":[{"internalType":"enum GameStatus","name":"status_","type":"uint8"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_claimIndex","type":"uint256"}],"name":"resolveClaim","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"resolvedAt","outputs":[{"internalType":"Timestamp","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rootClaim","outputs":[{"internalType":"Claim","name":"rootClaim_","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"splitDepth","outputs":[{"internalType":"uint256","name":"splitDepth_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"status","outputs":[{"internalType":"enum GameStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_claimIndex","type":"uint256"},{"internalType":"bool","name":"_isAttack","type":"bool"},{"internalType":"bytes","name":"_stateData","type":"bytes"},{"internalType":"bytes","name":"_proof","type":"bytes"}],"name":"step","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vm","outputs":[{"internalType":"contract IBigStepper","name":"vm_","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6101806040523480156200001257600080fd5b5060405162003a4138038062003a41833981016040819052620000359162000098565b838310620000565760405163e62ccf3960e01b815260040160405180910390fd5b60ff90971661016052608095909552610120939093526101409190915260a05260c0526001600160401b031660e0526001600160a01b0316610100526200013a565b600080600080600080600080610100898b031215620000b657600080fd5b885160ff81168114620000c857600080fd5b60208a015160408b015160608c015160808d015160a08e015160c08f0151959d50939b509199509750955093506001600160401b03811681146200010b57600080fd5b60e08a01519092506001600160a01b03811681146200012957600080fd5b809150509295985092959890939650565b60805160a05160c05160e051610100516101205161014051610160516138076200023a6000396000818161049b0152611ffa0152600081816103d30152612bad0152600081816101e10152818161122c01528181611e2e0152611e640152600081816102e6015281816119180152611c1d01526000818161063d01528181610db4015261215801526000818161067001528181610be301528181610cac0152818161177301528181611e04015281816124ff01528181612739015281816128670152818161296f0152612a4b0152600081816106e701528181610c4f015281816116620152611794015260008181610463015261182a01526138076000f3fe6080604052600436106101cd5760003560e01c80638d450a95116100f7578063d5d44d8011610095578063f8f43ff611610064578063f8f43ff614610694578063fa24f743146106b4578063fa315aa9146106d8578063fdffbb281461070b57600080fd5b8063d5d44d80146105e1578063d8cc1a3c1461060e578063e1f0c3761461062e578063ec5e63081461066157600080fd5b8063c395e1ca116100d1578063c395e1ca14610502578063c55cd0c714610523578063c6f0308c14610536578063cf09e0d0146105c057600080fd5b80638d450a9514610454578063bbdc02db14610487578063bcef3b55146104c557600080fd5b8063609d33341161016f57806368800abf1161013e57806368800abf146103c45780638129fc1c146103f75780638980e0cc146103ff5780638b85902b1461041457600080fd5b8063609d33341461036657806360e274641461037b578063632247ea1461039b5780636361506d146103ae57600080fd5b80632810e1d6116101ab5780632810e1d61461029557806335fef567146102aa5780633a768463146102bf57806354fd4d501461031057600080fd5b80630356fe3a146101d257806319effeb414610214578063200d2ed21461025a575b600080fd5b3480156101de57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040519081526020015b60405180910390f35b34801561022057600080fd5b506000546102419068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161020b565b34801561026657600080fd5b5060005461028890700100000000000000000000000000000000900460ff1681565b60405161020b9190613244565b3480156102a157600080fd5b5061028861071e565b6102bd6102b8366004613285565b61091b565b005b3480156102cb57600080fd5b5060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161020b565b34801561031c57600080fd5b506103596040518060400160405280600681526020017f302e302e3234000000000000000000000000000000000000000000000000000081525081565b60405161020b9190613312565b34801561037257600080fd5b5061035961092b565b34801561038757600080fd5b506102bd610396366004613347565b61093d565b6102bd6103a9366004613380565b6109ed565b3480156103ba57600080fd5b5061020160015481565b3480156103d057600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610201565b6102bd6111e8565b34801561040b57600080fd5b50600254610201565b34801561042057600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360200135610201565b34801561046057600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610201565b34801561049357600080fd5b5060405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161020b565b3480156104d157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335610201565b34801561050e57600080fd5b5061020161051d3660046133b5565b50600090565b6102bd610531366004613285565b61150e565b34801561054257600080fd5b506105566105513660046133e7565b61151a565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161020b565b3480156105cc57600080fd5b506000546102419067ffffffffffffffff1681565b3480156105ed57600080fd5b506102016105fc366004613347565b60036020526000908152604090205481565b34801561061a57600080fd5b506102bd610629366004613449565b6115b1565b34801561063a57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610241565b34801561066d57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610201565b3480156106a057600080fd5b506102bd6106af3660046134d3565b611b8f565b3480156106c057600080fd5b506106c9611ff8565b60405161020b939291906134ff565b3480156106e457600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610201565b6102bd6107193660046133e7565b612055565b600080600054700100000000000000000000000000000000900460ff16600281111561074c5761074c613215565b14610783576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60065460ff166107bf576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106107eb576107eb61352a565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614610826576001610829565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156108da576108da613215565b0217905560028111156108ef576108ef613215565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a290565b610927828260006109ed565b5050565b606061093860208061241c565b905090565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260036020526040808220805490839055905190929083908381818185875af1925050503d80600081146109a8576040519150601f19603f3d011682016040523d82523d6000602084013e6109ad565b606091505b50509050806109e8576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60008054700100000000000000000000000000000000900460ff166002811115610a1957610a19613215565b14610a50576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110610a6557610a6561352a565b600091825260208083206040805160e0810182526005909402909101805463ffffffff808216865273ffffffffffffffffffffffffffffffffffffffff6401000000009092048216948601949094526001820154169184019190915260028101546fffffffffffffffffffffffffffffffff90811660608501526003820154608085015260049091015480821660a0850181905270010000000000000000000000000000000090910490911660c0840152919350909190610b2a90839086906124b316565b90506000610bca826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169050861580610c0c5750610c097f00000000000000000000000000000000000000000000000000000000000000006002613588565b81145b8015610c16575084155b15610c4d576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000811115610ca7576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cd27f00000000000000000000000000000000000000000000000000000000000000006001613588565b8103610ce457610ce4868885886124bb565b835160009063ffffffff90811614610d44576002856000015163ffffffff1681548110610d1357610d1361352a565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b60c0850151600090610d689067ffffffffffffffff165b67ffffffffffffffff1690565b67ffffffffffffffff1642610d92610d5b856fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16610da69190613588565b610db091906135a0565b90507f000000000000000000000000000000000000000000000000000000000000000060011c677fffffffffffffff1667ffffffffffffffff82161115610e23576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000604082901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615610ea1576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555050503360028c815481106111265761112661352a565b60009182526020808320600592830201805473ffffffffffffffffffffffffffffffffffffffff95909516640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909516949094179093558d82529091526040902060025461119c906001906135a0565b8154600181018355600092835260208320015560405133918c918e917f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be91a45050505050505050505050565b600654610100900460ff161561122a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360200135116112e1576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560048201526024015b60405180910390fd5b60463611156112f85763c407e0256000526004601cfd5b6040805160e08101825263ffffffff8152600060208201523291810191909152346fffffffffffffffffffffffffffffffff16606082015260029060808101367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335815260016020820152604001426fffffffffffffffffffffffffffffffff90811690915282546001808201855560009485526020808620855160059094020180549186015163ffffffff9094167fffffffffffffffff0000000000000000000000000000000000000000000000009092169190911764010000000073ffffffffffffffffffffffffffffffffffffffff94851602178155604085015181830180547fffffffffffffffffffffffff000000000000000000000000000000000000000016919094161790925560608401516002830180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169185169190911790556080840151600383015560a084015160c09094015193831670010000000000000000000000000000000094909316939093029190911760049091015581547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff16179091556114dc90436135a0565b40600155600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b610927828260016109ed565b6002818154811061152a57600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff1660028111156115dd576115dd613215565b14611614576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600287815481106116295761162961352a565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506116887f00000000000000000000000000000000000000000000000000000000000000006001613588565b611724826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1614611765576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808915611854576117b87f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006135a0565b6001901b6117d7846fffffffffffffffffffffffffffffffff16612673565b67ffffffffffffffff166117eb91906135e6565b156118285761181f61181060016fffffffffffffffffffffffffffffffff87166135fa565b865463ffffffff166000612719565b6003015461184a565b7f00000000000000000000000000000000000000000000000000000000000000005b915084905061187e565b6003850154915061187b6118106fffffffffffffffffffffffffffffffff8616600161362b565b90505b600882901b60088a8a60405161189592919061365f565b6040518091039020901b146118d6576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006118e18c6127fd565b905060006118f0836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e14ced329061196a908f908f908f908f908a906004016136b8565b6020604051808303816000875af1158015611989573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ad91906136f2565b600485015491149150600090600290611a58906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b611af4896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b611afe919061370b565b611b08919061372c565b67ffffffffffffffff161590508115158103611b50576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff166002811115611bbb57611bbb613215565b14611bf2576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600080611c018661282c565b93509350935093506000611c1785858585612c59565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611caa9190613753565b905060018903611d725773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a846001545b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af1158015611d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d6c91906136f2565b50611fed565b60028903611d9e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489611cd6565b60038903611dca5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487611cd6565b60048903611f425760006fffffffffffffffffffffffffffffffff861615611e6257611e286fffffffffffffffffffffffffffffffff87167f0000000000000000000000000000000000000000000000000000000000000000612d18565b611e52907f0000000000000000000000000000000000000000000000000000000000000000613588565b611e5d906001613588565b611e84565b7f00000000000000000000000000000000000000000000000000000000000000005b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af1158015611f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3b91906136f2565b5050611fed565b60058903611fbb576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390524660c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a401611d29565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335606061204e61092b565b9050909192565b60008054700100000000000000000000000000000000900460ff16600281111561208157612081613215565b146120b8576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600282815481106120cd576120cd61352a565b60009182526020822060059190910201600481015490925061210f90700100000000000000000000000000000000900460401c67ffffffffffffffff16610d5b565b600483015490915060009061214190700100000000000000000000000000000000900467ffffffffffffffff16610d5b565b61214b904261370b565b9050677fffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000060011c166121858284613770565b67ffffffffffffffff16116121c6576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526005602052604090208054851580156121e6575060065460ff165b1561221d576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8015801561222a57508515155b1561225c5760018501546122549073ffffffffffffffffffffffffffffffffffffffff1686612dcd565b505050505050565b6000805b8281101561233b57600084828154811061227c5761227c61352a565b60009182526020808320909101548083526005909152604090912054909150156122d2576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600282815481106122e7576122e761352a565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff1661232857339350505061233b565b50508061233490613793565b9050612260565b5061238373ffffffffffffffffffffffffffffffffffffffff821615612361578161237d565b600187015473ffffffffffffffffffffffffffffffffffffffff165b87612dcd565b85547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff83160217865560008781526005602052604081206123df916131db565b8660000361241357600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b50505050505050565b6060600061245384367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003613588565b90508267ffffffffffffffff1667ffffffffffffffff811115612478576124786137cb565b6040519080825280601f01601f1916602001820160405280156124a2576020820181803683370190505b509150828160208401375092915050565b151760011b90565b60006124da6fffffffffffffffffffffffffffffffff8416600161362b565b905060006124ea82866001612719565b9050600086901a83806125dd575061252360027f00000000000000000000000000000000000000000000000000000000000000006135e6565b60048301546002906125c7906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6125d1919061372c565b67ffffffffffffffff16145b156126355760ff8116600114806125f7575060ff81166002145b612630576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016112d8565b612413565b60ff811615612413576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016112d8565b600080612700837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600167ffffffffffffffff919091161b90920392915050565b600080826127625761275d6fffffffffffffffffffffffffffffffff86167f0000000000000000000000000000000000000000000000000000000000000000612eb8565b61277d565b61277d856fffffffffffffffffffffffffffffffff1661307f565b9050600284815481106127925761279261352a565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146127f557815460028054909163ffffffff169081106127e0576127e061352a565b906000526020600020906005020191506127a3565b509392505050565b600080600080600061280e8661282c565b935093509350935061282284848484612c59565b9695505050505050565b600080600080600085905060006002828154811061284c5761284c61352a565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000090612923906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1611612964576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000090612a2b906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169250821115612aa757825463ffffffff16612a717f00000000000000000000000000000000000000000000000000000000000000006001613588565b8303612a7b578391505b60028181548110612a8e57612a8e61352a565b9060005260206000209060050201935080945050612968565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff16612b10612afb856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015612bf5576000612b48836fffffffffffffffffffffffffffffffff16612673565b67ffffffffffffffff161115612bab576000612b82612b7a60016fffffffffffffffffffffffffffffffff86166135fa565b896001612719565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50612bcf9050565b7f00000000000000000000000000000000000000000000000000000000000000009a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750612c4b565b6000612c17612b7a6fffffffffffffffffffffffffffffffff8516600161362b565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff84168103612cbf578282604051602001612ca29291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b604051602081830303815290604052805190602001209050612d10565b60408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a0016040516020818303038152906040528051906020012090505b949350505050565b600080612da5847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1690508083036001841b600180831b0386831b17039250505092915050565b60028101546fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff000000000000000000000000000000018101612e3d576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002820180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff17905573ffffffffffffffffffffffffffffffffffffffff831660009081526003602052604081208054839290612eae908490613588565b9091555050505050565b600081612f57846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1611612f98576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fa18361307f565b905081613040826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff16116130795761307661305d836001613588565b6fffffffffffffffffffffffffffffffff83169061312b565b90505b92915050565b60008119600183011681613113827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169390931c8015179392505050565b6000806131b8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169050808303600180821b0385821b179250505092915050565b50805460008255906000526020600020908101906131f991906131fc565b50565b5b8082111561321157600081556001016131fd565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061327f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561329857600080fd5b50508035926020909101359150565b6000815180845260005b818110156132cd576020818501810151868301820152016132b1565b818111156132df576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061307660208301846132a7565b73ffffffffffffffffffffffffffffffffffffffff811681146131f957600080fd5b60006020828403121561335957600080fd5b813561336481613325565b9392505050565b8035801515811461337b57600080fd5b919050565b60008060006060848603121561339557600080fd5b83359250602084013591506133ac6040850161336b565b90509250925092565b6000602082840312156133c757600080fd5b81356fffffffffffffffffffffffffffffffff8116811461336457600080fd5b6000602082840312156133f957600080fd5b5035919050565b60008083601f84011261341257600080fd5b50813567ffffffffffffffff81111561342a57600080fd5b60208301915083602082850101111561344257600080fd5b9250929050565b6000806000806000806080878903121561346257600080fd5b863595506134726020880161336b565b9450604087013567ffffffffffffffff8082111561348f57600080fd5b61349b8a838b01613400565b909650945060608901359150808211156134b457600080fd5b506134c189828a01613400565b979a9699509497509295939492505050565b6000806000606084860312156134e857600080fd5b505081359360208301359350604090920135919050565b60ff8416815282602082015260606040820152600061352160608301846132a7565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561359b5761359b613559565b500190565b6000828210156135b2576135b2613559565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826135f5576135f56135b7565b500690565b60006fffffffffffffffffffffffffffffffff8381169083168181101561362357613623613559565b039392505050565b60006fffffffffffffffffffffffffffffffff80831681851680830382111561365657613656613559565b01949350505050565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6060815260006136cc60608301878961366f565b82810360208401526136df81868861366f565b9150508260408301529695505050505050565b60006020828403121561370457600080fd5b5051919050565b600067ffffffffffffffff8381169083168181101561362357613623613559565b600067ffffffffffffffff80841680613747576137476135b7565b92169190910692915050565b60006020828403121561376557600080fd5b815161336481613325565b600067ffffffffffffffff80831681851680830382111561365657613656613559565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036137c4576137c4613559565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea164736f6c634300080f000a000000000000000000000000000000000000000000000000000000000000000003c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca9800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000004b00000000000000000000000008e3d2585592ec53538bb9d07e72f4ee9fb5c26ef
Deployed Bytecode
0x6080604052600436106101cd5760003560e01c80638d450a95116100f7578063d5d44d8011610095578063f8f43ff611610064578063f8f43ff614610694578063fa24f743146106b4578063fa315aa9146106d8578063fdffbb281461070b57600080fd5b8063d5d44d80146105e1578063d8cc1a3c1461060e578063e1f0c3761461062e578063ec5e63081461066157600080fd5b8063c395e1ca116100d1578063c395e1ca14610502578063c55cd0c714610523578063c6f0308c14610536578063cf09e0d0146105c057600080fd5b80638d450a9514610454578063bbdc02db14610487578063bcef3b55146104c557600080fd5b8063609d33341161016f57806368800abf1161013e57806368800abf146103c45780638129fc1c146103f75780638980e0cc146103ff5780638b85902b1461041457600080fd5b8063609d33341461036657806360e274641461037b578063632247ea1461039b5780636361506d146103ae57600080fd5b80632810e1d6116101ab5780632810e1d61461029557806335fef567146102aa5780633a768463146102bf57806354fd4d501461031057600080fd5b80630356fe3a146101d257806319effeb414610214578063200d2ed21461025a575b600080fd5b3480156101de57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040519081526020015b60405180910390f35b34801561022057600080fd5b506000546102419068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161020b565b34801561026657600080fd5b5060005461028890700100000000000000000000000000000000900460ff1681565b60405161020b9190613244565b3480156102a157600080fd5b5061028861071e565b6102bd6102b8366004613285565b61091b565b005b3480156102cb57600080fd5b5060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008e3d2585592ec53538bb9d07e72f4ee9fb5c26ef16815260200161020b565b34801561031c57600080fd5b506103596040518060400160405280600681526020017f302e302e3234000000000000000000000000000000000000000000000000000081525081565b60405161020b9190613312565b34801561037257600080fd5b5061035961092b565b34801561038757600080fd5b506102bd610396366004613347565b61093d565b6102bd6103a9366004613380565b6109ed565b3480156103ba57600080fd5b5061020160015481565b3480156103d057600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610201565b6102bd6111e8565b34801561040b57600080fd5b50600254610201565b34801561042057600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360200135610201565b34801561046057600080fd5b507f03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98610201565b34801561049357600080fd5b5060405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161020b565b3480156104d157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335610201565b34801561050e57600080fd5b5061020161051d3660046133b5565b50600090565b6102bd610531366004613285565b61150e565b34801561054257600080fd5b506105566105513660046133e7565b61151a565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161020b565b3480156105cc57600080fd5b506000546102419067ffffffffffffffff1681565b3480156105ed57600080fd5b506102016105fc366004613347565b60036020526000908152604090205481565b34801561061a57600080fd5b506102bd610629366004613449565b6115b1565b34801561063a57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b0610241565b34801561066d57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000e610201565b3480156106a057600080fd5b506102bd6106af3660046134d3565b611b8f565b3480156106c057600080fd5b506106c9611ff8565b60405161020b939291906134ff565b3480156106e457600080fd5b507f000000000000000000000000000000000000000000000000000000000000002c610201565b6102bd6107193660046133e7565b612055565b600080600054700100000000000000000000000000000000900460ff16600281111561074c5761074c613215565b14610783576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60065460ff166107bf576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106107eb576107eb61352a565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614610826576001610829565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156108da576108da613215565b0217905560028111156108ef576108ef613215565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a290565b610927828260006109ed565b5050565b606061093860208061241c565b905090565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260036020526040808220805490839055905190929083908381818185875af1925050503d80600081146109a8576040519150601f19603f3d011682016040523d82523d6000602084013e6109ad565b606091505b50509050806109e8576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60008054700100000000000000000000000000000000900460ff166002811115610a1957610a19613215565b14610a50576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110610a6557610a6561352a565b600091825260208083206040805160e0810182526005909402909101805463ffffffff808216865273ffffffffffffffffffffffffffffffffffffffff6401000000009092048216948601949094526001820154169184019190915260028101546fffffffffffffffffffffffffffffffff90811660608501526003820154608085015260049091015480821660a0850181905270010000000000000000000000000000000090910490911660c0840152919350909190610b2a90839086906124b316565b90506000610bca826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169050861580610c0c5750610c097f000000000000000000000000000000000000000000000000000000000000000e6002613588565b81145b8015610c16575084155b15610c4d576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000002c811115610ca7576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cd27f000000000000000000000000000000000000000000000000000000000000000e6001613588565b8103610ce457610ce4868885886124bb565b835160009063ffffffff90811614610d44576002856000015163ffffffff1681548110610d1357610d1361352a565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b60c0850151600090610d689067ffffffffffffffff165b67ffffffffffffffff1690565b67ffffffffffffffff1642610d92610d5b856fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16610da69190613588565b610db091906135a0565b90507f00000000000000000000000000000000000000000000000000000000000004b060011c677fffffffffffffff1667ffffffffffffffff82161115610e23576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000604082901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615610ea1576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555050503360028c815481106111265761112661352a565b60009182526020808320600592830201805473ffffffffffffffffffffffffffffffffffffffff95909516640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909516949094179093558d82529091526040902060025461119c906001906135a0565b8154600181018355600092835260208320015560405133918c918e917f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be91a45050505050505050505050565b600654610100900460ff161561122a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360200135116112e1576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560048201526024015b60405180910390fd5b60463611156112f85763c407e0256000526004601cfd5b6040805160e08101825263ffffffff8152600060208201523291810191909152346fffffffffffffffffffffffffffffffff16606082015260029060808101367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335815260016020820152604001426fffffffffffffffffffffffffffffffff90811690915282546001808201855560009485526020808620855160059094020180549186015163ffffffff9094167fffffffffffffffff0000000000000000000000000000000000000000000000009092169190911764010000000073ffffffffffffffffffffffffffffffffffffffff94851602178155604085015181830180547fffffffffffffffffffffffff000000000000000000000000000000000000000016919094161790925560608401516002830180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169185169190911790556080840151600383015560a084015160c09094015193831670010000000000000000000000000000000094909316939093029190911760049091015581547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff16179091556114dc90436135a0565b40600155600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b610927828260016109ed565b6002818154811061152a57600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff1660028111156115dd576115dd613215565b14611614576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600287815481106116295761162961352a565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506116887f000000000000000000000000000000000000000000000000000000000000002c6001613588565b611724826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1614611765576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808915611854576117b87f000000000000000000000000000000000000000000000000000000000000000e7f000000000000000000000000000000000000000000000000000000000000002c6135a0565b6001901b6117d7846fffffffffffffffffffffffffffffffff16612673565b67ffffffffffffffff166117eb91906135e6565b156118285761181f61181060016fffffffffffffffffffffffffffffffff87166135fa565b865463ffffffff166000612719565b6003015461184a565b7f03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca985b915084905061187e565b6003850154915061187b6118106fffffffffffffffffffffffffffffffff8616600161362b565b90505b600882901b60088a8a60405161189592919061365f565b6040518091039020901b146118d6576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006118e18c6127fd565b905060006118f0836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f0000000000000000000000008e3d2585592ec53538bb9d07e72f4ee9fb5c26ef73ffffffffffffffffffffffffffffffffffffffff169063e14ced329061196a908f908f908f908f908a906004016136b8565b6020604051808303816000875af1158015611989573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ad91906136f2565b600485015491149150600090600290611a58906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b611af4896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b611afe919061370b565b611b08919061372c565b67ffffffffffffffff161590508115158103611b50576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff166002811115611bbb57611bbb613215565b14611bf2576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600080611c018661282c565b93509350935093506000611c1785858585612c59565b905060007f0000000000000000000000008e3d2585592ec53538bb9d07e72f4ee9fb5c26ef73ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611caa9190613753565b905060018903611d725773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a846001545b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af1158015611d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d6c91906136f2565b50611fed565b60028903611d9e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489611cd6565b60038903611dca5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487611cd6565b60048903611f425760006fffffffffffffffffffffffffffffffff861615611e6257611e286fffffffffffffffffffffffffffffffff87167f000000000000000000000000000000000000000000000000000000000000000e612d18565b611e52907f0000000000000000000000000000000000000000000000000000000000000000613588565b611e5d906001613588565b611e84565b7f00000000000000000000000000000000000000000000000000000000000000005b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af1158015611f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3b91906136f2565b5050611fed565b60058903611fbb576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390524660c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a401611d29565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335606061204e61092b565b9050909192565b60008054700100000000000000000000000000000000900460ff16600281111561208157612081613215565b146120b8576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600282815481106120cd576120cd61352a565b60009182526020822060059190910201600481015490925061210f90700100000000000000000000000000000000900460401c67ffffffffffffffff16610d5b565b600483015490915060009061214190700100000000000000000000000000000000900467ffffffffffffffff16610d5b565b61214b904261370b565b9050677fffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b060011c166121858284613770565b67ffffffffffffffff16116121c6576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526005602052604090208054851580156121e6575060065460ff165b1561221d576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8015801561222a57508515155b1561225c5760018501546122549073ffffffffffffffffffffffffffffffffffffffff1686612dcd565b505050505050565b6000805b8281101561233b57600084828154811061227c5761227c61352a565b60009182526020808320909101548083526005909152604090912054909150156122d2576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600282815481106122e7576122e761352a565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff1661232857339350505061233b565b50508061233490613793565b9050612260565b5061238373ffffffffffffffffffffffffffffffffffffffff821615612361578161237d565b600187015473ffffffffffffffffffffffffffffffffffffffff165b87612dcd565b85547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff83160217865560008781526005602052604081206123df916131db565b8660000361241357600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b50505050505050565b6060600061245384367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003613588565b90508267ffffffffffffffff1667ffffffffffffffff811115612478576124786137cb565b6040519080825280601f01601f1916602001820160405280156124a2576020820181803683370190505b509150828160208401375092915050565b151760011b90565b60006124da6fffffffffffffffffffffffffffffffff8416600161362b565b905060006124ea82866001612719565b9050600086901a83806125dd575061252360027f000000000000000000000000000000000000000000000000000000000000000e6135e6565b60048301546002906125c7906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6125d1919061372c565b67ffffffffffffffff16145b156126355760ff8116600114806125f7575060ff81166002145b612630576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016112d8565b612413565b60ff811615612413576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016112d8565b600080612700837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600167ffffffffffffffff919091161b90920392915050565b600080826127625761275d6fffffffffffffffffffffffffffffffff86167f000000000000000000000000000000000000000000000000000000000000000e612eb8565b61277d565b61277d856fffffffffffffffffffffffffffffffff1661307f565b9050600284815481106127925761279261352a565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146127f557815460028054909163ffffffff169081106127e0576127e061352a565b906000526020600020906005020191506127a3565b509392505050565b600080600080600061280e8661282c565b935093509350935061282284848484612c59565b9695505050505050565b600080600080600085905060006002828154811061284c5761284c61352a565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000e90612923906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1611612964576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000e90612a2b906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169250821115612aa757825463ffffffff16612a717f000000000000000000000000000000000000000000000000000000000000000e6001613588565b8303612a7b578391505b60028181548110612a8e57612a8e61352a565b9060005260206000209060050201935080945050612968565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff16612b10612afb856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015612bf5576000612b48836fffffffffffffffffffffffffffffffff16612673565b67ffffffffffffffff161115612bab576000612b82612b7a60016fffffffffffffffffffffffffffffffff86166135fa565b896001612719565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50612bcf9050565b7f00000000000000000000000000000000000000000000000000000000000000009a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750612c4b565b6000612c17612b7a6fffffffffffffffffffffffffffffffff8516600161362b565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff84168103612cbf578282604051602001612ca29291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b604051602081830303815290604052805190602001209050612d10565b60408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a0016040516020818303038152906040528051906020012090505b949350505050565b600080612da5847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1690508083036001841b600180831b0386831b17039250505092915050565b60028101546fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff000000000000000000000000000000018101612e3d576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002820180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff17905573ffffffffffffffffffffffffffffffffffffffff831660009081526003602052604081208054839290612eae908490613588565b9091555050505050565b600081612f57846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1611612f98576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fa18361307f565b905081613040826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff16116130795761307661305d836001613588565b6fffffffffffffffffffffffffffffffff83169061312b565b90505b92915050565b60008119600183011681613113827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169390931c8015179392505050565b6000806131b8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169050808303600180821b0385821b179250505092915050565b50805460008255906000526020600020908101906131f991906131fc565b50565b5b8082111561321157600081556001016131fd565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061327f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561329857600080fd5b50508035926020909101359150565b6000815180845260005b818110156132cd576020818501810151868301820152016132b1565b818111156132df576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061307660208301846132a7565b73ffffffffffffffffffffffffffffffffffffffff811681146131f957600080fd5b60006020828403121561335957600080fd5b813561336481613325565b9392505050565b8035801515811461337b57600080fd5b919050565b60008060006060848603121561339557600080fd5b83359250602084013591506133ac6040850161336b565b90509250925092565b6000602082840312156133c757600080fd5b81356fffffffffffffffffffffffffffffffff8116811461336457600080fd5b6000602082840312156133f957600080fd5b5035919050565b60008083601f84011261341257600080fd5b50813567ffffffffffffffff81111561342a57600080fd5b60208301915083602082850101111561344257600080fd5b9250929050565b6000806000806000806080878903121561346257600080fd5b863595506134726020880161336b565b9450604087013567ffffffffffffffff8082111561348f57600080fd5b61349b8a838b01613400565b909650945060608901359150808211156134b457600080fd5b506134c189828a01613400565b979a9699509497509295939492505050565b6000806000606084860312156134e857600080fd5b505081359360208301359350604090920135919050565b60ff8416815282602082015260606040820152600061352160608301846132a7565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561359b5761359b613559565b500190565b6000828210156135b2576135b2613559565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826135f5576135f56135b7565b500690565b60006fffffffffffffffffffffffffffffffff8381169083168181101561362357613623613559565b039392505050565b60006fffffffffffffffffffffffffffffffff80831681851680830382111561365657613656613559565b01949350505050565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6060815260006136cc60608301878961366f565b82810360208401526136df81868861366f565b9150508260408301529695505050505050565b60006020828403121561370457600080fd5b5051919050565b600067ffffffffffffffff8381169083168181101561362357613623613559565b600067ffffffffffffffff80841680613747576137476135b7565b92169190910692915050565b60006020828403121561376557600080fd5b815161336481613325565b600067ffffffffffffffff80831681851680830382111561365657613656613559565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036137c4576137c4613559565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea164736f6c634300080f000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000000003c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca9800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000004b00000000000000000000000008e3d2585592ec53538bb9d07e72f4ee9fb5c26ef
-----Decoded View---------------
Arg [0] : _gameType (uint8): 0
Arg [1] : _absolutePrestate (bytes32): 0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98
Arg [2] : _genesisBlockNumber (uint256): 0
Arg [3] : _genesisOutputRoot (bytes32): 0x0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : _maxGameDepth (uint256): 44
Arg [5] : _splitDepth (uint256): 14
Arg [6] : _gameDuration (uint64): 1200
Arg [7] : _vm (address): 0x8E3d2585592EC53538bB9d07e72F4eE9Fb5c26ef
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [1] : 03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 000000000000000000000000000000000000000000000000000000000000002c
Arg [5] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [6] : 00000000000000000000000000000000000000000000000000000000000004b0
Arg [7] : 0000000000000000000000008e3d2585592ec53538bb9d07e72f4ee9fb5c26ef
Loading...
Loading
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.