Skip to content

Commit

Permalink
Remove unwraps from contracts module
Browse files Browse the repository at this point in the history
  • Loading branch information
LeanSerra committed Nov 26, 2024
1 parent 99c5fef commit 82a89ea
Showing 1 changed file with 110 additions and 49 deletions.
159 changes: 110 additions & 49 deletions crates/l2/contracts/deployer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ use std::{
};
use tracing::warn;

#[derive(Debug, thiserror::Error)]
pub enum DeployError {
#[error("Failed to lock SALT: {0}")]
FailedToLockSALT(String),
#[error("The path is not a valid utf-8 string")]
FailedToGetStringFromPath,
}

// 0x4e59b44847b379578588920cA78FbF26c0B4956C
const DETERMINISTIC_CREATE2_ADDRESS: Address = H160([
0x4e, 0x59, 0xb4, 0x48, 0x47, 0xb3, 0x79, 0x57, 0x85, 0x88, 0x92, 0x0c, 0xa7, 0x8f, 0xbf, 0x26,
Expand All @@ -28,19 +36,34 @@ lazy_static::lazy_static! {

#[tokio::main]
async fn main() {
let (
let Ok((
deployer,
deployer_private_key,
committer_private_key,
verifier_private_key,
contract_verifier_address,
eth_client,
contracts_path,
) = setup();
download_contract_deps(&contracts_path);
compile_contracts(&contracts_path);
let (on_chain_proposer, bridge_address) =
deploy_contracts(deployer, deployer_private_key, &eth_client, &contracts_path).await;
)) = setup()
else {
panic!("Failed on setup");
};
if let Err(e) = download_contract_deps(&contracts_path) {
panic!("Failed to download contracts {e}");
};
if let Err(e) = compile_contracts(&contracts_path) {
panic!("Failed to compile contracts {e}");
};

let on_chain_proposer;
let bridge_address;
match deploy_contracts(deployer, deployer_private_key, &eth_client, &contracts_path).await {
Ok((ocp, ba)) => {
on_chain_proposer = ocp;
bridge_address = ba;
}
Err(e) => panic!("Failed to deploy contracts {e}"),
};

initialize_contracts(
deployer,
Expand All @@ -57,8 +80,8 @@ async fn main() {
let env_lines = read_env_as_lines().expect("Failed to read env file as lines.");

let mut wr_lines: Vec<String> = Vec::new();
for line in env_lines {
let mut line = line.unwrap();
let mut env_lines_iter = env_lines.into_iter();
while let Some(Ok(mut line)) = env_lines_iter.next() {
if let Some(eq) = line.find('=') {
let (envar, _) = line.split_at(eq);
line = match envar {
Expand All @@ -76,15 +99,18 @@ async fn main() {
write_env(wr_lines).expect("Failed to write changes to the .env file.");
}

fn setup() -> (
Address,
SecretKey,
Address,
Address,
Address,
EthClient,
PathBuf,
) {
fn setup() -> Result<
(
Address,
SecretKey,
Address,
Address,
Address,
EthClient,
PathBuf,
),
DeployError,
> {
if let Err(e) = read_env_file() {
warn!("Failed to read .env file: {e}");
}
Expand Down Expand Up @@ -127,7 +153,9 @@ fn setup() -> (
match input.trim().to_lowercase().as_str() {
"true" | "1" => (),
"false" | "0" => {
let mut salt = SALT.lock().unwrap();
let mut salt = SALT
.lock()
.map_err(|err| DeployError::FailedToLockSALT(err.to_string()))?;
*salt = H256::random();
}
_ => panic!("Invalid boolean string: {input}"),
Expand All @@ -136,18 +164,18 @@ fn setup() -> (
.expect("DEPLOYER_CONTRACT_VERIFIER not set")
.parse()
.expect("Malformed DEPLOYER_CONTRACT_VERIFIER");
(
Ok((
deployer,
deployer_private_key,
committer,
verifier,
contract_verifier_address,
eth_client,
contracts_path,
)
))
}

fn download_contract_deps(contracts_path: &Path) {
fn download_contract_deps(contracts_path: &Path) -> Result<(), DeployError> {
std::fs::create_dir_all(contracts_path.join("lib")).expect("Failed to create contracts/lib");
Command::new("git")
.arg("clone")
Expand All @@ -156,15 +184,16 @@ fn download_contract_deps(contracts_path: &Path) {
contracts_path
.join("lib/openzeppelin-contracts")
.to_str()
.unwrap(),
.ok_or(DeployError::FailedToGetStringFromPath)?,
)
.spawn()
.expect("Failed to spawn git")
.wait()
.expect("Failed to wait for git");
Ok(())
}

fn compile_contracts(contracts_path: &Path) {
fn compile_contracts(contracts_path: &Path) -> Result<(), DeployError> {
// Both the contract path and the output path are relative to where the Makefile is.
assert!(
Command::new("solc")
Expand All @@ -173,13 +202,22 @@ fn compile_contracts(contracts_path: &Path) {
contracts_path
.join("src/l1/OnChainProposer.sol")
.to_str()
.unwrap()
.ok_or(DeployError::FailedToGetStringFromPath)?
)
.arg("-o")
.arg(contracts_path.join("solc_out").to_str().unwrap())
.arg(
contracts_path
.join("solc_out")
.to_str()
.ok_or(DeployError::FailedToGetStringFromPath)?,
)
.arg("--overwrite")
.arg("--allow-paths")
.arg(contracts_path.to_str().unwrap())
.arg(
contracts_path
.to_str()
.ok_or(DeployError::FailedToGetStringFromPath)?,
)
.spawn()
.expect("Failed to spawn solc")
.wait()
Expand All @@ -195,28 +233,38 @@ fn compile_contracts(contracts_path: &Path) {
contracts_path
.join("src/l1/CommonBridge.sol")
.to_str()
.unwrap()
.ok_or(DeployError::FailedToGetStringFromPath)?,
)
.arg("-o")
.arg(contracts_path.join("solc_out").to_str().unwrap())
.arg(
contracts_path
.join("solc_out")
.to_str()
.ok_or(DeployError::FailedToGetStringFromPath)?,
)
.arg("--overwrite")
.arg("--allow-paths")
.arg(contracts_path.to_str().unwrap())
.arg(
contracts_path
.to_str()
.ok_or(DeployError::FailedToGetStringFromPath)?,
)
.spawn()
.expect("Failed to spawn solc")
.wait()
.expect("Failed to wait for solc")
.success(),
"Failed to compile CommonBridge.sol"
);
Ok(())
}

async fn deploy_contracts(
deployer: Address,
deployer_private_key: SecretKey,
eth_client: &EthClient,
contracts_path: &Path,
) -> (Address, Address) {
) -> Result<(Address, Address), DeployError> {
let deploy_frames = spinner!(["📭❱❱", "❱📬❱", "❱❱📫"], 220);

let mut spinner = Spinner::new(
Expand All @@ -226,7 +274,8 @@ async fn deploy_contracts(
);

let (on_chain_proposer_deployment_tx_hash, on_chain_proposer_address) =
deploy_on_chain_proposer(deployer, deployer_private_key, eth_client, contracts_path).await;
deploy_on_chain_proposer(deployer, deployer_private_key, eth_client, contracts_path)
.await?;

let msg = format!(
"OnChainProposer:\n\tDeployed at address {} with tx hash {}",
Expand All @@ -237,7 +286,7 @@ async fn deploy_contracts(

let mut spinner = Spinner::new(deploy_frames, "Deploying CommonBridge", Color::Cyan);
let (bridge_deployment_tx_hash, bridge_address) =
deploy_bridge(deployer, deployer_private_key, eth_client, contracts_path).await;
deploy_bridge(deployer, deployer_private_key, eth_client, contracts_path).await?;

let msg = format!(
"CommonBridge:\n\tDeployed at address {} with tx hash {}",
Expand All @@ -246,15 +295,15 @@ async fn deploy_contracts(
);
spinner.success(&msg);

(on_chain_proposer_address, bridge_address)
Ok((on_chain_proposer_address, bridge_address))
}

async fn deploy_on_chain_proposer(
deployer: Address,
deployer_private_key: SecretKey,
eth_client: &EthClient,
contracts_path: &Path,
) -> (H256, Address) {
) -> Result<(H256, Address), DeployError> {
let on_chain_proposer_init_code = hex::decode(
std::fs::read_to_string(contracts_path.join("solc_out/OnChainProposer.bin"))
.expect("Failed to read on_chain_proposer_init_code"),
Expand All @@ -268,17 +317,17 @@ async fn deploy_on_chain_proposer(
&on_chain_proposer_init_code,
eth_client,
)
.await;
.await?;

(deploy_tx_hash, on_chain_proposer)
Ok((deploy_tx_hash, on_chain_proposer))
}

async fn deploy_bridge(
deployer: Address,
deployer_private_key: SecretKey,
eth_client: &EthClient,
contracts_path: &Path,
) -> (H256, Address) {
) -> Result<(H256, Address), DeployError> {
let mut bridge_init_code = hex::decode(
std::fs::read_to_string(contracts_path.join("solc_out/CommonBridge.bin"))
.expect("Failed to read bridge_init_code"),
Expand All @@ -300,18 +349,24 @@ async fn deploy_bridge(
&bridge_init_code.into(),
eth_client,
)
.await;
.await?;

(deploy_tx_hash, bridge_address)
Ok((deploy_tx_hash, bridge_address))
}

async fn create2_deploy(
deployer: Address,
deployer_private_key: SecretKey,
init_code: &Bytes,
eth_client: &EthClient,
) -> (H256, Address) {
let calldata = [SALT.lock().unwrap().as_bytes(), init_code].concat();
) -> Result<(H256, Address), DeployError> {
let calldata = [
SALT.lock()
.map_err(|err| DeployError::FailedToLockSALT(err.to_string()))?
.as_bytes(),
init_code,
]
.concat();
let deploy_tx = eth_client
.build_eip1559_transaction(
DETERMINISTIC_CREATE2_ADDRESS,
Expand All @@ -330,26 +385,28 @@ async fn create2_deploy(

wait_for_transaction_receipt(deploy_tx_hash, eth_client).await;

let deployed_address = create2_address(keccak(init_code));
let deployed_address = create2_address(keccak(init_code))?;

(deploy_tx_hash, deployed_address)
Ok((deploy_tx_hash, deployed_address))
}

fn create2_address(init_code_hash: H256) -> Address {
Address::from_slice(
fn create2_address(init_code_hash: H256) -> Result<Address, DeployError> {
Ok(Address::from_slice(
keccak(
[
&[0xff],
DETERMINISTIC_CREATE2_ADDRESS.as_bytes(),
SALT.lock().unwrap().as_bytes(),
SALT.lock()
.map_err(|err| DeployError::FailedToLockSALT(err.to_string()))?
.as_bytes(),
init_code_hash.as_bytes(),
]
.concat(),
)
.as_bytes()
.get(12..)
.expect("Failed to get create2 address"),
)
))
}

#[allow(clippy::too_many_arguments)]
Expand Down Expand Up @@ -556,8 +613,12 @@ mod test {
}
}

download_contract_deps(Path::new("contracts"));
compile_contracts(Path::new("contracts"));
if download_contract_deps(Path::new("contracts")).is_err() {
panic!()
};
if compile_contracts(Path::new("contracts")).is_err() {
panic!()
};

std::fs::remove_dir_all(solc_out).unwrap();
std::fs::remove_dir_all(lib).unwrap();
Expand Down

0 comments on commit 82a89ea

Please sign in to comment.