Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
69e67474
Unverified
Commit
69e67474
authored
Jun 16, 2023
by
protolambda
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into cannon
parents
d35fa879
0c1a113d
Changes
15
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
2718 additions
and
233 deletions
+2718
-233
few-shoes-deny.md
.changeset/few-shoes-deny.md
+5
-0
tag-service.yml
.github/workflows/tag-service.yml
+1
-0
Makefile
op-bindings/Makefile
+9
-0
crossdomainmessenger.go
op-bindings/bindings/crossdomainmessenger.go
+1371
-0
disputegamefactory.go
op-bindings/bindings/disputegamefactory.go
+60
-32
standardbridge.go
op-bindings/bindings/standardbridge.go
+1091
-0
.gas-snapshot
packages/contracts-bedrock/.gas-snapshot
+5
-5
.storage-layout
packages/contracts-bedrock/.storage-layout
+10
-10
DisputeGameFactory.sol
...ontracts-bedrock/contracts/dispute/DisputeGameFactory.sol
+61
-16
IDisputeGameFactory.sol
...rock/contracts/dispute/interfaces/IDisputeGameFactory.sol
+15
-1
DisputeTypes.sol
...es/contracts-bedrock/contracts/libraries/DisputeTypes.sol
+12
-0
DisputeGameFactory.t.sol
...contracts-bedrock/contracts/test/DisputeGameFactory.t.sol
+60
-11
FaultDisputeGame.t.sol
...s/contracts-bedrock/contracts/test/FaultDisputeGame.t.sol
+2
-2
deploy-utils.ts
packages/contracts-bedrock/src/deploy-utils.ts
+9
-149
helpers.ts
packages/fault-detector/src/helpers.ts
+7
-7
No files found.
.changeset/few-shoes-deny.md
0 → 100644
View file @
69e67474
---
'
@eth-optimism/fault-detector'
:
patch
---
Fix false error to warning
.github/workflows/tag-service.yml
View file @
69e67474
...
@@ -24,6 +24,7 @@ on:
...
@@ -24,6 +24,7 @@ on:
-
proxyd
-
proxyd
-
indexer
-
indexer
-
fault-detector
-
fault-detector
-
ci-builder
prerelease
:
prerelease
:
description
:
Increment major/minor/patch as prerelease?
description
:
Increment major/minor/patch as prerelease?
required
:
false
required
:
false
...
...
op-bindings/Makefile
View file @
69e67474
...
@@ -32,6 +32,8 @@ bindings: l1block-bindings \
...
@@ -32,6 +32,8 @@ bindings: l1block-bindings \
basefee-vault-bindings
\
basefee-vault-bindings
\
legacy-erc20-eth-bindings
\
legacy-erc20-eth-bindings
\
dispute-game-factory-bindings
\
dispute-game-factory-bindings
\
standard-bridge-bindings
\
cross-domain-messenger-bindings
\
cannon-mips
\
cannon-mips
\
cannon-oracle
cannon-oracle
...
@@ -128,12 +130,19 @@ l1-blocknumber-bindings: compile
...
@@ -128,12 +130,19 @@ l1-blocknumber-bindings: compile
dispute-game-factory-bindings
:
compile
dispute-game-factory-bindings
:
compile
./gen_bindings.sh contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory
$(pkg)
./gen_bindings.sh contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory
$(pkg)
standard-bridge-bindings
:
compile
./gen_bindings.sh contracts/universal/StandardBridge.sol:StandardBridge
$(pkg)
cross-domain-messenger-bindings
:
compile
./gen_bindings.sh contracts/universal/CrossDomainMessenger.sol:CrossDomainMessenger
$(pkg)
cannon-mips
:
compile
cannon-mips
:
compile
./gen_bindings.sh contracts/cannon/MIPS.sol:MIPS
$(pkg)
./gen_bindings.sh contracts/cannon/MIPS.sol:MIPS
$(pkg)
cannon-oracle
:
compile
cannon-oracle
:
compile
./gen_bindings.sh contracts/cannon/Oracle.sol:Oracle
$(pkg)
./gen_bindings.sh contracts/cannon/Oracle.sol:Oracle
$(pkg)
more
:
more
:
go run ./gen/main.go
\
go run ./gen/main.go
\
-artifacts
../packages/contracts-bedrock/artifacts
\
-artifacts
../packages/contracts-bedrock/artifacts
\
...
...
op-bindings/bindings/crossdomainmessenger.go
0 → 100644
View file @
69e67474
This diff is collapsed.
Click to expand it.
op-bindings/bindings/disputegamefactory.go
View file @
69e67474
This diff is collapsed.
Click to expand it.
op-bindings/bindings/standardbridge.go
0 → 100644
View file @
69e67474
This diff is collapsed.
Click to expand it.
packages/contracts-bedrock/.gas-snapshot
View file @
69e67474
...
@@ -27,11 +27,11 @@ CrossDomainOwnable_Test:test_onlyOwner_notOwner_reverts() (gas: 10597)
...
@@ -27,11 +27,11 @@ CrossDomainOwnable_Test:test_onlyOwner_notOwner_reverts() (gas: 10597)
CrossDomainOwnable_Test:test_onlyOwner_succeeds() (gas: 34883)
CrossDomainOwnable_Test:test_onlyOwner_succeeds() (gas: 34883)
DeployerWhitelist_Test:test_owner_succeeds() (gas: 7582)
DeployerWhitelist_Test:test_owner_succeeds() (gas: 7582)
DeployerWhitelist_Test:test_storageSlots_succeeds() (gas: 33395)
DeployerWhitelist_Test:test_storageSlots_succeeds() (gas: 33395)
DisputeGameFactory_
Test:test_owner_succeeds() (gas: 12610
)
DisputeGameFactory_
Owner_Test:test_owner_succeeds() (gas: 12559
)
DisputeGameFactory_
Test:test_setImplementation_notOwner_reverts() (gas: 16099
)
DisputeGameFactory_
SetImplementation_Test:test_setImplementation_notOwner_reverts() (gas: 16042
)
DisputeGameFactory_
Test:test_setImplementation_succeeds() (gas: 44302
)
DisputeGameFactory_
SetImplementation_Test:test_setImplementation_succeeds() (gas: 44243
)
DisputeGameFactory_T
est:test_transferOwnership_notOwner_reverts() (gas: 15974
)
DisputeGameFactory_T
ransferOwnership_Test:test_transferOwnership_notOwner_reverts() (gas: 15950
)
DisputeGameFactory_T
est:test_transferOwnership_succeeds() (gas: 18694
)
DisputeGameFactory_T
ransferOwnership_Test:test_transferOwnership_succeeds() (gas: 18642
)
FaultDisputeGame_Test:test_clockTimeExceeded_reverts() (gas: 26413)
FaultDisputeGame_Test:test_clockTimeExceeded_reverts() (gas: 26413)
FaultDisputeGame_Test:test_defendRoot_reverts() (gas: 13258)
FaultDisputeGame_Test:test_defendRoot_reverts() (gas: 13258)
FaultDisputeGame_Test:test_duplicateClaim_reverts() (gas: 103259)
FaultDisputeGame_Test:test_duplicateClaim_reverts() (gas: 103259)
...
...
packages/contracts-bedrock/.storage-layout
View file @
69e67474
...
@@ -253,13 +253,13 @@
...
@@ -253,13 +253,13 @@
➡ contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory
➡ contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory
=======================
=======================
| Name | Type | Slot | Offset | Bytes | Contract |
| Name
| Type | Slot | Offset | Bytes | Contract |
|-----------------|--------------------------------------------|------|--------|-------|-------------------------------------------------------------|
|-----------------
-
|--------------------------------------------|------|--------|-------|-------------------------------------------------------------|
| _initialized | uint8 | 0 | 0 | 1 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| _initialized
| uint8 | 0 | 0 | 1 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| _initializing | bool | 0 | 1 | 1 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| _initializing
| bool | 0 | 1 | 1 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| __gap | uint256[50] | 1 | 0 | 1600 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| __gap
| uint256[50] | 1 | 0 | 1600 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| _owner | address | 51 | 0 | 20 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| _owner
| address | 51 | 0 | 20 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| __gap | uint256[49] | 52 | 0 | 1568 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| __gap
| uint256[49] | 52 | 0 | 1568 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| gameImpls | mapping(GameType => contract IDisputeGame) | 101 | 0 | 32 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| gameImpls
| mapping(GameType => contract IDisputeGame) | 101 | 0 | 32 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
|
disputeGames | mapping(Hash => contract IDisputeGame)
| 102 | 0 | 32 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
|
_disputeGames | mapping(Hash => GameId)
| 102 | 0 | 32 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
|
disputeGameList | contract IDisputeGame[]
| 103 | 0 | 32 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
|
_disputeGameList | GameId[]
| 103 | 0 | 32 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
packages/contracts-bedrock/contracts/dispute/DisputeGameFactory.sol
View file @
69e67474
...
@@ -15,7 +15,11 @@ import { IVersioned } from "./interfaces/IVersioned.sol";
...
@@ -15,7 +15,11 @@ import { IVersioned } from "./interfaces/IVersioned.sol";
/**
/**
* @title DisputeGameFactory
* @title DisputeGameFactory
* @notice A factory contract for creating `IDisputeGame` contracts.
* @notice A factory contract for creating `IDisputeGame` contracts. All created dispute games
* are stored in both a mapping and an append only array. The timestamp of the creation
* time of the dispute game is packed tightly into the storage slot with the address of
* the dispute game. This is to make offchain discoverability of playable dispute games
* easier.
*/
*/
contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersioned {
contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersioned {
/**
/**
...
@@ -29,18 +33,18 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion
...
@@ -29,18 +33,18 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion
mapping(GameType => IDisputeGame) public gameImpls;
mapping(GameType => IDisputeGame) public gameImpls;
/**
/**
* @notice Mapping of a hash of `gameType
. rootClaim .
extraData` to
* @notice Mapping of a hash of `gameType
|| rootClaim ||
extraData` to
* the deployed `IDisputeGame` clone.
* the deployed `IDisputeGame` clone.
* @dev Note: `
.
` denotes concatenation.
* @dev Note: `
||
` denotes concatenation.
*/
*/
mapping(Hash =>
IDisputeGame) internal
disputeGames;
mapping(Hash =>
GameId) internal _
disputeGames;
/**
/**
* @notice An append-only array of disputeGames that have been created.
* @notice An append-only array of disputeGames that have been created.
* @dev This accessor is used by offchain game solvers to efficiently
* @dev This accessor is used by offchain game solvers to efficiently
* track dispute games
* track dispute games
*/
*/
IDisputeGame[] public
disputeGameList;
GameId[] internal _
disputeGameList;
/**
/**
* @notice Constructs a new DisputeGameFactory contract.
* @notice Constructs a new DisputeGameFactory contract.
...
@@ -60,27 +64,46 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion
...
@@ -60,27 +64,46 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion
/**
/**
* @inheritdoc IVersioned
* @inheritdoc IVersioned
* @custom:semver 0.0.2
*/
*/
function version() external pure returns (string memory) {
function version() external pure returns (string memory) {
return "0.0.
1
";
return "0.0.
2
";
}
}
/**
/**
* @inheritdoc IDisputeGameFactory
* @inheritdoc IDisputeGameFactory
*/
*/
function gameCount() external view returns (uint256
_gameCount
) {
function gameCount() external view returns (uint256
gameCount_
) {
_gameCount =
disputeGameList.length;
gameCount_ = _
disputeGameList.length;
}
}
/**
/**
* @inheritdoc IDisputeGameFactory
* @inheritdoc IDisputeGameFactory
*/
*/
function games(
function games(
GameType gameType,
GameType _gameType,
Claim rootClaim,
Claim _rootClaim,
bytes calldata extraData
bytes calldata _extraData
) external view returns (IDisputeGame _proxy) {
) external view returns (IDisputeGame proxy_, uint256 timestamp_) {
return disputeGames[getGameUUID(gameType, rootClaim, extraData)];
Hash uuid = getGameUUID(_gameType, _rootClaim, _extraData);
GameId slot = _disputeGames[uuid];
(address addr, uint256 timestamp) = _unpackSlot(slot);
proxy_ = IDisputeGame(addr);
timestamp_ = timestamp;
}
/**
* @inheritdoc IDisputeGameFactory
*/
function gameAtIndex(uint256 _index)
external
view
returns (IDisputeGame proxy_, uint256 timestamp_)
{
GameId slot = _disputeGameList[_index];
(address addr, uint256 timestamp) = _unpackSlot(slot);
proxy_ = IDisputeGame(addr);
timestamp_ = timestamp;
}
}
/**
/**
...
@@ -107,13 +130,15 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion
...
@@ -107,13 +130,15 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion
Hash uuid = getGameUUID(gameType, rootClaim, extraData);
Hash uuid = getGameUUID(gameType, rootClaim, extraData);
// If a dispute game with the same UUID already exists, revert.
// If a dispute game with the same UUID already exists, revert.
if (
address(disputeGames[uuid]) != address
(0)) {
if (
GameId.unwrap(_disputeGames[uuid]) != bytes32
(0)) {
revert GameAlreadyExists(uuid);
revert GameAlreadyExists(uuid);
}
}
GameId slot = _packSlot(address(proxy), block.timestamp);
// Store the dispute game in the mapping & emit the `DisputeGameCreated` event.
// Store the dispute game in the mapping & emit the `DisputeGameCreated` event.
disputeGames[uuid] = proxy
;
_disputeGames[uuid] = slot
;
disputeGameList.push(proxy
);
_disputeGameList.push(slot
);
emit DisputeGameCreated(address(proxy), gameType, rootClaim);
emit DisputeGameCreated(address(proxy), gameType, rootClaim);
}
}
...
@@ -163,4 +188,24 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion
...
@@ -163,4 +188,24 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion
gameImpls[gameType] = impl;
gameImpls[gameType] = impl;
emit ImplementationSet(address(impl), gameType);
emit ImplementationSet(address(impl), gameType);
}
}
/**
* @dev Packs an address and a uint256 into a single bytes32 slot. This
* is only safe for up to uint96 values.
*/
function _packSlot(address _addr, uint256 _num) internal pure returns (GameId slot_) {
assembly {
slot_ := or(shl(0xa0, _num), _addr)
}
}
/**
* @dev Unpacks an address and a uint256 from a single bytes32 slot.
*/
function _unpackSlot(GameId _slot) internal pure returns (address addr_, uint256 num_) {
assembly {
addr_ := and(_slot, 0xffffffffffffffffffffffffffffffffffffffff)
num_ := shr(0xa0, _slot)
}
}
}
}
packages/contracts-bedrock/contracts/dispute/interfaces/IDisputeGameFactory.sol
View file @
69e67474
...
@@ -44,12 +44,26 @@ interface IDisputeGameFactory {
...
@@ -44,12 +44,26 @@ interface IDisputeGameFactory {
* @param extraData Any extra data that should be provided to the created dispute game.
* @param extraData Any extra data that should be provided to the created dispute game.
* @return _proxy The clone of the `DisputeGame` created with the given parameters.
* @return _proxy The clone of the `DisputeGame` created with the given parameters.
* Returns `address(0)` if nonexistent.
* Returns `address(0)` if nonexistent.
* @return _timestamp The timestamp of the creation of the dispute game.
*/
*/
function games(
function games(
GameType gameType,
GameType gameType,
Claim rootClaim,
Claim rootClaim,
bytes calldata extraData
bytes calldata extraData
) external view returns (IDisputeGame _proxy);
) external view returns (IDisputeGame _proxy, uint256 _timestamp);
/**
* @notice `gameAtIndex` returns the dispute game contract address and its creation timestamp
* at the given index. Each created dispute game increments the underlying index.
* @param _index The index of the dispute game.
* @return _proxy The clone of the `DisputeGame` created with the given parameters.
* Returns `address(0)` if nonexistent.
* @return _timestamp The timestamp of the creation of the dispute game.
*/
function gameAtIndex(uint256 _index)
external
view
returns (IDisputeGame _proxy, uint256 _timestamp);
/**
/**
* @notice `gameImpls` is a mapping that maps `GameType`s to their respective
* @notice `gameImpls` is a mapping that maps `GameType`s to their respective
...
...
packages/contracts-bedrock/contracts/libraries/DisputeTypes.sol
View file @
69e67474
...
@@ -33,6 +33,18 @@ type Timestamp is uint64;
...
@@ -33,6 +33,18 @@ type Timestamp is uint64;
*/
*/
type Duration is uint64;
type Duration is uint64;
/**
* @notice A `GameId` represents a packed 12 byte timestamp and a 20 byte address.
* @dev The packed layout of this type is as follows:
* ┌────────────┬────────────────┐
* │ Bits │ Value │
* ├────────────┼────────────────┤
* │ [0, 96) │ Timestamp │
* │ [96, 256) │ Address │
* └────────────┴────────────────┘
*/
type GameId is bytes32;
/**
/**
* @notice A `Clock` represents a packed `Duration` and `Timestamp`
* @notice A `Clock` represents a packed `Duration` and `Timestamp`
* @dev The packed layout of this type is as follows:
* @dev The packed layout of this type is as follows:
...
...
packages/contracts-bedrock/contracts/test/DisputeGameFactory.t.sol
View file @
69e67474
...
@@ -9,8 +9,9 @@ import { DisputeGameFactory } from "../dispute/DisputeGameFactory.sol";
...
@@ -9,8 +9,9 @@ import { DisputeGameFactory } from "../dispute/DisputeGameFactory.sol";
import { IDisputeGame } from "../dispute/interfaces/IDisputeGame.sol";
import { IDisputeGame } from "../dispute/interfaces/IDisputeGame.sol";
import { Proxy } from "../universal/Proxy.sol";
import { Proxy } from "../universal/Proxy.sol";
contract DisputeGameFactory_Init
ializer
is Test {
contract DisputeGameFactory_Init is Test {
DisputeGameFactory factory;
DisputeGameFactory factory;
FakeClone fakeClone;
event DisputeGameCreated(
event DisputeGameCreated(
address indexed disputeProxy,
address indexed disputeProxy,
...
@@ -30,17 +31,12 @@ contract DisputeGameFactory_Initializer is Test {
...
@@ -30,17 +31,12 @@ contract DisputeGameFactory_Initializer is Test {
});
});
factory = DisputeGameFactory(address(proxy));
factory = DisputeGameFactory(address(proxy));
vm.label(address(factory), "DisputeGameFactoryProxy");
vm.label(address(factory), "DisputeGameFactoryProxy");
}
}
contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
FakeClone fakeClone;
function setUp() public override {
super.setUp();
fakeClone = new FakeClone();
fakeClone = new FakeClone();
}
}
}
contract DisputeGameFactory_Create_Test is DisputeGameFactory_Init {
/**
/**
* @dev Tests that the `create` function succeeds when creating a new dispute game
* @dev Tests that the `create` function succeeds when creating a new dispute game
* with a `GameType` that has an implementation set.
* with a `GameType` that has an implementation set.
...
@@ -62,10 +58,16 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
...
@@ -62,10 +58,16 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
emit DisputeGameCreated(address(0), gt, rootClaim);
emit DisputeGameCreated(address(0), gt, rootClaim);
IDisputeGame proxy = factory.create(gt, rootClaim, extraData);
IDisputeGame proxy = factory.create(gt, rootClaim, extraData);
(IDisputeGame game, uint256 timestamp) = factory.games(gt, rootClaim, extraData);
// Ensure that the dispute game was assigned to the `disputeGames` mapping.
// Ensure that the dispute game was assigned to the `disputeGames` mapping.
assertEq(address(factory.games(gt, rootClaim, extraData)), address(proxy));
assertEq(address(game), address(proxy));
assertEq(timestamp, block.timestamp);
assertEq(factory.gameCount(), 1);
assertEq(factory.gameCount(), 1);
assertEq(address(factory.disputeGameList(0)), address(proxy));
(IDisputeGame game2, uint256 timestamp2) = factory.gameAtIndex(0);
assertEq(address(game2), address(proxy));
assertEq(timestamp2, block.timestamp);
}
}
/**
/**
...
@@ -105,8 +107,10 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
...
@@ -105,8 +107,10 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
emit DisputeGameCreated(address(0), gt, rootClaim);
emit DisputeGameCreated(address(0), gt, rootClaim);
IDisputeGame proxy = factory.create(gt, rootClaim, extraData);
IDisputeGame proxy = factory.create(gt, rootClaim, extraData);
(IDisputeGame game, uint256 timestamp) = factory.games(gt, rootClaim, extraData);
// Ensure that the dispute game was assigned to the `disputeGames` mapping.
// Ensure that the dispute game was assigned to the `disputeGames` mapping.
assertEq(address(factory.games(gt, rootClaim, extraData)), address(proxy));
assertEq(address(game), address(proxy));
assertEq(timestamp, block.timestamp);
// Ensure that the `create` function reverts when called with parameters that would result in the same UUID.
// Ensure that the `create` function reverts when called with parameters that would result in the same UUID.
vm.expectRevert(
vm.expectRevert(
...
@@ -117,7 +121,9 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
...
@@ -117,7 +121,9 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
);
);
factory.create(gt, rootClaim, extraData);
factory.create(gt, rootClaim, extraData);
}
}
}
contract DisputeGameFactory_SetImplementation_Test is DisputeGameFactory_Init {
/**
/**
* @dev Tests that the `setImplementation` function properly sets the implementation for a given `GameType`.
* @dev Tests that the `setImplementation` function properly sets the implementation for a given `GameType`.
*/
*/
...
@@ -144,7 +150,9 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
...
@@ -144,7 +150,9 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
vm.expectRevert("Ownable: caller is not the owner");
vm.expectRevert("Ownable: caller is not the owner");
factory.setImplementation(GameTypes.FAULT, IDisputeGame(address(1)));
factory.setImplementation(GameTypes.FAULT, IDisputeGame(address(1)));
}
}
}
contract DisputeGameFactory_GetGameUUID_Test is DisputeGameFactory_Init {
/**
/**
* @dev Tests that the `getGameUUID` function returns the correct hash when comparing
* @dev Tests that the `getGameUUID` function returns the correct hash when comparing
* against the keccak256 hash of the abi-encoded parameters.
* against the keccak256 hash of the abi-encoded parameters.
...
@@ -162,14 +170,18 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
...
@@ -162,14 +170,18 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
keccak256(abi.encode(gt, rootClaim, extraData))
keccak256(abi.encode(gt, rootClaim, extraData))
);
);
}
}
}
contract DisputeGameFactory_Owner_Test is DisputeGameFactory_Init {
/**
/**
* @dev Tests that the `owner` function returns the correct address after deployment.
* @dev Tests that the `owner` function returns the correct address after deployment.
*/
*/
function test_owner_succeeds() public {
function test_owner_succeeds() public {
assertEq(factory.owner(), address(this));
assertEq(factory.owner(), address(this));
}
}
}
contract DisputeGameFactory_TransferOwnership_Test is DisputeGameFactory_Init {
/**
/**
* @dev Tests that the `transferOwnership` function succeeds when called by the owner.
* @dev Tests that the `transferOwnership` function succeeds when called by the owner.
*/
*/
...
@@ -188,6 +200,43 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
...
@@ -188,6 +200,43 @@ contract DisputeGameFactory_Test is DisputeGameFactory_Initializer {
}
}
}
}
/**
* @title PackingTester
* @notice Exposes the internal packing functions so that they can be fuzzed
* in a roundtrip manner.
*/
contract PackingTester is DisputeGameFactory {
function packSlot(address _addr, uint256 _num) external pure returns (GameId) {
return _packSlot(_addr, _num);
}
function unpackSlot(GameId _slot) external pure returns (address, uint256) {
return _unpackSlot(_slot);
}
}
/**
* @title DisputeGameFactory_PackSlot_Test
* @notice Fuzzes the PackingTester contract
*/
contract DisputeGameFactory_PackSlot_Test is Test {
PackingTester tester;
function setUp() public {
tester = new PackingTester();
}
/**
* @dev Tests that the `packSlot` and `unpackSlot` functions roundtrip correctly.
*/
function testFuzz_packSlot_succeeds(address _addr, uint96 _num) public {
GameId slot = tester.packSlot(_addr, uint256(_num));
(address addr, uint256 num) = tester.unpackSlot(slot);
assertEq(addr, _addr);
assertEq(num, _num);
}
}
/**
/**
* @dev A fake clone used for testing the `DisputeGameFactory` contract's `create` function.
* @dev A fake clone used for testing the `DisputeGameFactory` contract's `create` function.
*/
*/
...
...
packages/contracts-bedrock/contracts/test/FaultDisputeGame.t.sol
View file @
69e67474
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
pragma solidity ^0.8.15;
pragma solidity ^0.8.15;
import { Test } from "forge-std/Test.sol";
import { Test } from "forge-std/Test.sol";
import { DisputeGameFactory_Init
ializer
} from "./DisputeGameFactory.t.sol";
import { DisputeGameFactory_Init } from "./DisputeGameFactory.t.sol";
import { DisputeGameFactory } from "../dispute/DisputeGameFactory.sol";
import { DisputeGameFactory } from "../dispute/DisputeGameFactory.sol";
import { FaultDisputeGame } from "../dispute/FaultDisputeGame.sol";
import { FaultDisputeGame } from "../dispute/FaultDisputeGame.sol";
...
@@ -11,7 +11,7 @@ import "../libraries/DisputeErrors.sol";
...
@@ -11,7 +11,7 @@ import "../libraries/DisputeErrors.sol";
import { LibClock } from "../dispute/lib/LibClock.sol";
import { LibClock } from "../dispute/lib/LibClock.sol";
import { LibPosition } from "../dispute/lib/LibPosition.sol";
import { LibPosition } from "../dispute/lib/LibPosition.sol";
contract FaultDisputeGame_Test is DisputeGameFactory_Init
ializer
{
contract FaultDisputeGame_Test is DisputeGameFactory_Init {
/**
/**
* @dev The root claim of the game.
* @dev The root claim of the game.
*/
*/
...
...
packages/contracts-bedrock/src/deploy-utils.ts
View file @
69e67474
...
@@ -4,7 +4,7 @@ import { URLSearchParams } from 'url'
...
@@ -4,7 +4,7 @@ import { URLSearchParams } from 'url'
import
{
ethers
,
Contract
}
from
'
ethers
'
import
{
ethers
,
Contract
}
from
'
ethers
'
import
{
Provider
}
from
'
@ethersproject/abstract-provider
'
import
{
Provider
}
from
'
@ethersproject/abstract-provider
'
import
{
Signer
}
from
'
@ethersproject/abstract-signer
'
import
{
Signer
}
from
'
@ethersproject/abstract-signer
'
import
{
awaitCondition
,
sleep
}
from
'
@eth-optimism/core-utils
'
import
{
sleep
}
from
'
@eth-optimism/core-utils
'
import
{
HardhatRuntimeEnvironment
}
from
'
hardhat/types
'
import
{
HardhatRuntimeEnvironment
}
from
'
hardhat/types
'
import
{
Deployment
,
DeployResult
}
from
'
hardhat-deploy/dist/types
'
import
{
Deployment
,
DeployResult
}
from
'
hardhat-deploy/dist/types
'
import
'
hardhat-deploy
'
import
'
hardhat-deploy
'
...
@@ -323,35 +323,35 @@ export const printJsonTransaction = (tx: ethers.PopulatedTransaction): void => {
...
@@ -323,35 +323,35 @@ export const printJsonTransaction = (tx: ethers.PopulatedTransaction): void => {
}
}
/**
/**
*
Mini helper for transferring a Proxy to the MSD
*
Helper for transferring a Proxy to a target contract.
*
*
* @param opts Options for executing the step.
* @param opts Options for executing the step.
* @param opts.isLiveDeployer True if the deployer is live.
* @param opts.isLiveDeployer True if the deployer is live.
* @param opts.proxy proxy contract.
* @param opts.proxy proxy contract.
* @param opts.
dictator dictator
contract.
* @param opts.
target target
contract.
*/
*/
export
const
doOwnershipTransfer
=
async
(
opts
:
{
export
const
doOwnershipTransfer
=
async
(
opts
:
{
isLiveDeployer
?:
boolean
isLiveDeployer
?:
boolean
proxy
:
ethers
.
Contract
proxy
:
ethers
.
Contract
name
:
string
name
:
string
transferFunc
:
string
transferFunc
:
string
dictator
:
ethers
.
Contract
target
:
ethers
.
Contract
}):
Promise
<
void
>
=>
{
}):
Promise
<
void
>
=>
{
if
(
opts
.
isLiveDeployer
)
{
if
(
opts
.
isLiveDeployer
)
{
console
.
log
(
`Setting
${
opts
.
name
}
owner to
MSD
`
)
console
.
log
(
`Setting
${
opts
.
name
}
owner to
target
${
opts
.
target
.
address
}
`
)
await
opts
.
proxy
[
opts
.
transferFunc
](
opts
.
dictator
.
address
)
await
opts
.
proxy
[
opts
.
transferFunc
](
opts
.
target
.
address
)
}
else
{
}
else
{
const
tx
=
await
opts
.
proxy
.
populateTransaction
[
opts
.
transferFunc
](
const
tx
=
await
opts
.
proxy
.
populateTransaction
[
opts
.
transferFunc
](
opts
.
dictator
.
address
opts
.
target
.
address
)
)
console
.
log
(
`
console
.
log
(
`
Please transfer
${
opts
.
name
}
(proxy) owner to MSD
Please transfer
${
opts
.
name
}
(proxy) owner to MSD
-
${
opts
.
name
}
address:
${
opts
.
proxy
.
address
}
-
${
opts
.
name
}
address:
${
opts
.
proxy
.
address
}
-
MSD address:
${
opts
.
dictator
.
address
}
-
target address:
${
opts
.
target
.
address
}
`
)
`
)
printJsonTransaction
(
tx
)
printJsonTransaction
(
tx
)
printCastCommand
(
tx
)
printCastCommand
(
tx
)
await
printTenderlySimulationLink
(
opts
.
dictator
.
provider
,
tx
)
await
printTenderlySimulationLink
(
opts
.
target
.
provider
,
tx
)
}
}
}
}
...
@@ -377,146 +377,6 @@ export const liveDeployer = async (opts: {
...
@@ -377,146 +377,6 @@ export const liveDeployer = async (opts: {
return
ret
return
ret
}
}
/**
* Mini helper for checking if the current step is a target step.
*
* @param dictator SystemDictator contract.
* @param step Target step.
* @returns True if the current step is the target step.
*/
export
const
isStep
=
async
(
dictator
:
ethers
.
Contract
,
step
:
number
):
Promise
<
boolean
>
=>
{
return
(
await
dictator
.
currentStep
())
===
step
}
/**
* Mini helper for checking if the current step is the first step in target phase.
*
* @param dictator SystemDictator contract.
* @param phase Target phase.
* @returns True if the current step is the first step in target phase.
*/
export
const
isStartOfPhase
=
async
(
dictator
:
ethers
.
Contract
,
phase
:
number
):
Promise
<
boolean
>
=>
{
const
phaseToStep
=
{
1
:
1
,
2
:
3
,
3
:
6
,
}
return
(
await
dictator
.
currentStep
())
===
phaseToStep
[
phase
]
}
/**
* Mini helper for executing a given step.
*
* @param opts Options for executing the step.
* @param opts.isLiveDeployer True if the deployer is live.
* @param opts.SystemDictator SystemDictator contract.
* @param opts.step Step to execute.
* @param opts.message Message to print before executing the step.
* @param opts.checks Checks to perform after executing the step.
*/
export
const
doStep
=
async
(
opts
:
{
isLiveDeployer
?:
boolean
SystemDictator
:
ethers
.
Contract
step
:
number
message
:
string
checks
:
()
=>
Promise
<
void
>
}):
Promise
<
void
>
=>
{
const
isStepVal
=
await
isStep
(
opts
.
SystemDictator
,
opts
.
step
)
if
(
!
isStepVal
)
{
console
.
log
(
`Step already completed:
${
opts
.
step
}
`
)
return
}
// Extra message to help the user understand what's going on.
console
.
log
(
opts
.
message
)
// Either automatically or manually execute the step.
if
(
opts
.
isLiveDeployer
)
{
console
.
log
(
`Executing step
${
opts
.
step
}
...`
)
await
opts
.
SystemDictator
[
`step
${
opts
.
step
}
`
]()
}
else
{
const
tx
=
await
opts
.
SystemDictator
.
populateTransaction
[
`step
${
opts
.
step
}
`
]()
console
.
log
(
`Please execute step
${
opts
.
step
}
...`
)
console
.
log
(
`MSD address:
${
opts
.
SystemDictator
.
address
}
`
)
printJsonTransaction
(
tx
)
printCastCommand
(
tx
)
await
printTenderlySimulationLink
(
opts
.
SystemDictator
.
provider
,
tx
)
}
// Wait for the step to complete.
await
awaitCondition
(
async
()
=>
{
return
isStep
(
opts
.
SystemDictator
,
opts
.
step
+
1
)
},
30000
,
1000
)
// Perform post-step checks.
await
opts
.
checks
()
}
/**
* Mini helper for executing a given phase.
*
* @param opts Options for executing the step.
* @param opts.isLiveDeployer True if the deployer is live.
* @param opts.SystemDictator SystemDictator contract.
* @param opts.step Step to execute.
* @param opts.message Message to print before executing the step.
* @param opts.checks Checks to perform after executing the step.
*/
export
const
doPhase
=
async
(
opts
:
{
isLiveDeployer
?:
boolean
SystemDictator
:
ethers
.
Contract
phase
:
number
message
:
string
checks
:
()
=>
Promise
<
void
>
}):
Promise
<
void
>
=>
{
const
isStart
=
await
isStartOfPhase
(
opts
.
SystemDictator
,
opts
.
phase
)
if
(
!
isStart
)
{
console
.
log
(
`Start of phase
${
opts
.
phase
}
already completed`
)
return
}
// Extra message to help the user understand what's going on.
console
.
log
(
opts
.
message
)
// Either automatically or manually execute the step.
if
(
opts
.
isLiveDeployer
)
{
console
.
log
(
`Executing phase
${
opts
.
phase
}
...`
)
await
opts
.
SystemDictator
[
`phase
${
opts
.
phase
}
`
]()
}
else
{
const
tx
=
await
opts
.
SystemDictator
.
populateTransaction
[
`phase
${
opts
.
phase
}
`
]()
console
.
log
(
`Please execute phase
${
opts
.
phase
}
...`
)
console
.
log
(
`MSD address:
${
opts
.
SystemDictator
.
address
}
`
)
printJsonTransaction
(
tx
)
await
printTenderlySimulationLink
(
opts
.
SystemDictator
.
provider
,
tx
)
}
// Wait for the step to complete.
await
awaitCondition
(
async
()
=>
{
return
isStartOfPhase
(
opts
.
SystemDictator
,
opts
.
phase
+
1
)
},
30000
,
1000
)
// Perform post-step checks.
await
opts
.
checks
()
}
/**
/**
* Prints a direct link to a Tenderly simulation.
* Prints a direct link to a Tenderly simulation.
*
*
...
...
packages/fault-detector/src/helpers.ts
View file @
69e67474
...
@@ -66,7 +66,7 @@ export const updateOracleCache = async <TSubmissionEventArgs>(
...
@@ -66,7 +66,7 @@ export const updateOracleCache = async <TSubmissionEventArgs>(
latestBlock
:
endBlock
,
latestBlock
:
endBlock
,
})
})
let
failures
=
0
let
failures
=
[]
let
currentBlock
=
cache
.
highestBlock
+
1
let
currentBlock
=
cache
.
highestBlock
+
1
let
step
=
endBlock
-
currentBlock
let
step
=
endBlock
-
currentBlock
while
(
currentBlock
<
endBlock
)
{
while
(
currentBlock
<
endBlock
)
{
...
@@ -98,7 +98,7 @@ export const updateOracleCache = async <TSubmissionEventArgs>(
...
@@ -98,7 +98,7 @@ export const updateOracleCache = async <TSubmissionEventArgs>(
currentBlock
+=
step
currentBlock
+=
step
step
=
Math
.
ceil
(
step
*
2
)
step
=
Math
.
ceil
(
step
*
2
)
}
catch
(
err
)
{
}
catch
(
err
)
{
logger
?.
error
(
'
error fetching events
'
,
{
logger
?.
warn
(
'
error fetching events
'
,
{
err
,
err
,
node
:
'
l1
'
,
node
:
'
l1
'
,
section
:
'
getLogs
'
,
section
:
'
getLogs
'
,
...
@@ -110,14 +110,14 @@ export const updateOracleCache = async <TSubmissionEventArgs>(
...
@@ -110,14 +110,14 @@ export const updateOracleCache = async <TSubmissionEventArgs>(
// When the step gets down to zero, we're pretty much guaranteed that range size isn't the
// When the step gets down to zero, we're pretty much guaranteed that range size isn't the
// problem. If we get three failures like this in a row then we should just give up.
// problem. If we get three failures like this in a row then we should just give up.
if
(
step
===
0
)
{
if
(
step
===
0
)
{
failures
++
failures
.
push
(
err
)
}
else
{
}
else
{
failures
=
0
failures
=
[]
}
}
// We've failed
3
times in a row, we're probably stuck.
// We've failed
5
times in a row, we're probably stuck.
if
(
failures
>=
3
)
{
if
(
failures
.
length
>=
5
)
{
logger
?.
fatal
(
'
unable to fetch oracle events
'
,
{
err
})
logger
?.
fatal
(
'
unable to fetch oracle events
'
,
{
err
ors
:
failures
})
throw
new
Error
(
'
failed to update event cache
'
)
throw
new
Error
(
'
failed to update event cache
'
)
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment