Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Contracts deploy script #26

Merged
merged 11 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ rvgo/test/testdata

rvsol/cache
rvsol/out
rvsol/broadcast
rvsol/deployments/devnetL1

tests/go-tests/bin

Expand Down
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,11 @@ fuzz-mac:
.PHONY: \
fuzz \
fuzz-mac

OP_PROGRAM_PATH ?= ./op-program-client-riscv.elf

prestate: build-rvgo
./rvgo/bin/asterisc load-elf --path $(OP_PROGRAM_PATH) --out ./rvgo/bin/prestate.json --meta ./rvgo/bin/meta.json
./rvgo/bin/asterisc run --proof-at '=0' --stop-at '=1' --input ./rvgo/bin/prestate.json --meta ./rvgo/bin/meta.json --proof-fmt './rvgo/bin/%d.json' --output ""
mv ./rvgo/bin/0.json ./rvgo/bin/prestate-proof.json
.PHONY: prestate
31 changes: 31 additions & 0 deletions rvsol/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Asterisc VM contract

## Deployment
Currently, Asterisc only supports the local devnet launched from the Optimism monorepo.

### Prerequisites
1. Running local devnet launched from the Optimism monorepo
- Run ```make devnet-up``` in the monorepo root.
- Set the env var `TARGET_L1_RPC_URL` to the L1 RPC endpoint (Local devnet L1: `http://localhost:8545`)
- Set the env var `TARGET_L2_DEPLOYMENT_FILE` to the path of devnet deployment file (`optimism/packages/contracts-bedrock/deployments/devnetL1/.deploy`)
- Set the env var `TARGET_L2_DEPLOY_CONFIG` to the path of devnet deploy config file (`optimism/packages/contracts-bedrock/deploy-config/devnetL1.json`)
2. Asterisc absolute prestate of op-program
- Run ```make op-program-client-riscv``` in `optimism/op-program
- Set the built elf file path to the env var `OP_PROGRAM_PATH` (`optimism/op-program/bin/op-program-client-riscv.elf`)

### How to deploy
1. Build Asterisc binary and contracts
- Run ```make build``` in the project root
2. Generate prestate proof
- Run ```make prestate``` in the project root
3. Run deploy script
pcw109550 marked this conversation as resolved.
Show resolved Hide resolved
- Run ```./scripts/deploy.sh``` in `rvsol`

### Notes
- There are few issues with Foundry.
- Run script directly without manual build does not work with the current version of Foundry (2024-03-15 `3fa0270`).
You **must run** `make build` **before** running the deploy script. ([issue](https://github.com/foundry-rs/foundry/issues/6572))
- Some older version(2024-02-01 `2f4b5db`) of Foundry makes a dependency error reproted above issue.
Use the **latest version** of Foundry!
- The deploy script can be run only once on the devnet because of the `create2` salt.
To rerun the script for dev purpose, you must restart the devnet with `make devnet-clean && make devnet-up` command on the monorepo.
13 changes: 12 additions & 1 deletion rvsol/foundry.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[profile.default]
src = 'src'
out = 'out'
script = 'scripts'
libs = ['lib']
optimizer = true
optimizer_runs = 999999
Expand All @@ -13,10 +14,20 @@ remappings = [
'@lib-keccak/=lib/optimism/packages/contracts-bedrock/lib/lib-keccak/contracts/lib',
'safe-contracts/=lib/optimism/packages/contracts-bedrock/lib/safe-contracts/contracts',
'kontrol-cheatcodes/=lib/optimism/packages/contracts-bedrock/lib/kontrol-cheatcodes/src',
'solady/=lib/optimism/packages/contracts-bedrock/lib/solady/src',
'solady/=lib/optimism/packages/contracts-bedrock/lib/solady/src',

# We need these remappings to use the Optimism monorepo contracts as a library.
'src/dispute=lib/optimism/packages/contracts-bedrock/src/dispute',
'src/libraries=lib/optimism/packages/contracts-bedrock/src/libraries',
ImTei marked this conversation as resolved.
Show resolved Hide resolved

'forge-std/=lib/forge-std/src',
'ds-test/=lib/forge-std/lib/ds-test/src',
]

ffi = true
fs_permissions = [
{ access='read-write', path='./deployments' },
{ access='read', path='./' }
]

# See more config options https://github.com/foundry-rs/foundry/tree/master/config
2 changes: 1 addition & 1 deletion rvsol/lib/optimism
Submodule optimism updated 567 files
162 changes: 162 additions & 0 deletions rvsol/scripts/Artifacts.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import { console2 as console } from "forge-std/console2.sol";
import { stdJson } from "forge-std/StdJson.sol";
import { Vm } from "forge-std/Vm.sol";
import { Config } from "scripts/Config.sol";

/// @notice Represents a deployment. Is serialized to JSON as a key/value
/// pair. Can be accessed from within scripts.
struct Deployment {
string name;
address payable addr;
}

/// @title Artifacts
abstract contract Artifacts {
/// @notice Foundry cheatcode VM.
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));

/// @notice Error for when attempting to fetch a deployment and it does not exist
error DeploymentDoesNotExist(string);
/// @notice Error for when trying to save an invalid deployment
error InvalidDeployment(string);

/// @notice The set of chain deployments that have been already deployed.
mapping(string => Deployment) internal _chainDeployments;
/// @notice The set of deployments that have been done during execution.
mapping(string => Deployment) internal _namedDeployments;
/// @notice The path to the deployment artifact that is being written to.
string internal deploymentOutfile;

/// @notice Accepts a filepath and then ensures that the directory
/// exists for the file to live in.
function ensurePath(string memory _path) internal {
(, bytes memory returndata) =
address(vm).call(abi.encodeWithSignature("split(string,string)", _path, string("/")));
string[] memory outputs = abi.decode(returndata, (string[]));

string memory path = "";
for (uint256 i = 0; i < outputs.length - 1; i++) {
path = string.concat(path, outputs[i], "/");
}
vm.createDir(path, true);
}

/// @notice Setup function. The arguments here
function setUp() public virtual {
deploymentOutfile = Config.deploymentOutfile();
console.log("Writing artifact to %s", deploymentOutfile);
ensurePath(deploymentOutfile);

// Load addresses from a JSON file if the TARGET_L2_DEPLOYMENT_FILE environment variable
// is set. Great for loading addresses from `superchain-registry`.
string memory addresses = Config.chainDeploymentFile();
if (bytes(addresses).length > 0) {
console.log("Loading chain addresses from %s", addresses);
_loadChainAddresses(addresses);
}
}

/// @notice Populates the addresses to be used in a script based on a JSON file.
/// The JSON key is the name of the contract and the value is an address.
function _loadChainAddresses(string memory _path) internal {
string[] memory commands = new string[](3);
commands[0] = "bash";
commands[1] = "-c";
commands[2] = string.concat("jq -cr < ", _path);
string memory json = string(vm.ffi(commands));
string[] memory keys = vm.parseJsonKeys(json, "");
for (uint256 i; i < keys.length; i++) {
string memory key = keys[i];
address addr = stdJson.readAddress(json, string.concat("$.", key));
Deployment memory deployment = Deployment({ name: key, addr: payable(addr) });
_chainDeployments[key] = deployment;
console.log("Loading %s: %s", key, addr);
}
}

/// @notice Appends a deployment to disk as a JSON deploy artifact.
/// @param _name The name of the deployment.
/// @param _deployed The address of the deployment.
function save(string memory _name, address _deployed) public {
if (bytes(_name).length == 0) {
revert InvalidDeployment("EmptyName");
}
if (bytes(_namedDeployments[_name].name).length > 0) {
revert InvalidDeployment("AlreadyExists");
}

console.log("Saving %s: %s", _name, _deployed);
Deployment memory deployment = Deployment({ name: _name, addr: payable(_deployed) });
_namedDeployments[_name] = deployment;
_appendDeployment(_name, _deployed);
}

/// @notice Adds a deployment to the temp deployments file
function _appendDeployment(string memory _name, address _deployed) internal {
vm.writeJson({ json: stdJson.serialize("", _name, _deployed), path: deploymentOutfile });
}

/// @notice Returns a deployment that is suitable to be used to interact with contracts.
/// @param _name The name of the deployment.
/// @return The deployment.
function getChainDeployment(string memory _name) public view returns (Deployment memory) {
return _chainDeployments[_name];
}

/// @notice Returns the address of a deployment. Also handles the predeploys.
/// @param _name The name of the deployment.
/// @return The address of the deployment. May be `address(0)` if the deployment does not
/// exist.
function getChainAddress(string memory _name) public view returns (address payable) {
Deployment memory existing = _chainDeployments[_name];
if (existing.addr != address(0)) {
if (bytes(existing.name).length == 0) {
return payable(address(0));
}
return existing.addr;
}

return payable(address(0));
}

/// @notice Returns the address of a deployment and reverts if the deployment
/// does not exist.
/// @return The address of the deployment.
function mustGetChainAddress(string memory _name) public view returns (address payable) {
address addr = getChainAddress(_name);
if (addr == address(0)) {
revert DeploymentDoesNotExist(_name);
}
return payable(addr);
}

/// @notice Returns the address of a deployment. Also handles the predeploys.
/// @param _name The name of the deployment.
/// @return The address of the deployment. May be `address(0)` if the deployment does not
/// exist.
function getAddress(string memory _name) public view returns (address payable) {
Deployment memory existing = _namedDeployments[_name];
if (existing.addr != address(0)) {
if (bytes(existing.name).length == 0) {
return payable(address(0));
}
return existing.addr;
}

return payable(address(0));
}

/// @notice Returns the address of a deployment and reverts if the deployment
/// does not exist.
/// @return The address of the deployment.
function mustGetAddress(string memory _name) public view returns (address payable) {
address addr = getAddress(_name);
if (addr == address(0)) {
revert DeploymentDoesNotExist(_name);
}
return payable(addr);
}
}
16 changes: 16 additions & 0 deletions rvsol/scripts/Chains.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @notice Chain IDs for the various networks.
library Chains {
uint256 internal constant Mainnet = 1;
uint256 internal constant OPMainnet = 10;
uint256 internal constant Goerli = 5;
uint256 internal constant OPGoerli = 420;
uint256 internal constant Sepolia = 11155111;
uint256 internal constant OPSepolia = 11155420;
uint256 internal constant LocalDevnet = 900;
uint256 internal constant OPLocalDevnet = 901;
uint256 internal constant GethDevnet = 1337;
uint256 internal constant Hardhat = 31337;
}
81 changes: 81 additions & 0 deletions rvsol/scripts/Config.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

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

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

/// @title Config
library Config {
/// @notice Foundry cheatcode VM.
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));

/// @notice Returns the path on the local filesystem where the deployment artifact is
/// written to disk after doing a deployment.
function deploymentOutfile() internal view returns (string memory _env) {
_env = vm.envOr(
"DEPLOYMENT_OUTFILE", string.concat(vm.projectRoot(), "/deployments/", _getDeploymentContext(), "/.deploy")
);
}

/// @notice Returns the path on the local filesystem where the deploy config is
function deployConfigPath() internal view returns (string memory _env) {
_env = vm.envOr(
"TARGET_L2_DEPLOY_CONFIG",
string.concat(vm.projectRoot(), "/deploy-config/", _getDeploymentContext(), ".json")
);
}

/// @notice Returns the path on the local filesystem where the target chain deployment artifact is written.
function chainDeploymentFile() internal view returns (string memory _env) {
_env = vm.envOr("TARGET_L2_DEPLOYMENT_FILE", string("./.deploy"));
}

/// @notice Returns the chainid from the EVM context or the value of the CHAIN_ID env var as
/// an override.
function chainID() internal view returns (uint256 _env) {
_env = vm.envOr("CHAIN_ID", block.chainid);
}

/// @notice Returns the deployment context which was only useful in the hardhat deploy style
/// of deployments. It is now DEPRECATED and will be removed in the future.
function deploymentContext() internal view returns (string memory _env) {
_env = vm.envOr("DEPLOYMENT_CONTEXT", string(""));
}

/// @notice The CREATE2 salt to be used when deploying the implementations.
function implSalt() internal view returns (string memory _env) {
_env = vm.envOr("IMPL_SALT", string("ethers phoenix"));
}

/// @notice The context of the deployment is used to namespace the artifacts.
/// An unknown context will use the chainid as the context name.
/// This is legacy code and should be removed in the future.
function _getDeploymentContext() private view returns (string memory) {
string memory context = deploymentContext();
if (bytes(context).length > 0) {
return context;
}

uint256 chainid = Config.chainID();
if (chainid == Chains.Mainnet) {
return "mainnet";
} else if (chainid == Chains.Goerli) {
return "goerli";
} else if (chainid == Chains.OPGoerli) {
return "optimism-goerli";
} else if (chainid == Chains.OPMainnet) {
return "optimism-mainnet";
} else if (chainid == Chains.LocalDevnet || chainid == Chains.GethDevnet) {
return "devnetL1";
} else if (chainid == Chains.Hardhat) {
return "hardhat";
} else if (chainid == Chains.Sepolia) {
return "sepolia";
} else if (chainid == Chains.OPSepolia) {
return "optimism-sepolia";
} else {
return vm.toString(chainid);
}
}
}
Loading
Loading