Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5733899
feat: incident response improvements
smartcontracts Jan 11, 2025
e3df61d
fix tests and add specs
wildmolasses Jan 13, 2025
d8e3292
misc fixes
smartcontracts Jan 14, 2025
7e520b7
more fixes
wildmolasses Jan 14, 2025
2e0181d
emit event on setRespectedGameTypeUpdatedAt, and test wasRespectedGam…
wildmolasses Jan 14, 2025
fecbee6
withdrawal when gameWasNotRespectedGameType reverts
wildmolasses Jan 14, 2025
4844149
anchor game blacklisted and getAnchorGame tests
wildmolasses Jan 14, 2025
53f51da
isGameAirgapped
wildmolasses Jan 14, 2025
f2fcdb2
tiny specs change
wildmolasses Jan 14, 2025
18a0b64
add snapshots
wildmolasses Jan 14, 2025
643dd5e
fix specs test and ASR snapshot
wildmolasses Jan 14, 2025
198d8b0
update semver
wildmolasses Jan 14, 2025
5a3330f
no compilation rrestrictions when optimizer is off
wildmolasses Jan 14, 2025
cfd2c57
interop portal semver
wildmolasses Jan 14, 2025
05b6c9d
justfile ignore, semver
wildmolasses Jan 14, 2025
c5b8c57
minor tweaks
smartcontracts Jan 15, 2025
d1a1379
expanded test coverage
smartcontracts Jan 15, 2025
87a3a95
various logical tweaks
smartcontracts Jan 15, 2025
2256be9
test fix
smartcontracts Jan 15, 2025
c643792
clearer error
smartcontracts Jan 15, 2025
096d488
fix test flake in go tests
smartcontracts Jan 15, 2025
5d4e6c8
add portal tests
wildmolasses Jan 15, 2025
63658f1
portal2 tests: encodeCall
wildmolasses Jan 15, 2025
285c3bc
FDG test: recipient can't receive value reverts
wildmolasses Jan 15, 2025
f0372ca
various final tweaks
smartcontracts Jan 15, 2025
517acee
regenerate snapshots
smartcontracts Jan 15, 2025
4dcb7c4
fix specs tests
smartcontracts Jan 15, 2025
ea17af4
final test fixes
smartcontracts Jan 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ just = "1.37.0"
# Foundry dependencies
# Foundry is a special case because it supplies multiple binaries at the same
# GitHub release, so we need to use the aliasing trick to get mise to not error
forge = "nightly-59f354c179f4e7f6d7292acb3d068815c79286d1"
cast = "nightly-59f354c179f4e7f6d7292acb3d068815c79286d1"
anvil = "nightly-59f354c179f4e7f6d7292acb3d068815c79286d1"
forge = "nightly-017c59d6806ce11f1dc131f8607178efad79d84a"
cast = "nightly-017c59d6806ce11f1dc131f8607178efad79d84a"
anvil = "nightly-017c59d6806ce11f1dc131f8607178efad79d84a"

