Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade Contracts for Optimism Granite Network Upgrade - op contracts v1.6.0 #285

Merged
merged 19 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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: 5 additions & 1 deletion cannon/mipsevm/evm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package mipsevm
import (
"bytes"
"debug/elf"
"encoding/binary"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -137,11 +138,14 @@ func encodePreimageOracleInput(t *testing.T, wit *StepWitness, localContext Loca
}
preimage := localOracle.GetPreimage(preimage.Keccak256Key(wit.PreimageKey).PreimageKey())
precompile := common.BytesToAddress(preimage[:20])
callInput := preimage[20:]
requiredGas := binary.BigEndian.Uint64(preimage[20:28])
callInput := preimage[28:]

input, err := oracle.ABI.Pack(
"loadPrecompilePreimagePart",
new(big.Int).SetUint64(uint64(wit.PreimageOffset)),
precompile,
requiredGas,
callInput,
)
require.NoError(t, err)
Expand Down
Binary file modified cannon/mipsevm/open_mips_tests/test/bin/oracle_kzg.bin
Binary file not shown.
40 changes: 21 additions & 19 deletions cannon/mipsevm/open_mips_tests/test/oracle_kzg.asm
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,38 @@
.ent test

# load hash at 0x30001000
# point evaluation precompile input - 01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a
# 0x0a44472c cb798bc5 954fc466 e6ee2c31 e1ca8a87 d000966c 629d679a 4a29921f = keccak(address(0xa) ++ precompile_input)
# 0x0644472c cb798bc5 954fc466 e6ee2c31 e1ca8a87 d000966c 629d679a 4a29921f = keccak(address(0xa) ++ precompile_input).key (precompile)
# requiredGas is 50_000
# point evaluation precompile input (requiredGas ++ precompileInput) - 000000000000c35001e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a
# 0x3efd5c3c 1c555298 0c63aee5 4570c276 cbff7532 796b4d75 3132d51a 6bedf0c6 = keccak(address(0xa) ++ required_gas ++ precompile_input)
# 0x06fd5c3c 1c555298 0c63aee5 4570c276 cbff7532 796b4d75 3132d51a 6bedf0c6 = keccak(address(0xa) ++ required_gas ++ precompile_input).key (precompile)

test:
lui $s0, 0x3000
ori $s0, 0x1000

lui $t0, 0x0644
ori $t0, 0x472c
lui $t0, 0x06fd
ori $t0, 0x5c3c
sw $t0, 0($s0)
lui $t0, 0xcb79
ori $t0, 0x8bc5
lui $t0, 0x1c55
ori $t0, 0x5298
sw $t0, 4($s0)
lui $t0, 0x954f
ori $t0, 0xc466
lui $t0, 0x0c63
ori $t0, 0xaee5
sw $t0, 8($s0)
lui $t0, 0xe6ee
ori $t0, 0x2c31
lui $t0, 0x4570
ori $t0, 0xc276
sw $t0, 0xc($s0)
lui $t0, 0xe1ca
ori $t0, 0x8a87
lui $t0, 0xcbff
ori $t0, 0x7532
sw $t0, 0x10($s0)
lui $t0, 0xd000
ori $t0, 0x966c
lui $t0, 0x796b
ori $t0, 0x4d75
sw $t0, 0x14($s0)
lui $t0, 0x629d
ori $t0, 0x679a
lui $t0, 0x3132
ori $t0, 0xd51a
sw $t0, 0x18($s0)
lui $t0, 0x4a29
ori $t0, 0x921f
lui $t0, 0x6bed
ori $t0, 0xf0c6
sw $t0, 0x1c($s0)

# preimage request - write(fdPreimageWrite, preimageData, 32)
Expand Down
2 changes: 1 addition & 1 deletion cannon/mipsevm/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ func staticPrecompileOracle(t *testing.T, precompile common.Address, input []byt
func selectOracleFixture(t *testing.T, programName string) PreimageOracle {
if strings.HasPrefix(programName, "oracle_kzg") {
precompile := common.BytesToAddress([]byte{0xa})
input := common.FromHex("01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a")
input := common.FromHex("000000000000c35001e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a")
blobPrecompileReturnValue := common.FromHex("000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001")
return staticPrecompileOracle(t, precompile, input, append([]byte{0x1}, blobPrecompileReturnValue...))
} else if strings.HasPrefix(programName, "oracle") {
Expand Down
26 changes: 26 additions & 0 deletions packages/tokamak/contracts-bedrock/scripts/ChainAssertions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,32 @@ library ChainAssertions {
}
}

/// @notice Asserts that the permissioned DelayedWETH is setup correctly
function checkPermissionedDelayedWETH(
Types.ContractSet memory _contracts,
DeployConfig _cfg,
bool _isProxy,
address _expectedOwner
)
internal
view
{
console.log("Running chain assertions on the permissioned DelayedWETH");
DelayedWETH weth = DelayedWETH(payable(_contracts.PermissionedDelayedWETH));

// Check that the contract is initialized
assertSlotValueIsOne({ _contractAddress: address(weth), _slot: 0, _offset: 0 });

if (_isProxy) {
require(weth.owner() == _expectedOwner);
require(weth.delay() == _cfg.faultGameWithdrawalDelay());
require(weth.config() == SuperchainConfig(_contracts.SuperchainConfig));
} else {
require(weth.owner() == _expectedOwner);
require(weth.delay() == _cfg.faultGameWithdrawalDelay());
}
}

/// @notice Asserts that the L2OutputOracle is setup correctly
function checkL2OutputOracle(
Types.ContractSet memory _contracts,
Expand Down
95 changes: 95 additions & 0 deletions packages/tokamak/contracts-bedrock/scripts/Config.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,59 @@ pragma solidity ^0.8.0;

import { Vm, VmSafe } from "forge-std/Vm.sol";

/// @notice Enum representing different ways of outputting genesis allocs.
/// @custom:value NONE No output, used in internal tests.
/// @custom:value LATEST Output allocs only for latest fork.
/// @custom:value ALL Output allocs for all intermediary forks.
enum OutputMode {
NONE,
LATEST,
ALL
}

library OutputModeUtils {
function toString(OutputMode _mode) internal pure returns (string memory) {
if (_mode == OutputMode.NONE) {
return "none";
} else if (_mode == OutputMode.LATEST) {
return "latest";
} else if (_mode == OutputMode.ALL) {
return "all";
} else {
return "unknown";
}
}
}

/// @notice Enum of forks available for selection when generating genesis allocs.
enum Fork {
NONE,
DELTA,
ECOTONE,
FJORD,
GRANITE
}

Fork constant LATEST_FORK = Fork.GRANITE;

library ForkUtils {
function toString(Fork _fork) internal pure returns (string memory) {
if (_fork == Fork.NONE) {
return "none";
} else if (_fork == Fork.DELTA) {
return "delta";
} else if (_fork == Fork.ECOTONE) {
return "ecotone";
} else if (_fork == Fork.FJORD) {
return "fjord";
} else if (_fork == Fork.GRANITE) {
return "granite";
} else {
return "unknown";
}
}
}

/// @title Config
/// @notice Contains all env var based config. Add any new env var parsing to this file
/// to ensure that all config is in a single place.
Expand Down Expand Up @@ -67,4 +120,46 @@ library Config {
function drippieOwnerPrivateKey() internal view returns (uint256 _env) {
_env = vm.envUint("DRIPPIE_OWNER_PRIVATE_KEY");
}

/// @notice Returns the OutputMode for genesis allocs generation.
/// It reads the mode from the environment variable OUTPUT_MODE.
/// If it is unset, OutputMode.ALL is returned.
function outputMode() internal view returns (OutputMode) {
string memory modeStr = vm.envOr("OUTPUT_MODE", string("latest"));
bytes32 modeHash = keccak256(bytes(modeStr));
if (modeHash == keccak256(bytes("none"))) {
return OutputMode.NONE;
} else if (modeHash == keccak256(bytes("latest"))) {
return OutputMode.LATEST;
} else if (modeHash == keccak256(bytes("all"))) {
return OutputMode.ALL;
} else {
revert(string.concat("Config: unknown output mode: ", modeStr));
}
}

/// @notice Returns the latest fork to use for genesis allocs generation.
/// It reads the fork from the environment variable FORK. If it is
/// unset, NONE is returned.
/// If set to the special value "latest", the latest fork is returned.
function fork() internal view returns (Fork) {
string memory forkStr = vm.envOr("FORK", string(""));
if (bytes(forkStr).length == 0) {
return Fork.NONE;
}
bytes32 forkHash = keccak256(bytes(forkStr));
if (forkHash == keccak256(bytes("latest"))) {
return LATEST_FORK;
} else if (forkHash == keccak256(bytes("delta"))) {
return Fork.DELTA;
} else if (forkHash == keccak256(bytes("ecotone"))) {
return Fork.ECOTONE;
} else if (forkHash == keccak256(bytes("fjord"))) {
return Fork.FJORD;
} else if (forkHash == keccak256(bytes("granite"))) {
return Fork.GRANITE;
} else {
revert(string.concat("Config: unknown fork: ", forkStr));
}
}
}
58 changes: 53 additions & 5 deletions packages/tokamak/contracts-bedrock/scripts/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ contract Deploy is Deployer {
L2OutputOracle: mustGetAddress("L2OutputOracleProxy"),
DisputeGameFactory: mustGetAddress("DisputeGameFactoryProxy"),
DelayedWETH: mustGetAddress("DelayedWETHProxy"),
PermissionedDelayedWETH: mustGetAddress("PermissionedDelayedWETHProxy"),
AnchorStateRegistry: mustGetAddress("AnchorStateRegistryProxy"),
OptimismMintableERC20Factory: mustGetAddress("OptimismMintableERC20FactoryProxy"),
OptimismPortal: mustGetAddress("OptimismPortalProxy"),
Expand All @@ -174,6 +175,7 @@ contract Deploy is Deployer {
L2OutputOracle: getAddress("L2OutputOracleProxy"),
DisputeGameFactory: getAddress("DisputeGameFactoryProxy"),
DelayedWETH: getAddress("DelayedWETHProxy"),
PermissionedDelayedWETH: getAddress("PermissionedDelayedWETHProxy"),
AnchorStateRegistry: getAddress("AnchorStateRegistryProxy"),
OptimismMintableERC20Factory: getAddress("OptimismMintableERC20FactoryProxy"),
OptimismPortal: getAddress("OptimismPortalProxy"),
Expand Down Expand Up @@ -215,7 +217,7 @@ contract Deploy is Deployer {

/// @notice Make a call from the Safe contract to an arbitrary address with arbitrary data
function _callViaSafe(Safe _safe, address _target, bytes memory _data) internal {
// This is the signature format used the caller is also the signer.
// This is the signature format used when the caller is also the signer.
bytes memory signature = abi.encodePacked(uint256(uint160(msg.sender)), bytes32(0), uint8(1));

_safe.execTransaction({
Expand Down Expand Up @@ -281,7 +283,7 @@ contract Deploy is Deployer {
vm.dumpState(Config.stateDumpPath(""));
}

/// @notice Deploy all L1 contracts and write the state diff to a file.
/// @notice Deploy all L1 contracts and write the state diff to a file.DeployConfig
function runWithStateDiff() public stateDiff {
_run();
}
Expand Down Expand Up @@ -376,6 +378,7 @@ contract Deploy is Deployer {
deployERC1967Proxy("DisputeGameFactoryProxy");
deployERC1967Proxy("L2OutputOracleProxy");
deployERC1967Proxy("DelayedWETHProxy");
deployERC1967Proxy("PermissionedDelayedWETHProxy");
deployERC1967Proxy("AnchorStateRegistryProxy");

transferAddressManagerOwnership(); // to the ProxyAdmin
Expand Down Expand Up @@ -423,6 +426,7 @@ contract Deploy is Deployer {
initializeL2OutputOracle();
initializeDisputeGameFactory();
initializeDelayedWETH();
initializePermissionedDelayedWETH();
initializeAnchorStateRegistry();
}

Expand Down Expand Up @@ -1035,10 +1039,34 @@ contract Deploy is Deployer {
});
}

function initializePermissionedDelayedWETH() public broadcast {
console.log("Upgrading and initializing permissioned DelayedWETH proxy");
address delayedWETHProxy = mustGetAddress("PermissionedDelayedWETHProxy");
address delayedWETH = mustGetAddress("DelayedWETH");
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");

_upgradeAndCallViaSafe({
_proxy: payable(delayedWETHProxy),
_implementation: delayedWETH,
_innerCallData: abi.encodeCall(DelayedWETH.initialize, (msg.sender, SuperchainConfig(superchainConfigProxy)))
});

string memory version = DelayedWETH(payable(delayedWETHProxy)).version();
console.log("DelayedWETH version: %s", version);

ChainAssertions.checkPermissionedDelayedWETH({
_contracts: _proxiesUnstrict(),
_cfg: cfg,
_isProxy: true,
_expectedOwner: msg.sender
});
}

function initializeAnchorStateRegistry() public broadcast {
console.log("Upgrading and initializing AnchorStateRegistry proxy");
address anchorStateRegistryProxy = mustGetAddress("AnchorStateRegistryProxy");
address anchorStateRegistry = mustGetAddress("AnchorStateRegistry");
SuperchainConfig superchainConfig = SuperchainConfig(mustGetAddress("SuperchainConfigProxy"));

AnchorStateRegistry.StartingAnchorRoot[] memory roots = new AnchorStateRegistry.StartingAnchorRoot[](5);
roots[0] = AnchorStateRegistry.StartingAnchorRoot({
Expand Down Expand Up @@ -1080,7 +1108,7 @@ contract Deploy is Deployer {
_upgradeAndCallViaSafe({
_proxy: payable(anchorStateRegistryProxy),
_implementation: anchorStateRegistry,
_innerCallData: abi.encodeCall(AnchorStateRegistry.initialize, (roots))
_innerCallData: abi.encodeCall(AnchorStateRegistry.initialize, (roots, superchainConfig))
});

string memory version = AnchorStateRegistry(payable(anchorStateRegistryProxy)).version();
Expand Down Expand Up @@ -1433,6 +1461,25 @@ contract Deploy is Deployer {
ChainAssertions.checkDelayedWETH({ _contracts: _proxies(), _cfg: cfg, _isProxy: true, _expectedOwner: safe });
}

/// @notice Transfer ownership of the permissioned DelayedWETH contract to the final system owner
function transferPermissionedDelayedWETHOwnership() public broadcast {
console.log("Transferring permissioned DelayedWETH ownership to Safe");
DelayedWETH weth = DelayedWETH(mustGetAddress("PermissionedDelayedWETHProxy"));
address owner = weth.owner();

address safe = mustGetAddress("SystemOwnerSafe");
if (owner != safe) {
weth.transferOwnership(safe);
console.log("DelayedWETH ownership transferred to Safe at: %s", safe);
}
ChainAssertions.checkPermissionedDelayedWETH({
_contracts: _proxies(),
_cfg: cfg,
_isProxy: true,
_expectedOwner: safe
});
}

/// @notice Loads the mips absolute prestate from the prestate-proof for devnets otherwise
/// from the config.
function loadMipsAbsolutePrestate() internal returns (Claim mipsAbsolutePrestate_) {
Expand Down Expand Up @@ -1486,7 +1533,7 @@ contract Deploy is Deployer {
function setPermissionedCannonFaultGameImplementation(bool _allowUpgrade) public broadcast {
console.log("Setting Cannon PermissionedDisputeGame implementation");
DisputeGameFactory factory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"));
DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy"));
DelayedWETH weth = DelayedWETH(mustGetAddress("PermissionedDelayedWETHProxy"));

// Set the Cannon FaultDisputeGame implementation in the factory.
_setFaultGameImplementation({
Expand Down Expand Up @@ -1534,6 +1581,7 @@ contract Deploy is Deployer {
DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy"));

Claim outputAbsolutePrestate = Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate()));
PreimageOracle fastOracle = new PreimageOracle(cfg.preimageOracleMinProposalSize(), 0);
_setFaultGameImplementation({
_factory: factory,
_allowUpgrade: _allowUpgrade,
Expand All @@ -1542,7 +1590,7 @@ contract Deploy is Deployer {
weth: weth,
gameType: GameTypes.FAST,
absolutePrestate: outputAbsolutePrestate,
faultVm: IBigStepper(new AlphabetVM(outputAbsolutePrestate, PreimageOracle(mustGetAddress("PreimageOracle")))),
faultVm: IBigStepper(new AlphabetVM(outputAbsolutePrestate, fastOracle)),
// The max depth for the alphabet trace is always 3. Add 1 because split depth is fully inclusive.
maxGameDepth: cfg.faultGameSplitDepth() + 3 + 1,
maxClockDuration: Duration.wrap(0) // Resolvable immediately
Expand Down
Loading
Loading