Commit cd1cc103 authored by Maurelian's avatar Maurelian Committed by GitHub

test: Transfer to finalSystemOwner rather than SystemOwnerSafe (#12116)

* test: Transfer to finalSystemOwner rather than SystemOwnerSafe

* feat: Fix comment references to ProxyAdmin
parent d3402628
......@@ -2,7 +2,6 @@ package gastoken
import (
"context"
"fmt"
"math/big"
"testing"
"time"
......@@ -440,34 +439,6 @@ func TestCustomGasToken(t *testing.T) {
checkFeeWithdrawal(t, enabled)
}
// callViaSafe will use the Safe smart account at safeAddress to send a transaction to target using the provided data. The transaction signature is constructed from
// the supplied opts.
func callViaSafe(opts *bind.TransactOpts, client *ethclient.Client, safeAddress common.Address, target common.Address, data []byte) (*types.Transaction, error) {
signature := [65]byte{}
copy(signature[12:], opts.From[:])
signature[64] = uint8(1)
safe, err := bindings.NewSafe(safeAddress, client)
if err != nil {
return nil, err
}
owners, err := safe.GetOwners(&bind.CallOpts{})
if err != nil {
return nil, err
}
isOwner, err := safe.IsOwner(&bind.CallOpts{}, opts.From)
if err != nil {
return nil, err
}
if !isOwner {
return nil, fmt.Errorf("address %s is not in owners list %s", opts.From, owners)
}
return safe.ExecTransaction(opts, target, big.NewInt(0), data, 0, big.NewInt(0), big.NewInt(0), big.NewInt(0), common.Address{}, common.Address{}, signature[:])
}
// setCustomGasToeken enables the Custom Gas Token feature on a chain where it wasn't enabled at genesis.
// It reads existing parameters from the SystemConfig contract, inserts the supplied cgtAddress and reinitializes that contract.
// To do this it uses the ProxyAdmin and StorageSetter from the supplied cfg.
......@@ -518,27 +489,18 @@ func setCustomGasToken(t *testing.T, cfg e2esys.SystemConfig, sys *e2esys.System
proxyAdmin, err := bindings.NewProxyAdmin(cfg.L1Deployments.ProxyAdmin, l1Client)
require.NoError(t, err)
// Compute Proxy Admin Owner (this is a SAFE with 1 owner)
proxyAdminOwner, err := proxyAdmin.Owner(&bind.CallOpts{})
require.NoError(t, err)
// Deploy a new StorageSetter contract
storageSetterAddr, tx, _, err := bindings.DeployStorageSetter(deployerOpts, l1Client)
waitForTx(t, tx, err, l1Client)
// Set up a signer which controls the Proxy Admin Owner SAFE
safeOwnerOpts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Deployer, cfg.L1ChainIDBig())
require.NoError(t, err)
// Encode calldata for upgrading SystemConfigProxy to the StorageSetter implementation
proxyAdminABI, err := bindings.ProxyAdminMetaData.GetAbi()
require.NoError(t, err)
encodedUpgradeCall, err := proxyAdminABI.Pack("upgrade",
cfg.L1Deployments.SystemConfigProxy, storageSetterAddr)
// Set up a signer which controls the Proxy Admin.
// The deploy config's finalSystemOwner is the owner of the ProxyAdmin as well as the SystemConfig,
// so we can use that address for the proxy admin owner.
proxyAdminOwnerOpts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig())
require.NoError(t, err)
// Execute the upgrade SystemConfigProxy -> StorageSetter
tx, err = callViaSafe(safeOwnerOpts, l1Client, proxyAdminOwner, cfg.L1Deployments.ProxyAdmin, encodedUpgradeCall)
// Execute the upgrade SystemConfigProxy -> StorageSetter via ProxyAdmin
tx, err = proxyAdmin.Upgrade(proxyAdminOwnerOpts, cfg.L1Deployments.SystemConfigProxy, storageSetterAddr)
waitForTx(t, tx, err, l1Client)
// Bind a StorageSetter to the SystemConfigProxy address
......@@ -554,13 +516,8 @@ func setCustomGasToken(t *testing.T, cfg e2esys.SystemConfig, sys *e2esys.System
require.NoError(t, err)
require.Equal(t, currentSlotValue, [32]byte{0})
// Prepare calldata for SystemConfigProxy -> SystemConfig upgrade
encodedUpgradeCall, err = proxyAdminABI.Pack("upgrade",
cfg.L1Deployments.SystemConfigProxy, cfg.L1Deployments.SystemConfig)
require.NoError(t, err)
// Execute SystemConfigProxy -> SystemConfig upgrade
tx, err = callViaSafe(safeOwnerOpts, l1Client, proxyAdminOwner, cfg.L1Deployments.ProxyAdmin, encodedUpgradeCall)
tx, err = proxyAdmin.Upgrade(proxyAdminOwnerOpts, cfg.L1Deployments.SystemConfigProxy, cfg.L1Deployments.SystemConfig)
waitForTx(t, tx, err, l1Client)
// Reinitialise with existing initializer values but with custom gas token set
......
......@@ -9,12 +9,6 @@ import { stdJson } from "forge-std/StdJson.sol";
import { AlphabetVM } from "test/mocks/AlphabetVM.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
// Safe
import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol";
import { OwnerManager } from "safe-contracts/base/OwnerManager.sol";
import { GnosisSafeProxyFactory as SafeProxyFactory } from "safe-contracts/proxies/GnosisSafeProxyFactory.sol";
import { Enum as SafeOps } from "safe-contracts/common/Enum.sol";
// Scripts
import { Deployer } from "scripts/deploy/Deployer.sol";
import { Chains } from "scripts/libraries/Chains.sol";
......@@ -196,68 +190,15 @@ contract Deploy is Deployer {
// State Changing Helper Functions //
////////////////////////////////////////////////////////////////
/// @notice Gets the address of the SafeProxyFactory and Safe singleton for use in deploying a new GnosisSafe.
function _getSafeFactory() internal returns (SafeProxyFactory safeProxyFactory_, Safe safeSingleton_) {
if (getAddress("SafeProxyFactory") != address(0)) {
// The SafeProxyFactory is already saved, we can just use it.
safeProxyFactory_ = SafeProxyFactory(getAddress("SafeProxyFactory"));
safeSingleton_ = Safe(getAddress("SafeSingleton"));
return (safeProxyFactory_, safeSingleton_);
}
// These are the standard create2 deployed contracts. First we'll check if they are deployed,
// if not we'll deploy new ones, though not at these addresses.
address safeProxyFactory = 0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2;
address safeSingleton = 0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552;
safeProxyFactory.code.length == 0
? safeProxyFactory_ = new SafeProxyFactory()
: safeProxyFactory_ = SafeProxyFactory(safeProxyFactory);
safeSingleton.code.length == 0 ? safeSingleton_ = new Safe() : safeSingleton_ = Safe(payable(safeSingleton));
save("SafeProxyFactory", address(safeProxyFactory_));
save("SafeSingleton", address(safeSingleton_));
}
/// @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 when the caller is also the signer.
bytes memory signature = abi.encodePacked(uint256(uint160(msg.sender)), bytes32(0), uint8(1));
_safe.execTransaction({
to: _target,
value: 0,
data: _data,
operation: SafeOps.Operation.Call,
safeTxGas: 0,
baseGas: 0,
gasPrice: 0,
gasToken: address(0),
refundReceiver: payable(address(0)),
signatures: signature
});
}
/// @notice Call from the Safe contract to the Proxy Admin's upgrade and call method
function _upgradeAndCallViaSafe(address _proxy, address _implementation, bytes memory _innerCallData) internal {
address proxyAdmin = mustGetAddress("ProxyAdmin");
bytes memory data =
abi.encodeCall(IProxyAdmin.upgradeAndCall, (payable(_proxy), _implementation, _innerCallData));
Safe safe = Safe(mustGetAddress("SystemOwnerSafe"));
_callViaSafe({ _safe: safe, _target: proxyAdmin, _data: data });
}
/// @notice Transfer ownership of the ProxyAdmin contract to the final system owner
function transferProxyAdminOwnership() public broadcast {
IProxyAdmin proxyAdmin = IProxyAdmin(mustGetAddress("ProxyAdmin"));
address owner = proxyAdmin.owner();
address safe = mustGetAddress("SystemOwnerSafe");
if (owner != safe) {
proxyAdmin.transferOwnership(safe);
console.log("ProxyAdmin ownership transferred to Safe at: %s", safe);
address finalSystemOwner = cfg.finalSystemOwner();
if (owner != finalSystemOwner) {
proxyAdmin.transferOwnership(finalSystemOwner);
console.log("ProxyAdmin ownership transferred to final system owner at: %s", finalSystemOwner);
}
}
......@@ -334,8 +275,6 @@ contract Deploy is Deployer {
/// @notice Internal function containing the deploy logic.
function _run(bool _needsSuperchain) internal {
console.log("start of L1 Deploy!");
deploySafe("SystemOwnerSafe");
console.log("deployed Safe!");
// Deploy a new ProxyAdmin and AddressManager
// This proxy will be used on the SuperchainConfig and ProtocolVersions contracts, as well as the contracts
......@@ -366,7 +305,6 @@ contract Deploy is Deployer {
function setupAdmin() public {
deployAddressManager();
deployProxyAdmin();
transferProxyAdminOwnership();
}
/// @notice Deploy a full system with a new SuperchainConfig
......@@ -393,7 +331,6 @@ contract Deploy is Deployer {
// Ensure that the requisite contracts are deployed
mustGetAddress("SuperchainConfigProxy");
mustGetAddress("SystemOwnerSafe");
mustGetAddress("AddressManager");
mustGetAddress("ProxyAdmin");
......@@ -409,6 +346,7 @@ contract Deploy is Deployer {
transferDisputeGameFactoryOwnership();
transferDelayedWETHOwnership();
transferProxyAdminOwnership();
}
/// @notice Deploy all of the OP Chain specific contracts
......@@ -491,70 +429,6 @@ contract Deploy is Deployer {
// Non-Proxied Deployment Functions //
////////////////////////////////////////////////////////////////
/// @notice Deploy the Safe
function deploySafe(string memory _name) public broadcast returns (address addr_) {
address[] memory owners = new address[](0);
addr_ = deploySafe(_name, owners, 1, true);
}
/// @notice Deploy a new Safe contract. If the keepDeployer option is used to enable further setup actions, then
/// the removeDeployerFromSafe() function should be called on that safe after setup is complete.
/// Note this function does not have the broadcast modifier.
/// @param _name The name of the Safe to deploy.
/// @param _owners The owners of the Safe.
/// @param _threshold The threshold of the Safe.
/// @param _keepDeployer Wether or not the deployer address will be added as an owner of the Safe.
function deploySafe(
string memory _name,
address[] memory _owners,
uint256 _threshold,
bool _keepDeployer
)
public
returns (address addr_)
{
bytes32 salt = keccak256(abi.encode(_name, _implSalt()));
console.log("Deploying safe: %s with salt %s", _name, vm.toString(salt));
(SafeProxyFactory safeProxyFactory, Safe safeSingleton) = _getSafeFactory();
if (_keepDeployer) {
address[] memory expandedOwners = new address[](_owners.length + 1);
// By always adding msg.sender first we know that the previousOwner will be SENTINEL_OWNERS, which makes it
// easier to call removeOwner later.
expandedOwners[0] = msg.sender;
for (uint256 i = 0; i < _owners.length; i++) {
expandedOwners[i + 1] = _owners[i];
}
_owners = expandedOwners;
}
bytes memory initData = abi.encodeCall(
Safe.setup, (_owners, _threshold, address(0), hex"", address(0), address(0), 0, payable(address(0)))
);
addr_ = address(safeProxyFactory.createProxyWithNonce(address(safeSingleton), initData, uint256(salt)));
save(_name, addr_);
console.log("New safe: %s deployed at %s\n Note that this safe is owned by the deployer key", _name, addr_);
}
/// @notice If the keepDeployer option was used with deploySafe(), this function can be used to remove the deployer.
/// Note this function does not have the broadcast modifier.
function removeDeployerFromSafe(string memory _name, uint256 _newThreshold) public {
Safe safe = Safe(mustGetAddress(_name));
// The sentinel address is used to mark the start and end of the linked list of owners in the Safe.
address sentinelOwners = address(0x1);
// Because deploySafe() always adds msg.sender first (if keepDeployer is true), we know that the previousOwner
// will be sentinelOwners.
_callViaSafe({
_safe: safe,
_target: address(safe),
_data: abi.encodeCall(OwnerManager.removeOwner, (sentinelOwners, msg.sender, _newThreshold))
});
console.log("Removed deployer owner from ", _name);
}
/// @notice Deploy the AddressManager
function deployAddressManager() public broadcast returns (address addr_) {
console.log("Deploying AddressManager");
......@@ -1025,7 +899,7 @@ contract Deploy is Deployer {
/// @notice Transfer ownership of the address manager to the ProxyAdmin
function transferAddressManagerOwnership() public broadcast {
console.log("Transferring AddressManager ownership to ProxyAdmin");
console.log("Transferring AddressManager ownership to IProxyAdmin");
IAddressManager addressManager = IAddressManager(mustGetAddress("AddressManager"));
address owner = addressManager.owner();
address proxyAdmin = mustGetAddress("ProxyAdmin");
......@@ -1058,10 +932,12 @@ contract Deploy is Deployer {
function initializeSuperchainConfig() public broadcast {
address payable superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
address payable superchainConfig = mustGetAddress("SuperchainConfig");
_upgradeAndCallViaSafe({
IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: superchainConfigProxy,
_implementation: superchainConfig,
_innerCallData: abi.encodeCall(ISuperchainConfig.initialize, (cfg.superchainConfigGuardian(), false))
_data: abi.encodeCall(ISuperchainConfig.initialize, (cfg.superchainConfigGuardian(), false))
});
ChainAssertions.checkSuperchainConfig({ _contracts: _proxiesUnstrict(), _cfg: cfg, _isPaused: false });
......@@ -1073,10 +949,11 @@ contract Deploy is Deployer {
address disputeGameFactoryProxy = mustGetAddress("DisputeGameFactoryProxy");
address disputeGameFactory = mustGetAddress("DisputeGameFactory");
_upgradeAndCallViaSafe({
IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(disputeGameFactoryProxy),
_implementation: disputeGameFactory,
_innerCallData: abi.encodeCall(IDisputeGameFactory.initialize, (msg.sender))
_data: abi.encodeCall(IDisputeGameFactory.initialize, (msg.sender))
});
string memory version = IDisputeGameFactory(disputeGameFactoryProxy).version();
......@@ -1091,10 +968,11 @@ contract Deploy is Deployer {
address delayedWETH = mustGetAddress("DelayedWETH");
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
_upgradeAndCallViaSafe({
IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(delayedWETHProxy),
_implementation: delayedWETH,
_innerCallData: abi.encodeCall(IDelayedWETH.initialize, (msg.sender, ISuperchainConfig(superchainConfigProxy)))
_data: abi.encodeCall(IDelayedWETH.initialize, (msg.sender, ISuperchainConfig(superchainConfigProxy)))
});
string memory version = IDelayedWETH(payable(delayedWETHProxy)).version();
......@@ -1114,10 +992,11 @@ contract Deploy is Deployer {
address delayedWETH = mustGetAddress("DelayedWETH");
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
_upgradeAndCallViaSafe({
IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(delayedWETHProxy),
_implementation: delayedWETH,
_innerCallData: abi.encodeCall(IDelayedWETH.initialize, (msg.sender, ISuperchainConfig(superchainConfigProxy)))
_data: abi.encodeCall(IDelayedWETH.initialize, (msg.sender, ISuperchainConfig(superchainConfigProxy)))
});
string memory version = IDelayedWETH(payable(delayedWETHProxy)).version();
......@@ -1174,10 +1053,11 @@ contract Deploy is Deployer {
})
});
_upgradeAndCallViaSafe({
IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(anchorStateRegistryProxy),
_implementation: anchorStateRegistry,
_innerCallData: abi.encodeCall(IAnchorStateRegistry.initialize, (roots, superchainConfig))
_data: abi.encodeCall(IAnchorStateRegistry.initialize, (roots, superchainConfig))
});
string memory version = IAnchorStateRegistry(payable(anchorStateRegistryProxy)).version();
......@@ -1197,10 +1077,11 @@ contract Deploy is Deployer {
customGasTokenAddress = cfg.customGasTokenAddress();
}
_upgradeAndCallViaSafe({
IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(systemConfigProxy),
_implementation: systemConfig,
_innerCallData: abi.encodeCall(
_data: abi.encodeCall(
ISystemConfig.initialize,
(
cfg.finalSystemOwner(),
......@@ -1242,20 +1123,15 @@ contract Deploy is Deployer {
address systemConfigProxy = mustGetAddress("SystemConfigProxy");
uint256 proxyType = uint256(proxyAdmin.proxyType(l1StandardBridgeProxy));
Safe safe = Safe(mustGetAddress("SystemOwnerSafe"));
if (proxyType != uint256(IProxyAdmin.ProxyType.CHUGSPLASH)) {
_callViaSafe({
_safe: safe,
_target: address(proxyAdmin),
_data: abi.encodeCall(IProxyAdmin.setProxyType, (l1StandardBridgeProxy, IProxyAdmin.ProxyType.CHUGSPLASH))
});
proxyAdmin.setProxyType(l1StandardBridgeProxy, IProxyAdmin.ProxyType.CHUGSPLASH);
}
require(uint256(proxyAdmin.proxyType(l1StandardBridgeProxy)) == uint256(IProxyAdmin.ProxyType.CHUGSPLASH));
_upgradeAndCallViaSafe({
proxyAdmin.upgradeAndCall({
_proxy: payable(l1StandardBridgeProxy),
_implementation: l1StandardBridge,
_innerCallData: abi.encodeCall(
_data: abi.encodeCall(
IL1StandardBridge.initialize,
(
ICrossDomainMessenger(l1CrossDomainMessengerProxy),
......@@ -1279,10 +1155,11 @@ contract Deploy is Deployer {
address l1CrossDomainMessengerProxy = mustGetAddress("L1CrossDomainMessengerProxy");
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
_upgradeAndCallViaSafe({
IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(l1ERC721BridgeProxy),
_implementation: l1ERC721Bridge,
_innerCallData: abi.encodeCall(
_data: abi.encodeCall(
IL1ERC721Bridge.initialize,
(ICrossDomainMessenger(payable(l1CrossDomainMessengerProxy)), ISuperchainConfig(superchainConfigProxy))
)
......@@ -1302,10 +1179,11 @@ contract Deploy is Deployer {
address optimismMintableERC20Factory = mustGetAddress("OptimismMintableERC20Factory");
address l1StandardBridgeProxy = mustGetAddress("L1StandardBridgeProxy");
_upgradeAndCallViaSafe({
IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(optimismMintableERC20FactoryProxy),
_implementation: optimismMintableERC20Factory,
_innerCallData: abi.encodeCall(IOptimismMintableERC20Factory.initialize, (l1StandardBridgeProxy))
_data: abi.encodeCall(IOptimismMintableERC20Factory.initialize, (l1StandardBridgeProxy))
});
IOptimismMintableERC20Factory factory = IOptimismMintableERC20Factory(optimismMintableERC20FactoryProxy);
......@@ -1326,36 +1204,25 @@ contract Deploy is Deployer {
address systemConfigProxy = mustGetAddress("SystemConfigProxy");
uint256 proxyType = uint256(proxyAdmin.proxyType(l1CrossDomainMessengerProxy));
Safe safe = Safe(mustGetAddress("SystemOwnerSafe"));
if (proxyType != uint256(IProxyAdmin.ProxyType.RESOLVED)) {
_callViaSafe({
_safe: safe,
_target: address(proxyAdmin),
_data: abi.encodeCall(
IProxyAdmin.setProxyType, (l1CrossDomainMessengerProxy, IProxyAdmin.ProxyType.RESOLVED)
)
});
proxyAdmin.setProxyType(l1CrossDomainMessengerProxy, IProxyAdmin.ProxyType.RESOLVED);
}
require(uint256(proxyAdmin.proxyType(l1CrossDomainMessengerProxy)) == uint256(IProxyAdmin.ProxyType.RESOLVED));
string memory contractName = "OVM_L1CrossDomainMessenger";
string memory implName = proxyAdmin.implementationName(l1CrossDomainMessenger);
if (keccak256(bytes(contractName)) != keccak256(bytes(implName))) {
_callViaSafe({
_safe: safe,
_target: address(proxyAdmin),
_data: abi.encodeCall(IProxyAdmin.setImplementationName, (l1CrossDomainMessengerProxy, contractName))
});
proxyAdmin.setImplementationName(l1CrossDomainMessengerProxy, contractName);
}
require(
keccak256(bytes(proxyAdmin.implementationName(l1CrossDomainMessengerProxy)))
== keccak256(bytes(contractName))
);
_upgradeAndCallViaSafe({
proxyAdmin.upgradeAndCall({
_proxy: payable(l1CrossDomainMessengerProxy),
_implementation: l1CrossDomainMessenger,
_innerCallData: abi.encodeCall(
_data: abi.encodeCall(
IL1CrossDomainMessenger.initialize,
(
ISuperchainConfig(superchainConfigProxy),
......@@ -1378,10 +1245,11 @@ contract Deploy is Deployer {
address l2OutputOracleProxy = mustGetAddress("L2OutputOracleProxy");
address l2OutputOracle = mustGetAddress("L2OutputOracle");
_upgradeAndCallViaSafe({
IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(l2OutputOracleProxy),
_implementation: l2OutputOracle,
_innerCallData: abi.encodeCall(
_data: abi.encodeCall(
IL2OutputOracle.initialize,
(
cfg.l2OutputOracleSubmissionInterval(),
......@@ -1416,10 +1284,11 @@ contract Deploy is Deployer {
address systemConfigProxy = mustGetAddress("SystemConfigProxy");
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
_upgradeAndCallViaSafe({
IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(optimismPortalProxy),
_implementation: optimismPortal,
_innerCallData: abi.encodeCall(
_data: abi.encodeCall(
IOptimismPortal.initialize,
(
IL2OutputOracle(l2OutputOracleProxy),
......@@ -1445,10 +1314,11 @@ contract Deploy is Deployer {
address systemConfigProxy = mustGetAddress("SystemConfigProxy");
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
_upgradeAndCallViaSafe({
IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(optimismPortalProxy),
_implementation: optimismPortal2,
_innerCallData: abi.encodeCall(
_data: abi.encodeCall(
IOptimismPortal2.initialize,
(
IDisputeGameFactory(disputeGameFactoryProxy),
......@@ -1475,10 +1345,11 @@ contract Deploy is Deployer {
uint256 requiredProtocolVersion = cfg.requiredProtocolVersion();
uint256 recommendedProtocolVersion = cfg.recommendedProtocolVersion();
_upgradeAndCallViaSafe({
IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(protocolVersionsProxy),
_implementation: protocolVersions,
_innerCallData: abi.encodeCall(
_data: abi.encodeCall(
IProtocolVersions.initialize,
(
finalSystemOwner,
......@@ -1500,13 +1371,13 @@ contract Deploy is Deployer {
console.log("Transferring DisputeGameFactory ownership to Safe");
IDisputeGameFactory disputeGameFactory = IDisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"));
address owner = disputeGameFactory.owner();
address finalSystemOwner = cfg.finalSystemOwner();
address safe = mustGetAddress("SystemOwnerSafe");
if (owner != safe) {
disputeGameFactory.transferOwnership(safe);
console.log("DisputeGameFactory ownership transferred to Safe at: %s", safe);
if (owner != finalSystemOwner) {
disputeGameFactory.transferOwnership(finalSystemOwner);
console.log("DisputeGameFactory ownership transferred to final system owner at: %s", finalSystemOwner);
}
ChainAssertions.checkDisputeGameFactory({ _contracts: _proxies(), _expectedOwner: safe });
ChainAssertions.checkDisputeGameFactory({ _contracts: _proxies(), _expectedOwner: finalSystemOwner });
}
/// @notice Transfer ownership of the DelayedWETH contract to the final system owner
......@@ -1515,12 +1386,17 @@ contract Deploy is Deployer {
IDelayedWETH weth = IDelayedWETH(mustGetAddress("DelayedWETHProxy"));
address owner = weth.owner();
address safe = mustGetAddress("SystemOwnerSafe");
if (owner != safe) {
weth.transferOwnership(safe);
console.log("DelayedWETH ownership transferred to Safe at: %s", safe);
address finalSystemOwner = cfg.finalSystemOwner();
if (owner != finalSystemOwner) {
weth.transferOwnership(finalSystemOwner);
console.log("DelayedWETH ownership transferred to final system owner at: %s", finalSystemOwner);
}
ChainAssertions.checkDelayedWETH({ _contracts: _proxies(), _cfg: cfg, _isProxy: true, _expectedOwner: safe });
ChainAssertions.checkDelayedWETH({
_contracts: _proxies(),
_cfg: cfg,
_isProxy: true,
_expectedOwner: finalSystemOwner
});
}
/// @notice Transfer ownership of the permissioned DelayedWETH contract to the final system owner
......@@ -1529,16 +1405,16 @@ contract Deploy is Deployer {
IDelayedWETH weth = IDelayedWETH(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);
address finalSystemOwner = cfg.finalSystemOwner();
if (owner != finalSystemOwner) {
weth.transferOwnership(finalSystemOwner);
console.log("DelayedWETH ownership transferred to final system owner at: %s", finalSystemOwner);
}
ChainAssertions.checkPermissionedDelayedWETH({
_contracts: _proxies(),
_cfg: cfg,
_isProxy: true,
_expectedOwner: safe
_expectedOwner: finalSystemOwner
});
}
......@@ -1812,10 +1688,11 @@ contract Deploy is Deployer {
uint256 daBondSize = cfg.daBondSize();
uint256 daResolverRefundPercentage = cfg.daResolverRefundPercentage();
_upgradeAndCallViaSafe({
IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(dataAvailabilityChallengeProxy),
_implementation: dataAvailabilityChallenge,
_innerCallData: abi.encodeCall(
_data: abi.encodeCall(
IDataAvailabilityChallenge.initialize,
(finalSystemOwner, daChallengeWindow, daResolveWindow, daBondSize, daResolverRefundPercentage)
)
......
......@@ -5,9 +5,11 @@ import { console2 as console } from "forge-std/console2.sol";
import { stdJson } from "forge-std/StdJson.sol";
import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol";
import { GnosisSafeProxyFactory as SafeProxyFactory } from "safe-contracts/proxies/GnosisSafeProxyFactory.sol";
import { OwnerManager } from "safe-contracts/base/OwnerManager.sol";
import { ModuleManager } from "safe-contracts/base/ModuleManager.sol";
import { GuardManager } from "safe-contracts/base/GuardManager.sol";
import { Enum as SafeOps } from "safe-contracts/common/Enum.sol";
import { Deployer } from "scripts/deploy/Deployer.sol";
......@@ -17,8 +19,8 @@ import { DeputyGuardianModule } from "src/safe/DeputyGuardianModule.sol";
import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol";
import { Deploy } from "./Deploy.s.sol";
/// @notice Configuration for a Safe
struct SafeConfig {
uint256 threshold;
address[] owners;
......@@ -50,7 +52,7 @@ struct GuardianConfig {
DeputyGuardianModuleConfig deputyGuardianModuleConfig;
}
/// @title Deploy
/// @title DeployOwnership
/// @notice Script used to deploy and configure the Safe contracts which are used to manage the Superchain,
/// as the ProxyAdminOwner and other roles in the system. Note that this script is not executable in a
/// production environment as some steps depend on having a quorum of signers available. This script is meant to
......@@ -112,6 +114,113 @@ contract DeployOwnership is Deploy {
});
}
/// @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 when the caller is also the signer.
bytes memory signature = abi.encodePacked(uint256(uint160(msg.sender)), bytes32(0), uint8(1));
_safe.execTransaction({
to: _target,
value: 0,
data: _data,
operation: SafeOps.Operation.Call,
safeTxGas: 0,
baseGas: 0,
gasPrice: 0,
gasToken: address(0),
refundReceiver: payable(address(0)),
signatures: signature
});
}
/// @notice Deploy the Safe
function deploySafe(string memory _name) public broadcast returns (address addr_) {
address[] memory owners = new address[](0);
addr_ = deploySafe(_name, owners, 1, true);
}
/// @notice Deploy a new Safe contract. If the keepDeployer option is used to enable further setup actions, then
/// the removeDeployerFromSafe() function should be called on that safe after setup is complete.
/// Note this function does not have the broadcast modifier.
/// @param _name The name of the Safe to deploy.
/// @param _owners The owners of the Safe.
/// @param _threshold The threshold of the Safe.
/// @param _keepDeployer Wether or not the deployer address will be added as an owner of the Safe.
function deploySafe(
string memory _name,
address[] memory _owners,
uint256 _threshold,
bool _keepDeployer
)
public
returns (address addr_)
{
bytes32 salt = keccak256(abi.encode(_name, _implSalt()));
console.log("Deploying safe: %s with salt %s", _name, vm.toString(salt));
(SafeProxyFactory safeProxyFactory, Safe safeSingleton) = _getSafeFactory();
if (_keepDeployer) {
address[] memory expandedOwners = new address[](_owners.length + 1);
// By always adding msg.sender first we know that the previousOwner will be SENTINEL_OWNERS, which makes it
// easier to call removeOwner later.
expandedOwners[0] = msg.sender;
for (uint256 i = 0; i < _owners.length; i++) {
expandedOwners[i + 1] = _owners[i];
}
_owners = expandedOwners;
}
bytes memory initData = abi.encodeCall(
Safe.setup, (_owners, _threshold, address(0), hex"", address(0), address(0), 0, payable(address(0)))
);
addr_ = address(safeProxyFactory.createProxyWithNonce(address(safeSingleton), initData, uint256(salt)));
save(_name, addr_);
console.log("New safe: %s deployed at %s\n Note that this safe is owned by the deployer key", _name, addr_);
}
/// @notice If the keepDeployer option was used with deploySafe(), this function can be used to remove the deployer.
/// Note this function does not have the broadcast modifier.
function removeDeployerFromSafe(string memory _name, uint256 _newThreshold) public {
Safe safe = Safe(mustGetAddress(_name));
// The sentinel address is used to mark the start and end of the linked list of owners in the Safe.
address sentinelOwners = address(0x1);
// Because deploySafe() always adds msg.sender first (if keepDeployer is true), we know that the previousOwner
// will be sentinelOwners.
_callViaSafe({
_safe: safe,
_target: address(safe),
_data: abi.encodeCall(OwnerManager.removeOwner, (sentinelOwners, msg.sender, _newThreshold))
});
console.log("Removed deployer owner from ", _name);
}
/// @notice Gets the address of the SafeProxyFactory and Safe singleton for use in deploying a new GnosisSafe.
function _getSafeFactory() internal returns (SafeProxyFactory safeProxyFactory_, Safe safeSingleton_) {
if (getAddress("SafeProxyFactory") != address(0)) {
// The SafeProxyFactory is already saved, we can just use it.
safeProxyFactory_ = SafeProxyFactory(getAddress("SafeProxyFactory"));
safeSingleton_ = Safe(getAddress("SafeSingleton"));
return (safeProxyFactory_, safeSingleton_);
}
// These are the standard create2 deployed contracts. First we'll check if they are deployed,
// if not we'll deploy new ones, though not at these addresses.
address safeProxyFactory = 0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2;
address safeSingleton = 0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552;
safeProxyFactory.code.length == 0
? safeProxyFactory_ = new SafeProxyFactory()
: safeProxyFactory_ = SafeProxyFactory(safeProxyFactory);
safeSingleton.code.length == 0 ? safeSingleton_ = new Safe() : safeSingleton_ = Safe(payable(safeSingleton));
save("SafeProxyFactory", address(safeProxyFactory_));
save("SafeSingleton", address(safeSingleton_));
}
/// @notice Deploys a Safe with a configuration similar to that of the Foundation Safe on Mainnet.
function deployFoundationOperationsSafe() public broadcast returns (address addr_) {
SafeConfig memory exampleFoundationConfig = _getExampleFoundationConfig();
......
......@@ -22,11 +22,11 @@ contract FPACOPS is Deploy, StdAssertions {
// ENTRYPOINTS //
////////////////////////////////////////////////////////////////
function deployFPAC(address _proxyAdmin, address _systemOwnerSafe, address _superchainConfigProxy) public {
function deployFPAC(address _proxyAdmin, address _finalSystemOwner, address _superchainConfigProxy) public {
console.log("Deploying a fresh FPAC system and OptimismPortal2 implementation.");
prankDeployment("ProxyAdmin", msg.sender);
prankDeployment("SystemOwnerSafe", msg.sender);
prankDeployment("FinalSystemOwner", msg.sender);
prankDeployment("SuperchainConfigProxy", _superchainConfigProxy);
// Deploy the proxies.
......@@ -54,14 +54,14 @@ contract FPACOPS is Deploy, StdAssertions {
// Deploy the Permissioned Cannon Fault game implementation and set it as game ID = 1.
setPermissionedCannonFaultGameImplementation({ _allowUpgrade: false });
// Transfer ownership of the DisputeGameFactory to the SystemOwnerSafe, and transfer the administrative rights
// Transfer ownership of the DisputeGameFactory to the FinalSystemOwner, and transfer the administrative rights
// of the DisputeGameFactoryProxy to the ProxyAdmin.
transferDGFOwnershipFinal({ _proxyAdmin: _proxyAdmin, _systemOwnerSafe: _systemOwnerSafe });
transferWethOwnershipFinal({ _proxyAdmin: _proxyAdmin, _systemOwnerSafe: _systemOwnerSafe });
transferDGFOwnershipFinal({ _proxyAdmin: _proxyAdmin, _finalSystemOwner: _finalSystemOwner });
transferWethOwnershipFinal({ _proxyAdmin: _proxyAdmin, _finalSystemOwner: _finalSystemOwner });
transferAnchorStateOwnershipFinal({ _proxyAdmin: _proxyAdmin });
// Run post-deployment assertions.
postDeployAssertions({ _proxyAdmin: _proxyAdmin, _systemOwnerSafe: _systemOwnerSafe });
postDeployAssertions({ _proxyAdmin: _proxyAdmin, _finalSystemOwner: _finalSystemOwner });
// Print overview
printConfigReview();
......@@ -126,12 +126,12 @@ contract FPACOPS is Deploy, StdAssertions {
}
/// @notice Transfers admin rights of the `DisputeGameFactoryProxy` to the `ProxyAdmin` and sets the
/// `DisputeGameFactory` owner to the `SystemOwnerSafe`.
function transferDGFOwnershipFinal(address _proxyAdmin, address _systemOwnerSafe) internal broadcast {
/// `DisputeGameFactory` owner to the `FinalSystemOwner`.
function transferDGFOwnershipFinal(address _proxyAdmin, address _finalSystemOwner) internal broadcast {
IDisputeGameFactory dgf = IDisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"));
// Transfer the ownership of the DisputeGameFactory to the SystemOwnerSafe.
dgf.transferOwnership(_systemOwnerSafe);
// Transfer the ownership of the DisputeGameFactory to the FinalSystemOwner.
dgf.transferOwnership(_finalSystemOwner);
// Transfer the admin rights of the DisputeGameFactoryProxy to the ProxyAdmin.
IProxy prox = IProxy(payable(address(dgf)));
......@@ -139,12 +139,12 @@ contract FPACOPS is Deploy, StdAssertions {
}
/// @notice Transfers admin rights of the `DelayedWETHProxy` to the `ProxyAdmin` and sets the
/// `DelayedWETH` owner to the `SystemOwnerSafe`.
function transferWethOwnershipFinal(address _proxyAdmin, address _systemOwnerSafe) internal broadcast {
/// `DelayedWETH` owner to the `FinalSystemOwner`.
function transferWethOwnershipFinal(address _proxyAdmin, address _finalSystemOwner) internal broadcast {
IDelayedWETH weth = IDelayedWETH(mustGetAddress("DelayedWETHProxy"));
// Transfer the ownership of the DelayedWETH to the SystemOwnerSafe.
weth.transferOwnership(_systemOwnerSafe);
// Transfer the ownership of the DelayedWETH to the FinalSystemOwner.
weth.transferOwnership(_finalSystemOwner);
// Transfer the admin rights of the DelayedWETHProxy to the ProxyAdmin.
IProxy prox = IProxy(payable(address(weth)));
......@@ -161,7 +161,7 @@ contract FPACOPS is Deploy, StdAssertions {
}
/// @notice Checks that the deployed system is configured correctly.
function postDeployAssertions(address _proxyAdmin, address _systemOwnerSafe) internal view {
function postDeployAssertions(address _proxyAdmin, address _finalSystemOwner) internal view {
Types.ContractSet memory contracts = _proxiesUnstrict();
contracts.OptimismPortal2 = mustGetAddress("OptimismPortal2");
......@@ -172,10 +172,10 @@ contract FPACOPS is Deploy, StdAssertions {
address dgfProxyAddr = mustGetAddress("DisputeGameFactoryProxy");
IDisputeGameFactory dgfProxy = IDisputeGameFactory(dgfProxyAddr);
assertEq(address(uint160(uint256(vm.load(dgfProxyAddr, Constants.PROXY_OWNER_ADDRESS)))), _proxyAdmin);
ChainAssertions.checkDisputeGameFactory(contracts, _systemOwnerSafe);
ChainAssertions.checkDisputeGameFactory(contracts, _finalSystemOwner);
address wethProxyAddr = mustGetAddress("DelayedWETHProxy");
assertEq(address(uint160(uint256(vm.load(wethProxyAddr, Constants.PROXY_OWNER_ADDRESS)))), _proxyAdmin);
ChainAssertions.checkDelayedWETH(contracts, cfg, true, _systemOwnerSafe);
ChainAssertions.checkDelayedWETH(contracts, cfg, true, _finalSystemOwner);
// Check the config elements in the deployed contracts.
ChainAssertions.checkOptimismPortal2(contracts, cfg, false);
......
......@@ -30,13 +30,13 @@ contract FPACOPS2 is Deploy, StdAssertions {
/// AnchorStateRegistry. Does not deploy a new DisputeGameFactory. System
/// Owner is responsible for updating implementations later.
/// @param _proxyAdmin Address of the ProxyAdmin contract to transfer ownership to.
/// @param _systemOwnerSafe Address of the SystemOwner.
/// @param _finalSystemOwner Address of the SystemOwner.
/// @param _superchainConfigProxy Address of the SuperchainConfig proxy contract.
/// @param _disputeGameFactoryProxy Address of the DisputeGameFactory proxy contract.
/// @param _anchorStateRegistryProxy Address of the AnchorStateRegistry proxy contract.
function deployFPAC2(
address _proxyAdmin,
address _systemOwnerSafe,
address _finalSystemOwner,
address _superchainConfigProxy,
address _disputeGameFactoryProxy,
address _anchorStateRegistryProxy
......@@ -47,7 +47,7 @@ contract FPACOPS2 is Deploy, StdAssertions {
// Prank required deployments.
prankDeployment("ProxyAdmin", msg.sender);
prankDeployment("SystemOwnerSafe", msg.sender);
prankDeployment("FinalSystemOwner", msg.sender);
prankDeployment("SuperchainConfigProxy", _superchainConfigProxy);
prankDeployment("DisputeGameFactoryProxy", _disputeGameFactoryProxy);
prankDeployment("AnchorStateRegistryProxy", _anchorStateRegistryProxy);
......@@ -71,11 +71,11 @@ contract FPACOPS2 is Deploy, StdAssertions {
deployPermissionedDisputeGame();
// Transfer ownership of DelayedWETH to ProxyAdmin.
transferWethOwnershipFinal({ _proxyAdmin: _proxyAdmin, _systemOwnerSafe: _systemOwnerSafe });
transferPermissionedWETHOwnershipFinal({ _proxyAdmin: _proxyAdmin, _systemOwnerSafe: _systemOwnerSafe });
transferWethOwnershipFinal({ _proxyAdmin: _proxyAdmin, _finalSystemOwner: _finalSystemOwner });
transferPermissionedWETHOwnershipFinal({ _proxyAdmin: _proxyAdmin, _finalSystemOwner: _finalSystemOwner });
// Run post-deployment assertions.
postDeployAssertions({ _proxyAdmin: _proxyAdmin, _systemOwnerSafe: _systemOwnerSafe });
postDeployAssertions({ _proxyAdmin: _proxyAdmin, _finalSystemOwner: _finalSystemOwner });
// Print overview.
printConfigReview();
......@@ -169,14 +169,14 @@ contract FPACOPS2 is Deploy, StdAssertions {
}
/// @notice Transfers admin rights of the `DelayedWETHProxy` to the `ProxyAdmin` and sets the
/// `DelayedWETH` owner to the `SystemOwnerSafe`.
function transferWethOwnershipFinal(address _proxyAdmin, address _systemOwnerSafe) internal broadcast {
/// `DelayedWETH` owner to the `FinalSystemOwner`.
function transferWethOwnershipFinal(address _proxyAdmin, address _finalSystemOwner) internal broadcast {
console.log("Transferring ownership of DelayedWETHProxy");
IDelayedWETH weth = IDelayedWETH(mustGetAddress("DelayedWETHProxy"));
// Transfer the ownership of the DelayedWETH to the SystemOwnerSafe.
weth.transferOwnership(_systemOwnerSafe);
// Transfer the ownership of the DelayedWETH to the FinalSystemOwner.
weth.transferOwnership(_finalSystemOwner);
// Transfer the admin rights of the DelayedWETHProxy to the ProxyAdmin.
IProxy prox = IProxy(payable(address(weth)));
......@@ -184,14 +184,20 @@ contract FPACOPS2 is Deploy, StdAssertions {
}
/// @notice Transfers admin rights of the permissioned `DelayedWETHProxy` to the `ProxyAdmin`
/// and sets the `DelayedWETH` owner to the `SystemOwnerSafe`.
function transferPermissionedWETHOwnershipFinal(address _proxyAdmin, address _systemOwnerSafe) internal broadcast {
/// and sets the `DelayedWETH` owner to the `FinalSystemOwner`.
function transferPermissionedWETHOwnershipFinal(
address _proxyAdmin,
address _finalSystemOwner
)
internal
broadcast
{
console.log("Transferring ownership of permissioned DelayedWETHProxy");
IDelayedWETH weth = IDelayedWETH(mustGetAddress("PermissionedDelayedWETHProxy"));
// Transfer the ownership of the DelayedWETH to the SystemOwnerSafe.
weth.transferOwnership(_systemOwnerSafe);
// Transfer the ownership of the DelayedWETH to the FinalSystemOwner.
weth.transferOwnership(_finalSystemOwner);
// Transfer the admin rights of the DelayedWETHProxy to the ProxyAdmin.
IProxy prox = IProxy(payable(address(weth)));
......@@ -199,7 +205,7 @@ contract FPACOPS2 is Deploy, StdAssertions {
}
/// @notice Checks that the deployed system is configured correctly.
function postDeployAssertions(address _proxyAdmin, address _systemOwnerSafe) internal view {
function postDeployAssertions(address _proxyAdmin, address _finalSystemOwner) internal view {
Types.ContractSet memory contracts = _proxiesUnstrict();
// Ensure that `useFaultProofs` is set to `true`.
......@@ -218,9 +224,9 @@ contract FPACOPS2 is Deploy, StdAssertions {
assertEq(address(uint160(uint256(vm.load(soyWethProxyAddr, Constants.PROXY_OWNER_ADDRESS)))), _proxyAdmin);
// Run standard assertions for DGF and DelayedWETH.
ChainAssertions.checkDisputeGameFactory(contracts, _systemOwnerSafe);
ChainAssertions.checkDelayedWETH(contracts, cfg, true, _systemOwnerSafe);
ChainAssertions.checkPermissionedDelayedWETH(contracts, cfg, true, _systemOwnerSafe);
ChainAssertions.checkDisputeGameFactory(contracts, _finalSystemOwner);
ChainAssertions.checkDelayedWETH(contracts, cfg, true, _finalSystemOwner);
ChainAssertions.checkPermissionedDelayedWETH(contracts, cfg, true, _finalSystemOwner);
// Verify PreimageOracle configuration.
IPreimageOracle oracle = IPreimageOracle(mustGetAddress("PreimageOracle"));
......
......@@ -23,9 +23,9 @@ cannon-prestate: # Generate the cannon prestate, and tar the `op-program` + `can
.PHONY: deploy-fresh
deploy-fresh: cannon-prestate # Deploy a fresh version of the FPAC contracts. Pass `--broadcast` to send to the network.
forge script FPACOPS.s.sol --sig "deployFPAC(address,address,address)" $(proxy-admin) $(system-owner-safe) $(superchain-config-proxy) --chain $(chain) -vvv $(args)
forge script FPACOPS.s.sol --sig "deployFPAC(address,address,address)" $(proxy-admin) $(final-system-owner) $(superchain-config-proxy) --chain $(chain) -vvv $(args)
# TODO: Convert this whole file to a justfile
.PHONY: deploy-upgrade
deploy-upgrade: cannon-prestate # Deploy upgraded FP contracts. Pass `--broadcast` to send to the network.
forge script FPACOPS2.s.sol --sig "deployFPAC2(address,address,address,address,address)" $(proxy-admin) $(system-owner-safe) $(superchain-config-proxy) $(dispute-game-factory-proxy) $(anchor-state-registry-proxy) --chain $(chain) -vvv $(args)
forge script FPACOPS2.s.sol --sig "deployFPAC2(address,address,address,address,address)" $(proxy-admin) $(final-system-owner) $(superchain-config-proxy) $(dispute-game-factory-proxy) $(anchor-state-registry-proxy) --chain $(chain) -vvv $(args)
......@@ -17,5 +17,5 @@ make cannon-prestate chain=<chain-name>
_Description_: Deploys a fully fresh FPAC system to the passed chain. All args after the `args=` are forwarded to `forge script`.
```sh
make deploy-fresh chain=<chain-name> proxy-admin=<chain-proxy-admin-addr> system-owner-safe=<chain-safe-addr> [args=<forge-script-args>]
make deploy-fresh chain=<chain-name> proxy-admin=<chain-proxy-admin-addr> final-system-owner=<chain-safe-addr> [args=<forge-script-args>]
```
......@@ -22,7 +22,7 @@ contract DelayedWETH_Init is CommonTest {
super.setUp();
// Transfer ownership of delayed WETH to the test contract.
vm.prank(deploy.mustGetAddress("SystemOwnerSafe"));
vm.prank(delayedWeth.owner());
delayedWeth.transferOwnership(address(this));
}
}
......
......@@ -29,7 +29,7 @@ contract DisputeGameFactory_Init is CommonTest {
fakeClone = new FakeClone();
// Transfer ownership of the factory to the test contract.
vm.prank(deploy.mustGetAddress("SystemOwnerSafe"));
vm.prank(disputeGameFactory.owner());
disputeGameFactory.transferOwnership(address(this));
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment