Commit 78e1084e authored by Inphi's avatar Inphi Committed by GitHub

dispute-game: Sanity check disputed claim index (#10520)

* dispute-game: Sanity check disputed claim index

* Fix tests

* update snapshots

* fix docs

* move param

* op-challenger: Supply parent value when performing moves

Also moves calculation of the required bond into the contract bindings so the returned TxCandidate is ready to send.

* op-challenger: Add backwards compatibility with v1.1.1

* op-e2e: Update e2e for new FaultDisputeGame ABI

---------
Co-authored-by: default avatarAdrian Sutton <adrian@oplabs.co>
parent 5e5d3f70
...@@ -30,35 +30,13 @@ var ( ...@@ -30,35 +30,13 @@ var (
// FaultDisputeGameMetaData contains all meta data concerning the FaultDisputeGame contract. // FaultDisputeGameMetaData contains all meta data concerning the FaultDisputeGame contract.
var FaultDisputeGameMetaData = &bind.MetaData{ var FaultDisputeGameMetaData = &bind.MetaData{
ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint32\",\"internalType\":\"GameType\"},{\"name\":\"_absolutePrestate\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_maxGameDepth\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_splitDepth\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_clockExtension\",\"type\":\"uint64\",\"internalType\":\"Duration\"},{\"name\":\"_maxClockDuration\",\"type\":\"uint64\",\"internalType\":\"Duration\"},{\"name\":\"_vm\",\"type\":\"address\",\"internalType\":\"contractIBigStepper\"},{\"name\":\"_weth\",\"type\":\"address\",\"internalType\":\"contractIDelayedWETH\"},{\"name\":\"_anchorStateRegistry\",\"type\":\"address\",\"internalType\":\"contractIAnchorStateRegistry\"},{\"name\":\"_l2ChainId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"absolutePrestate\",\"inputs\":[],\"outputs\":[{\"name\":\"absolutePrestate_\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addLocalData\",\"inputs\":[{\"name\":\"_ident\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_execLeafIdx\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"anchorStateRegistry\",\"inputs\":[],\"outputs\":[{\"name\":\"registry_\",\"type\":\"address\",\"internalType\":\"contractIAnchorStateRegistry\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"attack\",\"inputs\":[{\"name\":\"_parentIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"claimCredit\",\"inputs\":[{\"name\":\"_recipient\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"claimData\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"parentIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"counteredBy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"bond\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"position\",\"type\":\"uint128\",\"internalType\":\"Position\"},{\"name\":\"clock\",\"type\":\"uint128\",\"internalType\":\"Clock\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"claimDataLen\",\"inputs\":[],\"outputs\":[{\"name\":\"len_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"claims\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"ClaimHash\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"clockExtension\",\"inputs\":[],\"outputs\":[{\"name\":\"clockExtension_\",\"type\":\"uint64\",\"internalType\":\"Duration\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createdAt\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"Timestamp\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"credit\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"defend\",\"inputs\":[{\"name\":\"_parentIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"extraData\",\"inputs\":[],\"outputs\":[{\"name\":\"extraData_\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"gameCreator\",\"inputs\":[],\"outputs\":[{\"name\":\"creator_\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"gameData\",\"inputs\":[],\"outputs\":[{\"name\":\"gameType_\",\"type\":\"uint32\",\"internalType\":\"GameType\"},{\"name\":\"rootClaim_\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"extraData_\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gameType\",\"inputs\":[],\"outputs\":[{\"name\":\"gameType_\",\"type\":\"uint32\",\"internalType\":\"GameType\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getChallengerDuration\",\"inputs\":[{\"name\":\"_claimIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"duration_\",\"type\":\"uint64\",\"internalType\":\"Duration\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNumToResolve\",\"inputs\":[{\"name\":\"_claimIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"numRemainingChildren_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRequiredBond\",\"inputs\":[{\"name\":\"_position\",\"type\":\"uint128\",\"internalType\":\"Position\"}],\"outputs\":[{\"name\":\"requiredBond_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"l1Head\",\"inputs\":[],\"outputs\":[{\"name\":\"l1Head_\",\"type\":\"bytes32\",\"internalType\":\"Hash\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"l2BlockNumber\",\"inputs\":[],\"outputs\":[{\"name\":\"l2BlockNumber_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"l2ChainId\",\"inputs\":[],\"outputs\":[{\"name\":\"l2ChainId_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxClockDuration\",\"inputs\":[],\"outputs\":[{\"name\":\"maxClockDuration_\",\"type\":\"uint64\",\"internalType\":\"Duration\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxGameDepth\",\"inputs\":[],\"outputs\":[{\"name\":\"maxGameDepth_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"move\",\"inputs\":[{\"name\":\"_challengeIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_isAttack\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"resolutionCheckpoints\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"initialCheckpointComplete\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"subgameIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"leftmostPosition\",\"type\":\"uint128\",\"internalType\":\"Position\"},{\"name\":\"counteredBy\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"resolve\",\"inputs\":[],\"outputs\":[{\"name\":\"status_\",\"type\":\"uint8\",\"internalType\":\"enumGameStatus\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resolveClaim\",\"inputs\":[{\"name\":\"_claimIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_numToResolve\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resolvedAt\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"Timestamp\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"resolvedSubgames\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"rootClaim\",\"inputs\":[],\"outputs\":[{\"name\":\"rootClaim_\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"splitDepth\",\"inputs\":[],\"outputs\":[{\"name\":\"splitDepth_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"startingBlockNumber\",\"inputs\":[],\"outputs\":[{\"name\":\"startingBlockNumber_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"startingOutputRoot\",\"inputs\":[],\"outputs\":[{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"Hash\"},{\"name\":\"l2BlockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"startingRootHash\",\"inputs\":[],\"outputs\":[{\"name\":\"startingRootHash_\",\"type\":\"bytes32\",\"internalType\":\"Hash\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"status\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumGameStatus\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"step\",\"inputs\":[{\"name\":\"_claimIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_isAttack\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"_stateData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"subgames\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"vm\",\"inputs\":[],\"outputs\":[{\"name\":\"vm_\",\"type\":\"address\",\"internalType\":\"contractIBigStepper\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"weth\",\"inputs\":[],\"outputs\":[{\"name\":\"weth_\",\"type\":\"address\",\"internalType\":\"contractIDelayedWETH\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"Move\",\"inputs\":[{\"name\":\"parentIndex\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"claim\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"Claim\"},{\"name\":\"claimant\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Resolved\",\"inputs\":[{\"name\":\"status\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"enumGameStatus\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AnchorRootNotFound\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BondTransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CannotDefendRootClaim\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClaimAboveSplit\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClaimAlreadyExists\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClaimAlreadyResolved\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClockNotExpired\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClockTimeExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DuplicateStep\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"GameDepthExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"GameNotInProgress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IncorrectBondAmount\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidClockExtension\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidLocalIdent\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidParent\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidPrestate\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSplitDepth\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MaxDepthTooLarge\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoCreditToClaim\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OutOfOrderResolution\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedRootClaim\",\"inputs\":[{\"name\":\"rootClaim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}]},{\"type\":\"error\",\"name\":\"ValidStep\",\"inputs\":[]}]", ABI: "[{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"_gameType\",\"type\":\"uint32\"},{\"internalType\":\"Claim\",\"name\":\"_absolutePrestate\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_maxGameDepth\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_splitDepth\",\"type\":\"uint256\"},{\"internalType\":\"Duration\",\"name\":\"_clockExtension\",\"type\":\"uint64\"},{\"internalType\":\"Duration\",\"name\":\"_maxClockDuration\",\"type\":\"uint64\"},{\"internalType\":\"contractIBigStepper\",\"name\":\"_vm\",\"type\":\"address\"},{\"internalType\":\"contractIDelayedWETH\",\"name\":\"_weth\",\"type\":\"address\"},{\"internalType\":\"contractIAnchorStateRegistry\",\"name\":\"_anchorStateRegistry\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_l2ChainId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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\":[],\"name\":\"anchorStateRegistry\",\"outputs\":[{\"internalType\":\"contractIAnchorStateRegistry\",\"name\":\"registry_\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"Claim\",\"name\":\"_disputed\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_parentIndex\",\"type\":\"uint256\"},{\"internalType\":\"Claim\",\"name\":\"_claim\",\"type\":\"bytes32\"}],\"name\":\"attack\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messagePasserStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structTypes.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_headerRLP\",\"type\":\"bytes\"}],\"name\":\"challengeRootL2Block\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":[{\"internalType\":\"Hash\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"claims\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clockExtension\",\"outputs\":[{\"internalType\":\"Duration\",\"name\":\"clockExtension_\",\"type\":\"uint64\"}],\"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\":\"Claim\",\"name\":\"_disputed\",\"type\":\"bytes32\"},{\"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\":\"gameCreator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"creator_\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameData\",\"outputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType_\",\"type\":\"uint32\"},{\"internalType\":\"Claim\",\"name\":\"rootClaim_\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"extraData_\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameType\",\"outputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType_\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_claimIndex\",\"type\":\"uint256\"}],\"name\":\"getChallengerDuration\",\"outputs\":[{\"internalType\":\"Duration\",\"name\":\"duration_\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_claimIndex\",\"type\":\"uint256\"}],\"name\":\"getNumToResolve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"numRemainingChildren_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"Position\",\"name\":\"_position\",\"type\":\"uint128\"}],\"name\":\"getRequiredBond\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"requiredBond_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1Head\",\"outputs\":[{\"internalType\":\"Hash\",\"name\":\"l1Head_\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"l2BlockNumber_\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockNumberChallenged\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockNumberChallenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2ChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"l2ChainId_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxClockDuration\",\"outputs\":[{\"internalType\":\"Duration\",\"name\":\"maxClockDuration_\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxGameDepth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"maxGameDepth_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"Claim\",\"name\":\"_disputed\",\"type\":\"bytes32\"},{\"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\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"resolutionCheckpoints\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"initialCheckpointComplete\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"subgameIndex\",\"type\":\"uint32\"},{\"internalType\":\"Position\",\"name\":\"leftmostPosition\",\"type\":\"uint128\"},{\"internalType\":\"address\",\"name\":\"counteredBy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"enumGameStatus\",\"name\":\"status_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_claimIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_numToResolve\",\"type\":\"uint256\"}],\"name\":\"resolveClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resolvedAt\",\"outputs\":[{\"internalType\":\"Timestamp\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"resolvedSubgames\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"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\":\"startingBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"startingBlockNumber_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingOutputRoot\",\"outputs\":[{\"internalType\":\"Hash\",\"name\":\"root\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"l2BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingRootHash\",\"outputs\":[{\"internalType\":\"Hash\",\"name\":\"startingRootHash_\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"status\",\"outputs\":[{\"internalType\":\"enumGameStatus\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"subgames\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vm\",\"outputs\":[{\"internalType\":\"contractIBigStepper\",\"name\":\"vm_\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contractIDelayedWETH\",\"name\":\"weth_\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\":\"enumGameStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"name\":\"Resolved\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AnchorRootNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BlockNumberMatches\",\"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\":\"ContentLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateStep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyItem\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GameDepthExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GameNotInProgress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectBondAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidClockExtension\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataRemainder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDisputedClaimIndex\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidHeader\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidHeaderRLP\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidLocalIdent\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOutputRootProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidParent\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPrestate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSplitDepth\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"L2BlockNumberChallenged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MaxDepthTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoCreditToClaim\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderResolution\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedList\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"}],\"name\":\"UnexpectedRootClaim\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedString\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValidStep\",\"type\":\"error\"}]",
Bin: "0x6101c06040523480156200001257600080fd5b506040516200511438038062005114833981016040819052620000359162000187565b620000436001607e62000248565b60ff168811156200006757604051633beff19960e11b815260040160405180910390fd5b878710620000885760405163e62ccf3960e01b815260040160405180910390fd5b620000a7856001600160401b03166200014e60201b620030381760201c565b6001600160401b0316620000cf876001600160401b03166200014e60201b620030381760201c565b6001600160401b03161115620000f85760405163235dfb2b60e21b815260040160405180910390fd5b63ffffffff9099166101205260809790975260a09590955260c0939093526001600160401b039182166101a0521660e0526001600160a01b0390811661010052908116610140521661016052610180526200027a565b90565b80516001600160401b03811681146200016957600080fd5b919050565b6001600160a01b03811681146200018457600080fd5b50565b6000806000806000806000806000806101408b8d031215620001a857600080fd5b8a5163ffffffff81168114620001bd57600080fd5b809a505060208b0151985060408b0151975060608b01519650620001e460808c0162000151565b9550620001f460a08c0162000151565b945060c08b015162000206816200016e565b60e08c015190945062000219816200016e565b6101008c01519093506200022d816200016e565b809250506101208b015190509295989b9194979a5092959850565b600060ff821660ff8416808210156200027157634e487b7160e01b600052601160045260246000fd5b90039392505050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a051614d22620003f26000396000818161061c0152818161198401528181611a420152611a6c01526000818161096c01526132890152600081816105610152818161131a0152611f95015260008181610488015281816114da01528181611e3c0152818161239601526134170152600081816107c801528181611f54015261331801526000818161045501528181612bfa0152612f4f0152600081816109bf01528181610b9d0152818161191e015281816119af01528181611aa4015281816125a201526125e40152600081816109f2015281816117c40152818161188d01528181611a0d01528181612a4d015281816131510152818161351601528181613c3c01528181613d6a01528181613e6b0152613f40015260008181610aa901528181611830015281816126b201528181612738015281816129430152612a6e0152600081816106c10152612b0c0152614d226000f3fe6080604052600436106102d15760003560e01c80638980e0cc11610179578063cf09e0d0116100d6578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610a76578063fa315aa914610a9a578063fe2bbeb214610acd57600080fd5b8063ec5e6308146109e3578063eff0f59214610a16578063f8f43ff614610a5657600080fd5b8063d6ae3cd5116100bb578063d6ae3cd51461095d578063d8cc1a3c14610990578063dabd396d146109b057600080fd5b8063cf09e0d01461090f578063d5d44d801461093057600080fd5b8063bcef3b551161012d578063c395e1ca11610112578063c395e1ca14610852578063c55cd0c714610872578063c6f0308c1461088557600080fd5b8063bcef3b55146107f2578063bd8da9561461083257600080fd5b80638d450a951161015e5780638d450a95146106b2578063a445ece6146106e5578063bbdc02db146107b157600080fd5b80638980e0cc1461065d5780638b85902b1461067257600080fd5b806354fd4d501161023257806360e27464116101e65780636b6716c0116101c05780636b6716c01461060d57806370872aa5146106405780638129fc1c1461065557600080fd5b806360e274641461059a578063632247ea146105ba5780636361506d146105cd57600080fd5b80635a5fa2d9116102175780635a5fa2d9146105325780635c0cba3314610552578063609d33341461058557600080fd5b806354fd4d50146104ac57806357da950e1461050257600080fd5b80632ad69aeb1161028957806337b1b2291161026e57806337b1b229146103e55780633a768463146104465780633fc8cef31461047957600080fd5b80632ad69aeb146103b257806335fef567146103d257600080fd5b8063200d2ed2116102ba578063200d2ed21461034357806325fc2ace1461037e5780632810e1d61461039d57600080fd5b806303c2924d146102d657806319effeb4146102f8575b600080fd5b3480156102e257600080fd5b506102f66102f136600461459e565b610afd565b005b34801561030457600080fd5b506000546103259068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561034f57600080fd5b5060005461037190700100000000000000000000000000000000900460ff1681565b60405161033a91906145ef565b34801561038a57600080fd5b506007545b60405190815260200161033a565b3480156103a957600080fd5b506103716110f6565b3480156103be57600080fd5b5061038f6103cd36600461459e565b61139b565b6102f66103e036600461459e565b6113cc565b3480156103f157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c5b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161033a565b34801561045257600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610421565b34801561048557600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610421565b3480156104b857600080fd5b506104f56040518060400160405280600681526020017f302e31382e30000000000000000000000000000000000000000000000000000081525081565b60405161033a919061469b565b34801561050e57600080fd5b5060075460085461051d919082565b6040805192835260208301919091520161033a565b34801561053e57600080fd5b5061038f61054d3660046146ae565b6113e1565b34801561055e57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610421565b34801561059157600080fd5b506104f561141b565b3480156105a657600080fd5b506102f66105b53660046146ec565b611429565b6102f66105c8366004614725565b6115d5565b3480156105d957600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013561038f565b34801561061957600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610325565b34801561064c57600080fd5b5060085461038f565b6102f6611ed5565b34801561066957600080fd5b5060015461038f565b34801561067e57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013561038f565b3480156106be57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061038f565b3480156106f157600080fd5b5061075d6107003660046146ae565b6006602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161033a565b3480156107bd57600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161033a565b3480156107fe57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013561038f565b34801561083e57600080fd5b5061032561084d3660046146ae565b61242d565b34801561085e57600080fd5b5061038f61086d36600461475a565b61260c565b6102f661088036600461459e565b6127ef565b34801561089157600080fd5b506108a56108a03660046146ae565b6127fb565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161033a565b34801561091b57600080fd5b506000546103259067ffffffffffffffff1681565b34801561093c57600080fd5b5061038f61094b3660046146ec565b60026020526000908152604090205481565b34801561096957600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061038f565b34801561099c57600080fd5b506102f66109ab3660046147d5565b612892565b3480156109bc57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610325565b3480156109ef57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061038f565b348015610a2257600080fd5b50610a46610a313660046146ae565b60036020526000908152604090205460ff1681565b604051901515815260200161033a565b348015610a6257600080fd5b506102f6610a7136600461485f565b612ec1565b348015610a8257600080fd5b50610a8b613316565b60405161033a9392919061488b565b348015610aa657600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061038f565b348015610ad957600080fd5b50610a46610ae83660046146ae565b60056020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610b2957610b296145c0565b14610b60576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060018381548110610b7557610b756148b0565b906000526020600020906005020190506000610b908461242d565b905067ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081169082161015610bf9576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526005602052604090205460ff1615610c42576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000848152600460205260409020805480158015610c5f57508515155b15610cfa578354640100000000900473ffffffffffffffffffffffffffffffffffffffff1660008115610c925781610cae565b600186015473ffffffffffffffffffffffffffffffffffffffff165b9050610cba8187613376565b50505060009485525050600560205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600660209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152610d9d576fffffffffffffffffffffffffffffffff6040820152600181526000869003610d9d578195505b600086826020015163ffffffff16610db5919061490e565b90506000838211610dc65781610dc8565b835b602084015190915063ffffffff165b81811015610f14576000868281548110610df357610df36148b0565b6000918252602080832090910154808352600590915260409091205490915060ff16610e4b576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060018281548110610e6057610e606148b0565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff16158015610ebd5750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b15610eff57600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b50508080610f0c90614926565b915050610dd7565b5063ffffffff818116602085810191825260008c81526006909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558490036110eb57606083015187547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff831690810291909117895560008b815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556110e990156110c757816110e3565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613376565b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff166002811115611124576111246145c0565b1461115b576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260056020527f05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc5460ff166111bf576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660016000815481106111eb576111eb6148b0565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611226576001611229565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156112da576112da6145c0565b0217905560028111156112ef576112ef6145c0565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561138057600080fd5b505af1158015611394573d6000803e3d6000fd5b5050505090565b600460205281600052604060002081815481106113b757600080fd5b90600052602060002001600091509150505481565b6113d8828260006115d5565b5050565b905090565b6000818152600660209081526040808320600490925282208054825461141290610100900463ffffffff168261495e565b95945050505050565b60606113dc60546020613478565b73ffffffffffffffffffffffffffffffffffffffff811660009081526002602052604081208054908290559081900361148e576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063f3fef3a390604401600060405180830381600087803b15801561151e57600080fd5b505af1158015611532573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611590576040519150601f19603f3d011682016040523d82523d6000602084013e611595565b606091505b50509050806115d0576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60008054700100000000000000000000000000000000900460ff166002811115611601576116016145c0565b14611638576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001848154811061164d5761164d6148b0565b600091825260208083206040805160e0810182526005909402909101805463ffffffff808216865273ffffffffffffffffffffffffffffffffffffffff6401000000009092048216948601949094526001820154169184019190915260028101546fffffffffffffffffffffffffffffffff90811660608501526003820154608085015260049091015480821660a0850181905270010000000000000000000000000000000090910490911660c084015291935090919061171290839086906134ca16565b905060006117b2826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508615806117ed57506117ea7f0000000000000000000000000000000000000000000000000000000000000000600261490e565b81145b80156117f7575084155b1561182e576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000811115611888576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118b37f0000000000000000000000000000000000000000000000000000000000000000600161490e565b81036118c5576118c5868885886134d2565b346118cf8361260c565b14611906576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006119118861242d565b905067ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811690821603611979576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001667ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166119d99190614975565b67ffffffffffffffff166119f48267ffffffffffffffff1690565b67ffffffffffffffff161115611ad6576000611a3160017f000000000000000000000000000000000000000000000000000000000000000061495e565b8314611a675767ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016611a9c565b611a9c7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16600261499e565b9050611ad2817f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16614975565b9150505b6000604082901b42176000898152608086901b6fffffffffffffffffffffffffffffffff8c1617602052604081209192509060008181526003602052604090205490915060ff1615611b54576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016003600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060016040518060e001604052808c63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018b8152602001876fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600460008b815260200190815260200160002060018080549050611de9919061495e565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263d0e30db09234926004808301939282900301818588803b158015611e8157600080fd5b505af1158015611e95573d6000803e3d6000fd5b50506040513393508c92508d91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a450505050505050505050565b60005471010000000000000000000000000000000000900460ff1615611f27576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690637258a807906024016040805180830381865afa158015611fdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fff91906149ce565b90925090508161203b576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526007829055600881905536607a1461206e57639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013511612108576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c0190815282548084018455928a529a5160059092027fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf681018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf787018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf8860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf985015551955182167001000000000000000000000000000000000295909116949094177fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfa9091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f00000000000000000000000000000000000000000000000000000000000000009092169363d0e30db093926004828101939282900301818588803b1580156123dc57600080fd5b505af11580156123f0573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff16600281111561245b5761245b6145c0565b14612492576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600183815481106124a7576124a76148b0565b600091825260208220600590910201805490925063ffffffff9081161461251657815460018054909163ffffffff169081106124e5576124e56148b0565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b600482015460009061254e90700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b6125629067ffffffffffffffff164261495e565b612581612541846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612595919061490e565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001667ffffffffffffffff168167ffffffffffffffff16116125e25780611412565b7f000000000000000000000000000000000000000000000000000000000000000095945050505050565b6000806126ab836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f000000000000000000000000000000000000000000000000000000000000000081111561270a576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a30060006127258383614a21565b9050670de0b6b3a7640000600061275c827f0000000000000000000000000000000000000000000000000000000000000000614a35565b9050600061277a612775670de0b6b3a764000086614a35565b613683565b9050600061278884846138de565b90506000612796838361392d565b905060006127a38261395b565b905060006127c2826127bd670de0b6b3a76400008f614a35565b613b43565b905060006127d08b8361392d565b90506127dc818d614a35565b9f9e505050505050505050505050505050565b6113d8828260016115d5565b6001818154811061280b57600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff1660028111156128be576128be6145c0565b146128f5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001878154811061290a5761290a6148b0565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506129697f0000000000000000000000000000000000000000000000000000000000000000600161490e565b612a05826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614612a3f576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808915612b3657612a927f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061495e565b6001901b612ab1846fffffffffffffffffffffffffffffffff16613b7d565b6fffffffffffffffffffffffffffffffff16612acd9190614a72565b15612b0a57612b01612af260016fffffffffffffffffffffffffffffffff8716614a86565b865463ffffffff166000613c1c565b60030154612b2c565b7f00000000000000000000000000000000000000000000000000000000000000005b9150849050612b60565b60038501549150612b5d612af26fffffffffffffffffffffffffffffffff86166001614aaf565b90505b600882901b60088a8a604051612b77929190614ae3565b6040518091039020901b14612bb8576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612bc38c613d00565b90506000612bd2836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e14ced3290612c4c908f908f908f908f908a90600401614b3c565b6020604051808303816000875af1158015612c6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c8f9190614b76565b600485015491149150600090600290612d3a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b612dd6896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b612de09190614b8f565b612dea9190614bb2565b60ff161590508115158103612e2b576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff1615612e82576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff166002811115612eed57612eed6145c0565b14612f24576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600080612f3386613d2f565b93509350935093506000612f4985858585614138565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fdc9190614bd4565b9050600189036130d75773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461303b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b90565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156130ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130d19190614b76565b506110eb565b600289036131035773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961303b565b6003890361312f5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761303b565b6004890361324b5760006131756fffffffffffffffffffffffffffffffff85167f00000000000000000000000000000000000000000000000000000000000000006141f2565b600854613182919061490e565b61318d90600161490e565b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af1158015613220573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132449190614b76565b50506110eb565b600589036132e4576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000000060c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a40161308e565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360140135606061336f61141b565b9050909192565b60028082015473ffffffffffffffffffffffffffffffffffffffff841660009081526020929092526040822080546fffffffffffffffffffffffffffffffff9092169283926133c690849061490e565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f00000000000000000000000000000000000000000000000000000000000000001690637eee288d90604401600060405180830381600087803b15801561345b57600080fd5b505af115801561346f573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b151760011b90565b60006134f16fffffffffffffffffffffffffffffffff84166001614aaf565b9050600061350182866001613c1c565b9050600086901a83806135ed575061353a60027f0000000000000000000000000000000000000000000000000000000000000000614a72565b60048301546002906135de906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6135e89190614bb2565b60ff16145b156136455760ff811660011480613607575060ff81166002145b613640576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016120ff565b61346f565b60ff81161561346f576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016120ff565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136136e257631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261391b57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b60008160001904831182021561394b5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361398957919050565b680755bf798b4a1bf1e582126139a75763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613b74670de0b6b3a764000083613b5b86613683565b613b659190614bf1565b613b6f9190614cad565b61395b565b90505b92915050565b600080613c0a837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b60008082613c6557613c606fffffffffffffffffffffffffffffffff86167f00000000000000000000000000000000000000000000000000000000000000006142a0565b613c80565b613c80856fffffffffffffffffffffffffffffffff16614450565b905060018481548110613c9557613c956148b0565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff828116911614613cf857815460018054909163ffffffff16908110613ce357613ce36148b0565b90600052602060002090600502019150613ca6565b509392505050565b6000806000806000613d1186613d2f565b9350935093509350613d2584848484614138565b9695505050505050565b6000806000806000859050600060018281548110613d4f57613d4f6148b0565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000090613e26906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613e60576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000090613f27906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169250821115613f9c57825463ffffffff16613f667f0000000000000000000000000000000000000000000000000000000000000000600161490e565b8303613f70578391505b60018181548110613f8357613f836148b0565b9060005260206000209060050201935080945050613e64565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff16614005613ff0856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1614905080156140d457600061403d836fffffffffffffffffffffffffffffffff16613b7d565b6fffffffffffffffffffffffffffffffff1611156140a857600061407f61407760016fffffffffffffffffffffffffffffffff8616614a86565b896001613c1c565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506140ae9050565b6007549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff16975061412a565b60006140f66140776fffffffffffffffffffffffffffffffff85166001614aaf565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff8416156141a55760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611412565b82826040516020016141d39291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b60008061427f847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008161433f846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611614379576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61438283614450565b905081614421826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613b7757613b7461443783600161490e565b6fffffffffffffffffffffffffffffffff8316906144f5565b600081196001830116816144e4827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b600080614582847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b600080604083850312156145b157600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061462a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000815180845260005b818110156146565760208185018101518683018201520161463a565b81811115614668576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613b746020830184614630565b6000602082840312156146c057600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146146e957600080fd5b50565b6000602082840312156146fe57600080fd5b8135614709816146c7565b9392505050565b8035801515811461472057600080fd5b919050565b60008060006060848603121561473a57600080fd5b833592506020840135915061475160408501614710565b90509250925092565b60006020828403121561476c57600080fd5b81356fffffffffffffffffffffffffffffffff8116811461470957600080fd5b60008083601f84011261479e57600080fd5b50813567ffffffffffffffff8111156147b657600080fd5b6020830191508360208285010111156147ce57600080fd5b9250929050565b600080600080600080608087890312156147ee57600080fd5b863595506147fe60208801614710565b9450604087013567ffffffffffffffff8082111561481b57600080fd5b6148278a838b0161478c565b9096509450606089013591508082111561484057600080fd5b5061484d89828a0161478c565b979a9699509497509295939492505050565b60008060006060848603121561487457600080fd5b505081359360208301359350604090920135919050565b63ffffffff841681528260208201526060604082015260006114126060830184614630565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115614921576149216148df565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614957576149576148df565b5060010190565b600082821015614970576149706148df565b500390565b600067ffffffffffffffff83811690831681811015614996576149966148df565b039392505050565b600067ffffffffffffffff808316818516818304811182151516156149c5576149c56148df565b02949350505050565b600080604083850312156149e157600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614a3057614a306149f2565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614a6d57614a6d6148df565b500290565b600082614a8157614a816149f2565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015614996576149966148df565b60006fffffffffffffffffffffffffffffffff808316818516808303821115614ada57614ada6148df565b01949350505050565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000614b50606083018789614af3565b8281036020840152614b63818688614af3565b9150508260408301529695505050505050565b600060208284031215614b8857600080fd5b5051919050565b600060ff821660ff841680821015614ba957614ba96148df565b90039392505050565b600060ff831680614bc557614bc56149f2565b8060ff84160691505092915050565b600060208284031215614be657600080fd5b8151614709816146c7565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615614c3257614c326148df565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615614c6d57614c6d6148df565b60008712925087820587128484161615614c8957614c896148df565b87850587128184161615614c9f57614c9f6148df565b505050929093029392505050565b600082614cbc57614cbc6149f2565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615614d1057614d106148df565b50059056fea164736f6c634300080f000a",
} }
// FaultDisputeGameABI is the input ABI used to generate the binding from. // FaultDisputeGameABI is the input ABI used to generate the binding from.
// Deprecated: Use FaultDisputeGameMetaData.ABI instead. // Deprecated: Use FaultDisputeGameMetaData.ABI instead.
var FaultDisputeGameABI = FaultDisputeGameMetaData.ABI var FaultDisputeGameABI = FaultDisputeGameMetaData.ABI
// FaultDisputeGameBin is the compiled bytecode used for deploying new contracts.
// Deprecated: Use FaultDisputeGameMetaData.Bin instead.
var FaultDisputeGameBin = FaultDisputeGameMetaData.Bin
// DeployFaultDisputeGame deploys a new Ethereum contract, binding an instance of FaultDisputeGame to it.
func DeployFaultDisputeGame(auth *bind.TransactOpts, backend bind.ContractBackend, _gameType uint32, _absolutePrestate [32]byte, _maxGameDepth *big.Int, _splitDepth *big.Int, _clockExtension uint64, _maxClockDuration uint64, _vm common.Address, _weth common.Address, _anchorStateRegistry common.Address, _l2ChainId *big.Int) (common.Address, *types.Transaction, *FaultDisputeGame, error) {
parsed, err := FaultDisputeGameMetaData.GetAbi()
if err != nil {
return common.Address{}, nil, nil, err
}
if parsed == nil {
return common.Address{}, nil, nil, errors.New("GetABI returned nil")
}
address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(FaultDisputeGameBin), backend, _gameType, _absolutePrestate, _maxGameDepth, _splitDepth, _clockExtension, _maxClockDuration, _vm, _weth, _anchorStateRegistry, _l2ChainId)
if err != nil {
return common.Address{}, nil, nil, err
}
return address, tx, &FaultDisputeGame{FaultDisputeGameCaller: FaultDisputeGameCaller{contract: contract}, FaultDisputeGameTransactor: FaultDisputeGameTransactor{contract: contract}, FaultDisputeGameFilterer: FaultDisputeGameFilterer{contract: contract}}, nil
}
// FaultDisputeGame is an auto generated Go binding around an Ethereum contract. // FaultDisputeGame is an auto generated Go binding around an Ethereum contract.
type FaultDisputeGame struct { type FaultDisputeGame struct {
FaultDisputeGameCaller // Read-only binding to the contract FaultDisputeGameCaller // Read-only binding to the contract
...@@ -786,6 +764,68 @@ func (_FaultDisputeGame *FaultDisputeGameCallerSession) L2BlockNumber() (*big.In ...@@ -786,6 +764,68 @@ func (_FaultDisputeGame *FaultDisputeGameCallerSession) L2BlockNumber() (*big.In
return _FaultDisputeGame.Contract.L2BlockNumber(&_FaultDisputeGame.CallOpts) return _FaultDisputeGame.Contract.L2BlockNumber(&_FaultDisputeGame.CallOpts)
} }
// L2BlockNumberChallenged is a free data retrieval call binding the contract method 0x3e3ac912.
//
// Solidity: function l2BlockNumberChallenged() view returns(bool)
func (_FaultDisputeGame *FaultDisputeGameCaller) L2BlockNumberChallenged(opts *bind.CallOpts) (bool, error) {
var out []interface{}
err := _FaultDisputeGame.contract.Call(opts, &out, "l2BlockNumberChallenged")
if err != nil {
return *new(bool), err
}
out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
return out0, err
}
// L2BlockNumberChallenged is a free data retrieval call binding the contract method 0x3e3ac912.
//
// Solidity: function l2BlockNumberChallenged() view returns(bool)
func (_FaultDisputeGame *FaultDisputeGameSession) L2BlockNumberChallenged() (bool, error) {
return _FaultDisputeGame.Contract.L2BlockNumberChallenged(&_FaultDisputeGame.CallOpts)
}
// L2BlockNumberChallenged is a free data retrieval call binding the contract method 0x3e3ac912.
//
// Solidity: function l2BlockNumberChallenged() view returns(bool)
func (_FaultDisputeGame *FaultDisputeGameCallerSession) L2BlockNumberChallenged() (bool, error) {
return _FaultDisputeGame.Contract.L2BlockNumberChallenged(&_FaultDisputeGame.CallOpts)
}
// L2BlockNumberChallenger is a free data retrieval call binding the contract method 0x30dbe570.
//
// Solidity: function l2BlockNumberChallenger() view returns(address)
func (_FaultDisputeGame *FaultDisputeGameCaller) L2BlockNumberChallenger(opts *bind.CallOpts) (common.Address, error) {
var out []interface{}
err := _FaultDisputeGame.contract.Call(opts, &out, "l2BlockNumberChallenger")
if err != nil {
return *new(common.Address), err
}
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
return out0, err
}
// L2BlockNumberChallenger is a free data retrieval call binding the contract method 0x30dbe570.
//
// Solidity: function l2BlockNumberChallenger() view returns(address)
func (_FaultDisputeGame *FaultDisputeGameSession) L2BlockNumberChallenger() (common.Address, error) {
return _FaultDisputeGame.Contract.L2BlockNumberChallenger(&_FaultDisputeGame.CallOpts)
}
// L2BlockNumberChallenger is a free data retrieval call binding the contract method 0x30dbe570.
//
// Solidity: function l2BlockNumberChallenger() view returns(address)
func (_FaultDisputeGame *FaultDisputeGameCallerSession) L2BlockNumberChallenger() (common.Address, error) {
return _FaultDisputeGame.Contract.L2BlockNumberChallenger(&_FaultDisputeGame.CallOpts)
}
// L2ChainId is a free data retrieval call binding the contract method 0xd6ae3cd5. // L2ChainId is a free data retrieval call binding the contract method 0xd6ae3cd5.
// //
// Solidity: function l2ChainId() view returns(uint256 l2ChainId_) // Solidity: function l2ChainId() view returns(uint256 l2ChainId_)
...@@ -1341,25 +1381,46 @@ func (_FaultDisputeGame *FaultDisputeGameTransactorSession) AddLocalData(_ident ...@@ -1341,25 +1381,46 @@ func (_FaultDisputeGame *FaultDisputeGameTransactorSession) AddLocalData(_ident
return _FaultDisputeGame.Contract.AddLocalData(&_FaultDisputeGame.TransactOpts, _ident, _execLeafIdx, _partOffset) return _FaultDisputeGame.Contract.AddLocalData(&_FaultDisputeGame.TransactOpts, _ident, _execLeafIdx, _partOffset)
} }
// Attack is a paid mutator transaction binding the contract method 0xc55cd0c7. // Attack is a paid mutator transaction binding the contract method 0x472777c6.
//
// Solidity: function attack(bytes32 _disputed, uint256 _parentIndex, bytes32 _claim) payable returns()
func (_FaultDisputeGame *FaultDisputeGameTransactor) Attack(opts *bind.TransactOpts, _disputed [32]byte, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) {
return _FaultDisputeGame.contract.Transact(opts, "attack", _disputed, _parentIndex, _claim)
}
// Attack is a paid mutator transaction binding the contract method 0x472777c6.
//
// Solidity: function attack(bytes32 _disputed, uint256 _parentIndex, bytes32 _claim) payable returns()
func (_FaultDisputeGame *FaultDisputeGameSession) Attack(_disputed [32]byte, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) {
return _FaultDisputeGame.Contract.Attack(&_FaultDisputeGame.TransactOpts, _disputed, _parentIndex, _claim)
}
// Attack is a paid mutator transaction binding the contract method 0x472777c6.
//
// Solidity: function attack(bytes32 _disputed, uint256 _parentIndex, bytes32 _claim) payable returns()
func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Attack(_disputed [32]byte, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) {
return _FaultDisputeGame.Contract.Attack(&_FaultDisputeGame.TransactOpts, _disputed, _parentIndex, _claim)
}
// ChallengeRootL2Block is a paid mutator transaction binding the contract method 0x01935130.
// //
// Solidity: function attack(uint256 _parentIndex, bytes32 _claim) payable returns() // Solidity: function challengeRootL2Block((bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _headerRLP) returns()
func (_FaultDisputeGame *FaultDisputeGameTransactor) Attack(opts *bind.TransactOpts, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { func (_FaultDisputeGame *FaultDisputeGameTransactor) ChallengeRootL2Block(opts *bind.TransactOpts, _outputRootProof TypesOutputRootProof, _headerRLP []byte) (*types.Transaction, error) {
return _FaultDisputeGame.contract.Transact(opts, "attack", _parentIndex, _claim) return _FaultDisputeGame.contract.Transact(opts, "challengeRootL2Block", _outputRootProof, _headerRLP)
} }
// Attack is a paid mutator transaction binding the contract method 0xc55cd0c7. // ChallengeRootL2Block is a paid mutator transaction binding the contract method 0x01935130.
// //
// Solidity: function attack(uint256 _parentIndex, bytes32 _claim) payable returns() // Solidity: function challengeRootL2Block((bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _headerRLP) returns()
func (_FaultDisputeGame *FaultDisputeGameSession) Attack(_parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { func (_FaultDisputeGame *FaultDisputeGameSession) ChallengeRootL2Block(_outputRootProof TypesOutputRootProof, _headerRLP []byte) (*types.Transaction, error) {
return _FaultDisputeGame.Contract.Attack(&_FaultDisputeGame.TransactOpts, _parentIndex, _claim) return _FaultDisputeGame.Contract.ChallengeRootL2Block(&_FaultDisputeGame.TransactOpts, _outputRootProof, _headerRLP)
} }
// Attack is a paid mutator transaction binding the contract method 0xc55cd0c7. // ChallengeRootL2Block is a paid mutator transaction binding the contract method 0x01935130.
// //
// Solidity: function attack(uint256 _parentIndex, bytes32 _claim) payable returns() // Solidity: function challengeRootL2Block((bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _headerRLP) returns()
func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Attack(_parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { func (_FaultDisputeGame *FaultDisputeGameTransactorSession) ChallengeRootL2Block(_outputRootProof TypesOutputRootProof, _headerRLP []byte) (*types.Transaction, error) {
return _FaultDisputeGame.Contract.Attack(&_FaultDisputeGame.TransactOpts, _parentIndex, _claim) return _FaultDisputeGame.Contract.ChallengeRootL2Block(&_FaultDisputeGame.TransactOpts, _outputRootProof, _headerRLP)
} }
// ClaimCredit is a paid mutator transaction binding the contract method 0x60e27464. // ClaimCredit is a paid mutator transaction binding the contract method 0x60e27464.
...@@ -1383,25 +1444,25 @@ func (_FaultDisputeGame *FaultDisputeGameTransactorSession) ClaimCredit(_recipie ...@@ -1383,25 +1444,25 @@ func (_FaultDisputeGame *FaultDisputeGameTransactorSession) ClaimCredit(_recipie
return _FaultDisputeGame.Contract.ClaimCredit(&_FaultDisputeGame.TransactOpts, _recipient) return _FaultDisputeGame.Contract.ClaimCredit(&_FaultDisputeGame.TransactOpts, _recipient)
} }
// Defend is a paid mutator transaction binding the contract method 0x35fef567. // Defend is a paid mutator transaction binding the contract method 0x7b0f0adc.
// //
// Solidity: function defend(uint256 _parentIndex, bytes32 _claim) payable returns() // Solidity: function defend(bytes32 _disputed, uint256 _parentIndex, bytes32 _claim) payable returns()
func (_FaultDisputeGame *FaultDisputeGameTransactor) Defend(opts *bind.TransactOpts, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { func (_FaultDisputeGame *FaultDisputeGameTransactor) Defend(opts *bind.TransactOpts, _disputed [32]byte, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) {
return _FaultDisputeGame.contract.Transact(opts, "defend", _parentIndex, _claim) return _FaultDisputeGame.contract.Transact(opts, "defend", _disputed, _parentIndex, _claim)
} }
// Defend is a paid mutator transaction binding the contract method 0x35fef567. // Defend is a paid mutator transaction binding the contract method 0x7b0f0adc.
// //
// Solidity: function defend(uint256 _parentIndex, bytes32 _claim) payable returns() // Solidity: function defend(bytes32 _disputed, uint256 _parentIndex, bytes32 _claim) payable returns()
func (_FaultDisputeGame *FaultDisputeGameSession) Defend(_parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { func (_FaultDisputeGame *FaultDisputeGameSession) Defend(_disputed [32]byte, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) {
return _FaultDisputeGame.Contract.Defend(&_FaultDisputeGame.TransactOpts, _parentIndex, _claim) return _FaultDisputeGame.Contract.Defend(&_FaultDisputeGame.TransactOpts, _disputed, _parentIndex, _claim)
} }
// Defend is a paid mutator transaction binding the contract method 0x35fef567. // Defend is a paid mutator transaction binding the contract method 0x7b0f0adc.
// //
// Solidity: function defend(uint256 _parentIndex, bytes32 _claim) payable returns() // Solidity: function defend(bytes32 _disputed, uint256 _parentIndex, bytes32 _claim) payable returns()
func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Defend(_parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Defend(_disputed [32]byte, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) {
return _FaultDisputeGame.Contract.Defend(&_FaultDisputeGame.TransactOpts, _parentIndex, _claim) return _FaultDisputeGame.Contract.Defend(&_FaultDisputeGame.TransactOpts, _disputed, _parentIndex, _claim)
} }
// Initialize is a paid mutator transaction binding the contract method 0x8129fc1c. // Initialize is a paid mutator transaction binding the contract method 0x8129fc1c.
...@@ -1425,25 +1486,25 @@ func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Initialize() (*types ...@@ -1425,25 +1486,25 @@ func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Initialize() (*types
return _FaultDisputeGame.Contract.Initialize(&_FaultDisputeGame.TransactOpts) return _FaultDisputeGame.Contract.Initialize(&_FaultDisputeGame.TransactOpts)
} }
// Move is a paid mutator transaction binding the contract method 0x632247ea. // Move is a paid mutator transaction binding the contract method 0x6f034409.
// //
// Solidity: function move(uint256 _challengeIndex, bytes32 _claim, bool _isAttack) payable returns() // Solidity: function move(bytes32 _disputed, uint256 _challengeIndex, bytes32 _claim, bool _isAttack) payable returns()
func (_FaultDisputeGame *FaultDisputeGameTransactor) Move(opts *bind.TransactOpts, _challengeIndex *big.Int, _claim [32]byte, _isAttack bool) (*types.Transaction, error) { func (_FaultDisputeGame *FaultDisputeGameTransactor) Move(opts *bind.TransactOpts, _disputed [32]byte, _challengeIndex *big.Int, _claim [32]byte, _isAttack bool) (*types.Transaction, error) {
return _FaultDisputeGame.contract.Transact(opts, "move", _challengeIndex, _claim, _isAttack) return _FaultDisputeGame.contract.Transact(opts, "move", _disputed, _challengeIndex, _claim, _isAttack)
} }
// Move is a paid mutator transaction binding the contract method 0x632247ea. // Move is a paid mutator transaction binding the contract method 0x6f034409.
// //
// Solidity: function move(uint256 _challengeIndex, bytes32 _claim, bool _isAttack) payable returns() // Solidity: function move(bytes32 _disputed, uint256 _challengeIndex, bytes32 _claim, bool _isAttack) payable returns()
func (_FaultDisputeGame *FaultDisputeGameSession) Move(_challengeIndex *big.Int, _claim [32]byte, _isAttack bool) (*types.Transaction, error) { func (_FaultDisputeGame *FaultDisputeGameSession) Move(_disputed [32]byte, _challengeIndex *big.Int, _claim [32]byte, _isAttack bool) (*types.Transaction, error) {
return _FaultDisputeGame.Contract.Move(&_FaultDisputeGame.TransactOpts, _challengeIndex, _claim, _isAttack) return _FaultDisputeGame.Contract.Move(&_FaultDisputeGame.TransactOpts, _disputed, _challengeIndex, _claim, _isAttack)
} }
// Move is a paid mutator transaction binding the contract method 0x632247ea. // Move is a paid mutator transaction binding the contract method 0x6f034409.
// //
// Solidity: function move(uint256 _challengeIndex, bytes32 _claim, bool _isAttack) payable returns() // Solidity: function move(bytes32 _disputed, uint256 _challengeIndex, bytes32 _claim, bool _isAttack) payable returns()
func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Move(_challengeIndex *big.Int, _claim [32]byte, _isAttack bool) (*types.Transaction, error) { func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Move(_disputed [32]byte, _challengeIndex *big.Int, _claim [32]byte, _isAttack bool) (*types.Transaction, error) {
return _FaultDisputeGame.Contract.Move(&_FaultDisputeGame.TransactOpts, _challengeIndex, _claim, _isAttack) return _FaultDisputeGame.Contract.Move(&_FaultDisputeGame.TransactOpts, _disputed, _challengeIndex, _claim, _isAttack)
} }
// Resolve is a paid mutator transaction binding the contract method 0x2810e1d6. // Resolve is a paid mutator transaction binding the contract method 0x2810e1d6.
......
...@@ -51,14 +51,18 @@ func Move(ctx *cli.Context) error { ...@@ -51,14 +51,18 @@ func Move(ctx *cli.Context) error {
return fmt.Errorf("failed to create dispute game bindings: %w", err) return fmt.Errorf("failed to create dispute game bindings: %w", err)
} }
parentClaim, err := contract.GetClaim(ctx.Context, parentIndex)
if err != nil {
return fmt.Errorf("failed to get parent claim: %w", err)
}
var tx txmgr.TxCandidate var tx txmgr.TxCandidate
if attack { if attack {
tx, err = contract.AttackTx(parentIndex, claim) tx, err = contract.AttackTx(ctx.Context, parentClaim, claim)
if err != nil { if err != nil {
return fmt.Errorf("failed to create attack tx: %w", err) return fmt.Errorf("failed to create attack tx: %w", err)
} }
} else if defend { } else if defend {
tx, err = contract.DefendTx(parentIndex, claim) tx, err = contract.DefendTx(ctx.Context, parentClaim, claim)
if err != nil { if err != nil {
return fmt.Errorf("failed to create defense tx: %w", err) return fmt.Errorf("failed to create defense tx: %w", err)
} }
......
...@@ -120,7 +120,7 @@ func (a *Agent) performAction(ctx context.Context, wg *sync.WaitGroup, action ty ...@@ -120,7 +120,7 @@ func (a *Agent) performAction(ctx context.Context, wg *sync.WaitGroup, action ty
isLocal := containsOracleData && action.OracleData.IsLocal isLocal := containsOracleData && action.OracleData.IsLocal
actionLog = actionLog.New( actionLog = actionLog.New(
"is_attack", action.IsAttack, "is_attack", action.IsAttack,
"parent", action.ParentIdx, "parent", action.ParentClaim.ContractIndex,
"prestate", common.Bytes2Hex(action.PreState), "prestate", common.Bytes2Hex(action.PreState),
"proof", common.Bytes2Hex(action.ProofData), "proof", common.Bytes2Hex(action.ProofData),
"containsOracleData", containsOracleData, "containsOracleData", containsOracleData,
...@@ -130,7 +130,7 @@ func (a *Agent) performAction(ctx context.Context, wg *sync.WaitGroup, action ty ...@@ -130,7 +130,7 @@ func (a *Agent) performAction(ctx context.Context, wg *sync.WaitGroup, action ty
actionLog = actionLog.New("oracleKey", common.Bytes2Hex(action.OracleData.OracleKey)) actionLog = actionLog.New("oracleKey", common.Bytes2Hex(action.OracleData.OracleKey))
} }
} else if action.Type == types.ActionTypeMove { } else if action.Type == types.ActionTypeMove {
actionLog = actionLog.New("is_attack", action.IsAttack, "parent", action.ParentIdx, "value", action.Value) actionLog = actionLog.New("is_attack", action.IsAttack, "parent", action.ParentClaim.ContractIndex, "value", action.Value)
} }
switch action.Type { switch action.Type {
......
[
{
"inputs": [
{
"internalType": "GameType",
"name": "_gameType",
"type": "uint32"
},
{
"internalType": "Claim",
"name": "_absolutePrestate",
"type": "bytes32"
},
{
"internalType": "uint256",
"name": "_maxGameDepth",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_splitDepth",
"type": "uint256"
},
{
"internalType": "Duration",
"name": "_clockExtension",
"type": "uint64"
},
{
"internalType": "Duration",
"name": "_maxClockDuration",
"type": "uint64"
},
{
"internalType": "contract IBigStepper",
"name": "_vm",
"type": "address"
},
{
"internalType": "contract IDelayedWETH",
"name": "_weth",
"type": "address"
},
{
"internalType": "contract IAnchorStateRegistry",
"name": "_anchorStateRegistry",
"type": "address"
},
{
"internalType": "uint256",
"name": "_l2ChainId",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"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": [],
"name": "anchorStateRegistry",
"outputs": [
{
"internalType": "contract IAnchorStateRegistry",
"name": "registry_",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_parentIndex",
"type": "uint256"
},
{
"internalType": "Claim",
"name": "_claim",
"type": "bytes32"
}
],
"name": "attack",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"internalType": "bytes32",
"name": "version",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "stateRoot",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "messagePasserStorageRoot",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "latestBlockhash",
"type": "bytes32"
}
],
"internalType": "struct Types.OutputRootProof",
"name": "_outputRootProof",
"type": "tuple"
},
{
"internalType": "bytes",
"name": "_headerRLP",
"type": "bytes"
}
],
"name": "challengeRootL2Block",
"outputs": [],
"stateMutability": "nonpayable",
"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": [
{
"internalType": "Hash",
"name": "",
"type": "bytes32"
}
],
"name": "claims",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "clockExtension",
"outputs": [
{
"internalType": "Duration",
"name": "clockExtension_",
"type": "uint64"
}
],
"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": "gameCreator",
"outputs": [
{
"internalType": "address",
"name": "creator_",
"type": "address"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "gameData",
"outputs": [
{
"internalType": "GameType",
"name": "gameType_",
"type": "uint32"
},
{
"internalType": "Claim",
"name": "rootClaim_",
"type": "bytes32"
},
{
"internalType": "bytes",
"name": "extraData_",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "gameType",
"outputs": [
{
"internalType": "GameType",
"name": "gameType_",
"type": "uint32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_claimIndex",
"type": "uint256"
}
],
"name": "getChallengerDuration",
"outputs": [
{
"internalType": "Duration",
"name": "duration_",
"type": "uint64"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_claimIndex",
"type": "uint256"
}
],
"name": "getNumToResolve",
"outputs": [
{
"internalType": "uint256",
"name": "numRemainingChildren_",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "Position",
"name": "_position",
"type": "uint128"
}
],
"name": "getRequiredBond",
"outputs": [
{
"internalType": "uint256",
"name": "requiredBond_",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "initialize",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "l1Head",
"outputs": [
{
"internalType": "Hash",
"name": "l1Head_",
"type": "bytes32"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "l2BlockNumber",
"outputs": [
{
"internalType": "uint256",
"name": "l2BlockNumber_",
"type": "uint256"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "l2BlockNumberChallenged",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "l2BlockNumberChallenger",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "l2ChainId",
"outputs": [
{
"internalType": "uint256",
"name": "l2ChainId_",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "maxClockDuration",
"outputs": [
{
"internalType": "Duration",
"name": "maxClockDuration_",
"type": "uint64"
}
],
"stateMutability": "view",
"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": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "resolutionCheckpoints",
"outputs": [
{
"internalType": "bool",
"name": "initialCheckpointComplete",
"type": "bool"
},
{
"internalType": "uint32",
"name": "subgameIndex",
"type": "uint32"
},
{
"internalType": "Position",
"name": "leftmostPosition",
"type": "uint128"
},
{
"internalType": "address",
"name": "counteredBy",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "resolve",
"outputs": [
{
"internalType": "enum GameStatus",
"name": "status_",
"type": "uint8"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_claimIndex",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_numToResolve",
"type": "uint256"
}
],
"name": "resolveClaim",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "resolvedAt",
"outputs": [
{
"internalType": "Timestamp",
"name": "",
"type": "uint64"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "resolvedSubgames",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"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": "startingBlockNumber",
"outputs": [
{
"internalType": "uint256",
"name": "startingBlockNumber_",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "startingOutputRoot",
"outputs": [
{
"internalType": "Hash",
"name": "root",
"type": "bytes32"
},
{
"internalType": "uint256",
"name": "l2BlockNumber",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "startingRootHash",
"outputs": [
{
"internalType": "Hash",
"name": "startingRootHash_",
"type": "bytes32"
}
],
"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": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "subgames",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"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"
},
{
"inputs": [],
"name": "weth",
"outputs": [
{
"internalType": "contract IDelayedWETH",
"name": "weth_",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"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": "AlreadyInitialized",
"type": "error"
},
{
"inputs": [],
"name": "AnchorRootNotFound",
"type": "error"
},
{
"inputs": [],
"name": "BlockNumberMatches",
"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": "ContentLengthMismatch",
"type": "error"
},
{
"inputs": [],
"name": "DuplicateStep",
"type": "error"
},
{
"inputs": [],
"name": "EmptyItem",
"type": "error"
},
{
"inputs": [],
"name": "GameDepthExceeded",
"type": "error"
},
{
"inputs": [],
"name": "GameNotInProgress",
"type": "error"
},
{
"inputs": [],
"name": "IncorrectBondAmount",
"type": "error"
},
{
"inputs": [],
"name": "InvalidClockExtension",
"type": "error"
},
{
"inputs": [],
"name": "InvalidDataRemainder",
"type": "error"
},
{
"inputs": [],
"name": "InvalidHeader",
"type": "error"
},
{
"inputs": [],
"name": "InvalidHeaderRLP",
"type": "error"
},
{
"inputs": [],
"name": "InvalidLocalIdent",
"type": "error"
},
{
"inputs": [],
"name": "InvalidOutputRootProof",
"type": "error"
},
{
"inputs": [],
"name": "InvalidParent",
"type": "error"
},
{
"inputs": [],
"name": "InvalidPrestate",
"type": "error"
},
{
"inputs": [],
"name": "InvalidSplitDepth",
"type": "error"
},
{
"inputs": [],
"name": "L2BlockNumberChallenged",
"type": "error"
},
{
"inputs": [],
"name": "MaxDepthTooLarge",
"type": "error"
},
{
"inputs": [],
"name": "NoCreditToClaim",
"type": "error"
},
{
"inputs": [],
"name": "OutOfOrderResolution",
"type": "error"
},
{
"inputs": [],
"name": "UnexpectedList",
"type": "error"
},
{
"inputs": [
{
"internalType": "Claim",
"name": "rootClaim",
"type": "bytes32"
}
],
"name": "UnexpectedRootClaim",
"type": "error"
},
{
"inputs": [],
"name": "UnexpectedString",
"type": "error"
},
{
"inputs": [],
"name": "ValidStep",
"type": "error"
}
]
\ No newline at end of file
...@@ -109,6 +109,16 @@ func NewFaultDisputeGameContract(ctx context.Context, metrics metrics.ContractMe ...@@ -109,6 +109,16 @@ func NewFaultDisputeGameContract(ctx context.Context, metrics metrics.ContractMe
contract: batching.NewBoundContract(legacyAbi, addr), contract: batching.NewBoundContract(legacyAbi, addr),
}, },
}, nil }, nil
} else if strings.HasPrefix(version, "1.1.") {
// Detected an older version of contracts, use a compatibility shim.
legacyAbi := mustParseAbi(faultDisputeGameAbi111)
return &FaultDisputeGameContract111{
FaultDisputeGameContractLatest: FaultDisputeGameContractLatest{
metrics: metrics,
multiCaller: caller,
contract: batching.NewBoundContract(legacyAbi, addr),
},
}, nil
} else { } else {
return &FaultDisputeGameContractLatest{ return &FaultDisputeGameContractLatest{
metrics: metrics, metrics: metrics,
...@@ -480,14 +490,26 @@ func (f *FaultDisputeGameContractLatest) ChallengeL2BlockNumberTx(challenge *typ ...@@ -480,14 +490,26 @@ func (f *FaultDisputeGameContractLatest) ChallengeL2BlockNumberTx(challenge *typ
}, headerRlp).ToTxCandidate() }, headerRlp).ToTxCandidate()
} }
func (f *FaultDisputeGameContractLatest) AttackTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) { func (f *FaultDisputeGameContractLatest) AttackTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) {
call := f.contract.Call(methodAttack, new(big.Int).SetUint64(parentContractIndex), pivot) call := f.contract.Call(methodAttack, parent.Value, big.NewInt(int64(parent.ContractIndex)), pivot)
return call.ToTxCandidate() return f.txWithBond(ctx, parent.Position.Attack(), call)
} }
func (f *FaultDisputeGameContractLatest) DefendTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) { func (f *FaultDisputeGameContractLatest) DefendTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) {
call := f.contract.Call(methodDefend, new(big.Int).SetUint64(parentContractIndex), pivot) call := f.contract.Call(methodDefend, parent.Value, big.NewInt(int64(parent.ContractIndex)), pivot)
return call.ToTxCandidate() return f.txWithBond(ctx, parent.Position.Defend(), call)
}
func (f *FaultDisputeGameContractLatest) txWithBond(ctx context.Context, position types.Position, call *batching.ContractCall) (txmgr.TxCandidate, error) {
tx, err := call.ToTxCandidate()
if err != nil {
return txmgr.TxCandidate{}, fmt.Errorf("failed to create transaction: %w", err)
}
tx.Value, err = f.GetRequiredBond(ctx, position)
if err != nil {
return txmgr.TxCandidate{}, fmt.Errorf("failed to fetch required bond: %w", err)
}
return tx, nil
} }
func (f *FaultDisputeGameContractLatest) StepTx(claimIdx uint64, isAttack bool, stateData []byte, proof []byte) (txmgr.TxCandidate, error) { func (f *FaultDisputeGameContractLatest) StepTx(claimIdx uint64, isAttack bool, stateData []byte, proof []byte) (txmgr.TxCandidate, error) {
...@@ -595,8 +617,8 @@ type FaultDisputeGameContract interface { ...@@ -595,8 +617,8 @@ type FaultDisputeGameContract interface {
IsResolved(ctx context.Context, block rpcblock.Block, claims ...types.Claim) ([]bool, error) IsResolved(ctx context.Context, block rpcblock.Block, claims ...types.Claim) ([]bool, error)
IsL2BlockNumberChallenged(ctx context.Context, block rpcblock.Block) (bool, error) IsL2BlockNumberChallenged(ctx context.Context, block rpcblock.Block) (bool, error)
ChallengeL2BlockNumberTx(challenge *types.InvalidL2BlockNumberChallenge) (txmgr.TxCandidate, error) ChallengeL2BlockNumberTx(challenge *types.InvalidL2BlockNumberChallenge) (txmgr.TxCandidate, error)
AttackTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) AttackTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error)
DefendTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) DefendTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error)
StepTx(claimIdx uint64, isAttack bool, stateData []byte, proof []byte) (txmgr.TxCandidate, error) StepTx(claimIdx uint64, isAttack bool, stateData []byte, proof []byte) (txmgr.TxCandidate, error)
CallResolveClaim(ctx context.Context, claimIdx uint64) error CallResolveClaim(ctx context.Context, claimIdx uint64) error
ResolveClaimTx(claimIdx uint64) (txmgr.TxCandidate, error) ResolveClaimTx(claimIdx uint64) (txmgr.TxCandidate, error)
......
...@@ -4,11 +4,13 @@ import ( ...@@ -4,11 +4,13 @@ import (
"context" "context"
_ "embed" _ "embed"
"fmt" "fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
) )
//go:embed abis/FaultDisputeGame-0.18.1.json //go:embed abis/FaultDisputeGame-0.18.1.json
...@@ -59,3 +61,13 @@ func (f *FaultDisputeGameContract0180) IsL2BlockNumberChallenged(_ context.Conte ...@@ -59,3 +61,13 @@ func (f *FaultDisputeGameContract0180) IsL2BlockNumberChallenged(_ context.Conte
func (f *FaultDisputeGameContract0180) ChallengeL2BlockNumberTx(_ *types.InvalidL2BlockNumberChallenge) (txmgr.TxCandidate, error) { func (f *FaultDisputeGameContract0180) ChallengeL2BlockNumberTx(_ *types.InvalidL2BlockNumberChallenge) (txmgr.TxCandidate, error) {
return txmgr.TxCandidate{}, ErrChallengeL2BlockNotSupported return txmgr.TxCandidate{}, ErrChallengeL2BlockNotSupported
} }
func (f *FaultDisputeGameContract0180) AttackTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) {
call := f.contract.Call(methodAttack, big.NewInt(int64(parent.ContractIndex)), pivot)
return f.txWithBond(ctx, parent.Position.Attack(), call)
}
func (f *FaultDisputeGameContract0180) DefendTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) {
call := f.contract.Call(methodDefend, big.NewInt(int64(parent.ContractIndex)), pivot)
return f.txWithBond(ctx, parent.Position.Defend(), call)
}
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"github.com/ethereum-optimism/optimism/op-service/sources/batching" "github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
) )
//go:embed abis/FaultDisputeGame-0.8.0.json //go:embed abis/FaultDisputeGame-0.8.0.json
...@@ -146,3 +147,13 @@ func (f *FaultDisputeGameContract080) IsL2BlockNumberChallenged(_ context.Contex ...@@ -146,3 +147,13 @@ func (f *FaultDisputeGameContract080) IsL2BlockNumberChallenged(_ context.Contex
func (f *FaultDisputeGameContract080) ChallengeL2BlockNumberTx(_ *types.InvalidL2BlockNumberChallenge) (txmgr.TxCandidate, error) { func (f *FaultDisputeGameContract080) ChallengeL2BlockNumberTx(_ *types.InvalidL2BlockNumberChallenge) (txmgr.TxCandidate, error) {
return txmgr.TxCandidate{}, ErrChallengeL2BlockNotSupported return txmgr.TxCandidate{}, ErrChallengeL2BlockNotSupported
} }
func (f *FaultDisputeGameContract080) AttackTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) {
call := f.contract.Call(methodAttack, big.NewInt(int64(parent.ContractIndex)), pivot)
return f.txWithBond(ctx, parent.Position.Attack(), call)
}
func (f *FaultDisputeGameContract080) DefendTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) {
call := f.contract.Call(methodDefend, big.NewInt(int64(parent.ContractIndex)), pivot)
return f.txWithBond(ctx, parent.Position.Defend(), call)
}
package contracts
import (
"context"
_ "embed"
"math/big"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
)
//go:embed abis/FaultDisputeGame-1.1.1.json
var faultDisputeGameAbi111 []byte
type FaultDisputeGameContract111 struct {
FaultDisputeGameContractLatest
}
func (f *FaultDisputeGameContract111) AttackTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) {
call := f.contract.Call(methodAttack, big.NewInt(int64(parent.ContractIndex)), pivot)
return f.txWithBond(ctx, parent.Position.Attack(), call)
}
func (f *FaultDisputeGameContract111) DefendTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) {
call := f.contract.Call(methodDefend, big.NewInt(int64(parent.ContractIndex)), pivot)
return f.txWithBond(ctx, parent.Position.Defend(), call)
}
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"math" "math"
"math/big" "math/big"
"math/rand" "math/rand"
"slices"
"testing" "testing"
"time" "time"
...@@ -37,10 +38,15 @@ type contractVersion struct { ...@@ -37,10 +38,15 @@ type contractVersion struct {
loadAbi func() *abi.ABI loadAbi func() *abi.ABI
} }
func (c contractVersion) Is(versions ...string) bool {
return slices.Contains(versions, c.version)
}
const ( const (
vers080 = "0.8.0" vers080 = "0.8.0"
vers0180 = "0.18.0" vers0180 = "0.18.0"
versLatest = "1.1.0" vers111 = "1.1.1"
versLatest = "1.2.0"
) )
var versions = []contractVersion{ var versions = []contractVersion{
...@@ -56,6 +62,12 @@ var versions = []contractVersion{ ...@@ -56,6 +62,12 @@ var versions = []contractVersion{
return mustParseAbi(faultDisputeGameAbi0180) return mustParseAbi(faultDisputeGameAbi0180)
}, },
}, },
{
version: vers111,
loadAbi: func() *abi.ABI {
return mustParseAbi(faultDisputeGameAbi111)
},
},
{ {
version: versLatest, version: versLatest,
loadAbi: snapshots.LoadFaultDisputeGameABI, loadAbi: snapshots.LoadFaultDisputeGameABI,
...@@ -379,11 +391,19 @@ func TestAttackTx(t *testing.T) { ...@@ -379,11 +391,19 @@ func TestAttackTx(t *testing.T) {
version := version version := version
t.Run(version.version, func(t *testing.T) { t.Run(version.version, func(t *testing.T) {
stubRpc, game := setupFaultDisputeGameTest(t, version) stubRpc, game := setupFaultDisputeGameTest(t, version)
bond := big.NewInt(1044)
value := common.Hash{0xaa} value := common.Hash{0xaa}
parent := faultTypes.Claim{ClaimData: faultTypes.ClaimData{Value: common.Hash{0xbb}}, ContractIndex: 111}
stubRpc.SetResponse(fdgAddr, methodRequiredBond, rpcblock.Latest, []interface{}{parent.Position.Attack().ToGIndex()}, []interface{}{bond})
if version.Is(vers080, vers0180, vers111) {
stubRpc.SetResponse(fdgAddr, methodAttack, rpcblock.Latest, []interface{}{big.NewInt(111), value}, nil) stubRpc.SetResponse(fdgAddr, methodAttack, rpcblock.Latest, []interface{}{big.NewInt(111), value}, nil)
tx, err := game.AttackTx(111, value) } else {
stubRpc.SetResponse(fdgAddr, methodAttack, rpcblock.Latest, []interface{}{parent.Value, big.NewInt(111), value}, nil)
}
tx, err := game.AttackTx(context.Background(), parent, value)
require.NoError(t, err) require.NoError(t, err)
stubRpc.VerifyTxCandidate(tx) stubRpc.VerifyTxCandidate(tx)
require.Equal(t, bond, tx.Value)
}) })
} }
} }
...@@ -393,11 +413,19 @@ func TestDefendTx(t *testing.T) { ...@@ -393,11 +413,19 @@ func TestDefendTx(t *testing.T) {
version := version version := version
t.Run(version.version, func(t *testing.T) { t.Run(version.version, func(t *testing.T) {
stubRpc, game := setupFaultDisputeGameTest(t, version) stubRpc, game := setupFaultDisputeGameTest(t, version)
bond := big.NewInt(1044)
value := common.Hash{0xaa} value := common.Hash{0xaa}
parent := faultTypes.Claim{ClaimData: faultTypes.ClaimData{Value: common.Hash{0xbb}}, ContractIndex: 111}
stubRpc.SetResponse(fdgAddr, methodRequiredBond, rpcblock.Latest, []interface{}{parent.Position.Defend().ToGIndex()}, []interface{}{bond})
if version.Is(vers080, vers0180, vers111) {
stubRpc.SetResponse(fdgAddr, methodDefend, rpcblock.Latest, []interface{}{big.NewInt(111), value}, nil) stubRpc.SetResponse(fdgAddr, methodDefend, rpcblock.Latest, []interface{}{big.NewInt(111), value}, nil)
tx, err := game.DefendTx(111, value) } else {
stubRpc.SetResponse(fdgAddr, methodDefend, rpcblock.Latest, []interface{}{parent.Value, big.NewInt(111), value}, nil)
}
tx, err := game.DefendTx(context.Background(), parent, value)
require.NoError(t, err) require.NoError(t, err)
stubRpc.VerifyTxCandidate(tx) stubRpc.VerifyTxCandidate(tx)
require.Equal(t, bond, tx.Value)
}) })
} }
} }
......
...@@ -4,7 +4,6 @@ import ( ...@@ -4,7 +4,6 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/preimages" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/preimages"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
...@@ -19,11 +18,10 @@ type GameContract interface { ...@@ -19,11 +18,10 @@ type GameContract interface {
ResolveTx() (txmgr.TxCandidate, error) ResolveTx() (txmgr.TxCandidate, error)
CallResolveClaim(ctx context.Context, claimIdx uint64) error CallResolveClaim(ctx context.Context, claimIdx uint64) error
ResolveClaimTx(claimIdx uint64) (txmgr.TxCandidate, error) ResolveClaimTx(claimIdx uint64) (txmgr.TxCandidate, error)
AttackTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) AttackTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error)
DefendTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) DefendTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error)
StepTx(claimIdx uint64, isAttack bool, stateData []byte, proof []byte) (txmgr.TxCandidate, error) StepTx(claimIdx uint64, isAttack bool, stateData []byte, proof []byte) (txmgr.TxCandidate, error)
ChallengeL2BlockNumberTx(challenge *types.InvalidL2BlockNumberChallenge) (txmgr.TxCandidate, error) ChallengeL2BlockNumberTx(challenge *types.InvalidL2BlockNumberChallenge) (txmgr.TxCandidate, error)
GetRequiredBond(ctx context.Context, position types.Position) (*big.Int, error)
} }
type Oracle interface { type Oracle interface {
...@@ -101,7 +99,7 @@ func (r *FaultResponder) PerformAction(ctx context.Context, action types.Action) ...@@ -101,7 +99,7 @@ func (r *FaultResponder) PerformAction(ctx context.Context, action types.Action)
} }
// Always upload local preimages // Always upload local preimages
if !preimageExists { if !preimageExists {
err := r.uploader.UploadPreimage(ctx, uint64(action.ParentIdx), action.OracleData) err := r.uploader.UploadPreimage(ctx, uint64(action.ParentClaim.ContractIndex), action.OracleData)
if errors.Is(err, preimages.ErrChallengePeriodNotOver) { if errors.Is(err, preimages.ErrChallengePeriodNotOver) {
r.log.Debug("Large Preimage Squeeze failed, challenge period not over") r.log.Debug("Large Preimage Squeeze failed, challenge period not over")
return nil return nil
...@@ -114,22 +112,13 @@ func (r *FaultResponder) PerformAction(ctx context.Context, action types.Action) ...@@ -114,22 +112,13 @@ func (r *FaultResponder) PerformAction(ctx context.Context, action types.Action)
var err error var err error
switch action.Type { switch action.Type {
case types.ActionTypeMove: case types.ActionTypeMove:
var movePos types.Position
if action.IsAttack { if action.IsAttack {
movePos = action.ParentPosition.Attack() candidate, err = r.contract.AttackTx(ctx, action.ParentClaim, action.Value)
candidate, err = r.contract.AttackTx(uint64(action.ParentIdx), action.Value)
} else { } else {
movePos = action.ParentPosition.Defend() candidate, err = r.contract.DefendTx(ctx, action.ParentClaim, action.Value)
candidate, err = r.contract.DefendTx(uint64(action.ParentIdx), action.Value)
} }
bondValue, err := r.contract.GetRequiredBond(ctx, movePos)
if err != nil {
return err
}
candidate.Value = bondValue
case types.ActionTypeStep: case types.ActionTypeStep:
candidate, err = r.contract.StepTx(uint64(action.ParentIdx), action.IsAttack, action.PreState, action.ProofData) candidate, err = r.contract.StepTx(uint64(action.ParentClaim.ContractIndex), action.IsAttack, action.PreState, action.ProofData)
case types.ActionTypeChallengeL2BlockNumber: case types.ActionTypeChallengeL2BlockNumber:
candidate, err = r.contract.ChallengeL2BlockNumberTx(action.InvalidL2BlockNumberChallenge) candidate, err = r.contract.ChallengeL2BlockNumberTx(action.InvalidL2BlockNumberChallenge)
} }
......
...@@ -110,7 +110,7 @@ func TestPerformAction(t *testing.T) { ...@@ -110,7 +110,7 @@ func TestPerformAction(t *testing.T) {
mockTxMgr.sendFails = true mockTxMgr.sendFails = true
err := responder.PerformAction(context.Background(), types.Action{ err := responder.PerformAction(context.Background(), types.Action{
Type: types.ActionTypeMove, Type: types.ActionTypeMove,
ParentIdx: 123, ParentClaim: types.Claim{ContractIndex: 123},
IsAttack: true, IsAttack: true,
Value: common.Hash{0xaa}, Value: common.Hash{0xaa},
}) })
...@@ -122,7 +122,7 @@ func TestPerformAction(t *testing.T) { ...@@ -122,7 +122,7 @@ func TestPerformAction(t *testing.T) {
responder, mockTxMgr, _, _, _ := newTestFaultResponder(t) responder, mockTxMgr, _, _, _ := newTestFaultResponder(t)
err := responder.PerformAction(context.Background(), types.Action{ err := responder.PerformAction(context.Background(), types.Action{
Type: types.ActionTypeMove, Type: types.ActionTypeMove,
ParentIdx: 123, ParentClaim: types.Claim{ContractIndex: 123},
IsAttack: true, IsAttack: true,
Value: common.Hash{0xaa}, Value: common.Hash{0xaa},
}) })
...@@ -134,7 +134,7 @@ func TestPerformAction(t *testing.T) { ...@@ -134,7 +134,7 @@ func TestPerformAction(t *testing.T) {
responder, mockTxMgr, contract, _, _ := newTestFaultResponder(t) responder, mockTxMgr, contract, _, _ := newTestFaultResponder(t)
action := types.Action{ action := types.Action{
Type: types.ActionTypeMove, Type: types.ActionTypeMove,
ParentIdx: 123, ParentClaim: types.Claim{ContractIndex: 123},
IsAttack: true, IsAttack: true,
Value: common.Hash{0xaa}, Value: common.Hash{0xaa},
} }
...@@ -142,7 +142,7 @@ func TestPerformAction(t *testing.T) { ...@@ -142,7 +142,7 @@ func TestPerformAction(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Len(t, mockTxMgr.sent, 1) require.Len(t, mockTxMgr.sent, 1)
require.EqualValues(t, []interface{}{uint64(action.ParentIdx), action.Value}, contract.attackArgs) require.EqualValues(t, []interface{}{action.ParentClaim, action.Value}, contract.attackArgs)
require.Equal(t, ([]byte)("attack"), mockTxMgr.sent[0].TxData) require.Equal(t, ([]byte)("attack"), mockTxMgr.sent[0].TxData)
}) })
...@@ -150,7 +150,7 @@ func TestPerformAction(t *testing.T) { ...@@ -150,7 +150,7 @@ func TestPerformAction(t *testing.T) {
responder, mockTxMgr, contract, _, _ := newTestFaultResponder(t) responder, mockTxMgr, contract, _, _ := newTestFaultResponder(t)
action := types.Action{ action := types.Action{
Type: types.ActionTypeMove, Type: types.ActionTypeMove,
ParentIdx: 123, ParentClaim: types.Claim{ContractIndex: 123},
IsAttack: false, IsAttack: false,
Value: common.Hash{0xaa}, Value: common.Hash{0xaa},
} }
...@@ -158,7 +158,7 @@ func TestPerformAction(t *testing.T) { ...@@ -158,7 +158,7 @@ func TestPerformAction(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Len(t, mockTxMgr.sent, 1) require.Len(t, mockTxMgr.sent, 1)
require.EqualValues(t, []interface{}{uint64(action.ParentIdx), action.Value}, contract.defendArgs) require.EqualValues(t, []interface{}{action.ParentClaim, action.Value}, contract.defendArgs)
require.Equal(t, ([]byte)("defend"), mockTxMgr.sent[0].TxData) require.Equal(t, ([]byte)("defend"), mockTxMgr.sent[0].TxData)
}) })
...@@ -166,7 +166,7 @@ func TestPerformAction(t *testing.T) { ...@@ -166,7 +166,7 @@ func TestPerformAction(t *testing.T) {
responder, mockTxMgr, contract, _, _ := newTestFaultResponder(t) responder, mockTxMgr, contract, _, _ := newTestFaultResponder(t)
action := types.Action{ action := types.Action{
Type: types.ActionTypeStep, Type: types.ActionTypeStep,
ParentIdx: 123, ParentClaim: types.Claim{ContractIndex: 123},
IsAttack: true, IsAttack: true,
PreState: []byte{1, 2, 3}, PreState: []byte{1, 2, 3},
ProofData: []byte{4, 5, 6}, ProofData: []byte{4, 5, 6},
...@@ -175,7 +175,7 @@ func TestPerformAction(t *testing.T) { ...@@ -175,7 +175,7 @@ func TestPerformAction(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Len(t, mockTxMgr.sent, 1) require.Len(t, mockTxMgr.sent, 1)
require.EqualValues(t, []interface{}{uint64(action.ParentIdx), action.IsAttack, action.PreState, action.ProofData}, contract.stepArgs) require.EqualValues(t, []interface{}{uint64(123), action.IsAttack, action.PreState, action.ProofData}, contract.stepArgs)
require.Equal(t, ([]byte)("step"), mockTxMgr.sent[0].TxData) require.Equal(t, ([]byte)("step"), mockTxMgr.sent[0].TxData)
}) })
...@@ -183,7 +183,7 @@ func TestPerformAction(t *testing.T) { ...@@ -183,7 +183,7 @@ func TestPerformAction(t *testing.T) {
responder, mockTxMgr, contract, uploader, oracle := newTestFaultResponder(t) responder, mockTxMgr, contract, uploader, oracle := newTestFaultResponder(t)
action := types.Action{ action := types.Action{
Type: types.ActionTypeStep, Type: types.ActionTypeStep,
ParentIdx: 123, ParentClaim: types.Claim{ContractIndex: 123},
IsAttack: true, IsAttack: true,
PreState: []byte{1, 2, 3}, PreState: []byte{1, 2, 3},
ProofData: []byte{4, 5, 6}, ProofData: []byte{4, 5, 6},
...@@ -205,7 +205,7 @@ func TestPerformAction(t *testing.T) { ...@@ -205,7 +205,7 @@ func TestPerformAction(t *testing.T) {
responder, mockTxMgr, contract, uploader, oracle := newTestFaultResponder(t) responder, mockTxMgr, contract, uploader, oracle := newTestFaultResponder(t)
action := types.Action{ action := types.Action{
Type: types.ActionTypeStep, Type: types.ActionTypeStep,
ParentIdx: 123, ParentClaim: types.Claim{ContractIndex: 123},
IsAttack: true, IsAttack: true,
PreState: []byte{1, 2, 3}, PreState: []byte{1, 2, 3},
ProofData: []byte{4, 5, 6}, ProofData: []byte{4, 5, 6},
...@@ -228,7 +228,7 @@ func TestPerformAction(t *testing.T) { ...@@ -228,7 +228,7 @@ func TestPerformAction(t *testing.T) {
uploader.uploadFails = true uploader.uploadFails = true
action := types.Action{ action := types.Action{
Type: types.ActionTypeStep, Type: types.ActionTypeStep,
ParentIdx: 123, ParentClaim: types.Claim{ContractIndex: 123},
IsAttack: true, IsAttack: true,
PreState: []byte{1, 2, 3}, PreState: []byte{1, 2, 3},
ProofData: []byte{4, 5, 6}, ProofData: []byte{4, 5, 6},
...@@ -248,7 +248,7 @@ func TestPerformAction(t *testing.T) { ...@@ -248,7 +248,7 @@ func TestPerformAction(t *testing.T) {
oracle.existsResult = true oracle.existsResult = true
action := types.Action{ action := types.Action{
Type: types.ActionTypeStep, Type: types.ActionTypeStep,
ParentIdx: 123, ParentClaim: types.Claim{ContractIndex: 123},
IsAttack: true, IsAttack: true,
PreState: []byte{1, 2, 3}, PreState: []byte{1, 2, 3},
ProofData: []byte{4, 5, 6}, ProofData: []byte{4, 5, 6},
...@@ -269,7 +269,7 @@ func TestPerformAction(t *testing.T) { ...@@ -269,7 +269,7 @@ func TestPerformAction(t *testing.T) {
oracle.existsFails = true oracle.existsFails = true
action := types.Action{ action := types.Action{
Type: types.ActionTypeStep, Type: types.ActionTypeStep,
ParentIdx: 123, ParentClaim: types.Claim{ContractIndex: 123},
IsAttack: true, IsAttack: true,
PreState: []byte{1, 2, 3}, PreState: []byte{1, 2, 3},
ProofData: []byte{4, 5, 6}, ProofData: []byte{4, 5, 6},
...@@ -406,13 +406,13 @@ func (m *mockContract) ChallengeL2BlockNumberTx(challenge *types.InvalidL2BlockN ...@@ -406,13 +406,13 @@ func (m *mockContract) ChallengeL2BlockNumberTx(challenge *types.InvalidL2BlockN
return txmgr.TxCandidate{TxData: ([]byte)("challenge")}, nil return txmgr.TxCandidate{TxData: ([]byte)("challenge")}, nil
} }
func (m *mockContract) AttackTx(parentClaimId uint64, claim common.Hash) (txmgr.TxCandidate, error) { func (m *mockContract) AttackTx(_ context.Context, parent types.Claim, claim common.Hash) (txmgr.TxCandidate, error) {
m.attackArgs = []interface{}{parentClaimId, claim} m.attackArgs = []interface{}{parent, claim}
return txmgr.TxCandidate{TxData: ([]byte)("attack")}, nil return txmgr.TxCandidate{TxData: ([]byte)("attack")}, nil
} }
func (m *mockContract) DefendTx(parentClaimId uint64, claim common.Hash) (txmgr.TxCandidate, error) { func (m *mockContract) DefendTx(_ context.Context, parent types.Claim, claim common.Hash) (txmgr.TxCandidate, error) {
m.defendArgs = []interface{}{parentClaimId, claim} m.defendArgs = []interface{}{parent, claim}
return txmgr.TxCandidate{TxData: ([]byte)("defend")}, nil return txmgr.TxCandidate{TxData: ([]byte)("defend")}, nil
} }
...@@ -427,10 +427,6 @@ func (m *mockContract) UpdateOracleTx(_ context.Context, claimIdx uint64, data * ...@@ -427,10 +427,6 @@ func (m *mockContract) UpdateOracleTx(_ context.Context, claimIdx uint64, data *
return txmgr.TxCandidate{TxData: ([]byte)("updateOracle")}, nil return txmgr.TxCandidate{TxData: ([]byte)("updateOracle")}, nil
} }
func (m *mockContract) GetRequiredBond(_ context.Context, position types.Position) (*big.Int, error) {
return big.NewInt(5), nil
}
func (m *mockContract) GetCredit(_ context.Context, _ common.Address) (*big.Int, error) { func (m *mockContract) GetCredit(_ context.Context, _ common.Address) (*big.Int, error) {
return big.NewInt(5), nil return big.NewInt(5), nil
} }
......
...@@ -86,8 +86,7 @@ func (s *GameSolver) calculateStep(ctx context.Context, game types.Game, claim t ...@@ -86,8 +86,7 @@ func (s *GameSolver) calculateStep(ctx context.Context, game types.Game, claim t
} }
return &types.Action{ return &types.Action{
Type: types.ActionTypeStep, Type: types.ActionTypeStep,
ParentIdx: step.LeafClaim.ContractIndex, ParentClaim: step.LeafClaim,
ParentPosition: step.LeafClaim.Position,
IsAttack: step.IsAttack, IsAttack: step.IsAttack,
PreState: step.PreState, PreState: step.PreState,
ProofData: step.ProofData, ProofData: step.ProofData,
...@@ -110,8 +109,7 @@ func (s *GameSolver) calculateMove(ctx context.Context, game types.Game, claim t ...@@ -110,8 +109,7 @@ func (s *GameSolver) calculateMove(ctx context.Context, game types.Game, claim t
return &types.Action{ return &types.Action{
Type: types.ActionTypeMove, Type: types.ActionTypeMove,
IsAttack: !game.DefendsParent(*move), IsAttack: !game.DefendsParent(*move),
ParentIdx: move.ParentContractIndex, ParentClaim: game.Claims()[move.ParentContractIndex],
ParentPosition: claim.Position,
Value: move.Value, Value: move.Value,
}, nil }, nil
} }
...@@ -209,7 +209,7 @@ func TestCalculateNextActions(t *testing.T) { ...@@ -209,7 +209,7 @@ func TestCalculateNextActions(t *testing.T) {
postState, actions := runStep(t, solver, game, claimBuilder.CorrectTraceProvider()) postState, actions := runStep(t, solver, game, claimBuilder.CorrectTraceProvider())
for i, action := range builder.ExpectedActions { for i, action := range builder.ExpectedActions {
t.Logf("Expect %v: Type: %v, ParentIdx: %v, Attack: %v, Value: %v, PreState: %v, ProofData: %v", t.Logf("Expect %v: Type: %v, ParentIdx: %v, Attack: %v, Value: %v, PreState: %v, ProofData: %v",
i, action.Type, action.ParentIdx, action.IsAttack, action.Value, hex.EncodeToString(action.PreState), hex.EncodeToString(action.ProofData)) i, action.Type, action.ParentClaim.ContractIndex, action.IsAttack, action.Value, hex.EncodeToString(action.PreState), hex.EncodeToString(action.ProofData))
require.Containsf(t, actions, action, "Expected claim %v missing", i) require.Containsf(t, actions, action, "Expected claim %v missing", i)
} }
require.Len(t, actions, len(builder.ExpectedActions), "Incorrect number of actions") require.Len(t, actions, len(builder.ExpectedActions), "Incorrect number of actions")
...@@ -227,7 +227,7 @@ func runStep(t *testing.T, solver *GameSolver, game types.Game, correctTraceProv ...@@ -227,7 +227,7 @@ func runStep(t *testing.T, solver *GameSolver, game types.Game, correctTraceProv
for i, action := range actions { for i, action := range actions {
t.Logf("Move %v: Type: %v, ParentIdx: %v, Attack: %v, Value: %v, PreState: %v, ProofData: %v", t.Logf("Move %v: Type: %v, ParentIdx: %v, Attack: %v, Value: %v, PreState: %v, ProofData: %v",
i, action.Type, action.ParentIdx, action.IsAttack, action.Value, hex.EncodeToString(action.PreState), hex.EncodeToString(action.ProofData)) i, action.Type, action.ParentClaim.ContractIndex, action.IsAttack, action.Value, hex.EncodeToString(action.PreState), hex.EncodeToString(action.ProofData))
// Check that every move the solver returns meets the generic validation rules // Check that every move the solver returns meets the generic validation rules
require.NoError(t, checkRules(game, action, correctTraceProvider), "Attempting to perform invalid action") require.NoError(t, checkRules(game, action, correctTraceProvider), "Attempting to perform invalid action")
} }
...@@ -333,9 +333,9 @@ func applyActions(game types.Game, claimant common.Address, actions []types.Acti ...@@ -333,9 +333,9 @@ func applyActions(game types.Game, claimant common.Address, actions []types.Acti
for _, action := range actions { for _, action := range actions {
switch action.Type { switch action.Type {
case types.ActionTypeMove: case types.ActionTypeMove:
newPosition := action.ParentPosition.Attack() newPosition := action.ParentClaim.Position.Attack()
if !action.IsAttack { if !action.IsAttack {
newPosition = action.ParentPosition.Defend() newPosition = action.ParentClaim.Position.Defend()
} }
claim := types.Claim{ claim := types.Claim{
ClaimData: types.ClaimData{ ClaimData: types.ClaimData{
...@@ -345,13 +345,13 @@ func applyActions(game types.Game, claimant common.Address, actions []types.Acti ...@@ -345,13 +345,13 @@ func applyActions(game types.Game, claimant common.Address, actions []types.Acti
}, },
Claimant: claimant, Claimant: claimant,
ContractIndex: len(claims), ContractIndex: len(claims),
ParentContractIndex: action.ParentIdx, ParentContractIndex: action.ParentClaim.ContractIndex,
} }
claims = append(claims, claim) claims = append(claims, claim)
case types.ActionTypeStep: case types.ActionTypeStep:
counteredClaim := claims[action.ParentIdx] counteredClaim := claims[action.ParentClaim.ContractIndex]
counteredClaim.CounteredBy = claimant counteredClaim.CounteredBy = claimant
claims[action.ParentIdx] = counteredClaim claims[action.ParentClaim.ContractIndex] = counteredClaim
default: default:
panic(fmt.Errorf("unknown move type: %v", action.Type)) panic(fmt.Errorf("unknown move type: %v", action.Type))
} }
......
...@@ -46,8 +46,8 @@ func checkRules(game types.Game, action types.Action, correctTrace types.TracePr ...@@ -46,8 +46,8 @@ func checkRules(game types.Game, action types.Action, correctTrace types.TracePr
// parentMustExist checks that every action performed has a valid parent claim // parentMustExist checks that every action performed has a valid parent claim
// Rationale: The action would be rejected by the contracts // Rationale: The action would be rejected by the contracts
func parentMustExist(game types.Game, action types.Action, _ types.TraceProvider) error { func parentMustExist(game types.Game, action types.Action, _ types.TraceProvider) error {
if len(game.Claims()) <= action.ParentIdx || action.ParentIdx < 0 { if len(game.Claims()) <= action.ParentClaim.ContractIndex || action.ParentClaim.ContractIndex < 0 {
return fmt.Errorf("parent claim %v does not exist in game with %v claims", action.ParentIdx, len(game.Claims())) return fmt.Errorf("parent claim %v does not exist in game with %v claims", action.ParentClaim.ContractIndex, len(game.Claims()))
} }
return nil return nil
} }
...@@ -58,7 +58,7 @@ func onlyStepAtMaxDepth(game types.Game, action types.Action, _ types.TraceProvi ...@@ -58,7 +58,7 @@ func onlyStepAtMaxDepth(game types.Game, action types.Action, _ types.TraceProvi
if action.Type == types.ActionTypeStep { if action.Type == types.ActionTypeStep {
return nil return nil
} }
parentDepth := game.Claims()[action.ParentIdx].Position.Depth() parentDepth := game.Claims()[action.ParentClaim.ContractIndex].Position.Depth()
if parentDepth >= game.MaxDepth() { if parentDepth >= game.MaxDepth() {
return fmt.Errorf("parent at max depth (%v) but attempting to perform %v action instead of step", return fmt.Errorf("parent at max depth (%v) but attempting to perform %v action instead of step",
parentDepth, action.Type) parentDepth, action.Type)
...@@ -72,7 +72,7 @@ func onlyMoveBeforeMaxDepth(game types.Game, action types.Action, _ types.TraceP ...@@ -72,7 +72,7 @@ func onlyMoveBeforeMaxDepth(game types.Game, action types.Action, _ types.TraceP
if action.Type == types.ActionTypeMove { if action.Type == types.ActionTypeMove {
return nil return nil
} }
parentDepth := game.Claims()[action.ParentIdx].Position.Depth() parentDepth := game.Claims()[action.ParentClaim.ContractIndex].Position.Depth()
if parentDepth < game.MaxDepth() { if parentDepth < game.MaxDepth() {
return fmt.Errorf("parent (%v) not at max depth (%v) but attempting to perform %v action instead of move", return fmt.Errorf("parent (%v) not at max depth (%v) but attempting to perform %v action instead of move",
parentDepth, game.MaxDepth(), action.Type) parentDepth, game.MaxDepth(), action.Type)
...@@ -87,7 +87,7 @@ func doNotDuplicateExistingMoves(game types.Game, action types.Action, _ types.T ...@@ -87,7 +87,7 @@ func doNotDuplicateExistingMoves(game types.Game, action types.Action, _ types.T
Value: action.Value, Value: action.Value,
Position: resultingPosition(game, action), Position: resultingPosition(game, action),
} }
if game.IsDuplicate(types.Claim{ClaimData: newClaimData, ParentContractIndex: action.ParentIdx}) { if game.IsDuplicate(types.Claim{ClaimData: newClaimData, ParentContractIndex: action.ParentClaim.ContractIndex}) {
return fmt.Errorf("creating duplicate claim at %v with value %v", newClaimData.Position.ToGIndex(), newClaimData.Value) return fmt.Errorf("creating duplicate claim at %v with value %v", newClaimData.Position.ToGIndex(), newClaimData.Value)
} }
return nil return nil
...@@ -96,7 +96,7 @@ func doNotDuplicateExistingMoves(game types.Game, action types.Action, _ types.T ...@@ -96,7 +96,7 @@ func doNotDuplicateExistingMoves(game types.Game, action types.Action, _ types.T
// doNotStepAlreadyCounteredClaims checks the challenger does not attempt to call step on already countered claims // doNotStepAlreadyCounteredClaims checks the challenger does not attempt to call step on already countered claims
// Rationale: The step call is redundant and a waste of gas // Rationale: The step call is redundant and a waste of gas
func doNotStepAlreadyCounteredClaims(game types.Game, action types.Action, _ types.TraceProvider) error { func doNotStepAlreadyCounteredClaims(game types.Game, action types.Action, _ types.TraceProvider) error {
claim := game.Claims()[action.ParentIdx] claim := game.Claims()[action.ParentClaim.ContractIndex]
if claim.CounteredBy != (common.Address{}) { if claim.CounteredBy != (common.Address{}) {
return fmt.Errorf("attempting to step already countered claim: %v", claim.ContractIndex) return fmt.Errorf("attempting to step already countered claim: %v", claim.ContractIndex)
} }
...@@ -106,8 +106,8 @@ func doNotStepAlreadyCounteredClaims(game types.Game, action types.Action, _ typ ...@@ -106,8 +106,8 @@ func doNotStepAlreadyCounteredClaims(game types.Game, action types.Action, _ typ
// doNotDefendRootClaim checks the challenger doesn't attempt to defend the root claim // doNotDefendRootClaim checks the challenger doesn't attempt to defend the root claim
// Rationale: The action would be rejected by the contracts // Rationale: The action would be rejected by the contracts
func doNotDefendRootClaim(game types.Game, action types.Action, _ types.TraceProvider) error { func doNotDefendRootClaim(game types.Game, action types.Action, _ types.TraceProvider) error {
if game.Claims()[action.ParentIdx].IsRootPosition() && !action.IsAttack { if game.Claims()[action.ParentClaim.ContractIndex].IsRootPosition() && !action.IsAttack {
return fmt.Errorf("defending the root claim at idx %v", action.ParentIdx) return fmt.Errorf("defending the root claim at idx %v", action.ParentClaim.ContractIndex)
} }
return nil return nil
} }
...@@ -115,9 +115,9 @@ func doNotDefendRootClaim(game types.Game, action types.Action, _ types.TracePro ...@@ -115,9 +115,9 @@ func doNotDefendRootClaim(game types.Game, action types.Action, _ types.TracePro
// doNotCounterSelf checks the challenger doesn't counter its own claims // doNotCounterSelf checks the challenger doesn't counter its own claims
// Rationale: The challenger should not disagree with itself // Rationale: The challenger should not disagree with itself
func doNotCounterSelf(game types.Game, action types.Action, _ types.TraceProvider) error { func doNotCounterSelf(game types.Game, action types.Action, _ types.TraceProvider) error {
claim := game.Claims()[action.ParentIdx] claim := game.Claims()[action.ParentClaim.ContractIndex]
if claim.Claimant == challengerAddr { if claim.Claimant == challengerAddr {
return fmt.Errorf("countering own claim at idx %v", action.ParentIdx) return fmt.Errorf("countering own claim at idx %v", action.ParentClaim.ContractIndex)
} }
return nil return nil
} }
...@@ -136,7 +136,7 @@ func avoidPoisonedPrestate(game types.Game, action types.Action, correctTrace ty ...@@ -136,7 +136,7 @@ func avoidPoisonedPrestate(game types.Game, action types.Action, correctTrace ty
movePosition := resultingPosition(game, action) movePosition := resultingPosition(game, action)
honestTraceIndex := movePosition.TraceIndex(game.MaxDepth()) honestTraceIndex := movePosition.TraceIndex(game.MaxDepth())
// Walk back up the claims and find the claim with highest trace index < honestTraceIndex // Walk back up the claims and find the claim with highest trace index < honestTraceIndex
claim := game.Claims()[action.ParentIdx] claim := game.Claims()[action.ParentClaim.ContractIndex]
var preStateClaim types.Claim var preStateClaim types.Claim
for { for {
ancestors += printClaim(claim, game) + "\n" ancestors += printClaim(claim, game) + "\n"
...@@ -164,7 +164,7 @@ func avoidPoisonedPrestate(game types.Game, action types.Action, correctTrace ty ...@@ -164,7 +164,7 @@ func avoidPoisonedPrestate(game types.Game, action types.Action, correctTrace ty
return fmt.Errorf("failed to get correct trace at position %v: %w", preStateClaim.Position, err) return fmt.Errorf("failed to get correct trace at position %v: %w", preStateClaim.Position, err)
} }
if correctValue != preStateClaim.Value { if correctValue != preStateClaim.Value {
err = fmt.Errorf("prestate poisoned claim %v has invalid prestate and is left of honest claim countering %v at trace index %v", preStateClaim.ContractIndex, action.ParentIdx, honestTraceIndex) err = fmt.Errorf("prestate poisoned claim %v has invalid prestate and is left of honest claim countering %v at trace index %v", preStateClaim.ContractIndex, action.ParentClaim.ContractIndex, honestTraceIndex)
return err return err
} }
return nil return nil
...@@ -199,10 +199,10 @@ func detectFailedStep(game types.Game, action types.Action, correctTrace types.T ...@@ -199,10 +199,10 @@ func detectFailedStep(game types.Game, action types.Action, correctTrace types.T
poststateIndex = new(big.Int).Add(honestTraceIndex, big.NewInt(1)) poststateIndex = new(big.Int).Add(honestTraceIndex, big.NewInt(1))
} }
// Walk back up the claims and find the claim required post state index // Walk back up the claims and find the claim required post state index
claim := game.Claims()[action.ParentIdx] claim := game.Claims()[action.ParentClaim.ContractIndex]
poststateClaim, ok := game.AncestorWithTraceIndex(claim, poststateIndex) poststateClaim, ok := game.AncestorWithTraceIndex(claim, poststateIndex)
if !ok { if !ok {
return fmt.Errorf("did not find required poststate at %v to counter claim %v", poststateIndex, action.ParentIdx) return fmt.Errorf("did not find required poststate at %v to counter claim %v", poststateIndex, action.ParentClaim.ContractIndex)
} }
correctValue, err := correctTrace.Get(context.Background(), poststateClaim.Position) correctValue, err := correctTrace.Get(context.Background(), poststateClaim.Position)
if err != nil { if err != nil {
...@@ -212,7 +212,7 @@ func detectFailedStep(game types.Game, action types.Action, correctTrace types.T ...@@ -212,7 +212,7 @@ func detectFailedStep(game types.Game, action types.Action, correctTrace types.T
parentPostAgree := (claim.Depth()-poststateClaim.Depth())%2 == 0 parentPostAgree := (claim.Depth()-poststateClaim.Depth())%2 == 0
if parentPostAgree == validStep { if parentPostAgree == validStep {
return fmt.Errorf("failed step against claim at %v using poststate from claim %v post state is correct? %v parentPostAgree? %v", return fmt.Errorf("failed step against claim at %v using poststate from claim %v post state is correct? %v parentPostAgree? %v",
action.ParentIdx, poststateClaim.ContractIndex, validStep, parentPostAgree) action.ParentClaim.ContractIndex, poststateClaim.ContractIndex, validStep, parentPostAgree)
} }
return nil return nil
} }
...@@ -242,7 +242,7 @@ func detectPoisonedStepPrestate(game types.Game, action types.Action, correctTra ...@@ -242,7 +242,7 @@ func detectPoisonedStepPrestate(game types.Game, action types.Action, correctTra
return nil return nil
} }
// Walk back up the claims and find the claim with highest trace index < honestTraceIndex // Walk back up the claims and find the claim with highest trace index < honestTraceIndex
claim := game.Claims()[action.ParentIdx] claim := game.Claims()[action.ParentClaim.ContractIndex]
preStateClaim, ok := game.AncestorWithTraceIndex(claim, prestateIndex) preStateClaim, ok := game.AncestorWithTraceIndex(claim, prestateIndex)
if !ok { if !ok {
return fmt.Errorf("performing step against claim %v with no prestate available at %v", claim.ContractIndex, prestateIndex) return fmt.Errorf("performing step against claim %v with no prestate available at %v", claim.ContractIndex, prestateIndex)
...@@ -253,9 +253,9 @@ func detectPoisonedStepPrestate(game types.Game, action types.Action, correctTra ...@@ -253,9 +253,9 @@ func detectPoisonedStepPrestate(game types.Game, action types.Action, correctTra
} }
if correctValue != preStateClaim.Value { if correctValue != preStateClaim.Value {
if action.Type == types.ActionTypeStep { if action.Type == types.ActionTypeStep {
return fmt.Errorf("stepping from poisoned prestate at claim %v when countering %v", preStateClaim.ContractIndex, action.ParentIdx) return fmt.Errorf("stepping from poisoned prestate at claim %v when countering %v", preStateClaim.ContractIndex, action.ParentClaim.ContractIndex)
} else { } else {
return fmt.Errorf("posting leaf claim with poisoned prestate from claim %v when countering %v", preStateClaim.ContractIndex, action.ParentIdx) return fmt.Errorf("posting leaf claim with poisoned prestate from claim %v when countering %v", preStateClaim.ContractIndex, action.ParentClaim.ContractIndex)
} }
} }
if action.Type == types.ActionTypeStep { if action.Type == types.ActionTypeStep {
...@@ -268,7 +268,7 @@ func detectPoisonedStepPrestate(game types.Game, action types.Action, correctTra ...@@ -268,7 +268,7 @@ func detectPoisonedStepPrestate(game types.Game, action types.Action, correctTra
} }
func resultingPosition(game types.Game, action types.Action) types.Position { func resultingPosition(game types.Game, action types.Action) types.Position {
parentPos := game.Claims()[action.ParentIdx].Position parentPos := game.Claims()[action.ParentClaim.ContractIndex].Position
if action.Type == types.ActionTypeStep { if action.Type == types.ActionTypeStep {
return parentPos return parentPos
} }
......
...@@ -103,8 +103,7 @@ func (s *GameBuilderSeq) ExpectAttack() *GameBuilderSeq { ...@@ -103,8 +103,7 @@ func (s *GameBuilderSeq) ExpectAttack() *GameBuilderSeq {
value := s.builder.CorrectClaimAtPosition(newPos) value := s.builder.CorrectClaimAtPosition(newPos)
s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{ s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{
Type: types.ActionTypeMove, Type: types.ActionTypeMove,
ParentIdx: s.lastClaim.ContractIndex, ParentClaim: s.lastClaim,
ParentPosition: s.lastClaim.Position,
IsAttack: true, IsAttack: true,
Value: value, Value: value,
}) })
...@@ -116,8 +115,7 @@ func (s *GameBuilderSeq) ExpectDefend() *GameBuilderSeq { ...@@ -116,8 +115,7 @@ func (s *GameBuilderSeq) ExpectDefend() *GameBuilderSeq {
value := s.builder.CorrectClaimAtPosition(newPos) value := s.builder.CorrectClaimAtPosition(newPos)
s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{ s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{
Type: types.ActionTypeMove, Type: types.ActionTypeMove,
ParentIdx: s.lastClaim.ContractIndex, ParentClaim: s.lastClaim,
ParentPosition: s.lastClaim.Position,
IsAttack: false, IsAttack: false,
Value: value, Value: value,
}) })
...@@ -128,8 +126,7 @@ func (s *GameBuilderSeq) ExpectStepAttack() *GameBuilderSeq { ...@@ -128,8 +126,7 @@ func (s *GameBuilderSeq) ExpectStepAttack() *GameBuilderSeq {
traceIdx := s.lastClaim.TraceIndex(s.builder.maxDepth) traceIdx := s.lastClaim.TraceIndex(s.builder.maxDepth)
s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{ s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{
Type: types.ActionTypeStep, Type: types.ActionTypeStep,
ParentIdx: s.lastClaim.ContractIndex, ParentClaim: s.lastClaim,
ParentPosition: s.lastClaim.Position,
IsAttack: true, IsAttack: true,
PreState: s.builder.CorrectPreState(traceIdx), PreState: s.builder.CorrectPreState(traceIdx),
ProofData: s.builder.CorrectProofData(traceIdx), ProofData: s.builder.CorrectProofData(traceIdx),
...@@ -142,8 +139,7 @@ func (s *GameBuilderSeq) ExpectStepDefend() *GameBuilderSeq { ...@@ -142,8 +139,7 @@ func (s *GameBuilderSeq) ExpectStepDefend() *GameBuilderSeq {
traceIdx := new(big.Int).Add(s.lastClaim.TraceIndex(s.builder.maxDepth), big.NewInt(1)) traceIdx := new(big.Int).Add(s.lastClaim.TraceIndex(s.builder.maxDepth), big.NewInt(1))
s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{ s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{
Type: types.ActionTypeStep, Type: types.ActionTypeStep,
ParentIdx: s.lastClaim.ContractIndex, ParentClaim: s.lastClaim,
ParentPosition: s.lastClaim.Position,
IsAttack: false, IsAttack: false,
PreState: s.builder.CorrectPreState(traceIdx), PreState: s.builder.CorrectPreState(traceIdx),
ProofData: s.builder.CorrectProofData(traceIdx), ProofData: s.builder.CorrectProofData(traceIdx),
......
...@@ -18,8 +18,7 @@ type Action struct { ...@@ -18,8 +18,7 @@ type Action struct {
Type ActionType Type ActionType
// Moves and Steps // Moves and Steps
ParentIdx int ParentClaim Claim
ParentPosition Position
IsAttack bool IsAttack bool
// Moves // Moves
......
...@@ -568,7 +568,7 @@ func (g *OutputGameHelper) Attack(ctx context.Context, claimIdx int64, claim com ...@@ -568,7 +568,7 @@ func (g *OutputGameHelper) Attack(ctx context.Context, claimIdx int64, claim com
transactOpts := g.makeBondedTransactOpts(ctx, pos.Attack().ToGIndex(), cfg.Opts) transactOpts := g.makeBondedTransactOpts(ctx, pos.Attack().ToGIndex(), cfg.Opts)
err = g.sendMove(ctx, func() (*gethtypes.Transaction, error) { err = g.sendMove(ctx, func() (*gethtypes.Transaction, error) {
return g.Game.Attack(transactOpts, big.NewInt(claimIdx), claim) return g.Game.Attack(transactOpts, claimData.Claim, big.NewInt(claimIdx), claim)
}) })
if err != nil { if err != nil {
if cfg.ignoreDupes && g.hasClaim(ctx, claimIdx, attackPos, claim) { if cfg.ignoreDupes && g.hasClaim(ctx, claimIdx, attackPos, claim) {
...@@ -589,7 +589,7 @@ func (g *OutputGameHelper) Defend(ctx context.Context, claimIdx int64, claim com ...@@ -589,7 +589,7 @@ func (g *OutputGameHelper) Defend(ctx context.Context, claimIdx int64, claim com
transactOpts := g.makeBondedTransactOpts(ctx, defendPos.ToGIndex(), cfg.Opts) transactOpts := g.makeBondedTransactOpts(ctx, defendPos.ToGIndex(), cfg.Opts)
err = g.sendMove(ctx, func() (*gethtypes.Transaction, error) { err = g.sendMove(ctx, func() (*gethtypes.Transaction, error) {
return g.Game.Defend(transactOpts, big.NewInt(claimIdx), claim) return g.Game.Defend(transactOpts, claimData.Claim, big.NewInt(claimIdx), claim)
}) })
if err != nil { if err != nil {
if cfg.ignoreDupes && g.hasClaim(ctx, claimIdx, defendPos, claim) { if cfg.ignoreDupes && g.hasClaim(ctx, claimIdx, defendPos, claim) {
......
...@@ -132,8 +132,8 @@ ...@@ -132,8 +132,8 @@
"sourceCodeHash": "0x918c395ac5d77357f2551616aad0613e68893862edd14e554623eb16ee6ba148" "sourceCodeHash": "0x918c395ac5d77357f2551616aad0613e68893862edd14e554623eb16ee6ba148"
}, },
"src/dispute/FaultDisputeGame.sol": { "src/dispute/FaultDisputeGame.sol": {
"initCodeHash": "0x923d5c668370010e84a0318a813c2979962b1007d692344f5496bcda6fa85e53", "initCodeHash": "0x5ea5b544b8d7b32f55f7864c25a2443a5db363ffd1c66e0799cbc7bccaf98526",
"sourceCodeHash": "0xf77ee4322aeb08559469c3bd42ec266547a170b48ea1cffcf633de80543f3c09" "sourceCodeHash": "0xe8d90f1a8f92732707e370767df260bc806be5be9808f150ebed2c6caa158734"
}, },
"src/dispute/weth/DelayedWETH.sol": { "src/dispute/weth/DelayedWETH.sol": {
"initCodeHash": "0xb9bbe005874922cd8f499e7a0a092967cfca03e012c1e41912b0c77481c71777", "initCodeHash": "0xb9bbe005874922cd8f499e7a0a092967cfca03e012c1e41912b0c77481c71777",
......
...@@ -106,6 +106,11 @@ ...@@ -106,6 +106,11 @@
}, },
{ {
"inputs": [ "inputs": [
{
"internalType": "Claim",
"name": "_disputed",
"type": "bytes32"
},
{ {
"internalType": "uint256", "internalType": "uint256",
"name": "_parentIndex", "name": "_parentIndex",
...@@ -303,6 +308,11 @@ ...@@ -303,6 +308,11 @@
}, },
{ {
"inputs": [ "inputs": [
{
"internalType": "Claim",
"name": "_disputed",
"type": "bytes32"
},
{ {
"internalType": "uint256", "internalType": "uint256",
"name": "_parentIndex", "name": "_parentIndex",
...@@ -538,6 +548,11 @@ ...@@ -538,6 +548,11 @@
}, },
{ {
"inputs": [ "inputs": [
{
"internalType": "Claim",
"name": "_disputed",
"type": "bytes32"
},
{ {
"internalType": "uint256", "internalType": "uint256",
"name": "_challengeIndex", "name": "_challengeIndex",
...@@ -958,6 +973,11 @@ ...@@ -958,6 +973,11 @@
"name": "InvalidDataRemainder", "name": "InvalidDataRemainder",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "InvalidDisputedClaimIndex",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "InvalidHeader", "name": "InvalidHeader",
......
...@@ -116,6 +116,11 @@ ...@@ -116,6 +116,11 @@
}, },
{ {
"inputs": [ "inputs": [
{
"internalType": "Claim",
"name": "_disputed",
"type": "bytes32"
},
{ {
"internalType": "uint256", "internalType": "uint256",
"name": "_parentIndex", "name": "_parentIndex",
...@@ -326,6 +331,11 @@ ...@@ -326,6 +331,11 @@
}, },
{ {
"inputs": [ "inputs": [
{
"internalType": "Claim",
"name": "_disputed",
"type": "bytes32"
},
{ {
"internalType": "uint256", "internalType": "uint256",
"name": "_parentIndex", "name": "_parentIndex",
...@@ -561,6 +571,11 @@ ...@@ -561,6 +571,11 @@
}, },
{ {
"inputs": [ "inputs": [
{
"internalType": "Claim",
"name": "_disputed",
"type": "bytes32"
},
{ {
"internalType": "uint256", "internalType": "uint256",
"name": "_challengeIndex", "name": "_challengeIndex",
...@@ -999,6 +1014,11 @@ ...@@ -999,6 +1014,11 @@
"name": "InvalidDataRemainder", "name": "InvalidDataRemainder",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "InvalidDisputedClaimIndex",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "InvalidHeader", "name": "InvalidHeader",
......
...@@ -69,8 +69,8 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { ...@@ -69,8 +69,8 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver {
uint256 internal constant HEADER_BLOCK_NUMBER_INDEX = 8; uint256 internal constant HEADER_BLOCK_NUMBER_INDEX = 8;
/// @notice Semantic version. /// @notice Semantic version.
/// @custom:semver 1.1.1 /// @custom:semver 1.2.0
string public constant version = "1.1.1"; string public constant version = "1.2.0";
/// @notice The starting timestamp of the game /// @notice The starting timestamp of the game
Timestamp public createdAt; Timestamp public createdAt;
...@@ -312,16 +312,20 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { ...@@ -312,16 +312,20 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver {
} }
/// @notice Generic move function, used for both `attack` and `defend` moves. /// @notice Generic move function, used for both `attack` and `defend` moves.
/// @param _disputed The disputed `Claim`.
/// @param _challengeIndex The index of the claim being moved against. /// @param _challengeIndex The index of the claim being moved against.
/// @param _claim The claim at the next logical position in the game. /// @param _claim The claim at the next logical position in the game.
/// @param _isAttack Whether or not the move is an attack or defense. /// @param _isAttack Whether or not the move is an attack or defense.
function move(uint256 _challengeIndex, Claim _claim, bool _isAttack) public payable virtual { function move(Claim _disputed, uint256 _challengeIndex, Claim _claim, bool _isAttack) public payable virtual {
// INVARIANT: Moves cannot be made unless the game is currently in progress. // INVARIANT: Moves cannot be made unless the game is currently in progress.
if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress(); if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress();
// Get the parent. If it does not exist, the call will revert with OOB. // Get the parent. If it does not exist, the call will revert with OOB.
ClaimData memory parent = claimData[_challengeIndex]; ClaimData memory parent = claimData[_challengeIndex];
// INVARIANT: The claim at the _challengeIndex must be the disputed claim.
if (Claim.unwrap(parent.claim) != Claim.unwrap(_disputed)) revert InvalidDisputedClaimIndex();
// Compute the position that the claim commits to. Because the parent's position is already // 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 // known, we can compute the next position by moving left or right depending on whether
// or not the move is an attack or defense. // or not the move is an attack or defense.
...@@ -412,13 +416,13 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { ...@@ -412,13 +416,13 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver {
} }
/// @inheritdoc IFaultDisputeGame /// @inheritdoc IFaultDisputeGame
function attack(uint256 _parentIndex, Claim _claim) external payable { function attack(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable {
move(_parentIndex, _claim, true); move(_disputed, _parentIndex, _claim, true);
} }
/// @inheritdoc IFaultDisputeGame /// @inheritdoc IFaultDisputeGame
function defend(uint256 _parentIndex, Claim _claim) external payable { function defend(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable {
move(_parentIndex, _claim, false); move(_disputed, _parentIndex, _claim, false);
} }
/// @inheritdoc IFaultDisputeGame /// @inheritdoc IFaultDisputeGame
......
...@@ -88,11 +88,22 @@ contract PermissionedDisputeGame is FaultDisputeGame { ...@@ -88,11 +88,22 @@ contract PermissionedDisputeGame is FaultDisputeGame {
} }
/// @notice Generic move function, used for both `attack` and `defend` moves. /// @notice Generic move function, used for both `attack` and `defend` moves.
/// @param _challengeIndex The index of the claim being moved against. /// @notice _disputed The disputed `Claim`.
/// @param _challengeIndex The index of the claim being moved against. This must match the `_disputed` claim.
/// @param _claim The claim at the next logical position in the game. /// @param _claim The claim at the next logical position in the game.
/// @param _isAttack Whether or not the move is an attack or defense. /// @param _isAttack Whether or not the move is an attack or defense.
function move(uint256 _challengeIndex, Claim _claim, bool _isAttack) public payable override onlyAuthorized { function move(
super.move(_challengeIndex, _claim, _isAttack); Claim _disputed,
uint256 _challengeIndex,
Claim _claim,
bool _isAttack
)
public
payable
override
onlyAuthorized
{
super.move(_disputed, _challengeIndex, _claim, _isAttack);
} }
/// @inheritdoc IInitializable /// @inheritdoc IInitializable
......
...@@ -34,14 +34,18 @@ interface IFaultDisputeGame is IDisputeGame { ...@@ -34,14 +34,18 @@ interface IFaultDisputeGame is IDisputeGame {
event Move(uint256 indexed parentIndex, Claim indexed claim, address indexed claimant); event Move(uint256 indexed parentIndex, Claim indexed claim, address indexed claimant);
/// @notice Attack a disagreed upon `Claim`. /// @notice Attack a disagreed upon `Claim`.
/// @param _parentIndex Index of the `Claim` to attack in the `claimData` array. /// @param _disputed The `Claim` being attacked.
/// @param _parentIndex Index of the `Claim` to attack in the `claimData` array. This must match the `_disputed`
/// claim.
/// @param _claim The `Claim` at the relative attack position. /// @param _claim The `Claim` at the relative attack position.
function attack(uint256 _parentIndex, Claim _claim) external payable; function attack(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable;
/// @notice Defend an agreed upon `Claim`. /// @notice Defend an agreed upon `Claim`.
/// @param _parentIndex Index of the claim to defend in the `claimData` array. /// @notice _disputed The `Claim` being defended.
/// @param _parentIndex Index of the claim to defend in the `claimData` array. This must match the `_disputed`
/// claim.
/// @param _claim The `Claim` at the relative defense position. /// @param _claim The `Claim` at the relative defense position.
function defend(uint256 _parentIndex, Claim _claim) external payable; function defend(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable;
/// @notice Perform an instruction step via an on-chain fault proof processor. /// @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 /// @dev This function should point to a fault proof processor in order to execute
......
...@@ -45,8 +45,8 @@ error CannotDefendRootClaim(); ...@@ -45,8 +45,8 @@ error CannotDefendRootClaim();
/// @notice Thrown when a claim is attempting to be made that already exists. /// @notice Thrown when a claim is attempting to be made that already exists.
error ClaimAlreadyExists(); error ClaimAlreadyExists();
/// @notice Thrown when a given claim is invalid. /// @notice Thrown when a disputed claim does not match its index in the game.
error InvalidClaim(); error InvalidDisputedClaimIndex();
/// @notice Thrown when an action that requires the game to be `IN_PROGRESS` is invoked when /// @notice Thrown when an action that requires the game to be `IN_PROGRESS` is invoked when
/// the game is not in progress. /// the game is not in progress.
......
...@@ -218,11 +218,12 @@ contract HonestGameSolver is GameSolver { ...@@ -218,11 +218,12 @@ contract HonestGameSolver is GameSolver {
bool isAttack = _direction == Direction.Attack; bool isAttack = _direction == Direction.Attack;
uint256 bond = GAME.getRequiredBond(_movePos); uint256 bond = GAME.getRequiredBond(_movePos);
(,,,, Claim disputed,,) = GAME.claimData(_challengeIndex);
move_ = Move({ move_ = Move({
kind: isAttack ? MoveKind.Attack : MoveKind.Defend, kind: isAttack ? MoveKind.Attack : MoveKind.Defend,
value: bond, value: bond,
data: abi.encodeCall(FaultDisputeGame.move, (_challengeIndex, claimAt(_movePos), isAttack)) data: abi.encodeCall(FaultDisputeGame.move, (disputed, _challengeIndex, claimAt(_movePos), isAttack))
}); });
} }
......
...@@ -358,15 +358,17 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -358,15 +358,17 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
GameStatus status = gameProxy.status(); GameStatus status = gameProxy.status();
assertEq(uint256(status), chalWins); assertEq(uint256(status), chalWins);
(,,,, Claim root,,) = gameProxy.claimData(0);
// Attempt to make a move. Should revert. // Attempt to make a move. Should revert.
vm.expectRevert(GameNotInProgress.selector); vm.expectRevert(GameNotInProgress.selector);
gameProxy.attack(0, Claim.wrap(0)); gameProxy.attack(root, 0, Claim.wrap(0));
} }
/// @dev Tests that an attempt to defend the root claim reverts with the `CannotDefendRootClaim` error. /// @dev Tests that an attempt to defend the root claim reverts with the `CannotDefendRootClaim` error.
function test_move_defendRoot_reverts() public { function test_move_defendRoot_reverts() public {
(,,,, Claim root,,) = gameProxy.claimData(0);
vm.expectRevert(CannotDefendRootClaim.selector); vm.expectRevert(CannotDefendRootClaim.selector);
gameProxy.defend(0, _dummyClaim()); gameProxy.defend(root, 0, _dummyClaim());
} }
/// @dev Tests that an attempt to move against a claim that does not exist reverts with the /// @dev Tests that an attempt to move against a claim that does not exist reverts with the
...@@ -376,11 +378,11 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -376,11 +378,11 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// Expect an out of bounds revert for an attack // Expect an out of bounds revert for an attack
vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x32)); vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x32));
gameProxy.attack(1, claim); gameProxy.attack(_dummyClaim(), 1, claim);
// Expect an out of bounds revert for a defense // Expect an out of bounds revert for a defense
vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x32)); vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x32));
gameProxy.defend(1, claim); gameProxy.defend(_dummyClaim(), 1, claim);
} }
/// @dev Tests that an attempt to move at the maximum game depth reverts with the /// @dev Tests that an attempt to move at the maximum game depth reverts with the
...@@ -391,13 +393,14 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -391,13 +393,14 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
uint256 maxDepth = gameProxy.maxGameDepth(); uint256 maxDepth = gameProxy.maxGameDepth();
for (uint256 i = 0; i <= maxDepth; i++) { for (uint256 i = 0; i <= maxDepth; i++) {
(,,,, Claim disputed,,) = gameProxy.claimData(i);
// At the max game depth, the `_move` function should revert with // At the max game depth, the `_move` function should revert with
// the `GameDepthExceeded` error. // the `GameDepthExceeded` error.
if (i == maxDepth) { if (i == maxDepth) {
vm.expectRevert(GameDepthExceeded.selector); vm.expectRevert(GameDepthExceeded.selector);
gameProxy.attack{ value: 100 ether }(i, claim); gameProxy.attack{ value: 100 ether }(disputed, i, claim);
} else { } else {
gameProxy.attack{ value: _getRequiredBond(i) }(i, claim); gameProxy.attack{ value: _getRequiredBond(i) }(disputed, i, claim);
} }
} }
} }
...@@ -408,8 +411,9 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -408,8 +411,9 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// Warp ahead past the clock time for the first move (3 1/2 days) // Warp ahead past the clock time for the first move (3 1/2 days)
vm.warp(block.timestamp + 3 days + 12 hours + 1); vm.warp(block.timestamp + 3 days + 12 hours + 1);
uint256 bond = _getRequiredBond(0); uint256 bond = _getRequiredBond(0);
(,,,, Claim disputed,,) = gameProxy.claimData(0);
vm.expectRevert(ClockTimeExceeded.selector); vm.expectRevert(ClockTimeExceeded.selector);
gameProxy.attack{ value: bond }(0, _dummyClaim()); gameProxy.attack{ value: bond }(disputed, 0, _dummyClaim());
} }
/// @notice Static unit test for the correctness of the chess clock incrementation. /// @notice Static unit test for the correctness of the chess clock incrementation.
...@@ -421,13 +425,15 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -421,13 +425,15 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
vm.warp(block.timestamp + 15); vm.warp(block.timestamp + 15);
uint256 bond = _getRequiredBond(0); uint256 bond = _getRequiredBond(0);
gameProxy.attack{ value: bond }(0, claim); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: bond }(disputed, 0, claim);
(,,,,,, clock) = gameProxy.claimData(1); (,,,,,, clock) = gameProxy.claimData(1);
assertEq(clock.raw(), LibClock.wrap(Duration.wrap(15), Timestamp.wrap(uint64(block.timestamp))).raw()); assertEq(clock.raw(), LibClock.wrap(Duration.wrap(15), Timestamp.wrap(uint64(block.timestamp))).raw());
vm.warp(block.timestamp + 10); vm.warp(block.timestamp + 10);
bond = _getRequiredBond(1); bond = _getRequiredBond(1);
gameProxy.attack{ value: bond }(1, claim); (,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.attack{ value: bond }(disputed, 1, claim);
(,,,,,, clock) = gameProxy.claimData(2); (,,,,,, clock) = gameProxy.claimData(2);
assertEq(clock.raw(), LibClock.wrap(Duration.wrap(10), Timestamp.wrap(uint64(block.timestamp))).raw()); assertEq(clock.raw(), LibClock.wrap(Duration.wrap(10), Timestamp.wrap(uint64(block.timestamp))).raw());
...@@ -437,13 +443,15 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -437,13 +443,15 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
vm.warp(block.timestamp + 10); vm.warp(block.timestamp + 10);
bond = _getRequiredBond(2); bond = _getRequiredBond(2);
gameProxy.attack{ value: bond }(2, claim); (,,,, disputed,,) = gameProxy.claimData(2);
gameProxy.attack{ value: bond }(disputed, 2, claim);
(,,,,,, clock) = gameProxy.claimData(3); (,,,,,, clock) = gameProxy.claimData(3);
assertEq(clock.raw(), LibClock.wrap(Duration.wrap(25), Timestamp.wrap(uint64(block.timestamp))).raw()); assertEq(clock.raw(), LibClock.wrap(Duration.wrap(25), Timestamp.wrap(uint64(block.timestamp))).raw());
vm.warp(block.timestamp + 10); vm.warp(block.timestamp + 10);
bond = _getRequiredBond(3); bond = _getRequiredBond(3);
gameProxy.attack{ value: bond }(3, claim); (,,,, disputed,,) = gameProxy.claimData(3);
gameProxy.attack{ value: bond }(disputed, 3, claim);
(,,,,,, clock) = gameProxy.claimData(4); (,,,,,, clock) = gameProxy.claimData(4);
assertEq(clock.raw(), LibClock.wrap(Duration.wrap(20), Timestamp.wrap(uint64(block.timestamp))).raw()); assertEq(clock.raw(), LibClock.wrap(Duration.wrap(20), Timestamp.wrap(uint64(block.timestamp))).raw());
} }
...@@ -462,7 +470,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -462,7 +470,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// allocated exactly `clockExtension` seconds remaining on their potential clock. // allocated exactly `clockExtension` seconds remaining on their potential clock.
vm.warp(block.timestamp + halfGameDuration - 1 seconds); vm.warp(block.timestamp + halfGameDuration - 1 seconds);
uint256 bond = _getRequiredBond(0); uint256 bond = _getRequiredBond(0);
gameProxy.attack{ value: bond }(0, claim); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: bond }(disputed, 0, claim);
(,,,,,, clock) = gameProxy.claimData(1); (,,,,,, clock) = gameProxy.claimData(1);
assertEq(clock.duration().raw(), halfGameDuration - clockExtension); assertEq(clock.duration().raw(), halfGameDuration - clockExtension);
...@@ -471,7 +480,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -471,7 +480,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
vm.warp(block.timestamp + halfGameDuration - 1 seconds); vm.warp(block.timestamp + halfGameDuration - 1 seconds);
for (uint256 i = 1; i < splitDepth - 2; i++) { for (uint256 i = 1; i < splitDepth - 2; i++) {
bond = _getRequiredBond(i); bond = _getRequiredBond(i);
gameProxy.attack{ value: bond }(i, claim); (,,,, disputed,,) = gameProxy.claimData(i);
gameProxy.attack{ value: bond }(disputed, i, claim);
} }
// Warp ahead 1 seconds to have `clockExtension - 1 seconds` left on the next move's clock. // Warp ahead 1 seconds to have `clockExtension - 1 seconds` left on the next move's clock.
...@@ -481,7 +491,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -481,7 +491,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// be allocated `clockExtension * 2` seconds on their potential clock, if currently they have less than // be allocated `clockExtension * 2` seconds on their potential clock, if currently they have less than
// `clockExtension` seconds left. // `clockExtension` seconds left.
bond = _getRequiredBond(splitDepth - 2); bond = _getRequiredBond(splitDepth - 2);
gameProxy.attack{ value: bond }(splitDepth - 2, claim); (,,,, disputed,,) = gameProxy.claimData(splitDepth - 2);
gameProxy.attack{ value: bond }(disputed, splitDepth - 2, claim);
(,,,,,, clock) = gameProxy.claimData(splitDepth - 1); (,,,,,, clock) = gameProxy.claimData(splitDepth - 1);
assertEq(clock.duration().raw(), halfGameDuration - clockExtension * 2); assertEq(clock.duration().raw(), halfGameDuration - clockExtension * 2);
} }
...@@ -493,11 +504,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -493,11 +504,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// Make the first move. This should succeed. // Make the first move. This should succeed.
uint256 bond = _getRequiredBond(0); uint256 bond = _getRequiredBond(0);
gameProxy.attack{ value: bond }(0, claim); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: bond }(disputed, 0, claim);
// Attempt to make the same move again. // Attempt to make the same move again.
vm.expectRevert(ClaimAlreadyExists.selector); vm.expectRevert(ClaimAlreadyExists.selector);
gameProxy.attack{ value: bond }(0, claim); gameProxy.attack{ value: bond }(disputed, 0, claim);
} }
/// @dev Static unit test asserting that identical claims at the same position can be made in different subgames. /// @dev Static unit test asserting that identical claims at the same position can be made in different subgames.
...@@ -507,15 +519,18 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -507,15 +519,18 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// Make the first moves. This should succeed. // Make the first moves. This should succeed.
uint256 bond = _getRequiredBond(0); uint256 bond = _getRequiredBond(0);
gameProxy.attack{ value: bond }(0, claimA); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: bond }(0, claimB); gameProxy.attack{ value: bond }(disputed, 0, claimA);
gameProxy.attack{ value: bond }(disputed, 0, claimB);
// Perform an attack at the same position with the same claim value in both subgames. // Perform an attack at the same position with the same claim value in both subgames.
// These both should succeed. // These both should succeed.
bond = _getRequiredBond(1); bond = _getRequiredBond(1);
gameProxy.attack{ value: bond }(1, claimA); (,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.attack{ value: bond }(disputed, 1, claimA);
bond = _getRequiredBond(2); bond = _getRequiredBond(2);
gameProxy.attack{ value: bond }(2, claimA); (,,,, disputed,,) = gameProxy.claimData(2);
gameProxy.attack{ value: bond }(disputed, 2, claimA);
} }
/// @dev Static unit test for the correctness of an opening attack. /// @dev Static unit test for the correctness of an opening attack.
...@@ -529,7 +544,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -529,7 +544,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
uint256 reqBond = _getRequiredBond(0); uint256 reqBond = _getRequiredBond(0);
vm.expectEmit(true, true, true, false); vm.expectEmit(true, true, true, false);
emit Move(0, counter, address(this)); emit Move(0, counter, address(this));
gameProxy.attack{ value: reqBond }(0, counter); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: reqBond }(disputed, 0, counter);
// Grab the claim data of the attack. // Grab the claim data of the attack.
( (
...@@ -567,30 +583,46 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -567,30 +583,46 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// @dev Tests that making a claim at the execution trace bisection root level with an invalid status /// @dev Tests that making a claim at the execution trace bisection root level with an invalid status
/// byte reverts with the `UnexpectedRootClaim` error. /// byte reverts with the `UnexpectedRootClaim` error.
function test_move_incorrectStatusExecRoot_reverts() public { function test_move_incorrectStatusExecRoot_reverts() public {
Claim disputed;
for (uint256 i; i < 4; i++) { for (uint256 i; i < 4; i++) {
gameProxy.attack{ value: _getRequiredBond(i) }(i, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(i);
gameProxy.attack{ value: _getRequiredBond(i) }(disputed, i, _dummyClaim());
} }
uint256 bond = _getRequiredBond(4); uint256 bond = _getRequiredBond(4);
(,,,, disputed,,) = gameProxy.claimData(4);
vm.expectRevert(abi.encodeWithSelector(UnexpectedRootClaim.selector, bytes32(0))); vm.expectRevert(abi.encodeWithSelector(UnexpectedRootClaim.selector, bytes32(0)));
gameProxy.attack{ value: bond }(4, Claim.wrap(bytes32(0))); gameProxy.attack{ value: bond }(disputed, 4, Claim.wrap(bytes32(0)));
} }
/// @dev Tests that making a claim at the execution trace bisection root level with a valid status /// @dev Tests that making a claim at the execution trace bisection root level with a valid status
/// byte succeeds. /// byte succeeds.
function test_move_correctStatusExecRoot_succeeds() public { function test_move_correctStatusExecRoot_succeeds() public {
Claim disputed;
for (uint256 i; i < 4; i++) { for (uint256 i; i < 4; i++) {
uint256 bond = _getRequiredBond(i); uint256 bond = _getRequiredBond(i);
gameProxy.attack{ value: bond }(i, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(i);
gameProxy.attack{ value: bond }(disputed, i, _dummyClaim());
} }
uint256 lastBond = _getRequiredBond(4); uint256 lastBond = _getRequiredBond(4);
gameProxy.attack{ value: lastBond }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); (,,,, disputed,,) = gameProxy.claimData(4);
gameProxy.attack{ value: lastBond }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC));
} }
/// @dev Static unit test asserting that a move reverts when the bonded amount is incorrect. /// @dev Static unit test asserting that a move reverts when the bonded amount is incorrect.
function test_move_incorrectBondAmount_reverts() public { function test_move_incorrectBondAmount_reverts() public {
(,,,, Claim disputed,,) = gameProxy.claimData(0);
vm.expectRevert(IncorrectBondAmount.selector); vm.expectRevert(IncorrectBondAmount.selector);
gameProxy.attack{ value: 0 }(0, _dummyClaim()); gameProxy.attack{ value: 0 }(disputed, 0, _dummyClaim());
}
/// @dev Static unit test asserting that a move reverts when the disputed claim does not match its index.
function test_move_incorrectDisputedIndex_reverts() public {
(,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim());
uint256 bond = _getRequiredBond(1);
vm.expectRevert(InvalidDisputedClaimIndex.selector);
gameProxy.attack{ value: bond }(disputed, 1, _dummyClaim());
} }
/// @dev Tests that challenging the root claim's L2 block number by providing the real preimage of the output root /// @dev Tests that challenging the root claim's L2 block number by providing the real preimage of the output root
...@@ -654,8 +686,9 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -654,8 +686,9 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// Attack the root as 0xb0b // Attack the root as 0xb0b
uint256 bond = _getRequiredBond(0); uint256 bond = _getRequiredBond(0);
(,,,, Claim disputed,,) = fdg.claimData(0);
vm.prank(address(0xb0b)); vm.prank(address(0xb0b));
fdg.attack{ value: bond }(0, Claim.wrap(0)); fdg.attack{ value: bond }(disputed, 0, Claim.wrap(0));
// Challenge the L2 block number as 0xace. This claim should receive the root claim's bond. // Challenge the L2 block number as 0xace. This claim should receive the root claim's bond.
vm.prank(address(0xace)); vm.prank(address(0xace));
...@@ -761,14 +794,22 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -761,14 +794,22 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
vm.deal(address(this), 1000 ether); vm.deal(address(this), 1000 ether);
// Make claims all the way down the tree. // Make claims all the way down the tree.
gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: _getRequiredBond(1) }(1, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim());
gameProxy.attack{ value: _getRequiredBond(2) }(2, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.attack{ value: _getRequiredBond(3) }(3, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim());
gameProxy.attack{ value: _getRequiredBond(4) }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); (,,,, disputed,,) = gameProxy.claimData(2);
gameProxy.attack{ value: _getRequiredBond(5) }(5, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(2) }(disputed, 2, _dummyClaim());
gameProxy.attack{ value: _getRequiredBond(6) }(6, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(3);
gameProxy.attack{ value: _getRequiredBond(7) }(7, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(3) }(disputed, 3, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(4);
gameProxy.attack{ value: _getRequiredBond(4) }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC));
(,,,, disputed,,) = gameProxy.claimData(5);
gameProxy.attack{ value: _getRequiredBond(5) }(disputed, 5, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(6);
gameProxy.attack{ value: _getRequiredBond(6) }(disputed, 6, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(7);
gameProxy.attack{ value: _getRequiredBond(7) }(disputed, 7, _dummyClaim());
gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0);
gameProxy.step(8, true, absolutePrestateData, hex""); gameProxy.step(8, true, absolutePrestateData, hex"");
...@@ -783,16 +824,24 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -783,16 +824,24 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
vm.deal(address(this), 1000 ether); vm.deal(address(this), 1000 ether);
// Make claims all the way down the tree. // Make claims all the way down the tree.
gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: _getRequiredBond(1) }(1, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim());
gameProxy.attack{ value: _getRequiredBond(2) }(2, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.attack{ value: _getRequiredBond(3) }(3, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim());
gameProxy.attack{ value: _getRequiredBond(4) }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); (,,,, disputed,,) = gameProxy.claimData(2);
gameProxy.attack{ value: _getRequiredBond(2) }(disputed, 2, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(3);
gameProxy.attack{ value: _getRequiredBond(3) }(disputed, 3, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(4);
gameProxy.attack{ value: _getRequiredBond(4) }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC));
bytes memory claimData5 = abi.encode(5, 5); bytes memory claimData5 = abi.encode(5, 5);
Claim claim5 = Claim.wrap(keccak256(claimData5)); Claim claim5 = Claim.wrap(keccak256(claimData5));
gameProxy.attack{ value: _getRequiredBond(5) }(5, claim5); (,,,, disputed,,) = gameProxy.claimData(5);
gameProxy.defend{ value: _getRequiredBond(6) }(6, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(5) }(disputed, 5, claim5);
gameProxy.attack{ value: _getRequiredBond(7) }(7, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(6);
gameProxy.defend{ value: _getRequiredBond(6) }(disputed, 6, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(7);
gameProxy.attack{ value: _getRequiredBond(7) }(disputed, 7, _dummyClaim());
gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0);
gameProxy.step(8, true, claimData5, hex""); gameProxy.step(8, true, claimData5, hex"");
} }
...@@ -804,17 +853,25 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -804,17 +853,25 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
vm.deal(address(this), 1000 ether); vm.deal(address(this), 1000 ether);
// Make claims all the way down the tree. // Make claims all the way down the tree.
gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: _getRequiredBond(1) }(1, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim());
gameProxy.attack{ value: _getRequiredBond(2) }(2, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.attack{ value: _getRequiredBond(3) }(3, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim());
gameProxy.attack{ value: _getRequiredBond(4) }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); (,,,, disputed,,) = gameProxy.claimData(2);
gameProxy.attack{ value: _getRequiredBond(2) }(disputed, 2, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(3);
gameProxy.attack{ value: _getRequiredBond(3) }(disputed, 3, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(4);
gameProxy.attack{ value: _getRequiredBond(4) }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC));
bytes memory claimData5 = abi.encode(5, 5); bytes memory claimData5 = abi.encode(5, 5);
Claim claim5 = Claim.wrap(keccak256(claimData5)); Claim claim5 = Claim.wrap(keccak256(claimData5));
gameProxy.attack{ value: _getRequiredBond(5) }(5, claim5); (,,,, disputed,,) = gameProxy.claimData(5);
gameProxy.defend{ value: _getRequiredBond(6) }(6, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(5) }(disputed, 5, claim5);
(,,,, disputed,,) = gameProxy.claimData(6);
gameProxy.defend{ value: _getRequiredBond(6) }(disputed, 6, _dummyClaim());
Claim postState_ = Claim.wrap(gameImpl.vm().step(claimData5, hex"", bytes32(0))); Claim postState_ = Claim.wrap(gameImpl.vm().step(claimData5, hex"", bytes32(0)));
gameProxy.attack{ value: _getRequiredBond(7) }(7, postState_); (,,,, disputed,,) = gameProxy.claimData(7);
gameProxy.attack{ value: _getRequiredBond(7) }(disputed, 7, postState_);
gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0);
vm.expectRevert(ValidStep.selector); vm.expectRevert(ValidStep.selector);
...@@ -828,21 +885,29 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -828,21 +885,29 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
vm.deal(address(this), 1000 ether); vm.deal(address(this), 1000 ether);
// Make claims all the way down the tree. // Make claims all the way down the tree.
gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: _getRequiredBond(1) }(1, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim());
gameProxy.attack{ value: _getRequiredBond(2) }(2, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.attack{ value: _getRequiredBond(3) }(3, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim());
gameProxy.attack{ value: _getRequiredBond(4) }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); (,,,, disputed,,) = gameProxy.claimData(2);
gameProxy.attack{ value: _getRequiredBond(2) }(disputed, 2, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(3);
gameProxy.attack{ value: _getRequiredBond(3) }(disputed, 3, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(4);
gameProxy.attack{ value: _getRequiredBond(4) }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC));
bytes memory claimData7 = abi.encode(5, 5); bytes memory claimData7 = abi.encode(5, 5);
Claim postState_ = Claim.wrap(gameImpl.vm().step(claimData7, hex"", bytes32(0))); Claim postState_ = Claim.wrap(gameImpl.vm().step(claimData7, hex"", bytes32(0)));
gameProxy.attack{ value: _getRequiredBond(5) }(5, postState_); (,,,, disputed,,) = gameProxy.claimData(5);
gameProxy.defend{ value: _getRequiredBond(6) }(6, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(5) }(disputed, 5, postState_);
(,,,, disputed,,) = gameProxy.claimData(6);
gameProxy.defend{ value: _getRequiredBond(6) }(disputed, 6, _dummyClaim());
bytes memory _dummyClaimData = abi.encode(gasleft(), gasleft()); bytes memory _dummyClaimData = abi.encode(gasleft(), gasleft());
Claim dummyClaim7 = Claim.wrap(keccak256(_dummyClaimData)); Claim dummyClaim7 = Claim.wrap(keccak256(_dummyClaimData));
gameProxy.attack{ value: _getRequiredBond(7) }(7, dummyClaim7); (,,,, disputed,,) = gameProxy.claimData(7);
gameProxy.attack{ value: _getRequiredBond(7) }(disputed, 7, dummyClaim7);
gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0);
vm.expectRevert(ValidStep.selector); vm.expectRevert(ValidStep.selector);
gameProxy.step(8, false, _dummyClaimData, hex""); gameProxy.step(8, false, _dummyClaimData, hex"");
...@@ -855,19 +920,27 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -855,19 +920,27 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
vm.deal(address(this), 1000 ether); vm.deal(address(this), 1000 ether);
// Make claims all the way down the tree. // Make claims all the way down the tree.
gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: _getRequiredBond(1) }(1, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim());
gameProxy.attack{ value: _getRequiredBond(2) }(2, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.attack{ value: _getRequiredBond(3) }(3, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim());
gameProxy.attack{ value: _getRequiredBond(4) }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); (,,,, disputed,,) = gameProxy.claimData(2);
gameProxy.attack{ value: _getRequiredBond(2) }(disputed, 2, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(3);
gameProxy.attack{ value: _getRequiredBond(3) }(disputed, 3, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(4);
gameProxy.attack{ value: _getRequiredBond(4) }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC));
bytes memory claimData7 = abi.encode(5, 5); bytes memory claimData7 = abi.encode(5, 5);
Claim claim7 = Claim.wrap(keccak256(claimData7)); Claim claim7 = Claim.wrap(keccak256(claimData7));
Claim postState_ = Claim.wrap(gameImpl.vm().step(claimData7, hex"", bytes32(0))); Claim postState_ = Claim.wrap(gameImpl.vm().step(claimData7, hex"", bytes32(0)));
gameProxy.attack{ value: _getRequiredBond(5) }(5, postState_); (,,,, disputed,,) = gameProxy.claimData(5);
gameProxy.defend{ value: _getRequiredBond(6) }(6, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(5) }(disputed, 5, postState_);
gameProxy.attack{ value: _getRequiredBond(7) }(7, claim7); (,,,, disputed,,) = gameProxy.claimData(6);
gameProxy.defend{ value: _getRequiredBond(6) }(disputed, 6, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(7);
gameProxy.attack{ value: _getRequiredBond(7) }(disputed, 7, claim7);
gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0);
vm.expectRevert(ValidStep.selector); vm.expectRevert(ValidStep.selector);
...@@ -894,7 +967,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -894,7 +967,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
uint256 bond = _getRequiredBond(0); uint256 bond = _getRequiredBond(0);
for (uint256 i = 0; i < 2048; i++) { for (uint256 i = 0; i < 2048; i++) {
gameProxy.attack{ value: bond }(0, Claim.wrap(bytes32(i))); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: bond }(disputed, 0, Claim.wrap(bytes32(i)));
} }
// Warp past the clock period. // Warp past the clock period.
...@@ -965,7 +1039,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -965,7 +1039,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// @dev Static unit test for the correctness of resolving a single attack game state. /// @dev Static unit test for the correctness of resolving a single attack game state.
function test_resolve_rootContested_succeeds() public { function test_resolve_rootContested_succeeds() public {
gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim());
vm.warp(block.timestamp + 3 days + 12 hours); vm.warp(block.timestamp + 3 days + 12 hours);
...@@ -976,8 +1051,10 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -976,8 +1051,10 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// @dev Static unit test for the correctness of resolving a game with a contested challenge claim. /// @dev Static unit test for the correctness of resolving a game with a contested challenge claim.
function test_resolve_challengeContested_succeeds() public { function test_resolve_challengeContested_succeeds() public {
gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.defend{ value: _getRequiredBond(1) }(1, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.defend{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim());
vm.warp(block.timestamp + 3 days + 12 hours); vm.warp(block.timestamp + 3 days + 12 hours);
...@@ -989,10 +1066,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -989,10 +1066,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// @dev Static unit test for the correctness of resolving a game with multiplayer moves. /// @dev Static unit test for the correctness of resolving a game with multiplayer moves.
function test_resolve_teamDeathmatch_succeeds() public { function test_resolve_teamDeathmatch_succeeds() public {
gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim());
gameProxy.defend{ value: _getRequiredBond(1) }(1, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim());
gameProxy.defend{ value: _getRequiredBond(1) }(1, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.defend{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim());
gameProxy.defend{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim());
vm.warp(block.timestamp + 3 days + 12 hours); vm.warp(block.timestamp + 3 days + 12 hours);
...@@ -1008,12 +1087,14 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1008,12 +1087,14 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
function test_resolve_stepReached_succeeds() public { function test_resolve_stepReached_succeeds() public {
Claim claim = _dummyClaim(); Claim claim = _dummyClaim();
for (uint256 i; i < gameProxy.splitDepth(); i++) { for (uint256 i; i < gameProxy.splitDepth(); i++) {
gameProxy.attack{ value: _getRequiredBond(i) }(i, claim); (,,,, Claim disputed,,) = gameProxy.claimData(i);
gameProxy.attack{ value: _getRequiredBond(i) }(disputed, i, claim);
} }
claim = _changeClaimStatus(claim, VMStatuses.PANIC); claim = _changeClaimStatus(claim, VMStatuses.PANIC);
for (uint256 i = gameProxy.claimDataLen() - 1; i < gameProxy.maxGameDepth(); i++) { for (uint256 i = gameProxy.claimDataLen() - 1; i < gameProxy.maxGameDepth(); i++) {
gameProxy.attack{ value: _getRequiredBond(i) }(i, claim); (,,,, Claim disputed,,) = gameProxy.claimData(i);
gameProxy.attack{ value: _getRequiredBond(i) }(disputed, i, claim);
} }
vm.warp(block.timestamp + 3 days + 12 hours); vm.warp(block.timestamp + 3 days + 12 hours);
...@@ -1029,10 +1110,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1029,10 +1110,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
Claim claim = _dummyClaim(); Claim claim = _dummyClaim();
uint256 firstBond = _getRequiredBond(0); uint256 firstBond = _getRequiredBond(0);
vm.deal(address(this), firstBond); vm.deal(address(this), firstBond);
gameProxy.attack{ value: firstBond }(0, claim); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: firstBond }(disputed, 0, claim);
uint256 secondBond = _getRequiredBond(1); uint256 secondBond = _getRequiredBond(1);
vm.deal(address(this), secondBond); vm.deal(address(this), secondBond);
gameProxy.attack{ value: secondBond }(1, claim); (,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.attack{ value: secondBond }(disputed, 1, claim);
vm.warp(block.timestamp + 3 days + 12 hours); vm.warp(block.timestamp + 3 days + 12 hours);
...@@ -1055,13 +1138,15 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1055,13 +1138,15 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
function test_resolve_claimAtMaxDepthAlreadyResolved_reverts() public { function test_resolve_claimAtMaxDepthAlreadyResolved_reverts() public {
Claim claim = _dummyClaim(); Claim claim = _dummyClaim();
for (uint256 i; i < gameProxy.splitDepth(); i++) { for (uint256 i; i < gameProxy.splitDepth(); i++) {
gameProxy.attack{ value: _getRequiredBond(i) }(i, claim); (,,,, Claim disputed,,) = gameProxy.claimData(i);
gameProxy.attack{ value: _getRequiredBond(i) }(disputed, i, claim);
} }
vm.deal(address(this), 10000 ether); vm.deal(address(this), 10000 ether);
claim = _changeClaimStatus(claim, VMStatuses.PANIC); claim = _changeClaimStatus(claim, VMStatuses.PANIC);
for (uint256 i = gameProxy.claimDataLen() - 1; i < gameProxy.maxGameDepth(); i++) { for (uint256 i = gameProxy.claimDataLen() - 1; i < gameProxy.maxGameDepth(); i++) {
gameProxy.attack{ value: _getRequiredBond(i) }(i, claim); (,,,, Claim disputed,,) = gameProxy.claimData(i);
gameProxy.attack{ value: _getRequiredBond(i) }(disputed, i, claim);
} }
vm.warp(block.timestamp + 3 days + 12 hours); vm.warp(block.timestamp + 3 days + 12 hours);
...@@ -1082,8 +1167,10 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1082,8 +1167,10 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// @dev Static unit test asserting that resolve reverts when attempting to resolve subgames out of order /// @dev Static unit test asserting that resolve reverts when attempting to resolve subgames out of order
function test_resolve_outOfOrderResolution_reverts() public { function test_resolve_outOfOrderResolution_reverts() public {
gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: _getRequiredBond(1) }(1, _dummyClaim()); gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim());
(,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.attack{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim());
vm.warp(block.timestamp + 3 days + 12 hours); vm.warp(block.timestamp + 3 days + 12 hours);
...@@ -1101,28 +1188,36 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1101,28 +1188,36 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// Make claims all the way down the tree. // Make claims all the way down the tree.
uint256 bond = _getRequiredBond(0); uint256 bond = _getRequiredBond(0);
uint256 totalBonded = bond; uint256 totalBonded = bond;
gameProxy.attack{ value: bond }(0, _dummyClaim()); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: bond }(disputed, 0, _dummyClaim());
bond = _getRequiredBond(1); bond = _getRequiredBond(1);
totalBonded += bond; totalBonded += bond;
gameProxy.attack{ value: bond }(1, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.attack{ value: bond }(disputed, 1, _dummyClaim());
bond = _getRequiredBond(2); bond = _getRequiredBond(2);
totalBonded += bond; totalBonded += bond;
gameProxy.attack{ value: bond }(2, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(2);
gameProxy.attack{ value: bond }(disputed, 2, _dummyClaim());
bond = _getRequiredBond(3); bond = _getRequiredBond(3);
totalBonded += bond; totalBonded += bond;
gameProxy.attack{ value: bond }(3, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(3);
gameProxy.attack{ value: bond }(disputed, 3, _dummyClaim());
bond = _getRequiredBond(4); bond = _getRequiredBond(4);
totalBonded += bond; totalBonded += bond;
gameProxy.attack{ value: bond }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); (,,,, disputed,,) = gameProxy.claimData(4);
gameProxy.attack{ value: bond }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC));
bond = _getRequiredBond(5); bond = _getRequiredBond(5);
totalBonded += bond; totalBonded += bond;
gameProxy.attack{ value: bond }(5, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(5);
gameProxy.attack{ value: bond }(disputed, 5, _dummyClaim());
bond = _getRequiredBond(6); bond = _getRequiredBond(6);
totalBonded += bond; totalBonded += bond;
gameProxy.attack{ value: bond }(6, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(6);
gameProxy.attack{ value: bond }(disputed, 6, _dummyClaim());
bond = _getRequiredBond(7); bond = _getRequiredBond(7);
totalBonded += bond; totalBonded += bond;
gameProxy.attack{ value: bond }(7, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(7);
gameProxy.attack{ value: bond }(disputed, 7, _dummyClaim());
gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0);
gameProxy.step(8, true, absolutePrestateData, hex""); gameProxy.step(8, true, absolutePrestateData, hex"");
...@@ -1161,47 +1256,56 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1161,47 +1256,56 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// moves with 2 actors and a dishonest root claim. /// moves with 2 actors and a dishonest root claim.
function test_resolve_bondPayoutsSeveralActors_succeeds() public { function test_resolve_bondPayoutsSeveralActors_succeeds() public {
// Give the test contract and bob some ether // Give the test contract and bob some ether
uint256 bal = 1000 ether; // We use the "1000 ether" literal for `bal`, the initial balance, to avoid stack too deep
//uint256 bal = 1000 ether;
address bob = address(0xb0b); address bob = address(0xb0b);
vm.deal(address(this), bal); vm.deal(address(this), 1000 ether);
vm.deal(bob, bal); vm.deal(bob, 1000 ether);
// Make claims all the way down the tree, trading off between bob and the test contract. // Make claims all the way down the tree, trading off between bob and the test contract.
uint256 firstBond = _getRequiredBond(0); uint256 firstBond = _getRequiredBond(0);
uint256 thisBonded = firstBond; uint256 thisBonded = firstBond;
gameProxy.attack{ value: firstBond }(0, _dummyClaim()); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: firstBond }(disputed, 0, _dummyClaim());
uint256 secondBond = _getRequiredBond(1); uint256 secondBond = _getRequiredBond(1);
uint256 bobBonded = secondBond; uint256 bobBonded = secondBond;
(,,,, disputed,,) = gameProxy.claimData(1);
vm.prank(bob); vm.prank(bob);
gameProxy.attack{ value: secondBond }(1, _dummyClaim()); gameProxy.attack{ value: secondBond }(disputed, 1, _dummyClaim());
uint256 thirdBond = _getRequiredBond(2); uint256 thirdBond = _getRequiredBond(2);
thisBonded += thirdBond; thisBonded += thirdBond;
gameProxy.attack{ value: thirdBond }(2, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(2);
gameProxy.attack{ value: thirdBond }(disputed, 2, _dummyClaim());
uint256 fourthBond = _getRequiredBond(3); uint256 fourthBond = _getRequiredBond(3);
bobBonded += fourthBond; bobBonded += fourthBond;
(,,,, disputed,,) = gameProxy.claimData(3);
vm.prank(bob); vm.prank(bob);
gameProxy.attack{ value: fourthBond }(3, _dummyClaim()); gameProxy.attack{ value: fourthBond }(disputed, 3, _dummyClaim());
uint256 fifthBond = _getRequiredBond(4); uint256 fifthBond = _getRequiredBond(4);
thisBonded += fifthBond; thisBonded += fifthBond;
gameProxy.attack{ value: fifthBond }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); (,,,, disputed,,) = gameProxy.claimData(4);
gameProxy.attack{ value: fifthBond }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC));
uint256 sixthBond = _getRequiredBond(5); uint256 sixthBond = _getRequiredBond(5);
bobBonded += sixthBond; bobBonded += sixthBond;
(,,,, disputed,,) = gameProxy.claimData(5);
vm.prank(bob); vm.prank(bob);
gameProxy.attack{ value: sixthBond }(5, _dummyClaim()); gameProxy.attack{ value: sixthBond }(disputed, 5, _dummyClaim());
uint256 seventhBond = _getRequiredBond(6); uint256 seventhBond = _getRequiredBond(6);
thisBonded += seventhBond; thisBonded += seventhBond;
gameProxy.attack{ value: seventhBond }(6, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(6);
gameProxy.attack{ value: seventhBond }(disputed, 6, _dummyClaim());
uint256 eighthBond = _getRequiredBond(7); uint256 eighthBond = _getRequiredBond(7);
bobBonded += eighthBond; bobBonded += eighthBond;
(,,,, disputed,,) = gameProxy.claimData(7);
vm.prank(bob); vm.prank(bob);
gameProxy.attack{ value: eighthBond }(7, _dummyClaim()); gameProxy.attack{ value: eighthBond }(disputed, 7, _dummyClaim());
gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0);
gameProxy.step(8, true, absolutePrestateData, hex""); gameProxy.step(8, true, absolutePrestateData, hex"");
...@@ -1211,8 +1315,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1211,8 +1315,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
assertEq(counteredBy, address(this)); assertEq(counteredBy, address(this));
// Ensure we bonded the correct amounts // Ensure we bonded the correct amounts
assertEq(address(this).balance, bal - thisBonded); assertEq(address(this).balance, 1000 ether - thisBonded);
assertEq(bob.balance, bal - bobBonded); assertEq(bob.balance, 1000 ether - bobBonded);
assertEq(address(gameProxy).balance, 0); assertEq(address(gameProxy).balance, 0);
assertEq(delayedWeth.balanceOf(address(gameProxy)), thisBonded + bobBonded); assertEq(delayedWeth.balanceOf(address(gameProxy)), thisBonded + bobBonded);
...@@ -1234,8 +1338,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1234,8 +1338,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
gameProxy.claimCredit(bob); gameProxy.claimCredit(bob);
// Ensure that bonds were paid out correctly. // Ensure that bonds were paid out correctly.
assertEq(address(this).balance, bal + bobBonded); assertEq(address(this).balance, 1000 ether + bobBonded);
assertEq(bob.balance, bal - bobBonded); assertEq(bob.balance, 1000 ether - bobBonded);
assertEq(address(gameProxy).balance, 0); assertEq(address(gameProxy).balance, 0);
assertEq(delayedWeth.balanceOf(address(gameProxy)), 0); assertEq(delayedWeth.balanceOf(address(gameProxy)), 0);
...@@ -1259,19 +1363,22 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1259,19 +1363,22 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// charlie is successfully countered by alice // charlie is successfully countered by alice
// alice is successfully countered by both bob and the test contract // alice is successfully countered by both bob and the test contract
uint256 firstBond = _getRequiredBond(0); uint256 firstBond = _getRequiredBond(0);
(,,,, Claim disputed,,) = gameProxy.claimData(0);
vm.prank(alice); vm.prank(alice);
gameProxy.attack{ value: firstBond }(0, _dummyClaim()); gameProxy.attack{ value: firstBond }(disputed, 0, _dummyClaim());
uint256 secondBond = _getRequiredBond(1); uint256 secondBond = _getRequiredBond(1);
(,,,, disputed,,) = gameProxy.claimData(1);
vm.prank(bob); vm.prank(bob);
gameProxy.defend{ value: secondBond }(1, _dummyClaim()); gameProxy.defend{ value: secondBond }(disputed, 1, _dummyClaim());
vm.prank(charlie); vm.prank(charlie);
gameProxy.attack{ value: secondBond }(1, _dummyClaim()); gameProxy.attack{ value: secondBond }(disputed, 1, _dummyClaim());
gameProxy.attack{ value: secondBond }(1, _dummyClaim()); gameProxy.attack{ value: secondBond }(disputed, 1, _dummyClaim());
uint256 thirdBond = _getRequiredBond(3); uint256 thirdBond = _getRequiredBond(3);
(,,,, disputed,,) = gameProxy.claimData(3);
vm.prank(alice); vm.prank(alice);
gameProxy.attack{ value: thirdBond }(3, _dummyClaim()); gameProxy.attack{ value: thirdBond }(disputed, 3, _dummyClaim());
// Resolve all claims // Resolve all claims
vm.warp(block.timestamp + 3 days + 12 hours); vm.warp(block.timestamp + 3 days + 12 hours);
...@@ -1353,7 +1460,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1353,7 +1460,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
assert(l2BlockNumber < gameProxy.l2BlockNumber()); assert(l2BlockNumber < gameProxy.l2BlockNumber());
// Challenge the claim and resolve it. // Challenge the claim and resolve it.
gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim());
vm.warp(block.timestamp + 3 days + 12 hours); vm.warp(block.timestamp + 3 days + 12 hours);
gameProxy.resolveClaim(1, 0); gameProxy.resolveClaim(1, 0);
gameProxy.resolveClaim(0, 0); gameProxy.resolveClaim(0, 0);
...@@ -1377,10 +1485,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1377,10 +1485,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
Claim claim = _dummyClaim(); Claim claim = _dummyClaim();
uint256 firstBond = _getRequiredBond(0); uint256 firstBond = _getRequiredBond(0);
vm.deal(address(reenter), firstBond); vm.deal(address(reenter), firstBond);
gameProxy.attack{ value: firstBond }(0, claim); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: firstBond }(disputed, 0, claim);
uint256 secondBond = _getRequiredBond(1); uint256 secondBond = _getRequiredBond(1);
vm.deal(address(reenter), secondBond); vm.deal(address(reenter), secondBond);
gameProxy.attack{ value: secondBond }(1, claim); (,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.attack{ value: secondBond }(disputed, 1, claim);
uint256 reenterBond = firstBond + secondBond; uint256 reenterBond = firstBond + secondBond;
// Warp past the finalization period // Warp past the finalization period
...@@ -1422,13 +1532,16 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1422,13 +1532,16 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// @dev Tests that adding local data with an out of bounds identifier reverts. /// @dev Tests that adding local data with an out of bounds identifier reverts.
function testFuzz_addLocalData_oob_reverts(uint256 _ident) public { function testFuzz_addLocalData_oob_reverts(uint256 _ident) public {
Claim disputed;
// Get a claim below the split depth so that we can add local data for an execution trace subgame. // Get a claim below the split depth so that we can add local data for an execution trace subgame.
for (uint256 i; i < 4; i++) { for (uint256 i; i < 4; i++) {
uint256 bond = _getRequiredBond(i); uint256 bond = _getRequiredBond(i);
gameProxy.attack{ value: bond }(i, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(i);
gameProxy.attack{ value: bond }(disputed, i, _dummyClaim());
} }
uint256 lastBond = _getRequiredBond(4); uint256 lastBond = _getRequiredBond(4);
gameProxy.attack{ value: lastBond }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); (,,,, disputed,,) = gameProxy.claimData(4);
gameProxy.attack{ value: lastBond }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC));
// [1, 5] are valid local data identifiers. // [1, 5] are valid local data identifiers.
if (_ident <= 5) _ident = 0; if (_ident <= 5) _ident = 0;
...@@ -1441,14 +1554,17 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1441,14 +1554,17 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// that is disputing the transition from `GENESIS -> GENESIS + 1` /// that is disputing the transition from `GENESIS -> GENESIS + 1`
function test_addLocalDataGenesisTransition_static_succeeds() public { function test_addLocalDataGenesisTransition_static_succeeds() public {
IPreimageOracle oracle = IPreimageOracle(address(gameProxy.vm().oracle())); IPreimageOracle oracle = IPreimageOracle(address(gameProxy.vm().oracle()));
Claim disputed;
// Get a claim below the split depth so that we can add local data for an execution trace subgame. // Get a claim below the split depth so that we can add local data for an execution trace subgame.
for (uint256 i; i < 4; i++) { for (uint256 i; i < 4; i++) {
uint256 bond = _getRequiredBond(i); uint256 bond = _getRequiredBond(i);
gameProxy.attack{ value: bond }(i, Claim.wrap(bytes32(i))); (,,,, disputed,,) = gameProxy.claimData(i);
gameProxy.attack{ value: bond }(disputed, i, Claim.wrap(bytes32(i)));
} }
uint256 lastBond = _getRequiredBond(4); uint256 lastBond = _getRequiredBond(4);
gameProxy.attack{ value: lastBond }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); (,,,, disputed,,) = gameProxy.claimData(4);
gameProxy.attack{ value: lastBond }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC));
// Expected start/disputed claims // Expected start/disputed claims
(Hash root,) = gameProxy.startingOutputRoot(); (Hash root,) = gameProxy.startingOutputRoot();
...@@ -1489,14 +1605,17 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1489,14 +1605,17 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// @dev Tests that local data is loaded into the preimage oracle correctly. /// @dev Tests that local data is loaded into the preimage oracle correctly.
function test_addLocalDataMiddle_static_succeeds() public { function test_addLocalDataMiddle_static_succeeds() public {
IPreimageOracle oracle = IPreimageOracle(address(gameProxy.vm().oracle())); IPreimageOracle oracle = IPreimageOracle(address(gameProxy.vm().oracle()));
Claim disputed;
// Get a claim below the split depth so that we can add local data for an execution trace subgame. // Get a claim below the split depth so that we can add local data for an execution trace subgame.
for (uint256 i; i < 4; i++) { for (uint256 i; i < 4; i++) {
uint256 bond = _getRequiredBond(i); uint256 bond = _getRequiredBond(i);
gameProxy.attack{ value: bond }(i, Claim.wrap(bytes32(i))); (,,,, disputed,,) = gameProxy.claimData(i);
gameProxy.attack{ value: bond }(disputed, i, Claim.wrap(bytes32(i)));
} }
uint256 lastBond = _getRequiredBond(4); uint256 lastBond = _getRequiredBond(4);
gameProxy.defend{ value: lastBond }(4, _changeClaimStatus(ROOT_CLAIM, VMStatuses.VALID)); (,,,, disputed,,) = gameProxy.claimData(4);
gameProxy.defend{ value: lastBond }(disputed, 4, _changeClaimStatus(ROOT_CLAIM, VMStatuses.VALID));
// Expected start/disputed claims // Expected start/disputed claims
bytes32 startingClaim = bytes32(uint256(3)); bytes32 startingClaim = bytes32(uint256(3));
...@@ -1541,7 +1660,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1541,7 +1660,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// Defender's turn // Defender's turn
vm.warp(block.timestamp + 3.5 days - 1 seconds); vm.warp(block.timestamp + 3.5 days - 1 seconds);
gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim());
// Chess clock time accumulated: // Chess clock time accumulated:
assertEq(gameProxy.getChallengerDuration(0).raw(), 3.5 days - 1 seconds); assertEq(gameProxy.getChallengerDuration(0).raw(), 3.5 days - 1 seconds);
assertEq(gameProxy.getChallengerDuration(1).raw(), 0); assertEq(gameProxy.getChallengerDuration(1).raw(), 0);
...@@ -1551,7 +1671,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1551,7 +1671,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// Attempt a second attack against the root claim. This should revert since the challenger clock is expired. // Attempt a second attack against the root claim. This should revert since the challenger clock is expired.
uint256 expectedBond = _getRequiredBond(0); uint256 expectedBond = _getRequiredBond(0);
vm.expectRevert(ClockTimeExceeded.selector); vm.expectRevert(ClockTimeExceeded.selector);
gameProxy.attack{ value: expectedBond }(0, _dummyClaim()); gameProxy.attack{ value: expectedBond }(disputed, 0, _dummyClaim());
// Chess clock time accumulated: // Chess clock time accumulated:
assertEq(gameProxy.getChallengerDuration(0).raw(), 3.5 days); assertEq(gameProxy.getChallengerDuration(0).raw(), 3.5 days);
assertEq(gameProxy.getChallengerDuration(1).raw(), 1 seconds); assertEq(gameProxy.getChallengerDuration(1).raw(), 1 seconds);
...@@ -1565,7 +1685,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1565,7 +1685,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// Warp to the last second of the root claim defender clock. // Warp to the last second of the root claim defender clock.
vm.warp(block.timestamp + 3.5 days - 2 seconds); vm.warp(block.timestamp + 3.5 days - 2 seconds);
// Attack the challenge to the root claim. This should succeed, since the defender clock is not expired. // Attack the challenge to the root claim. This should succeed, since the defender clock is not expired.
gameProxy.attack{ value: _getRequiredBond(1) }(1, _dummyClaim()); (,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.attack{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim());
// Chess clock time accumulated: // Chess clock time accumulated:
assertEq(gameProxy.getChallengerDuration(0).raw(), 3.5 days); assertEq(gameProxy.getChallengerDuration(0).raw(), 3.5 days);
assertEq(gameProxy.getChallengerDuration(1).raw(), 3.5 days - 1 seconds); assertEq(gameProxy.getChallengerDuration(1).raw(), 3.5 days - 1 seconds);
...@@ -1598,10 +1719,11 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -1598,10 +1719,11 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
vm.warp(block.timestamp + 1 seconds); vm.warp(block.timestamp + 1 seconds);
expectedBond = _getRequiredBond(1); expectedBond = _getRequiredBond(1);
vm.expectRevert(ClockTimeExceeded.selector); // no further move can be made vm.expectRevert(ClockTimeExceeded.selector); // no further move can be made
gameProxy.attack{ value: expectedBond }(1, _dummyClaim()); gameProxy.attack{ value: expectedBond }(disputed, 1, _dummyClaim());
expectedBond = _getRequiredBond(2); expectedBond = _getRequiredBond(2);
(,,,, disputed,,) = gameProxy.claimData(2);
vm.expectRevert(ClockTimeExceeded.selector); // no further move can be made vm.expectRevert(ClockTimeExceeded.selector); // no further move can be made
gameProxy.attack{ value: expectedBond }(2, _dummyClaim()); gameProxy.attack{ value: expectedBond }(disputed, 2, _dummyClaim());
// Chess clock time accumulated: // Chess clock time accumulated:
assertEq(gameProxy.getChallengerDuration(0).raw(), 3.5 days); assertEq(gameProxy.getChallengerDuration(0).raw(), 3.5 days);
assertEq(gameProxy.getChallengerDuration(1).raw(), 3.5 days); assertEq(gameProxy.getChallengerDuration(1).raw(), 3.5 days);
......
...@@ -131,13 +131,16 @@ contract PermissionedDisputeGame_Test is PermissionedDisputeGame_Init { ...@@ -131,13 +131,16 @@ contract PermissionedDisputeGame_Test is PermissionedDisputeGame_Init {
vm.startPrank(CHALLENGER, CHALLENGER); vm.startPrank(CHALLENGER, CHALLENGER);
uint256 firstBond = _getRequiredBond(0); uint256 firstBond = _getRequiredBond(0);
vm.deal(CHALLENGER, firstBond); vm.deal(CHALLENGER, firstBond);
gameProxy.attack{ value: firstBond }(0, Claim.wrap(0)); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: firstBond }(disputed, 0, Claim.wrap(0));
uint256 secondBond = _getRequiredBond(1); uint256 secondBond = _getRequiredBond(1);
vm.deal(CHALLENGER, secondBond); vm.deal(CHALLENGER, secondBond);
gameProxy.defend{ value: secondBond }(1, Claim.wrap(0)); (,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.defend{ value: secondBond }(disputed, 1, Claim.wrap(0));
uint256 thirdBond = _getRequiredBond(2); uint256 thirdBond = _getRequiredBond(2);
vm.deal(CHALLENGER, thirdBond); vm.deal(CHALLENGER, thirdBond);
gameProxy.move{ value: thirdBond }(2, Claim.wrap(0), true); (,,,, disputed,,) = gameProxy.claimData(2);
gameProxy.move{ value: thirdBond }(disputed, 2, Claim.wrap(0), true);
vm.stopPrank(); vm.stopPrank();
} }
...@@ -146,13 +149,16 @@ contract PermissionedDisputeGame_Test is PermissionedDisputeGame_Init { ...@@ -146,13 +149,16 @@ contract PermissionedDisputeGame_Test is PermissionedDisputeGame_Init {
vm.startPrank(PROPOSER, PROPOSER); vm.startPrank(PROPOSER, PROPOSER);
uint256 firstBond = _getRequiredBond(0); uint256 firstBond = _getRequiredBond(0);
vm.deal(PROPOSER, firstBond); vm.deal(PROPOSER, firstBond);
gameProxy.attack{ value: firstBond }(0, Claim.wrap(0)); (,,,, Claim disputed,,) = gameProxy.claimData(0);
gameProxy.attack{ value: firstBond }(disputed, 0, Claim.wrap(0));
uint256 secondBond = _getRequiredBond(1); uint256 secondBond = _getRequiredBond(1);
vm.deal(PROPOSER, secondBond); vm.deal(PROPOSER, secondBond);
gameProxy.defend{ value: secondBond }(1, Claim.wrap(0)); (,,,, disputed,,) = gameProxy.claimData(1);
gameProxy.defend{ value: secondBond }(disputed, 1, Claim.wrap(0));
uint256 thirdBond = _getRequiredBond(2); uint256 thirdBond = _getRequiredBond(2);
vm.deal(PROPOSER, thirdBond); vm.deal(PROPOSER, thirdBond);
gameProxy.move{ value: thirdBond }(2, Claim.wrap(0), true); (,,,, disputed,,) = gameProxy.claimData(2);
gameProxy.move{ value: thirdBond }(disputed, 2, Claim.wrap(0), true);
vm.stopPrank(); vm.stopPrank();
} }
...@@ -162,12 +168,13 @@ contract PermissionedDisputeGame_Test is PermissionedDisputeGame_Init { ...@@ -162,12 +168,13 @@ contract PermissionedDisputeGame_Test is PermissionedDisputeGame_Init {
vm.assume(_p != PROPOSER && _p != CHALLENGER); vm.assume(_p != PROPOSER && _p != CHALLENGER);
vm.startPrank(_p, _p); vm.startPrank(_p, _p);
(,,,, Claim disputed,,) = gameProxy.claimData(0);
vm.expectRevert(BadAuth.selector); vm.expectRevert(BadAuth.selector);
gameProxy.attack(0, Claim.wrap(0)); gameProxy.attack(disputed, 0, Claim.wrap(0));
vm.expectRevert(BadAuth.selector); vm.expectRevert(BadAuth.selector);
gameProxy.defend(1, Claim.wrap(0)); gameProxy.defend(disputed, 0, Claim.wrap(0));
vm.expectRevert(BadAuth.selector); vm.expectRevert(BadAuth.selector);
gameProxy.move(2, Claim.wrap(0), true); gameProxy.move(disputed, 0, Claim.wrap(0), true);
vm.expectRevert(BadAuth.selector); vm.expectRevert(BadAuth.selector);
gameProxy.step(0, true, absolutePrestateData, hex""); gameProxy.step(0, true, absolutePrestateData, hex"");
vm.stopPrank(); vm.stopPrank();
......
...@@ -89,7 +89,8 @@ contract RandomClaimActor is StdUtils { ...@@ -89,7 +89,8 @@ contract RandomClaimActor is StdUtils {
totalBonded += _bondAmount; totalBonded += _bondAmount;
GAME.move{ value: _bondAmount }(_parentIndex, _claim, _isAttack); (,,,, Claim disputed,,) = GAME.claimData(_parentIndex);
GAME.move{ value: _bondAmount }(disputed, _parentIndex, _claim, _isAttack);
} }
fallback() external payable { } fallback() external payable { }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment