Skip to content

Commit

Permalink
scripts: Stage 1.4 deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
pcw109550 committed Jun 17, 2024
1 parent 5a20396 commit bfff21a
Show file tree
Hide file tree
Showing 3 changed files with 230 additions and 0 deletions.
1 change: 1 addition & 0 deletions rvsol/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ remappings = [
'@openzeppelin/contracts/=lib/optimism/packages/contracts-bedrock/lib/openzeppelin-contracts/contracts',
'@lib-keccak/=lib/optimism/packages/contracts-bedrock/lib/lib-keccak/contracts/lib',
'@solady/=lib/optimism/packages/contracts-bedrock/lib/solady/src',
'@rari-capital/solmate=lib/optimism/packages/contracts-bedrock/lib/solmate',
'safe-contracts/=lib/optimism/packages/contracts-bedrock/lib/safe-contracts/contracts',

# We need these remappings to use the Optimism monorepo contracts as a library.
Expand Down
205 changes: 205 additions & 0 deletions rvsol/scripts/Deploy_Stage_1_4.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import { Deployer } from "scripts/Deployer.sol";
import { IPreimageOracle } from "@optimism/src/cannon/interfaces/IPreimageOracle.sol";

import { Config } from "scripts/Config.sol";

import { DisputeGameFactory } from "@optimism/src/dispute/DisputeGameFactory.sol";
import { DelayedWETH } from "@optimism/src/dispute/weth/DelayedWETH.sol";
import { AnchorStateRegistry } from "@optimism/src/dispute/AnchorStateRegistry.sol";
import { PreimageOracle } from "@optimism/src/cannon/PreimageOracle.sol";
import { RISCV } from "../src/RISCV.sol";
import { Types } from "@optimism/scripts/Types.sol";
import { OutputRoot, Hash, GameTypes } from "@optimism/src/dispute/lib/Types.sol";
import { console2 as console } from "forge-std/console2.sol";

import { ProxyAdmin } from "@optimism/src/universal/ProxyAdmin.sol";
import { AddressManager } from "@optimism/src/legacy/AddressManager.sol";
import { Proxy } from "@optimism/src/universal/Proxy.sol";
import { EIP1967Helper } from "@optimism/test/mocks/EIP1967Helper.sol";

contract Deploy is Deployer {
/// @notice Modifier that wraps a function in broadcasting.
modifier broadcast() {
vm.startBroadcast(msg.sender);
_;
vm.stopBroadcast();
}

/// @inheritdoc Deployer
function name() public pure override returns (string memory name_) {
name_ = "Deploy_Stage_1_4";
}

function run() public {
// Intentionally not using Safe contracts for brevity
// We do not need AddressManager because no legacies
deployProxyAdmin();

deployProxies();
deployImplementations();
initializeImplementations();
}

/// @notice The create2 salt used for deployment of the contract implementations.
/// Using this helps to reduce config across networks as the implementation
/// addresses will be the same across networks when deployed with create2.
function _implSalt() internal view returns (bytes32) {
return keccak256(bytes(Config.implSalt()));
}

/// @notice Deploy RISCV
function deployRiscv() public broadcast returns (address addr_) {
console.log("Deploying RISCV implementation");
RISCV riscv = new RISCV{ salt: _implSalt() }(IPreimageOracle(mustGetChainAddress("PreimageOracle")));
save("RISCV", address(riscv));
console.log("RISCV deployed at %s", address(riscv));
addr_ = address(riscv);
}

/// @notice Deploy all of the implementations
function deployImplementations() public {
console.log("Deploying implementations");
deployDisputeGameFactory();
deployRiscv();
deployAnchorStateRegistry();
}

/// @notice Deploy all of the proxies
function deployProxies() public {
console.log("Deploying proxies");
deployERC1967Proxy("DisputeGameFactoryProxy");
deployERC1967Proxy("AnchorStateRegistryProxy");
}

/// @notice Deploy the ProxyAdmin
function deployProxyAdmin() public broadcast returns (address addr_) {
console.log("Deploying ProxyAdmin");
ProxyAdmin admin = new ProxyAdmin({ _owner: msg.sender });
require(admin.owner() == msg.sender);

save("ProxyAdmin", address(admin));
console.log("ProxyAdmin deployed at %s", address(admin));
addr_ = address(admin);
}

/// @notice Deploy the DisputeGameFactory
function deployDisputeGameFactory() public broadcast returns (address addr_) {
console.log("Deploying DisputeGameFactory implementation");
DisputeGameFactory disputeGameFactory = new DisputeGameFactory{ salt: _implSalt() }();
save("DisputeGameFactory", address(disputeGameFactory));
console.log("DisputeGameFactory deployed at %s", address(disputeGameFactory));

// Check that the contract is initialized
assertSlotValueIsOne({ _contractAddress: address(disputeGameFactory), _slot: 0, _offset: 0 });
require(disputeGameFactory.owner() == address(0));

addr_ = address(disputeGameFactory);
}

/// @notice Deploy the AnchorStateRegistry
function deployAnchorStateRegistry() public broadcast returns (address addr_) {
console.log("Deploying AnchorStateRegistry implementation");
AnchorStateRegistry anchorStateRegistry =
new AnchorStateRegistry{ salt: _implSalt() }(DisputeGameFactory(mustGetAddress("DisputeGameFactory")));
save("AnchorStateRegistry", address(anchorStateRegistry));
console.log("AnchorStateRegistry deployed at %s", address(anchorStateRegistry));

addr_ = address(anchorStateRegistry);
}

/// @notice Initialize all of the implementations
function initializeImplementations() public {
console.log("Initializing implementations");
initializeDisputeGameFactory();
initializeAnchorStateRegistry();
}

/// @notice Initialize the DisputeGameFactory
function initializeDisputeGameFactory() public broadcast {
console.log("Upgrading and initializing DisputeGameFactory");
address disputeGameFactoryProxy = mustGetAddress("DisputeGameFactoryProxy");
address disputeGameFactory = mustGetAddress("DisputeGameFactory");

_upgradeAndCall({
_proxy: payable(disputeGameFactoryProxy),
_implementation: disputeGameFactory,
_innerCallData: abi.encodeCall(DisputeGameFactory.initialize, (msg.sender))
});

string memory version = DisputeGameFactory(disputeGameFactoryProxy).version();
console.log("DisputeGameFactory version: %s", version);

// Check that the contract is initialized
assertSlotValueIsOne({ _contractAddress: address(disputeGameFactoryProxy), _slot: 0, _offset: 0 });
require(DisputeGameFactory(disputeGameFactoryProxy).owner() == msg.sender);
}

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

AnchorStateRegistry.StartingAnchorRoot[] memory roots = new AnchorStateRegistry.StartingAnchorRoot[](1);
roots[0] = AnchorStateRegistry.StartingAnchorRoot({
gameType: GameTypes.ASTERISC,
outputRoot: OutputRoot({
root: Hash.wrap(cfg.faultGameGenesisOutputRoot()),
l2BlockNumber: cfg.faultGameGenesisBlock()
})
});

_upgradeAndCall({
_proxy: payable(anchorStateRegistryProxy),
_implementation: anchorStateRegistry,
_innerCallData: abi.encodeCall(AnchorStateRegistry.initialize, (roots))
});

string memory version = AnchorStateRegistry(payable(anchorStateRegistryProxy)).version();
console.log("AnchorStateRegistry version: %s", version);
}

function assertSlotValueIsOne(address _contractAddress, uint256 _slot, uint256 _offset) internal view {
bytes32 slotVal = vm.load(_contractAddress, bytes32(_slot));
require(
uint8((uint256(slotVal) >> (_offset * 8)) & 0xFF) == uint8(1),
"Storage value is not 1 at the given slot and offset"
);
}

function _upgradeAndCall(address _proxy, address _implementation, bytes memory _innerCallData) internal {
ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin"));
proxyAdmin.upgradeAndCall(payable(_proxy), _implementation, _innerCallData);
}

/// @notice Deploys an ERC1967Proxy contract with the ProxyAdmin as the owner.
/// @param _name The name of the proxy contract to be deployed.
/// @return addr_ The address of the deployed proxy contract.
function deployERC1967Proxy(string memory _name) public returns (address addr_) {
addr_ = deployERC1967ProxyWithOwner(_name, mustGetAddress("ProxyAdmin"));
}

/// @notice Deploys an ERC1967Proxy contract with a specified owner.
/// @param _name The name of the proxy contract to be deployed.
/// @param _proxyOwner The address of the owner of the proxy contract.
/// @return addr_ The address of the deployed proxy contract.
function deployERC1967ProxyWithOwner(
string memory _name,
address _proxyOwner
)
public
broadcast
returns (address addr_)
{
console.log(string.concat("Deploying ERC1967 proxy for ", _name));
Proxy proxy = new Proxy({ _admin: _proxyOwner });

require(EIP1967Helper.getAdmin(address(proxy)) == _proxyOwner);

save(_name, address(proxy));
console.log(" at %s", address(proxy));
addr_ = address(proxy);
}
}
24 changes: 24 additions & 0 deletions rvsol/scripts/deploy_stage_1_4.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -eo pipefail

TARGET_L1_RPC_URL="${TARGET_L1_RPC_URL:-"http://localhost:8545"}"
# foundry pre-funded account #4: gnosis safe's owner(0x90F79bf6EB2c4f870365E785982E1f101E93b906)
# DEPLOY_PRIVATE_KEY="${DEPLOY_PRIVATE_KEY:-"0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6"}"
DEPLOY_PRIVATE_KEY="${DEPLOY_PRIVATE_KEY:-"0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a"}"

if [ -z "${TARGET_L2_DEPLOYMENT_FILE}" ]; then
echo "TARGET_L2_DEPLOYMENT_FILE is not set. Must point target chain deployment file (optimism/packages/contracts-bedrock/deployments/devnetL1/.deploy)"
exit 1
fi

if [ -z "${TARGET_L2_DEPLOY_CONFIG}" ]; then
echo "TARGET_L2_DEPLOY_CONFIG is not set. Must point target chain deploy config file (optimism/packages/contracts-bedrock/deploy-config/devnetL1.json)"
exit 1
fi
SCRIPTS_DIR="$(dirname "$(realpath "$0")")"
LOCAL_DEPLOY_CONFIG_PATH="$(dirname "${SCRIPTS_DIR}")/deploy-config.json"
cp "$TARGET_L2_DEPLOY_CONFIG" "$LOCAL_DEPLOY_CONFIG_PATH"


echo "> Deploying contracts"
TARGET_L2_DEPLOY_CONFIG=$LOCAL_DEPLOY_CONFIG_PATH forge script -vvv "${SCRIPTS_DIR}"/Deploy_Stage_1_4.sol:Deploy --rpc-url "$TARGET_L1_RPC_URL" --broadcast --private-key "$DEPLOY_PRIVATE_KEY"

0 comments on commit bfff21a

Please sign in to comment.