# Fake dependencies
# Put things here if you need to track versions of tools or projects that can't
Expand Down
2 changes: 1 addition & 1 deletion op-chain-ops/interopgen/recipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (r *InteropDevRecipe) Build(addrs devkeys.Addresses) (*WorldConfig, error)
Implementations: OPCMImplementationsConfig{
L1ContractsRelease: "dev",
FaultProof: SuperFaultProofConfig{
WithdrawalDelaySeconds: big.NewInt(604800),
WithdrawalDelaySeconds: big.NewInt(302400),
MinProposalSizeBytes: big.NewInt(10000),
ChallengePeriodSeconds: big.NewInt(120),
ProofMaturityDelaySeconds: big.NewInt(12),
Expand Down
10 changes: 10 additions & 0 deletions op-challenger/game/fault/contracts/faultdisputegame.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ var (
methodL2BlockNumberChallenged = "l2BlockNumberChallenged"
methodL2BlockNumberChallenger = "l2BlockNumberChallenger"
methodChallengeRootL2Block = "challengeRootL2Block"
methodBondDistributionMode = "bondDistributionMode"
)

var (
Expand Down Expand Up @@ -455,6 +456,14 @@ func (f *FaultDisputeGameContractLatest) GetAllClaims(ctx context.Context, block
return claims, nil
}

func (f *FaultDisputeGameContractLatest) BondDistributionMode(ctx context.Context) (uint8, error) {
result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodBondDistributionMode))
if err != nil {
return 0, fmt.Errorf("failed to fetch bond mode: %w", err)
}
return result.GetUint8(0), nil
}

func (f *FaultDisputeGameContractLatest) IsResolved(ctx context.Context, block rpcblock.Block, claims ...types.Claim) ([]bool, error) {
defer f.metrics.StartContractRequest("IsResolved")()
calls := make([]batching.Call, 0, len(claims))
Expand Down Expand Up @@ -639,4 +648,5 @@ type FaultDisputeGameContract interface {
CallResolve(ctx context.Context) (gameTypes.GameStatus, error)
ResolveTx() (txmgr.TxCandidate, error)
Vm(ctx context.Context) (*VMContract, error)
BondDistributionMode(ctx context.Context) (uint8, error)
}
2 changes: 1 addition & 1 deletion op-deployer/pkg/deployer/standard/standard.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const (
GasLimit uint64 = 60_000_000
BasefeeScalar uint32 = 1368
BlobBaseFeeScalar uint32 = 801949
WithdrawalDelaySeconds uint64 = 604800
WithdrawalDelaySeconds uint64 = 302400
MinProposalSizeBytes uint64 = 126000
ChallengePeriodSeconds uint64 = 86400
ProofMaturityDelaySeconds uint64 = 604800
Expand Down
12 changes: 12 additions & 0 deletions op-e2e/e2eutils/disputegame/output_game_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,18 @@ func (g *OutputGameHelper) Status(ctx context.Context) gameTypes.GameStatus {
return status
}

func (g *OutputGameHelper) WaitForBondModeSet(ctx context.Context) {
g.T.Logf("Waiting for game %v to have bond mode set", g.Addr)
timedCtx, cancel := context.WithTimeout(ctx, defaultTimeout)
defer cancel()
err := wait.For(timedCtx, time.Second, func() (bool, error) {
bondMode, err := g.Game.BondDistributionMode(ctx)
g.Require.NoError(err)
return bondMode != 0, nil
})
g.Require.NoError(err, "Failed to wait for bond mode to be set")
}

func (g *OutputGameHelper) WaitForGameStatus(ctx context.Context, expected gameTypes.GameStatus) {
g.T.Logf("Waiting for game %v to have status %v", g.Addr, expected)
timedCtx, cancel := context.WithTimeout(ctx, defaultTimeout)
Expand Down
11 changes: 10 additions & 1 deletion op-e2e/faultproofs/output_alphabet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,18 +115,27 @@ func TestOutputAlphabetGame_ReclaimBond(t *testing.T) {
game.WaitForGameStatus(ctx, types.GameStatusChallengerWon)
game.LogGameData(ctx)

// Wait for the game to have bond mode set
game.WaitForBondModeSet(ctx)

// Expect Alice's credit to be non-zero
// But it can't be claimed right now since there is a delay on the weth unlock
require.Truef(t, game.AvailableCredit(ctx, alice).Cmp(big.NewInt(0)) > 0, "Expected alice credit to be above zero")

// The actor should have no credit available because all its bonds were paid to Alice.
actorCredit := game.AvailableCredit(ctx, disputegame.TestAddress)
require.True(t, actorCredit.Cmp(big.NewInt(0)) == 0, "Expected alice available credit to be zero")
require.True(t, actorCredit.Cmp(big.NewInt(0)) == 0, "Expected actor available credit to be zero")

// Advance the time past the weth unlock delay
sys.TimeTravelClock.AdvanceTime(game.CreditUnlockDuration(ctx))
require.NoError(t, wait.ForNextBlock(ctx, l1Client))

// Advance the time past the finalization delay
// Finalization delay is the same as the credit unlock delay
// But just warp way into the future to be safe
sys.TimeTravelClock.AdvanceTime(game.CreditUnlockDuration(ctx) * 2)
require.NoError(t, wait.ForNextBlock(ctx, l1Client))

// Wait for alice to have no available credit
// aka, wait for the challenger to claim its credit
game.WaitForNoAvailableCredit(ctx, alice)
Expand Down
11 changes: 11 additions & 0 deletions packages/contracts-bedrock/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ snapshots = 'notarealpath' # workaround for foundry#9477
optimizer = true
optimizer_runs = 999999

additional_compiler_profiles = [
{ name = "dispute", optimizer_runs = 5000 },
]
compilation_restrictions = [
{ paths = "src/dispute/FaultDisputeGame.sol", optimizer_runs = 5000 },
{ paths = "src/dispute/PermissionedDisputeGame.sol", optimizer_runs = 5000 },
]

extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout']
bytecode_hash = 'none'
ast = true
Expand Down Expand Up @@ -85,6 +93,7 @@ depth = 32

[profile.cicoverage]
optimizer = false
compilation_restrictions = []

[profile.cicoverage.fuzz]
runs = 1
Expand Down Expand Up @@ -112,6 +121,8 @@ timeout = 300

[profile.lite]
optimizer = false
compilation_restrictions = []


################################################################
# PROFILE: KONTROL #
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ interface IOptimismPortal2 {
error UnexpectedList();
error UnexpectedString();
error Unproven();
error LegacyGame();

event DisputeGameBlacklisted(IDisputeGame indexed disputeGame);
event Initialized(uint8 version);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ interface IOptimismPortalInterop {
error UnexpectedList();
error UnexpectedString();
error Unproven();
error LegacyGame();

event DisputeGameBlacklisted(IDisputeGame indexed disputeGame);
event Initialized(uint8 version);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { GameType, Hash, OutputRoot } from "src/dispute/lib/Types.sol";

interface IAnchorStateRegistry {
error AnchorStateRegistry_Unauthorized();
error AnchorStateRegistry_ImproperAnchorGame();
error AnchorStateRegistry_InvalidAnchorGame();
error AnchorStateRegistry_AnchorGameBlacklisted();

event AnchorNotUpdated(IFaultDisputeGame indexed game);
event AnchorUpdated(IFaultDisputeGame indexed game);
Expand All @@ -21,16 +21,27 @@ interface IAnchorStateRegistry {
function anchors(GameType) external view returns (Hash, uint256);
function getAnchorRoot() external view returns (Hash, uint256);
function disputeGameFactory() external view returns (IDisputeGameFactory);
function initialize(ISuperchainConfig _superchainConfig, IDisputeGameFactory _disputeGameFactory, IOptimismPortal2 _portal, OutputRoot memory _startingAnchorRoot) external;
function isGameRegistered(IDisputeGame _game) external view returns (bool);
function initialize(
ISuperchainConfig _superchainConfig,
IDisputeGameFactory _disputeGameFactory,
IOptimismPortal2 _portal,
OutputRoot memory _startingAnchorRoot
)
external;

function isGameAirgapped(IDisputeGame _game) external view returns (bool);
function isGameBlacklisted(IDisputeGame _game) external view returns (bool);
function isGameProper(IDisputeGame _game) external view returns (bool);
function isGameRegistered(IDisputeGame _game) external view returns (bool);
function isGameResolved(IDisputeGame _game) external view returns (bool);
function isGameRespected(IDisputeGame _game) external view returns (bool);
function isGameRetired(IDisputeGame _game) external view returns (bool);
function isGameProper(IDisputeGame _game) external view returns (bool);
function isGameFinalized(IDisputeGame _game) external view returns (bool);
function isGameClaimValid(IDisputeGame _game) external view returns (bool);
function portal() external view returns (IOptimismPortal2);
function setAnchorState(IFaultDisputeGame _game) external;
function respectedGameType() external view returns (GameType);
function setAnchorState(IDisputeGame _game) external;
function superchainConfig() external view returns (ISuperchainConfig);
function tryUpdateAnchorState() external;
function version() external view returns (string memory);

function __constructor__() external;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ interface IDelayedWETH {

event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
event Initialized(uint8 version);
event Unwrap(address indexed src, uint256 wad);

fallback() external payable;
receive() external payable;

function config() external view returns (ISuperchainConfig);
function delay() external view returns (uint256);
function hold(address _guy) external;
function hold(address _guy, uint256 _wad) external;
function initialize(address _owner, ISuperchainConfig _config) external;
function owner() external view returns (address);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ interface IDisputeGame is IInitializable {
function gameCreator() external pure returns (address creator_);
function rootClaim() external pure returns (Claim rootClaim_);
function l1Head() external pure returns (Hash l1Head_);
function l2BlockNumber() external pure returns (uint256 l2BlockNumber_);
function extraData() external pure returns (bytes memory extraData_);
function resolve() external returns (GameStatus status_);
function gameData() external view returns (GameType gameType_, Claim rootClaim_, bytes memory extraData_);
function wasRespectedGameTypeWhenCreated() external view returns (bool);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { IDelayedWETH } from "interfaces/dispute/IDelayedWETH.sol";
import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol";
import { IBigStepper } from "interfaces/dispute/IBigStepper.sol";
import { Types } from "src/libraries/Types.sol";
import { GameType, Claim, Position, Clock, Hash, Duration } from "src/dispute/lib/Types.sol";
import { GameType, Claim, Position, Clock, Hash, Duration, BondDistributionMode } from "src/dispute/lib/Types.sol";

interface IFaultDisputeGame is IDisputeGame {
struct ClaimData {
Expand Down Expand Up @@ -74,13 +74,19 @@ interface IFaultDisputeGame is IDisputeGame {
error UnexpectedRootClaim(Claim rootClaim);
error UnexpectedString();
error ValidStep();
error InvalidBondDistributionMode();
error GameNotFinalized();
error GameNotResolved();
error ReservedGameType();

event Move(uint256 indexed parentIndex, Claim indexed claim, address indexed claimant);
event GameClosed(BondDistributionMode bondDistributionMode);

function absolutePrestate() external view returns (Claim absolutePrestate_);
function addLocalData(uint256 _ident, uint256 _execLeafIdx, uint256 _partOffset) external;
function anchorStateRegistry() external view returns (IAnchorStateRegistry registry_);
function attack(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable;
function bondDistributionMode() external view returns (BondDistributionMode);
function challengeRootL2Block(Types.OutputRootProof memory _outputRootProof, bytes memory _headerRLP) external;
function claimCredit(address _recipient) external;
function claimData(uint256)
Expand All @@ -98,18 +104,21 @@ interface IFaultDisputeGame is IDisputeGame {
function claimDataLen() external view returns (uint256 len_);
function claims(Hash) external view returns (bool);
function clockExtension() external view returns (Duration clockExtension_);
function closeGame() external;
function credit(address) external view returns (uint256);
function defend(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable;
function getChallengerDuration(uint256 _claimIndex) external view returns (Duration duration_);
function getNumToResolve(uint256 _claimIndex) external view returns (uint256 numRemainingChildren_);
function getRequiredBond(Position _position) external view returns (uint256 requiredBond_);
function hasUnlockedCredit(address) external view returns (bool);
function l2BlockNumber() external pure returns (uint256 l2BlockNumber_);
function l2BlockNumberChallenged() external view returns (bool);
function l2BlockNumberChallenger() external view returns (address);
function l2ChainId() external view returns (uint256 l2ChainId_);
function maxClockDuration() external view returns (Duration maxClockDuration_);
function maxGameDepth() external view returns (uint256 maxGameDepth_);
function move(Claim _disputed, uint256 _challengeIndex, Claim _claim, bool _isAttack) external payable;
function refundModeCredit(address) external view returns (uint256);
function resolutionCheckpoints(uint256)
external
view
Expand All @@ -124,6 +133,7 @@ interface IFaultDisputeGame is IDisputeGame {
function subgames(uint256, uint256) external view returns (uint256);
function version() external view returns (string memory);
function vm() external view returns (IBigStepper vm_);
function wasRespectedGameTypeWhenCreated() external view returns (bool);
function weth() external view returns (IDelayedWETH weth_);

function __constructor__(GameConstructorParams memory _params) external;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.0;

import { Types } from "src/libraries/Types.sol";
import { Claim, Position, Clock, Hash, Duration } from "src/dispute/lib/Types.sol";
import { Claim, Position, Clock, Hash, Duration, BondDistributionMode } from "src/dispute/lib/Types.sol";

import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol";
import { IDelayedWETH } from "interfaces/dispute/IDelayedWETH.sol";
Expand Down Expand Up @@ -63,13 +63,19 @@ interface IPermissionedDisputeGame is IDisputeGame {
error UnexpectedRootClaim(Claim rootClaim);
error UnexpectedString();
error ValidStep();
error InvalidBondDistributionMode();
error GameNotFinalized();
error GameNotResolved();
error ReservedGameType();

event Move(uint256 indexed parentIndex, Claim indexed claim, address indexed claimant);
event GameClosed(BondDistributionMode bondDistributionMode);

function absolutePrestate() external view returns (Claim absolutePrestate_);
function addLocalData(uint256 _ident, uint256 _execLeafIdx, uint256 _partOffset) external;
function anchorStateRegistry() external view returns (IAnchorStateRegistry registry_);
function attack(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable;
function bondDistributionMode() external view returns (BondDistributionMode);
function challengeRootL2Block(Types.OutputRootProof memory _outputRootProof, bytes memory _headerRLP) external;
function claimCredit(address _recipient) external;
function claimData(uint256)
Expand All @@ -87,18 +93,22 @@ interface IPermissionedDisputeGame is IDisputeGame {
function claimDataLen() external view returns (uint256 len_);
function claims(Hash) external view returns (bool);
function clockExtension() external view returns (Duration clockExtension_);
function closeGame() external;
function credit(address) external view returns (uint256);
function defend(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable;
function getChallengerDuration(uint256 _claimIndex) external view returns (Duration duration_);
function getNumToResolve(uint256 _claimIndex) external view returns (uint256 numRemainingChildren_);
function getRequiredBond(Position _position) external view returns (uint256 requiredBond_);
function hasUnlockedCredit(address) external view returns (bool);
function initialize() external payable;
function l2BlockNumber() external pure returns (uint256 l2BlockNumber_);
function l2BlockNumberChallenged() external view returns (bool);
function l2BlockNumberChallenger() external view returns (address);
function l2ChainId() external view returns (uint256 l2ChainId_);
function maxClockDuration() external view returns (Duration maxClockDuration_);
function maxGameDepth() external view returns (uint256 maxGameDepth_);
function move(Claim _disputed, uint256 _challengeIndex, Claim _claim, bool _isAttack) external payable;
function refundModeCredit(address) external view returns (uint256);
function resolutionCheckpoints(uint256)
external
view
Expand All @@ -113,6 +123,7 @@ interface IPermissionedDisputeGame is IDisputeGame {
function subgames(uint256, uint256) external view returns (uint256);
function version() external view returns (string memory);
function vm() external view returns (IBigStepper vm_);
function wasRespectedGameTypeWhenCreated() external view returns (bool);
function weth() external view returns (IDelayedWETH weth_);

error BadAuth();
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts-bedrock/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ test-upgrade *ARGS: build-go-ffi
#!/bin/bash
echo "Running upgrade tests at block $pinnedBlockNumber"
export FORK_BLOCK_NUMBER=$pinnedBlockNumber
export NO_MATCH_CONTRACTS="OptimismPortal2WithMockERC20_Test|OptimismPortal2_FinalizeWithdrawal_Test|'AnchorStateRegistry_*'|FaultDisputeGame_Test|FaultDispute_1v1_Actors_Test"
export NO_MATCH_CONTRACTS="OptimismPortal2WithMockERC20_Test|OptimismPortal2_FinalizeWithdrawal_Test|'AnchorStateRegistry_*'|FaultDisputeGame_Test|PermissionedDisputeGame_Test|FaultDispute_1v1_Actors_Test|DelayedWETH_Hold_Test"
export NO_MATCH_PATHS="test/dispute/AnchorStateRegistry.t.sol"
FORK_RPC_URL=$ETH_RPC_URL \
FORK_TEST=true \
Expand Down
Loading