Skip to content

Commit 6e6618e

Browse files
committed
poc
1 parent 7426ac5 commit 6e6618e

5 files changed

Lines changed: 69 additions & 37 deletions

File tree

bun.lockb

4.6 KB
Binary file not shown.

contracts/op/OPFaultGameFinder.sol

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ import {
1111

1212
// https://github.com/ethereum-optimism/optimism/issues/11269
1313

14-
// https://github.com/ethereum-optimism/optimism/blob/v1.13.7/packages/contracts-bedrock/src/dispute/lib/Types.sol
15-
uint256 constant CHALLENGER_WINS = 1;
16-
uint256 constant DEFENDER_WINS = 2;
14+
// https://github.com/ethereum-optimism/optimism/blob/v1.18.1/packages/contracts-bedrock/src/dispute/lib/Types.sol
15+
uint256 constant GAME_STATUS_IN_PROGRESS = 0;
16+
uint256 constant GAME_STATUS_CHALLENGER_WINS = 1;
17+
uint256 constant GAME_STATUS_DEFENDER_WINS = 2;
18+
19+
uint256 constant GAME_TYPE_AGGREGATE_VERIFIER = 621;
20+
uint256 constant GAME_TYPE_SUCCINCT = 42;
1721

1822
error GameNotFound();
1923

@@ -106,9 +110,9 @@ contract OPFaultGameFinder {
106110
if (!params.asr.isGameProper(gameProxy)) return false;
107111
if (params.minAgeSec > 0) {
108112
if (created > block.timestamp - params.minAgeSec) return false;
109-
if (_isUnchallenged(gameProxy, params, state)) return true;
113+
if (_isUnchallenged(gameProxy, gameType, params, state)) return true;
110114
}
111-
return gameProxy.status() == DEFENDER_WINS; // require resolved
115+
return gameProxy.status() == GAME_STATUS_DEFENDER_WINS; // require resolved
112116
}
113117

114118
function _isAllowedGameType(
@@ -134,22 +138,13 @@ contract OPFaultGameFinder {
134138
/// @dev Attempt to determine if the game is challenged in any sense.
135139
function _isUnchallenged(
136140
IDisputeGame gameProxy,
141+
uint256 gameType,
137142
OPFaultParams memory params,
138143
FinderState memory state
139144
) internal view returns (bool) {
140-
try
141-
IFaultDisputeGame(address(gameProxy)).l2BlockNumberChallenged()
142-
returns (bool challenged) {
143-
// this challenge is independent of the game resolution
144-
if (challenged) return false;
145-
} catch {}
146-
// if supportsInterface(IFaultDisputeGame)
147-
try IFaultDisputeGame(address(gameProxy)).claimDataLen() returns (
148-
uint256 claims
149-
) {
150-
if (claims == 1) return true;
151-
} catch {
152-
// else if supportsInterface(IOPSuccinctFaultDisputeGame)
145+
if (gameType == GAME_TYPE_AGGREGATE_VERIFIER) {
146+
return gameProxy.status() != GAME_STATUS_CHALLENGER_WINS;
147+
} else if (gameType == GAME_TYPE_SUCCINCT) {
153148
try
154149
IOPSuccinctFaultDisputeGame(address(gameProxy)).claimData()
155150
returns (IOPSuccinctFaultDisputeGame.ClaimData memory data) {
@@ -161,16 +156,16 @@ contract OPFaultGameFinder {
161156
if (gameIndex == type(uint32).max) return true; // anchor state is resolved
162157
if (gameIndex >= state.succinctGameIndex) return false; // already checked
163158
(
164-
uint256 gameType,
159+
uint256 gameType1,
165160
uint256 created,
166161
IDisputeGame parentGame
167162
) = dgf.gameAtIndex(gameIndex);
168-
if (gameType != gameType0) {
163+
if (gameType1 != gameType0) {
169164
// this is a different game type
170165
return
171166
_isGameUsable(
172167
parentGame,
173-
gameType,
168+
gameType1,
174169
created,
175170
params,
176171
state
@@ -187,12 +182,24 @@ contract OPFaultGameFinder {
187182
IOPSuccinctFaultDisputeGame
188183
.ProposalStatus
189184
.Resolved &&
190-
parentGame.status() == DEFENDER_WINS;
185+
parentGame.status() == GAME_STATUS_DEFENDER_WINS;
191186
}
192187
}
193188
}
194189
} catch {}
195190
}
191+
try
192+
IFaultDisputeGame(address(gameProxy)).l2BlockNumberChallenged()
193+
returns (bool challenged) {
194+
// this challenge is independent of the game resolution
195+
if (challenged) return false;
196+
} catch {}
197+
// if supportsInterface(IFaultDisputeGame)
198+
try IFaultDisputeGame(address(gameProxy)).claimDataLen() returns (
199+
uint256 claims
200+
) {
201+
if (claims == 1) return true;
202+
} catch {}
196203
// unknown type
197204
// assume challenged and require resolved
198205
return false;

test/debug/op-fault-js.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { CHAINS } from '../../src/chains.js';
2+
import { OPFaultRollup } from '../../src/op/OPFaultRollup.js';
3+
import { createProviderPair } from '../providers.js';
4+
import { Contract } from 'ethers';
5+
6+
const rollup = new OPFaultRollup(createProviderPair(CHAINS.BASE), OPFaultRollup.baseMainnetConfig);
7+
8+
const DisputeGameFactory = new Contract(
9+
await rollup.AnchorStateRegistry.disputeGameFactory(),
10+
[
11+
`function gameCount() view returns (uint256)`,
12+
`function gameAtIndex(uint256) view returns (uint256 gameType, uint256 created, address gameProxy)`,
13+
],
14+
rollup.provider1,
15+
);
16+
17+
const gameCount = await DisputeGameFactory.gameCount();
18+
19+
console.log({
20+
GameFinder: rollup.GameFinder.target,
21+
AnchorStateRegistry: rollup.AnchorStateRegistry.target,
22+
DisputeGameFactory: DisputeGameFactory.target,
23+
gameCount
24+
});
25+
26+
console.log(await rollup.GameFinder.gameAtIndex(rollup.paramTuple, gameCount - 1n));

test/debug/op-fault.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,22 @@ import { providerURL } from '../providers.js';
55

66
const foundry = await Foundry.launch({
77
infoLog: true,
8-
fork: providerURL(CHAINS.SEPOLIA),
8+
fork: providerURL(CHAINS.MAINNET),
99
});
1010

1111
const OPFaultGameFinder = await foundry.deploy({ file: 'OPFaultGameFinder' });
1212

13-
const index = await OPFaultGameFinder.findGameIndex(
14-
[OPFaultRollup.sepoliaConfig.AnchorStateRegistry, 21600, [], []],
15-
0
16-
);
13+
const paramTuple = [
14+
OPFaultRollup.mainnetConfig.AnchorStateRegistry,
15+
21600,
16+
[],
17+
[],
18+
];
19+
20+
const index = await OPFaultGameFinder.findGameIndex(paramTuple, 0);
1721

1822
console.log({ index });
1923

20-
console.log(
21-
await OPFaultGameFinder.gameAtIndex(
22-
[OPFaultRollup.sepoliaConfig.AnchorStateRegistry, 21600, [], []],
23-
index
24-
)
25-
);
24+
console.log(await OPFaultGameFinder.gameAtIndex(paramTuple, index));
2625

2726
await foundry.shutdown();

test/providers.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export const RPC_INFO = new Map<Chain, RPCInfo>(
3434
[
3535
{
3636
chain: CHAINS.MAINNET,
37-
publicHTTP: 'https://rpc.ankr.com/eth', // https://cloudflare-eth.com is too rate limited
37+
publicHTTP: 'https://eth.drpc.org/eth', // https://cloudflare-eth.com is too rate limited
3838
publicBeacon: 'https://ethereum-beacon-api.publicnode.com',
3939
ankr: 'eth',
4040
ankrBeaconPremium: true,
@@ -45,7 +45,7 @@ export const RPC_INFO = new Map<Chain, RPCInfo>(
4545
},
4646
{
4747
chain: CHAINS.SEPOLIA,
48-
publicHTTP: 'https://rpc.ankr.com/eth_sepolia',
48+
publicHTTP: 'https://sepolia.drpc.org',
4949
publicBeacon: 'https://ethereum-sepolia-beacon-api.publicnode.com',
5050
ankr: 'eth_sepolia',
5151
//infura: 'sepolia', // 20251003: no eth_getProof depth
@@ -55,7 +55,7 @@ export const RPC_INFO = new Map<Chain, RPCInfo>(
5555
},
5656
{
5757
chain: CHAINS.HOLESKY,
58-
publicHTTP: 'https://rpc.ankr.com/eth_holesky', //'https://rpc.holesky.ethpandaops.io',
58+
publicHTTP: 'https://holesky.drpc.org', //'https://rpc.holesky.ethpandaops.io',
5959
publicBeacon: 'https://ethereum-holesky-beacon-api.publicnode.com',
6060
ankr: 'eth_holesky',
6161
infura: 'holesky',
@@ -65,7 +65,7 @@ export const RPC_INFO = new Map<Chain, RPCInfo>(
6565
},
6666
{
6767
chain: CHAINS.HOODI,
68-
publicHTTP: 'https://ethereum-hoodi-rpc.publicnode.com',
68+
publicHTTP: 'https://hoodi.drpc.org',
6969
publicBeacon: 'https://ethereum-hoodi-beacon-api.publicnode.com',
7070
infura: 'hoodi',
7171
drpc: 'hoodi',

0 commit comments

Comments
 (0)