We have prepared a set of scripts to deploy all contracts in one click. Otherwise, you can look into and customize each contract as you like.
we reference to OPStack 's version of v1.9.4
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"OptimismPortalProxy": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>"
}
Without this artifact file, the next deployment scripts can not be run.
Note: This script is not completed yet. It is for one layer only. Check our final script for full deployment.
forge script script/000_DeployAllScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DeploySafeProxyScript} from "@script/101_DeploySafeProxyScript.s.sol";
import {Script} from "@redprint-forge-std/Script.sol";
import {SetupOpAltDAScript} from "@script/300_SetupOpAltDAScript.s.sol";
import {SetupOpchainScript} from "@script/400_SetupOpchain.s.sol";
import {SetupSuperchainScript} from "@script/200_SetupSuperchain.s.sol";
contract DeployAllScript is Script {
function run() public {
DeploySafeProxyScript safeDeployments = new DeploySafeProxyScript();
//1) set up Safe Multisig
safeDeployments.deploy();
SetupSuperchainScript superchainSetups = new SetupSuperchainScript();
superchainSetups.run();
SetupOpAltDAScript opAltDASetups = new SetupOpAltDAScript();
opAltDASetups.run();
SetupOpchainScript opchainSetups = new SetupOpchainScript();
opchainSetups.run();
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {AddressManager} from "@redprint-core/legacy/AddressManager.sol";
import {DeployAnchorStateRegistryProxyScript} from "@script/401K_DeployAnchorStateRegistryProxyScript.s.sol";
import {DeployDelayedWETHProxyScript} from "@script/401I_DeployDelayedWETHProxyScript.s.sol";
import {DeployDisputeGameFactoryProxyScript} from "@script/401G_DeployDisputeGameFactoryProxyScript.s.sol";
import {DeployL1CrossDomainMessengerProxyScript} from "@script/401D_DeployL1CrossDomainMessengerProxyScript.s.sol";
import {DeployL1ERC721BridgeProxyScript} from "@script/401F_DeployL1ERC721BridgeProxyScript.s.sol";
import {DeployL1StandardBridgeProxyScript} from "@script/401C_DeployL1StandardBridgeProxyScript.s.sol";
import {DeployL2OutputOracleProxyScript} from "@script/401H_DeployL2OutputOracleProxyScript.s.sol";
import {DeployOptimismMintableERC20FactoryProxyScript} from "@script/401E_DeployOptimismMintableERC20FactoryProxyScript.s.sol";
import {DeployOptimismPortalProxyScript} from "@script/401A_DeployOptimismPortalProxyScript.s.sol";
import {DeployPermissionedDelayedWETHProxyScript} from "@script/401J_DeployPermissionedDelayedWETHProxyScript.s.sol";
import {DeploySystemConfigProxyScript} from "@script/401B_DeploySystemConfigProxyScript.s.sol";
import {IDeployer, getDeployer} from "@redprint-deploy/deployer/DeployScript.sol";
import {Script} from "@redprint-forge-std/Script.sol";
import {TransferAddressManagerOwnershipScript} from "@script/401L_TransferAddressManagerOwnershipScript.s.sol";
import {Vm, VmSafe} from "@redprint-forge-std/Vm.sol";
import {console} from "@redprint-forge-std/console.sol";
contract SetupOpchainScript is Script {
IDeployer deployerProcedue;
function run() public {
deployerProcedue = getDeployer();
deployerProcedue.setAutoSave(true);
DeployOptimismPortalProxyScript optimismPortalProxyDeployments = new DeployOptimismPortalProxyScript();
DeploySystemConfigProxyScript systemConfigProxyDeployments = new DeploySystemConfigProxyScript();
DeployL1StandardBridgeProxyScript l1StandardBridgeProxyDeployments = new DeployL1StandardBridgeProxyScript();
DeployL1CrossDomainMessengerProxyScript l1CrossDomainMessengerProxyDeployments = new DeployL1CrossDomainMessengerProxyScript();
DeployOptimismMintableERC20FactoryProxyScript optimismMintableERC20FactoryProxyDeployments = new DeployOptimismMintableERC20FactoryProxyScript();
DeployL1ERC721BridgeProxyScript l1ERC721BridgeProxyDeployments = new DeployL1ERC721BridgeProxyScript();
DeployDisputeGameFactoryProxyScript disputeGameFactoryProxyDeployments = new DeployDisputeGameFactoryProxyScript();
DeployL2OutputOracleProxyScript l2OutputOracleProxyDeployments = new DeployL2OutputOracleProxyScript();
DeployDelayedWETHProxyScript delayedWETHProxyDeployments = new DeployDelayedWETHProxyScript();
DeployPermissionedDelayedWETHProxyScript permissionedDelayedWETHProxyDeployments = new DeployPermissionedDelayedWETHProxyScript();
DeployAnchorStateRegistryProxyScript anchorStateRegistryProxyDeployments = new DeployAnchorStateRegistryProxyScript();
TransferAddressManagerOwnershipScript transferAddressManagerOwnership = new TransferAddressManagerOwnershipScript();
optimismPortalProxyDeployments.deploy();
systemConfigProxyDeployments.deploy();
l1StandardBridgeProxyDeployments.deploy();
l1CrossDomainMessengerProxyDeployments.deploy();
optimismMintableERC20FactoryProxyDeployments.deploy();
l1ERC721BridgeProxyDeployments.deploy();
disputeGameFactoryProxyDeployments.deploy();
l2OutputOracleProxyDeployments.deploy();
delayedWETHProxyDeployments.deploy();
permissionedDelayedWETHProxyDeployments.deploy();
anchorStateRegistryProxyDeployments.deploy();
transferAddressManagerOwnership.run();
console.log("Setup Opchain ... ");
console.log("OptimismPortalProxy at: ", deployerProcedue.getAddress("OptimismPortalProxy"));
console.log("SystemConfigProxy at: ", deployerProcedue.getAddress("SystemConfigProxy"));
console.log("L1CrossDomainMessengerProxy at: ", deployerProcedue.getAddress("L1CrossDomainMessengerProxy"));
console.log("L1ERC721BridgeProxy at: ", deployerProcedue.getAddress("L1ERC721BridgeProxy"));
console.log("DisputeGameFactoryProxy at: ", deployerProcedue.getAddress("DisputeGameFactoryProxy"));
console.log("L2OutputOracleProxy at: ", deployerProcedue.getAddress("L2OutputOracleProxy"));
console.log("DelayedWETHProxy at: ", deployerProcedue.getAddress("DelayedWETHProxy"));
console.log("PermissionedDelayedWETHProxy at: ", deployerProcedue.getAddress("PermissionedDelayedWETHProxy"));
console.log("AnchorStateRegistryProxy at: ", deployerProcedue.getAddress("AnchorStateRegistryProxy"));
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"OptimismPortalProxy": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional
"DataAvailabilityChallenge": "<ADDRESS_11>", // optional
"OptimismPortalProxy": "<ADDRESS_12>",
"SystemConfigProxy": "<ADDRESS_13>",
"L1StandardBridgeProxy": "<ADDRESS_14>",
"L1CrossDomainMessengerProxy": "<ADDRESS_15>",
"OptimismMintableERC20FactoryProxy": "<ADDRESS_16>",
"L1ERC721BridgeProxy": "<ADDRESS_17>",
"DisputeGameFactoryProxy": "<ADDRESS_18>",
"L2OutputOracleProxy": "<ADDRESS_19>",
"DelayedWETHProxy": "<ADDRESS_20>",
"PermissionedDelayedWETHProxy": "<ADDRESS_21>",
"AnchorStateRegistryProxy": "<ADDRESS_22>"
}
click on ✕ button to close
4.1 : Deploy Proxies Contracts
4.1A : Deploy OptimismPortalProxy Contract
forge script script/401A_DeployOptimismPortalProxyScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Constants} from "@redprint-core/libraries/Constants.sol";
/// @custom:security-contact Consult full code at https://github.com/ethereum-optimism/optimism/blob/1.9.4/packages/contracts-bedrock/src/universal/Proxy.sol
contract Proxy {
/**
* @notice An event that is emitted each time the implementation is changed. This event is part
* of the EIP-1967 specification.
*
* @param implementation The address of the implementation contract
*/
event Upgraded(address indexed implementation);
/**
* @notice An event that is emitted each time the owner is upgraded. This event is part of the
* EIP-1967 specification.
*
* @param previousAdmin The previous owner of the contract
* @param newAdmin The new owner of the contract
*/
event AdminChanged(address previousAdmin, address newAdmin);
modifier proxyCallIfNotAdmin() {
if (msg.sender == _getAdmin() || msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_doProxyCall();
}
}
constructor(address _admin) {
_changeAdmin(_admin);
}
receive() external payable {
// Proxy call by default.
_doProxyCall();
}
fallback() external payable {
// Proxy call by default.
_doProxyCall();
}
function upgradeTo(address _implementation)
public
virtual
returns (proxyCallIfNotAdmin)
{
_setImplementation(_implementation);
}
function upgradeToAndCall(address _implementation, bytes calldata _data)
public
payable virtual proxyCallIfNotAdmin
returns (bytes memory)
{
_setImplementation(_implementation);
(bool success, bytes memory returndata) = _implementation.delegatecall(_data);
require(success, "Proxy: delegatecall to new implementation contract failed");
return returndata;
}
function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin {
_changeAdmin(_admin);
}
function admin() public virtual proxyCallIfNotAdmin returns (address) {
return _getAdmin();
}
function implementation()
public
virtual proxyCallIfNotAdmin
returns (address)
{
return _getImplementation();
}
function _setImplementation(address _implementation) internal {
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
sstore(proxyImplementation, _implementation)
}
emit Upgraded(_implementation);
}
function _changeAdmin(address _admin) internal {
address previous = _getAdmin();
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
sstore(proxyOwner, _admin)
}
emit AdminChanged(previous, _admin);
}
function _doProxyCall() internal {
address impl = _getImplementation();
require(impl != address(0), "Proxy: implementation not initialized");
assembly {
// Copy calldata into memory at 0x0....calldatasize.
calldatacopy(0x0, 0x0, calldatasize())
// Perform the delegatecall, make sure to pass all available gas.
let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)
// Copy returndata into memory at 0x0....returndatasize. Note that this *will*
// overwrite the calldata that we just copied into memory but that doesn't really
// matter because we'll be returning in a second anyway.
returndatacopy(0x0, 0x0, returndatasize())
// Success == 0 means a revert. We'll revert too and pass the data up.
if iszero(success) { revert(0x0, returndatasize()) }
// Otherwise we'll just return and pass the data up.
return(0x0, returndatasize())
}
}
function _getImplementation() internal view returns (address) {
address impl;
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
impl := sload(proxyImplementation)
}
return impl;
}
function _getAdmin() internal view returns (address) {
address owner;
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
owner := sload(proxyOwner)
}
return owner;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DeployScript} from "@redprint-deploy/deployer/DeployScript.sol";
import {DeployerFunctions, IDeployer} from "@redprint-deploy/deployer/DeployerFunctions.sol";
import {Proxy} from "@redprint-core/universal/Proxy.sol";
/// @custom:security-contact Consult full internal deploy script at https://github.com/Ratimon/redprint-forge
contract DeployOptimismPortalProxyScript is DeployScript {
using DeployerFunctions for IDeployer ;
function deploy() external returns (Proxy) {
address proxyOwner = deployer.mustGetAddress("ProxyAdmin");
return Proxy(deployer.deploy_ERC1967Proxy("OptimismPortalProxy", proxyOwner));
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"OptimismPortalProxy": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional
"DataAvailabilityChallenge": "<ADDRESS_11>", // optional
"OptimismPortalProxy": "<ADDRESS_12>"
}
click on ✕ button to close
4.1B : Deploy SystemConfigProxy Contract
forge script script/401B_DeploySystemConfigProxyScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Constants} from "@redprint-core/libraries/Constants.sol";
/// @custom:security-contact Consult full code at https://github.com/ethereum-optimism/optimism/blob/v1.9.4/packages/contracts-bedrock/src/universal/Proxy.sol
contract Proxy {
/**
* @notice An event that is emitted each time the implementation is changed. This event is part
* of the EIP-1967 specification.
*
* @param implementation The address of the implementation contract
*/
event Upgraded(address indexed implementation);
/**
* @notice An event that is emitted each time the owner is upgraded. This event is part of the
* EIP-1967 specification.
*
* @param previousAdmin The previous owner of the contract
* @param newAdmin The new owner of the contract
*/
event AdminChanged(address previousAdmin, address newAdmin);
modifier proxyCallIfNotAdmin() {
if (msg.sender == _getAdmin() || msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_doProxyCall();
}
}
constructor(address _admin) {
_changeAdmin(_admin);
}
receive() external payable {
// Proxy call by default.
_doProxyCall();
}
fallback() external payable {
// Proxy call by default.
_doProxyCall();
}
function upgradeTo(address _implementation)
public
virtual
returns (proxyCallIfNotAdmin)
{
_setImplementation(_implementation);
}
function upgradeToAndCall(address _implementation, bytes calldata _data)
public
payable virtual proxyCallIfNotAdmin
returns (bytes memory)
{
_setImplementation(_implementation);
(bool success, bytes memory returndata) = _implementation.delegatecall(_data);
require(success, "Proxy: delegatecall to new implementation contract failed");
return returndata;
}
function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin {
_changeAdmin(_admin);
}
function admin() public virtual proxyCallIfNotAdmin returns (address) {
return _getAdmin();
}
function implementation()
public
virtual proxyCallIfNotAdmin
returns (address)
{
return _getImplementation();
}
function _setImplementation(address _implementation) internal {
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
sstore(proxyImplementation, _implementation)
}
emit Upgraded(_implementation);
}
function _changeAdmin(address _admin) internal {
address previous = _getAdmin();
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
sstore(proxyOwner, _admin)
}
emit AdminChanged(previous, _admin);
}
function _doProxyCall() internal {
address impl = _getImplementation();
require(impl != address(0), "Proxy: implementation not initialized");
assembly {
// Copy calldata into memory at 0x0....calldatasize.
calldatacopy(0x0, 0x0, calldatasize())
// Perform the delegatecall, make sure to pass all available gas.
let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)
// Copy returndata into memory at 0x0....returndatasize. Note that this *will*
// overwrite the calldata that we just copied into memory but that doesn't really
// matter because we'll be returning in a second anyway.
returndatacopy(0x0, 0x0, returndatasize())
// Success == 0 means a revert. We'll revert too and pass the data up.
if iszero(success) { revert(0x0, returndatasize()) }
// Otherwise we'll just return and pass the data up.
return(0x0, returndatasize())
}
}
function _getImplementation() internal view returns (address) {
address impl;
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
impl := sload(proxyImplementation)
}
return impl;
}
function _getAdmin() internal view returns (address) {
address owner;
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
owner := sload(proxyOwner)
}
return owner;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DeployScript} from "@redprint-deploy/deployer/DeployScript.sol";
import {DeployerFunctions, IDeployer} from "@redprint-deploy/deployer/DeployerFunctions.sol";
import {Proxy} from "@redprint-core/universal/Proxy.sol";
/// @custom:security-contact Consult full internal deploy script at https://github.com/Ratimon/redprint-forge
contract DeploySystemConfigProxyScript is DeployScript {
using DeployerFunctions for IDeployer ;
function deploy() external returns (Proxy) {
address proxyOwner = deployer.mustGetAddress("ProxyAdmin");
return Proxy(deployer.deploy_ERC1967Proxy("SystemConfigProxy", proxyOwner));
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingletosn": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"OptimismPortalProxy": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional
"DataAvailabilityChallenge": "<ADDRESS_11>", // optional
"OptimismPortalProxy": "<ADDRESS_12>",
"SystemConfigProxy": "<ADDRESS_13>"
}
click on ✕ button to close
4.1C : Deploy L1StandardBridgeProxy Contract
forge script script/401C_DeployL1StandardBridgeProxyScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Constants} from "@redprint-core/libraries/Constants.sol";
import {IL1ChugSplashDeployer} from "@redprint-core/legacy/L1ChugSplashProxy.sol";
/// @custom:security-contact Consult full code at https://github.com/ethereum-optimism/optimism/blob/v1.9.4/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol
contract L1ChugSplashProxy {
/// @notice "Magic" prefix. When prepended to some arbitrary bytecode and used to create a
/// contract, the appended bytecode will be deployed as given.
bytes13 internal constant DEPLOY_CODE_PREFIX = 0x600D380380600D6000396000f3;
modifier onlyWhenNotPaused() {
address owner = _getOwner();
// We do a low-level call because there's no guarantee that the owner actually *is* an
// L1ChugSplashDeployer contract and Solidity will throw errors if we do a normal call and
// it turns out that it isn't the right type of contract.
(bool success, bytes memory returndata) =
owner.staticcall(abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector));
// If the call was unsuccessful then we assume that there's no "isUpgrading" method and we
// can just continue as normal. We also expect that the return value is exactly 32 bytes
// long. If this isn't the case then we can safely ignore the result.
if (success && returndata.length == 32) {
// Although the expected value is a *boolean*, it's safer to decode as a uint256 in the
// case that the isUpgrading function returned something other than 0 or 1. But we only
// really care about the case where this value is 0 (= false).
uint256 ret = abi.decode(returndata, (uint256));
require(ret == 0, "L1ChugSplashProxy: system is currently being upgraded");
}
_;
}
modifier proxyCallIfNotOwner() {
if (msg.sender == _getOwner() || msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_doProxyCall();
}
}
constructor(address _owner) {
_setOwner(_owner);
}
receive() external payable {
// Proxy call by default.
_doProxyCall();
}
fallback() external payable {
// Proxy call by default.
_doProxyCall();
}
function setCode(bytes memory _code) external proxyCallIfNotOwner {
// Get the code hash of the current implementation.
address implementation = _getImplementation();
// If the code hash matches the new implementation then we return early.
if (keccak256(_code) == _getAccountCodeHash(implementation)) {
return;
}
// Create the deploycode by appending the magic prefix.
bytes memory deploycode = abi.encodePacked(DEPLOY_CODE_PREFIX, _code);
// Deploy the code and set the new implementation address.
address newImplementation;
assembly {
newImplementation := create(0x0, add(deploycode, 0x20), mload(deploycode))
}
// Check that the code was actually deployed correctly. I'm not sure if you can ever
// actually fail this check. Should only happen if the contract creation from above runs
// out of gas but this parent execution thread does NOT run out of gas. Seems like we
// should be doing this check anyway though.
require(
_getAccountCodeHash(newImplementation) == keccak256(_code),
"L1ChugSplashProxy: code was not correctly deployed"
);
_setImplementation(newImplementation);
}
function setStorage(bytes32 _key, bytes32 _value) external proxyCallIfNotOwner {
assembly {
sstore(_key, _value)
}
}
function getOwner() public proxyCallIfNotOwner returns (address) {
return _getOwner();
}
function getImplementation() external proxyCallIfNotOwner returns (address) {
return _getImplementation();
}
function _setImplementation(address _implementation) internal {
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
sstore(proxyImplementation, _implementation)
}
}
function _setOwner(address _owner) internal {
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
sstore(proxyOwner, _owner)
}
}
function _doProxyCall() internal onlyWhenNotPaused {
address implementation = _getImplementation();
require(implementation != address(0), "L1ChugSplashProxy: implementation is not set yet");
assembly {
// Copy calldata into memory at 0x0....calldatasize.
calldatacopy(0x0, 0x0, calldatasize())
// Perform the delegatecall, make sure to pass all available gas.
let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0)
// Copy returndata into memory at 0x0....returndatasize. Note that this *will*
// overwrite the calldata that we just copied into memory but that doesn't really
// matter because we'll be returning in a second anyway.
returndatacopy(0x0, 0x0, returndatasize())
// Success == 0 means a revert. We'll revert too and pass the data up.
if iszero(success) { revert(0x0, returndatasize()) }
// Otherwise we'll just return and pass the data up.
return(0x0, returndatasize())
}
}
function _getImplementation() internal view returns (address) {
address implementation;
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
implementation := sload(proxyImplementation)
}
return implementation;
}
function _getOwner() internal view returns (address) {
address owner;
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
owner := sload(proxyOwner)
}
return owner;
}
function _getAccountCodeHash(address _account)
internal
view
returns (bytes32)
{
bytes32 codeHash;
assembly {
codeHash := extcodehash(_account)
}
return codeHash;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DeployScript} from "@redprint-deploy/deployer/DeployScript.sol";
import {DeployerFunctions, IDeployer} from "@redprint-deploy/deployer/DeployerFunctions.sol";
import {L1ChugSplashProxy} from "@redprint-core/legacy/L1ChugSplashProxy.sol";
/// @custom:security-contact Consult full internal deploy script at https://github.com/Ratimon/redprint-forge
contract DeployL1StandardBridgeProxyScript is DeployScript {
using DeployerFunctions for IDeployer ;
function deploy() external returns (L1ChugSplashProxy) {
address proxyOwner = deployer.mustGetAddress("ProxyAdmin");
return L1ChugSplashProxy(deployer.deploy_L1ChugSplashProxy("L1StandardBridgeProxy", proxyOwner ));
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"OptimismPortalProxy": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional
"DataAvailabilityChallenge": "<ADDRESS_11>", // optional
"OptimismPortalProxy": "<ADDRESS_12>",
"SystemConfigProxy": "<ADDRESS_13>",
"L1StandardBridgeProxy": "<ADDRESS_14>"
}
click on ✕ button to close
4.1D : Deploy L1CrossDomainMessengerProxy Contract
forge script script/401D_DeployL1CrossDomainMessengerProxyScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {AddressManager} from "@redprint-core/legacy/AddressManager.sol";
/// @custom:security-contact Consult full code at https://github.com/ethereum-optimism/optimism/blob/v1.9.4/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol
contract ResolvedDelegateProxy {
/// @notice Mapping used to store the implementation name that corresponds to this contract. A
/// mapping was originally used as a way to bypass the same issue normally solved by
/// storing the implementation address in a specific storage slot that does not conflict
/// with any other storage slot. Generally NOT a safe solution but works as long as the
/// implementation does not also keep a mapping in the first storage slot.
mapping(address => string) private implementationName;
/// @notice Mapping used to store the address of the AddressManager contract where the
/// implementation address will be resolved from. Same concept here as with the above
/// mapping. Also generally unsafe but fine if the implementation doesn't keep a mapping
/// in the second storage slot.
mapping(address => AddressManager) private addressManager;
constructor(AddressManager _addressManager, string memory _implementationName)
{
addressManager[address(this)] = _addressManager;
implementationName[address(this)] = _implementationName;
}
fallback() external payable {
address target = addressManager[address(this)].getAddress((implementationName[address(this)]));
require(target != address(0), "ResolvedDelegateProxy: target address must be initialized");
// slither-disable-next-line controlled-delegatecall
(bool success, bytes memory returndata) = target.delegatecall(msg.data);
if (success == true) {
assembly {
return(add(returndata, 0x20), mload(returndata))
}
} else {
assembly {
revert(add(returndata, 0x20), mload(returndata))
}
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {AddressManager} from "@redprint-core/legacy/AddressManager.sol";
import {DeployScript} from "@redprint-deploy/deployer/DeployScript.sol";
import {DeployerFunctions, IDeployer} from "@redprint-deploy/deployer/DeployerFunctions.sol";
import {ResolvedDelegateProxy} from "@redprint-core/legacy/ResolvedDelegateProxy.sol";
/// @custom:security-contact Consult full internal deploy script at https://github.com/Ratimon/redprint-forge
contract DeployL1CrossDomainMessengerProxyScript is DeployScript {
using DeployerFunctions for IDeployer ;
function deploy() external returns (ResolvedDelegateProxy) {
address addressManager = deployer.mustGetAddress("AddressManager");
return ResolvedDelegateProxy(deployer.deploy_ResolvedDelegateProxy("L1CrossDomainMessengerProxy", addressManager, "OVM_L1CrossDomainMessenger" ));
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"OptimismPortalProxy": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional
"DataAvailabilityChallenge": "<ADDRESS_11>", // optional
"OptimismPortalProxy": "<ADDRESS_12>",
"SystemConfigProxy": "<ADDRESS_13>",
"L1StandardBridgeProxy": "<ADDRESS_14>",
"L1CrossDomainMessengerProxy": "<ADDRESS_15>"
}
click on ✕ button to close
4.1E : Deploy OptimismMintableERC20FactoryProxy Contract
forge script script/401E_DeployOptimismMintableERC20FactoryProxyScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Constants} from "@redprint-core/libraries/Constants.sol";
/// @custom:security-contact Consult full code at https://github.com/ethereum-optimism/optimism/blob/v1.9.4/packages/contracts-bedrock/src/universal/Proxy.sol
contract Proxy {
/**
* @notice An event that is emitted each time the implementation is changed. This event is part
* of the EIP-1967 specification.
*
* @param implementation The address of the implementation contract
*/
event Upgraded(address indexed implementation);
/**
* @notice An event that is emitted each time the owner is upgraded. This event is part of the
* EIP-1967 specification.
*
* @param previousAdmin The previous owner of the contract
* @param newAdmin The new owner of the contract
*/
event AdminChanged(address previousAdmin, address newAdmin);
modifier proxyCallIfNotAdmin() {
if (msg.sender == _getAdmin() || msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_doProxyCall();
}
}
constructor(address _admin) {
_changeAdmin(_admin);
}
receive() external payable {
// Proxy call by default.
_doProxyCall();
}
fallback() external payable {
// Proxy call by default.
_doProxyCall();
}
function upgradeTo(address _implementation)
public
virtual
returns (proxyCallIfNotAdmin)
{
_setImplementation(_implementation);
}
function upgradeToAndCall(address _implementation, bytes calldata _data)
public
payable virtual proxyCallIfNotAdmin
returns (bytes memory)
{
_setImplementation(_implementation);
(bool success, bytes memory returndata) = _implementation.delegatecall(_data);
require(success, "Proxy: delegatecall to new implementation contract failed");
return returndata;
}
function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin {
_changeAdmin(_admin);
}
function admin() public virtual proxyCallIfNotAdmin returns (address) {
return _getAdmin();
}
function implementation()
public
virtual proxyCallIfNotAdmin
returns (address)
{
return _getImplementation();
}
function _setImplementation(address _implementation) internal {
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
sstore(proxyImplementation, _implementation)
}
emit Upgraded(_implementation);
}
function _changeAdmin(address _admin) internal {
address previous = _getAdmin();
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
sstore(proxyOwner, _admin)
}
emit AdminChanged(previous, _admin);
}
function _doProxyCall() internal {
address impl = _getImplementation();
require(impl != address(0), "Proxy: implementation not initialized");
assembly {
// Copy calldata into memory at 0x0....calldatasize.
calldatacopy(0x0, 0x0, calldatasize())
// Perform the delegatecall, make sure to pass all available gas.
let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)
// Copy returndata into memory at 0x0....returndatasize. Note that this *will*
// overwrite the calldata that we just copied into memory but that doesn't really
// matter because we'll be returning in a second anyway.
returndatacopy(0x0, 0x0, returndatasize())
// Success == 0 means a revert. We'll revert too and pass the data up.
if iszero(success) { revert(0x0, returndatasize()) }
// Otherwise we'll just return and pass the data up.
return(0x0, returndatasize())
}
}
function _getImplementation() internal view returns (address) {
address impl;
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
impl := sload(proxyImplementation)
}
return impl;
}
function _getAdmin() internal view returns (address) {
address owner;
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
owner := sload(proxyOwner)
}
return owner;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DeployScript} from "@redprint-deploy/deployer/DeployScript.sol";
import {DeployerFunctions, IDeployer} from "@redprint-deploy/deployer/DeployerFunctions.sol";
import {Proxy} from "@redprint-core/universal/Proxy.sol";
/// @custom:security-contact Consult full internal deploy script at https://github.com/Ratimon/redprint-forge
contract DeployOptimismMintableERC20FactoryProxyScript is DeployScript {
using DeployerFunctions for IDeployer ;
function deploy() external returns (Proxy) {
address proxyOwner = deployer.mustGetAddress("ProxyAdmin");
return Proxy(deployer.deploy_ERC1967Proxy("OptimismMintableERC20FactoryProxy", proxyOwner));
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"OptimismPortalProxy": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional
"DataAvailabilityChallenge": "<ADDRESS_11>", // optional
"OptimismPortalProxy": "<ADDRESS_12>",
"SystemConfigProxy": "<ADDRESS_13>",
"L1StandardBridgeProxy": "<ADDRESS_14>",
"L1CrossDomainMessengerProxy": "<ADDRESS_15>",
"OptimismMintableERC20FactoryProxy": "<ADDRESS_16>"
}
click on ✕ button to close
4.1F : Deploy L1ERC721BridgeProxy Contract
forge script script/401F_DeployL1ERC721BridgeProxyScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Constants} from "@redprint-core/libraries/Constants.sol";
/// @custom:security-contact Consult full code at https://github.com/ethereum-optimism/optimism/blob/v1.9.4/packages/contracts-bedrock/src/universal/Proxy.sol
contract Proxy {
/**
* @notice An event that is emitted each time the implementation is changed. This event is part
* of the EIP-1967 specification.
*
* @param implementation The address of the implementation contract
*/
event Upgraded(address indexed implementation);
/**
* @notice An event that is emitted each time the owner is upgraded. This event is part of the
* EIP-1967 specification.
*
* @param previousAdmin The previous owner of the contract
* @param newAdmin The new owner of the contract
*/
event AdminChanged(address previousAdmin, address newAdmin);
modifier proxyCallIfNotAdmin() {
if (msg.sender == _getAdmin() || msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_doProxyCall();
}
}
constructor(address _admin) {
_changeAdmin(_admin);
}
receive() external payable {
// Proxy call by default.
_doProxyCall();
}
fallback() external payable {
// Proxy call by default.
_doProxyCall();
}
function upgradeTo(address _implementation)
public
virtual
returns (proxyCallIfNotAdmin)
{
_setImplementation(_implementation);
}
function upgradeToAndCall(address _implementation, bytes calldata _data)
public
payable virtual proxyCallIfNotAdmin
returns (bytes memory)
{
_setImplementation(_implementation);
(bool success, bytes memory returndata) = _implementation.delegatecall(_data);
require(success, "Proxy: delegatecall to new implementation contract failed");
return returndata;
}
function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin {
_changeAdmin(_admin);
}
function admin() public virtual proxyCallIfNotAdmin returns (address) {
return _getAdmin();
}
function implementation()
public
virtual proxyCallIfNotAdmin
returns (address)
{
return _getImplementation();
}
function _setImplementation(address _implementation) internal {
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
sstore(proxyImplementation, _implementation)
}
emit Upgraded(_implementation);
}
function _changeAdmin(address _admin) internal {
address previous = _getAdmin();
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
sstore(proxyOwner, _admin)
}
emit AdminChanged(previous, _admin);
}
function _doProxyCall() internal {
address impl = _getImplementation();
require(impl != address(0), "Proxy: implementation not initialized");
assembly {
// Copy calldata into memory at 0x0....calldatasize.
calldatacopy(0x0, 0x0, calldatasize())
// Perform the delegatecall, make sure to pass all available gas.
let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)
// Copy returndata into memory at 0x0....returndatasize. Note that this *will*
// overwrite the calldata that we just copied into memory but that doesn't really
// matter because we'll be returning in a second anyway.
returndatacopy(0x0, 0x0, returndatasize())
// Success == 0 means a revert. We'll revert too and pass the data up.
if iszero(success) { revert(0x0, returndatasize()) }
// Otherwise we'll just return and pass the data up.
return(0x0, returndatasize())
}
}
function _getImplementation() internal view returns (address) {
address impl;
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
impl := sload(proxyImplementation)
}
return impl;
}
function _getAdmin() internal view returns (address) {
address owner;
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
owner := sload(proxyOwner)
}
return owner;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DeployScript} from "@redprint-deploy/deployer/DeployScript.sol";
import {DeployerFunctions, IDeployer} from "@redprint-deploy/deployer/DeployerFunctions.sol";
import {Proxy} from "@redprint-core/universal/Proxy.sol";
/// @custom:security-contact Consult full internal deploy script at https://github.com/Ratimon/redprint-forge
contract DeployL1ERC721BridgeProxyScript is DeployScript {
using DeployerFunctions for IDeployer ;
function deploy() external returns (Proxy) {
address proxyOwner = deployer.mustGetAddress("ProxyAdmin");
return Proxy(deployer.deploy_ERC1967Proxy("L1ERC721BridgeProxy", proxyOwner));
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"OptimismPortalProxy": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional
"DataAvailabilityChallenge": "<ADDRESS_11>" // optional
"OptimismPortalProxy": "<ADDRESS_10>",
"SystemConfigProxy": "<ADDRESS_11>",
"L1StandardBridgeProxy": "<ADDRESS_12>",
"L1CrossDomainMessengerProxy": "<ADDRESS_13>",
"OptimismMintableERC20FactoryProxy": "<ADDRESS_14>",
"L1ERC721BridgeProxy": "<ADDRESS_15>"
}
click on ✕ button to close
4.1G : Deploy DisputeGameFactoryProxy Contract
forge script script/401G_DeployDisputeGameFactoryProxyScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Constants} from "@redprint-core/libraries/Constants.sol";
/// @custom:security-contact Consult full code at https://github.com/ethereum-optimism/optimism/blob/4/packages/contracts-bedrock/src/universal/Proxy.sol
contract Proxy {
/**
* @notice An event that is emitted each time the implementation is changed. This event is part
* of the EIP-1967 specification.
*
* @param implementation The address of the implementation contract
*/
event Upgraded(address indexed implementation);
/**
* @notice An event that is emitted each time the owner is upgraded. This event is part of the
* EIP-1967 specification.
*
* @param previousAdmin The previous owner of the contract
* @param newAdmin The new owner of the contract
*/
event AdminChanged(address previousAdmin, address newAdmin);
modifier proxyCallIfNotAdmin() {
if (msg.sender == _getAdmin() || msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_doProxyCall();
}
}
constructor(address _admin) {
_changeAdmin(_admin);
}
receive() external payable {
// Proxy call by default.
_doProxyCall();
}
fallback() external payable {
// Proxy call by default.
_doProxyCall();
}
function upgradeTo(address _implementation)
public
virtual
returns (proxyCallIfNotAdmin)
{
_setImplementation(_implementation);
}
function upgradeToAndCall(address _implementation, bytes calldata _data)
public
payable virtual proxyCallIfNotAdmin
returns (bytes memory)
{
_setImplementation(_implementation);
(bool success, bytes memory returndata) = _implementation.delegatecall(_data);
require(success, "Proxy: delegatecall to new implementation contract failed");
return returndata;
}
function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin {
_changeAdmin(_admin);
}
function admin() public virtual proxyCallIfNotAdmin returns (address) {
return _getAdmin();
}
function implementation()
public
virtual proxyCallIfNotAdmin
returns (address)
{
return _getImplementation();
}
function _setImplementation(address _implementation) internal {
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
sstore(proxyImplementation, _implementation)
}
emit Upgraded(_implementation);
}
function _changeAdmin(address _admin) internal {
address previous = _getAdmin();
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
sstore(proxyOwner, _admin)
}
emit AdminChanged(previous, _admin);
}
function _doProxyCall() internal {
address impl = _getImplementation();
require(impl != address(0), "Proxy: implementation not initialized");
assembly {
// Copy calldata into memory at 0x0....calldatasize.
calldatacopy(0x0, 0x0, calldatasize())
// Perform the delegatecall, make sure to pass all available gas.
let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)
// Copy returndata into memory at 0x0....returndatasize. Note that this *will*
// overwrite the calldata that we just copied into memory but that doesn't really
// matter because we'll be returning in a second anyway.
returndatacopy(0x0, 0x0, returndatasize())
// Success == 0 means a revert. We'll revert too and pass the data up.
if iszero(success) { revert(0x0, returndatasize()) }
// Otherwise we'll just return and pass the data up.
return(0x0, returndatasize())
}
}
function _getImplementation() internal view returns (address) {
address impl;
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
impl := sload(proxyImplementation)
}
return impl;
}
function _getAdmin() internal view returns (address) {
address owner;
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
owner := sload(proxyOwner)
}
return owner;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DeployScript} from "@redprint-deploy/deployer/DeployScript.sol";
import {DeployerFunctions, IDeployer} from "@redprint-deploy/deployer/DeployerFunctions.sol";
import {Proxy} from "@redprint-core/universal/Proxy.sol";
/// @custom:security-contact Consult full internal deploy script at https://github.com/Ratimon/redprint-forge
contract DeployDisputeGameFactoryProxyScript is DeployScript {
using DeployerFunctions for IDeployer ;
function deploy() external returns (Proxy) {
address proxyOwner = deployer.mustGetAddress("ProxyAdmin");
return Proxy(deployer.deploy_ERC1967Proxy("DisputeGameFactoryProxy", proxyOwner));
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"OptimismPortalProxy": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional
"DataAvailabilityChallenge": "<ADDRESS_11>", // optional
"OptimismPortalProxy": "<ADDRESS_12>",
"SystemConfigProxy": "<ADDRESS_13>",
"L1StandardBridgeProxy": "<ADDRESS_14>",
"L1CrossDomainMessengerProxy": "<ADDRESS_15>",
"OptimismMintableERC20FactoryProxy": "<ADDRESS_16>",
"L1ERC721BridgeProxy": "<ADDRESS_17>",
"DisputeGameFactoryProxy": "<ADDRESS_18>"
}
click on ✕ button to close
4.1H : Deploy L2OutputOracleProxy Contract
forge script script/401H_DeployL2OutputOracleProxyScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Constants} from "@redprint-core/libraries/Constants.sol";
/// @custom:security-contact Consult full code at https://github.com/ethereum-optimism/optimism/blob/v1.9.4/packages/contracts-bedrock/src/universal/Proxy.sol
contract Proxy {
/**
* @notice An event that is emitted each time the implementation is changed. This event is part
* of the EIP-1967 specification.
*
* @param implementation The address of the implementation contract
*/
event Upgraded(address indexed implementation);
/**
* @notice An event that is emitted each time the owner is upgraded. This event is part of the
* EIP-1967 specification.
*
* @param previousAdmin The previous owner of the contract
* @param newAdmin The new owner of the contract
*/
event AdminChanged(address previousAdmin, address newAdmin);
modifier proxyCallIfNotAdmin() {
if (msg.sender == _getAdmin() || msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_doProxyCall();
}
}
constructor(address _admin) {
_changeAdmin(_admin);
}
receive() external payable {
// Proxy call by default.
_doProxyCall();
}
fallback() external payable {
// Proxy call by default.
_doProxyCall();
}
function upgradeTo(address _implementation)
public
virtual
returns (proxyCallIfNotAdmin)
{
_setImplementation(_implementation);
}
function upgradeToAndCall(address _implementation, bytes calldata _data)
public
payable virtual proxyCallIfNotAdmin
returns (bytes memory)
{
_setImplementation(_implementation);
(bool success, bytes memory returndata) = _implementation.delegatecall(_data);
require(success, "Proxy: delegatecall to new implementation contract failed");
return returndata;
}
function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin {
_changeAdmin(_admin);
}
function admin() public virtual proxyCallIfNotAdmin returns (address) {
return _getAdmin();
}
function implementation()
public
virtual proxyCallIfNotAdmin
returns (address)
{
return _getImplementation();
}
function _setImplementation(address _implementation) internal {
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
sstore(proxyImplementation, _implementation)
}
emit Upgraded(_implementation);
}
function _changeAdmin(address _admin) internal {
address previous = _getAdmin();
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
sstore(proxyOwner, _admin)
}
emit AdminChanged(previous, _admin);
}
function _doProxyCall() internal {
address impl = _getImplementation();
require(impl != address(0), "Proxy: implementation not initialized");
assembly {
// Copy calldata into memory at 0x0....calldatasize.
calldatacopy(0x0, 0x0, calldatasize())
// Perform the delegatecall, make sure to pass all available gas.
let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)
// Copy returndata into memory at 0x0....returndatasize. Note that this *will*
// overwrite the calldata that we just copied into memory but that doesn't really
// matter because we'll be returning in a second anyway.
returndatacopy(0x0, 0x0, returndatasize())
// Success == 0 means a revert. We'll revert too and pass the data up.
if iszero(success) { revert(0x0, returndatasize()) }
// Otherwise we'll just return and pass the data up.
return(0x0, returndatasize())
}
}
function _getImplementation() internal view returns (address) {
address impl;
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
impl := sload(proxyImplementation)
}
return impl;
}
function _getAdmin() internal view returns (address) {
address owner;
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
owner := sload(proxyOwner)
}
return owner;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DeployScript} from "@redprint-deploy/deployer/DeployScript.sol";
import {DeployerFunctions, IDeployer} from "@redprint-deploy/deployer/DeployerFunctions.sol";
import {Proxy} from "@redprint-core/universal/Proxy.sol";
/// @custom:security-contact Consult full internal deploy script at https://github.com/Ratimon/redprint-forge
contract DeployL2OutputOracleProxyScript is DeployScript {
using DeployerFunctions for IDeployer ;
function deploy() external returns (Proxy) {
address proxyOwner = deployer.mustGetAddress("ProxyAdmin");
return Proxy(deployer.deploy_ERC1967Proxy("L2OutputOracleProxy", proxyOwner));
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"OptimismPortalProxy": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional
"DataAvailabilityChallenge": "<ADDRESS_11>", // optional
"OptimismPortalProxy": "<ADDRESS_12>",
"SystemConfigProxy": "<ADDRESS_13>",
"L1StandardBridgeProxy": "<ADDRESS_14>",
"L1CrossDomainMessengerProxy": "<ADDRESS_15>",
"OptimismMintableERC20FactoryProxy": "<ADDRESS_16>",
"L1ERC721BridgeProxy": "<ADDRESS_17>",
"DisputeGameFactoryProxy": "<ADDRESS_18>",
"L2OutputOracleProxy": "<ADDRESS_19>"
}
click on ✕ button to close
4.1I : Deploy DelayedWETHProxy Contract
forge script script/401I_DeployDelayedWETHProxyScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Constants} from "@redprint-core/libraries/Constants.sol";
/// @custom:security-contact Consult full code at https://github.com/ethereum-optimism/optimism/blob/4/packages/contracts-bedrock/src/universal/Proxy.sol
contract Proxy {
/**
* @notice An event that is emitted each time the implementation is changed. This event is part
* of the EIP-1967 specification.
*
* @param implementation The address of the implementation contract
*/
event Upgraded(address indexed implementation);
/**
* @notice An event that is emitted each time the owner is upgraded. This event is part of the
* EIP-1967 specification.
*
* @param previousAdmin The previous owner of the contract
* @param newAdmin The new owner of the contract
*/
event AdminChanged(address previousAdmin, address newAdmin);
modifier proxyCallIfNotAdmin() {
if (msg.sender == _getAdmin() || msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_doProxyCall();
}
}
constructor(address _admin) {
_changeAdmin(_admin);
}
receive() external payable {
// Proxy call by default.
_doProxyCall();
}
fallback() external payable {
// Proxy call by default.
_doProxyCall();
}
function upgradeTo(address _implementation)
public
virtual
returns (proxyCallIfNotAdmin)
{
_setImplementation(_implementation);
}
function upgradeToAndCall(address _implementation, bytes calldata _data)
public
payable virtual proxyCallIfNotAdmin
returns (bytes memory)
{
_setImplementation(_implementation);
(bool success, bytes memory returndata) = _implementation.delegatecall(_data);
require(success, "Proxy: delegatecall to new implementation contract failed");
return returndata;
}
function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin {
_changeAdmin(_admin);
}
function admin() public virtual proxyCallIfNotAdmin returns (address) {
return _getAdmin();
}
function implementation()
public
virtual proxyCallIfNotAdmin
returns (address)
{
return _getImplementation();
}
function _setImplementation(address _implementation) internal {
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
sstore(proxyImplementation, _implementation)
}
emit Upgraded(_implementation);
}
function _changeAdmin(address _admin) internal {
address previous = _getAdmin();
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
sstore(proxyOwner, _admin)
}
emit AdminChanged(previous, _admin);
}
function _doProxyCall() internal {
address impl = _getImplementation();
require(impl != address(0), "Proxy: implementation not initialized");
assembly {
// Copy calldata into memory at 0x0....calldatasize.
calldatacopy(0x0, 0x0, calldatasize())
// Perform the delegatecall, make sure to pass all available gas.
let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)
// Copy returndata into memory at 0x0....returndatasize. Note that this *will*
// overwrite the calldata that we just copied into memory but that doesn't really
// matter because we'll be returning in a second anyway.
returndatacopy(0x0, 0x0, returndatasize())
// Success == 0 means a revert. We'll revert too and pass the data up.
if iszero(success) { revert(0x0, returndatasize()) }
// Otherwise we'll just return and pass the data up.
return(0x0, returndatasize())
}
}
function _getImplementation() internal view returns (address) {
address impl;
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
impl := sload(proxyImplementation)
}
return impl;
}
function _getAdmin() internal view returns (address) {
address owner;
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
owner := sload(proxyOwner)
}
return owner;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DeployScript} from "@redprint-deploy/deployer/DeployScript.sol";
import {DeployerFunctions, IDeployer} from "@redprint-deploy/deployer/DeployerFunctions.sol";
import {Proxy} from "@redprint-core/universal/Proxy.sol";
/// @custom:security-contact Consult full internal deploy script at https://github.com/Ratimon/redprint-forge
contract DeployDelayedWETHProxyScript is DeployScript {
using DeployerFunctions for IDeployer ;
function deploy() external returns (Proxy) {
address proxyOwner = deployer.mustGetAddress("ProxyAdmin");
return Proxy(deployer.deploy_ERC1967Proxy("DelayedWETHProxy", proxyOwner));
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"OptimismPortalProxy": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional
"DataAvailabilityChallenge": "<ADDRESS_11>", // optional
"OptimismPortalProxy": "<ADDRESS_12>",
"SystemConfigProxy": "<ADDRESS_13>",
"L1StandardBridgeProxy": "<ADDRESS_14>",
"L1CrossDomainMessengerProxy": "<ADDRESS_15>",
"OptimismMintableERC20FactoryProxy": "<ADDRESS_16>",
"L1ERC721BridgeProxy": "<ADDRESS_17>",
"DisputeGameFactoryProxy": "<ADDRESS_18>",
"L2OutputOracleProxy": "<ADDRESS_19>",
"DelayedWETHProxy": "<ADDRESS_20>"
}
click on ✕ button to close
4.1J : Deploy PermissionedDelayedWETHProxy Contract
forge script script/401J_DeployPermissionedDelayedWETHProxyScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Constants} from "@redprint-core/libraries/Constants.sol";
/// @custom:security-contact Consult full code at https://github.com/ethereum-optimism/optimism/blob/v1.9.4/packages/contracts-bedrock/src/universal/Proxy.sol
contract Proxy {
/**
* @notice An event that is emitted each time the implementation is changed. This event is part
* of the EIP-1967 specification.
*
* @param implementation The address of the implementation contract
*/
event Upgraded(address indexed implementation);
/**
* @notice An event that is emitted each time the owner is upgraded. This event is part of the
* EIP-1967 specification.
*
* @param previousAdmin The previous owner of the contract
* @param newAdmin The new owner of the contract
*/
event AdminChanged(address previousAdmin, address newAdmin);
modifier proxyCallIfNotAdmin() {
if (msg.sender == _getAdmin() || msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_doProxyCall();
}
}
constructor(address _admin) {
_changeAdmin(_admin);
}
receive() external payable {
// Proxy call by default.
_doProxyCall();
}
fallback() external payable {
// Proxy call by default.
_doProxyCall();
}
function upgradeTo(address _implementation)
public
virtual
returns (proxyCallIfNotAdmin)
{
_setImplementation(_implementation);
}
function upgradeToAndCall(address _implementation, bytes calldata _data)
public
payable virtual proxyCallIfNotAdmin
returns (bytes memory)
{
_setImplementation(_implementation);
(bool success, bytes memory returndata) = _implementation.delegatecall(_data);
require(success, "Proxy: delegatecall to new implementation contract failed");
return returndata;
}
function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin {
_changeAdmin(_admin);
}
function admin() public virtual proxyCallIfNotAdmin returns (address) {
return _getAdmin();
}
function implementation()
public
virtual proxyCallIfNotAdmin
returns (address)
{
return _getImplementation();
}
function _setImplementation(address _implementation) internal {
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
sstore(proxyImplementation, _implementation)
}
emit Upgraded(_implementation);
}
function _changeAdmin(address _admin) internal {
address previous = _getAdmin();
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
sstore(proxyOwner, _admin)
}
emit AdminChanged(previous, _admin);
}
function _doProxyCall() internal {
address impl = _getImplementation();
require(impl != address(0), "Proxy: implementation not initialized");
assembly {
// Copy calldata into memory at 0x0....calldatasize.
calldatacopy(0x0, 0x0, calldatasize())
// Perform the delegatecall, make sure to pass all available gas.
let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)
// Copy returndata into memory at 0x0....returndatasize. Note that this *will*
// overwrite the calldata that we just copied into memory but that doesn't really
// matter because we'll be returning in a second anyway.
returndatacopy(0x0, 0x0, returndatasize())
// Success == 0 means a revert. We'll revert too and pass the data up.
if iszero(success) { revert(0x0, returndatasize()) }
// Otherwise we'll just return and pass the data up.
return(0x0, returndatasize())
}
}
function _getImplementation() internal view returns (address) {
address impl;
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
impl := sload(proxyImplementation)
}
return impl;
}
function _getAdmin() internal view returns (address) {
address owner;
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
owner := sload(proxyOwner)
}
return owner;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DeployScript} from "@redprint-deploy/deployer/DeployScript.sol";
import {DeployerFunctions, IDeployer} from "@redprint-deploy/deployer/DeployerFunctions.sol";
import {Proxy} from "@redprint-core/universal/Proxy.sol";
/// @custom:security-contact Consult full internal deploy script at https://github.com/Ratimon/redprint-forge
contract DeployPermissionedDelayedWETHProxyScript is DeployScript {
using DeployerFunctions for IDeployer ;
function deploy() external returns (Proxy) {
address proxyOwner = deployer.mustGetAddress("ProxyAdmin");
return Proxy(deployer.deploy_ERC1967Proxy("PermissionedDelayedWETHProxy", proxyOwner));
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"OptimismPortalProxy": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional
"DataAvailabilityChallenge": "<ADDRESS_11>", // optional
"OptimismPortalProxy": "<ADDRESS_12>",
"SystemConfigProxy": "<ADDRESS_13>",
"L1StandardBridgeProxy": "<ADDRESS_14>",
"L1CrossDomainMessengerProxy": "<ADDRESS_15>",
"OptimismMintableERC20FactoryProxy": "<ADDRESS_16>",
"L1ERC721BridgeProxy": "<ADDRESS_17>",
"DisputeGameFactoryProxy": "<ADDRESS_18>",
"L2OutputOracleProxy": "<ADDRESS_19>",
"DelayedWETHProxy": "<ADDRESS_20>",
"PermissionedDelayedWETHProxy": "<ADDRESS_21>"
}
click on ✕ button to close
4.1K : Deploy AnchorStateRegistryProxy Contract
forge script script/401K_DeployAnchorStateRegistryProxyScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Constants} from "@redprint-core/libraries/Constants.sol";
/// @custom:security-contact Consult full code at https://github.com/ethereum-optimism/optimism/blob/v1.9.4/packages/contracts-bedrock/src/universal/Proxy.sol
contract Proxy {
/**
* @notice An event that is emitted each time the implementation is changed. This event is part
* of the EIP-1967 specification.
*
* @param implementation The address of the implementation contract
*/
event Upgraded(address indexed implementation);
/**
* @notice An event that is emitted each time the owner is upgraded. This event is part of the
* EIP-1967 specification.
*
* @param previousAdmin The previous owner of the contract
* @param newAdmin The new owner of the contract
*/
event AdminChanged(address previousAdmin, address newAdmin);
modifier proxyCallIfNotAdmin() {
if (msg.sender == _getAdmin() || msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_doProxyCall();
}
}
constructor(address _admin) {
_changeAdmin(_admin);
}
receive() external payable {
// Proxy call by default.
_doProxyCall();
}
fallback() external payable {
// Proxy call by default.
_doProxyCall();
}
function upgradeTo(address _implementation)
public
virtual
returns (proxyCallIfNotAdmin)
{
_setImplementation(_implementation);
}
function upgradeToAndCall(address _implementation, bytes calldata _data)
public
payable virtual proxyCallIfNotAdmin
returns (bytes memory)
{
_setImplementation(_implementation);
(bool success, bytes memory returndata) = _implementation.delegatecall(_data);
require(success, "Proxy: delegatecall to new implementation contract failed");
return returndata;
}
function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin {
_changeAdmin(_admin);
}
function admin() public virtual proxyCallIfNotAdmin returns (address) {
return _getAdmin();
}
function implementation()
public
virtual proxyCallIfNotAdmin
returns (address)
{
return _getImplementation();
}
function _setImplementation(address _implementation) internal {
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
sstore(proxyImplementation, _implementation)
}
emit Upgraded(_implementation);
}
function _changeAdmin(address _admin) internal {
address previous = _getAdmin();
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
sstore(proxyOwner, _admin)
}
emit AdminChanged(previous, _admin);
}
function _doProxyCall() internal {
address impl = _getImplementation();
require(impl != address(0), "Proxy: implementation not initialized");
assembly {
// Copy calldata into memory at 0x0....calldatasize.
calldatacopy(0x0, 0x0, calldatasize())
// Perform the delegatecall, make sure to pass all available gas.
let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)
// Copy returndata into memory at 0x0....returndatasize. Note that this *will*
// overwrite the calldata that we just copied into memory but that doesn't really
// matter because we'll be returning in a second anyway.
returndatacopy(0x0, 0x0, returndatasize())
// Success == 0 means a revert. We'll revert too and pass the data up.
if iszero(success) { revert(0x0, returndatasize()) }
// Otherwise we'll just return and pass the data up.
return(0x0, returndatasize())
}
}
function _getImplementation() internal view returns (address) {
address impl;
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
impl := sload(proxyImplementation)
}
return impl;
}
function _getAdmin() internal view returns (address) {
address owner;
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
owner := sload(proxyOwner)
}
return owner;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DeployScript} from "@redprint-deploy/deployer/DeployScript.sol";
import {DeployerFunctions, IDeployer} from "@redprint-deploy/deployer/DeployerFunctions.sol";
import {Proxy} from "@redprint-core/universal/Proxy.sol";
/// @custom:security-contact Consult full internal deploy script at https://github.com/Ratimon/redprint-forge
contract DeployAnchorStateRegistryProxyScript is DeployScript {
using DeployerFunctions for IDeployer ;
function deploy() external returns (Proxy) {
address proxyOwner = deployer.mustGetAddress("ProxyAdmin");
return Proxy(deployer.deploy_ERC1967Proxy("AnchorStateRegistryProxy", proxyOwner));
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"OptimismPortalProxy": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional
"DataAvailabilityChallenge": "<ADDRESS_11>", // optional
"OptimismPortalProxy": "<ADDRESS_12>",
"SystemConfigProxy": "<ADDRESS_13>",
"L1StandardBridgeProxy": "<ADDRESS_14>",
"L1CrossDomainMessengerProxy": "<ADDRESS_15>",
"OptimismMintableERC20FactoryProxy": "<ADDRESS_16>",
"L1ERC721BridgeProxy": "<ADDRESS_17>",
"DisputeGameFactoryProxy": "<ADDRESS_18>",
"L2OutputOracleProxy": "<ADDRESS_19>",
"DelayedWETHProxy": "<ADDRESS_20>",
"PermissionedDelayedWETHProxy": "<ADDRESS_21>",
"AnchorStateRegistryProxy": "<ADDRESS_22>"
}
click on ✕ button to close
4.1L : Transfer AddressManager Ownership
forge script script/401L_TransferAddressManagerOwnershipScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {AddressManager} from "@redprint-core/legacy/AddressManager.sol";
import {IDeployer, getDeployer} from "@redprint-deploy/deployer/DeployScript.sol";
import {Script} from "@redprint-forge-std/Script.sol";
import {Vm, VmSafe} from "@redprint-forge-std/Vm.sol";
import {console} from "@redprint-forge-std/console.sol";
contract TransferAddressManagerOwnershipScript is Script {
IDeployer deployerProcedue;
function run() public {
deployerProcedue = getDeployer();
deployerProcedue.setAutoSave(true);
console.log("Transferring AddressManager ownership to ProxyAdmin");
AddressManager addressManager = AddressManager(deployerProcedue.mustGetAddress("AddressManager"));
address owner = addressManager.owner();
address proxyAdmin = deployerProcedue.mustGetAddress("ProxyAdmin");
(VmSafe.CallerMode mode ,address msgSender, ) = vm.readCallers();
if (owner != proxyAdmin) {
if(mode != VmSafe.CallerMode.Broadcast && msgSender != owner) {
console.log("Pranking owner ...");
vm.prank(owner);
} else {
console.log("Broadcasting ...");
vm.broadcast(owner);
}
addressManager.transferOwnership(proxyAdmin);
console.log("AddressManager ownership transferred to %s", proxyAdmin);
}
require(addressManager.owner() == proxyAdmin);
}
}