Skip to content

Commit 984bae9

Browse files
feat: incident response improvements (#13711)
* feat: incident response improvements First half of the original incident response improvements PR. Co-authored-by: wildmolasses <[email protected]> * fix tests and add specs * misc fixes * more fixes * emit event on setRespectedGameTypeUpdatedAt, and test wasRespectedGameType as withdrawal finality condition * withdrawal when gameWasNotRespectedGameType reverts * anchor game blacklisted and getAnchorGame tests * isGameAirgapped * tiny specs change * add snapshots * fix specs test and ASR snapshot * update semver * no compilation rrestrictions when optimizer is off * interop portal semver * justfile ignore, semver * minor tweaks * expanded test coverage * various logical tweaks * test fix * clearer error * fix test flake in go tests * add portal tests * portal2 tests: encodeCall * FDG test: recipient can't receive value reverts * various final tweaks * regenerate snapshots * fix specs tests * final test fixes --------- Co-authored-by: wildmolasses <[email protected]>
1 parent 10defcd commit 984bae9

40 files changed

+1782
-590
lines changed

mise.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ just = "1.37.0"
3131
# Foundry dependencies
3232
# Foundry is a special case because it supplies multiple binaries at the same
3333
# GitHub release, so we need to use the aliasing trick to get mise to not error
34-
forge = "nightly-59f354c179f4e7f6d7292acb3d068815c79286d1"
35-
cast = "nightly-59f354c179f4e7f6d7292acb3d068815c79286d1"
36-
anvil = "nightly-59f354c179f4e7f6d7292acb3d068815c79286d1"
34+
forge = "nightly-017c59d6806ce11f1dc131f8607178efad79d84a"
35+
cast = "nightly-017c59d6806ce11f1dc131f8607178efad79d84a"
36+
anvil = "nightly-017c59d6806ce11f1dc131f8607178efad79d84a"
3737

3838
# Fake dependencies
3939
# Put things here if you need to track versions of tools or projects that can't

op-chain-ops/interopgen/recipe.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func (r *InteropDevRecipe) Build(addrs devkeys.Addresses) (*WorldConfig, error)
7171
Implementations: OPCMImplementationsConfig{
7272
L1ContractsRelease: "dev",
7373
FaultProof: SuperFaultProofConfig{
74-
WithdrawalDelaySeconds: big.NewInt(604800),
74+
WithdrawalDelaySeconds: big.NewInt(302400),
7575
MinProposalSizeBytes: big.NewInt(10000),
7676
ChallengePeriodSeconds: big.NewInt(120),
7777
ProofMaturityDelaySeconds: big.NewInt(12),

op-challenger/game/fault/contracts/faultdisputegame.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ var (
5353
methodL2BlockNumberChallenged = "l2BlockNumberChallenged"
5454
methodL2BlockNumberChallenger = "l2BlockNumberChallenger"
5555
methodChallengeRootL2Block = "challengeRootL2Block"
56+
methodBondDistributionMode = "bondDistributionMode"
5657
)
5758

5859
var (
@@ -455,6 +456,14 @@ func (f *FaultDisputeGameContractLatest) GetAllClaims(ctx context.Context, block
455456
return claims, nil
456457
}
457458

459+
func (f *FaultDisputeGameContractLatest) BondDistributionMode(ctx context.Context) (uint8, error) {
460+
result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodBondDistributionMode))
461+
if err != nil {
462+
return 0, fmt.Errorf("failed to fetch bond mode: %w", err)
463+
}
464+
return result.GetUint8(0), nil
465+
}
466+
458467
func (f *FaultDisputeGameContractLatest) IsResolved(ctx context.Context, block rpcblock.Block, claims ...types.Claim) ([]bool, error) {
459468
defer f.metrics.StartContractRequest("IsResolved")()
460469
calls := make([]batching.Call, 0, len(claims))
@@ -639,4 +648,5 @@ type FaultDisputeGameContract interface {
639648
CallResolve(ctx context.Context) (gameTypes.GameStatus, error)
640649
ResolveTx() (txmgr.TxCandidate, error)
641650
Vm(ctx context.Context) (*VMContract, error)
651+
BondDistributionMode(ctx context.Context) (uint8, error)
642652
}

op-deployer/pkg/deployer/standard/standard.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const (
1515
GasLimit uint64 = 60_000_000
1616
BasefeeScalar uint32 = 1368
1717
BlobBaseFeeScalar uint32 = 801949
18-
WithdrawalDelaySeconds uint64 = 604800
18+
WithdrawalDelaySeconds uint64 = 302400
1919
MinProposalSizeBytes uint64 = 126000
2020
ChallengePeriodSeconds uint64 = 86400
2121
ProofMaturityDelaySeconds uint64 = 604800

op-e2e/e2eutils/disputegame/output_game_helper.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,18 @@ func (g *OutputGameHelper) Status(ctx context.Context) gameTypes.GameStatus {
368368
return status
369369
}
370370

371+
func (g *OutputGameHelper) WaitForBondModeSet(ctx context.Context) {
372+
g.T.Logf("Waiting for game %v to have bond mode set", g.Addr)
373+
timedCtx, cancel := context.WithTimeout(ctx, defaultTimeout)
374+
defer cancel()
375+
err := wait.For(timedCtx, time.Second, func() (bool, error) {
376+
bondMode, err := g.Game.BondDistributionMode(ctx)
377+
g.Require.NoError(err)
378+
return bondMode != 0, nil
379+
})
380+
g.Require.NoError(err, "Failed to wait for bond mode to be set")
381+
}
382+
371383
func (g *OutputGameHelper) WaitForGameStatus(ctx context.Context, expected gameTypes.GameStatus) {
372384
g.T.Logf("Waiting for game %v to have status %v", g.Addr, expected)
373385
timedCtx, cancel := context.WithTimeout(ctx, defaultTimeout)

op-e2e/faultproofs/output_alphabet_test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,22 @@ func TestOutputAlphabetGame_ReclaimBond(t *testing.T) {
115115
game.WaitForGameStatus(ctx, types.GameStatusChallengerWon)
116116
game.LogGameData(ctx)
117117

118+
// Advance the time past the finalization delay
119+
// Finalization delay is the same as the credit unlock delay
120+
// But just warp way into the future to be safe
121+
sys.TimeTravelClock.AdvanceTime(game.CreditUnlockDuration(ctx) * 2)
122+
require.NoError(t, wait.ForNextBlock(ctx, l1Client))
123+
124+
// Wait for the game to have bond mode set
125+
game.WaitForBondModeSet(ctx)
126+
118127
// Expect Alice's credit to be non-zero
119128
// But it can't be claimed right now since there is a delay on the weth unlock
120129
require.Truef(t, game.AvailableCredit(ctx, alice).Cmp(big.NewInt(0)) > 0, "Expected alice credit to be above zero")
121130

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

126135
// Advance the time past the weth unlock delay
127136
sys.TimeTravelClock.AdvanceTime(game.CreditUnlockDuration(ctx))

packages/contracts-bedrock/foundry.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ snapshots = 'notarealpath' # workaround for foundry#9477
1313
optimizer = true
1414
optimizer_runs = 999999
1515

16+
additional_compiler_profiles = [
17+
{ name = "dispute", optimizer_runs = 5000 },
18+
]
19+
compilation_restrictions = [
20+
{ paths = "src/dispute/FaultDisputeGame.sol", optimizer_runs = 5000 },
21+
{ paths = "src/dispute/PermissionedDisputeGame.sol", optimizer_runs = 5000 },
22+
]
23+
1624
extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout']
1725
bytecode_hash = 'none'
1826
ast = true
@@ -85,6 +93,7 @@ depth = 32
8593

8694
[profile.cicoverage]
8795
optimizer = false
96+
compilation_restrictions = []
8897

8998
[profile.cicoverage.fuzz]
9099
runs = 1
@@ -112,6 +121,8 @@ timeout = 300
112121

113122
[profile.lite]
114123
optimizer = false
124+
compilation_restrictions = []
125+
115126

116127
################################################################
117128
# PROFILE: KONTROL #

packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ interface IOptimismPortal2 {
3131
error UnexpectedList();
3232
error UnexpectedString();
3333
error Unproven();
34+
error LegacyGame();
3435

3536
event DisputeGameBlacklisted(IDisputeGame indexed disputeGame);
3637
event Initialized(uint8 version);

packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ interface IOptimismPortalInterop {
3333
error UnexpectedList();
3434
error UnexpectedString();
3535
error Unproven();
36+
error LegacyGame();
3637

3738
event DisputeGameBlacklisted(IDisputeGame indexed disputeGame);
3839
event Initialized(uint8 version);

packages/contracts-bedrock/interfaces/dispute/IAnchorStateRegistry.sol

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import { GameType, Hash, OutputRoot } from "src/dispute/lib/Types.sol";
1010

1111
interface IAnchorStateRegistry {
1212
error AnchorStateRegistry_Unauthorized();
13-
error AnchorStateRegistry_ImproperAnchorGame();
1413
error AnchorStateRegistry_InvalidAnchorGame();
14+
error AnchorStateRegistry_AnchorGameBlacklisted();
1515

1616
event AnchorNotUpdated(IFaultDisputeGame indexed game);
1717
event AnchorUpdated(IFaultDisputeGame indexed game);
@@ -21,16 +21,27 @@ interface IAnchorStateRegistry {
2121
function anchors(GameType) external view returns (Hash, uint256);
2222
function getAnchorRoot() external view returns (Hash, uint256);
2323
function disputeGameFactory() external view returns (IDisputeGameFactory);
24-
function initialize(ISuperchainConfig _superchainConfig, IDisputeGameFactory _disputeGameFactory, IOptimismPortal2 _portal, OutputRoot memory _startingAnchorRoot) external;
25-
function isGameRegistered(IDisputeGame _game) external view returns (bool);
24+
function initialize(
25+
ISuperchainConfig _superchainConfig,
26+
IDisputeGameFactory _disputeGameFactory,
27+
IOptimismPortal2 _portal,
28+
OutputRoot memory _startingAnchorRoot
29+
)
30+
external;
31+
32+
function isGameAirgapped(IDisputeGame _game) external view returns (bool);
2633
function isGameBlacklisted(IDisputeGame _game) external view returns (bool);
34+
function isGameProper(IDisputeGame _game) external view returns (bool);
35+
function isGameRegistered(IDisputeGame _game) external view returns (bool);
36+
function isGameResolved(IDisputeGame _game) external view returns (bool);
2737
function isGameRespected(IDisputeGame _game) external view returns (bool);
2838
function isGameRetired(IDisputeGame _game) external view returns (bool);
29-
function isGameProper(IDisputeGame _game) external view returns (bool);
39+
function isGameFinalized(IDisputeGame _game) external view returns (bool);
40+
function isGameClaimValid(IDisputeGame _game) external view returns (bool);
3041
function portal() external view returns (IOptimismPortal2);
31-
function setAnchorState(IFaultDisputeGame _game) external;
42+
function respectedGameType() external view returns (GameType);
43+
function setAnchorState(IDisputeGame _game) external;
3244
function superchainConfig() external view returns (ISuperchainConfig);
33-
function tryUpdateAnchorState() external;
3445
function version() external view returns (string memory);
3546

3647
function __constructor__() external;

0 commit comments

Comments
 (0)