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

feat(era-revm): Move era-revm to foundry #191

Merged
merged 3 commits into from
Dec 12, 2023
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
53 changes: 30 additions & 23 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ members = [
"crates/forge/",
"crates/macros/",
"crates/test-utils/",
"crates/era-cheatcodes/",
"crates/zkcast",
"crates/zkforge",
]
Expand Down Expand Up @@ -126,14 +127,14 @@ foundry-evm-fuzz = { path = "crates/evm/fuzz" }
foundry-evm-traces = { path = "crates/evm/traces" }
foundry-macros = { path = "crates/macros" }
foundry-test-utils = { path = "crates/test-utils" }
era_cheatcodes = { path = "crates/era-cheatcodes" }

foundry-block-explorers = { version = "0.1.2", default-features = false }

## revm
# no default features to avoid c-kzg
revm = { version = "3", default-features = false }
revm-primitives = { version = "1", default-features = false }
era_revm = { git="https://github.com/matter-labs/era-revm", rev = "2662bb19427a421662a7e463cf1ed6a15da361e5" }

## ethers
ethers = { version = "2.0", default-features = false }
Expand All @@ -157,6 +158,15 @@ alloy-chains = "0.1.4"
alloy-rlp = "0.3.3"
solang-parser = "=0.3.3"

## zksync
era_test_node = { git = "https://github.com/matter-labs/era-test-node.git", rev = "21b48af90a9f9d98ec38cb93a32c119a3266f401" }
zksync_basic_types = { git = "https://github.com/matter-labs/zksync-era.git", rev = "bd268ac02bc3530c1d3247cb9496c3e13c2e52d9" }
zksync_types = { git = "https://github.com/matter-labs/zksync-era.git", rev = "bd268ac02bc3530c1d3247cb9496c3e13c2e52d9" }
zksync_state = { git = "https://github.com/matter-labs/zksync-era.git", rev = "bd268ac02bc3530c1d3247cb9496c3e13c2e52d9" }
multivm = { git = "https://github.com/matter-labs/zksync-era.git", rev = "bd268ac02bc3530c1d3247cb9496c3e13c2e52d9" }
zksync_web3_decl = { git = "https://github.com/matter-labs/zksync-era.git", rev = "bd268ac02bc3530c1d3247cb9496c3e13c2e52d9" }
zksync_utils = { git = "https://github.com/matter-labs/zksync-era.git", rev = "bd268ac02bc3530c1d3247cb9496c3e13c2e52d9" }

## misc
chrono = { version = "0.4", default-features = false, features = ["clock", "std"] }
color-eyre = "0.6"
Expand Down
5 changes: 4 additions & 1 deletion crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ ethers-providers = { workspace = true, features = ["ws", "ipc"] }

# zksync
zksync-web3-rs = {git = "https://github.com/lambdaclass/zksync-web3-rs.git", rev = "70327ae5413c517bd4d27502507cdd96ee40cd22"}
era_revm = { workspace = true }
zksync_basic_types.workspace = true
zksync_utils.workspace = true
revm.workspace = true

anyhow = {version = "1.0.70"}
dirs = {version = "5.0.0"}
ansi_term = "0.12.1"
Expand Down
2 changes: 1 addition & 1 deletion crates/common/src/zk_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ impl ZkSolc {
.collect();

let packed_bytecode = Bytes::from(
era_revm::factory_deps::PackedEraBytecode::new(
foundry_common::zk_utils::factory_deps::PackedEraBytecode::new(
contract.hash.as_ref().unwrap().clone(),
contract.evm.bytecode.as_ref().unwrap().object.clone(),
factory_deps,
Expand Down
101 changes: 101 additions & 0 deletions crates/common/src/zk_utils/conversion_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/// Conversion between REVM units and zkSync units.
use revm::primitives::U256 as revmU256;
use revm::primitives::{Address, B256};

use zksync_basic_types::{H160, H256, U256};
use zksync_utils::h256_to_u256;

/// Convert address to h160
pub fn address_to_h160(i: Address) -> H160 {
H160::from(i.0 .0)
}

/// Convert h160 to address
pub fn h160_to_address(i: H160) -> Address {
i.as_fixed_bytes().into()
}

/// Convert u256 to b256
pub fn u256_to_b256(i: U256) -> B256 {
let mut payload: [u8; 32] = [0; 32];
i.to_big_endian(&mut payload);
B256::from_slice(&payload)
}

/// Convert u256 to revm u256
pub fn u256_to_revm_u256(i: U256) -> revmU256 {
let mut payload: [u8; 32] = [0; 32];
i.to_big_endian(&mut payload);
revmU256::from_be_bytes(payload)
}

/// Convert revm u256 to u256
pub fn revm_u256_to_u256(i: revmU256) -> U256 {
U256::from_big_endian(&i.to_be_bytes::<32>())
}

/// Convert revm u256 to h256
pub fn revm_u256_to_h256(i: revmU256) -> H256 {
i.to_be_bytes::<32>().into()
}

/// Convert h256 to revm u256
pub fn h256_to_revm_u256(i: H256) -> revmU256 {
u256_to_revm_u256(h256_to_u256(i))
}

/// Convert h256 to b256
pub fn h256_to_b256(i: H256) -> B256 {
i.to_fixed_bytes().into()
}

/// Convert h256 to h160
pub fn h256_to_h160(i: &H256) -> H160 {
H160::from_slice(&i.0[12..32])
}

#[cfg(test)]
mod test {
use std::str::FromStr;

use zksync_utils::u256_to_h256;

use super::*;

#[test]
fn test_160_conversion() {
let b = Address::from_str("0x000000000000000000000000000000000000800b").unwrap();
let h = address_to_h160(b);
assert_eq!(h.to_string(), "0x0000…800b");
let b2 = h160_to_address(h);
assert_eq!(b, b2);
}

#[test]
fn test_256_conversion() {
let h =
H256::from_str("0xb99acb716b354b9be88d3eaba99ad36792ccdd4349404cbb812adf0b0b14d601")
.unwrap();
let b = h256_to_b256(h);
assert_eq!(
b.to_string(),
"0xb99acb716b354b9be88d3eaba99ad36792ccdd4349404cbb812adf0b0b14d601"
);
let u = h256_to_u256(h);
assert_eq!(
u.to_string(),
"83951375548152864551218308881540843734370423742152710934930688330188941743617"
);

let revm_u = u256_to_revm_u256(u);
assert_eq!(
revm_u.to_string(),
"83951375548152864551218308881540843734370423742152710934930688330188941743617"
);
assert_eq!(u, revm_u256_to_u256(revm_u));

assert_eq!(h, revm_u256_to_h256(revm_u));

assert_eq!(h, u256_to_h256(u));
}
}
75 changes: 75 additions & 0 deletions crates/common/src/zk_utils/factory_deps.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use std::str::FromStr;

use zksync_basic_types::H256;
use zksync_utils::bytecode::hash_bytecode;

/// Factory deps packer.
///
/// EVM assumes that all the necessary bytecodes (factory deps) are present within the original
/// bytecode. In case of Era - they are actually returned separate from the compiler.
///
/// So in order to fit to the REVM / Forge - we "serialize" all the factory deps into
/// one huge "fake" bytecode string - and then pass them around.

/// Struct with the contract bytecode, and all the other factory deps.
#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub struct PackedEraBytecode {
hash: String,
bytecode: String,
factory_deps: Vec<String>,
}

impl PackedEraBytecode {
/// Create a new instance of the `PackedEraBytecode`.
pub fn new(hash: String, bytecode: String, factory_deps: Vec<String>) -> Self {
Self { hash, bytecode, factory_deps }
}

/// Convert the `PackedEraBytecode` into a `Vec<u8>`.
pub fn to_vec(&self) -> Vec<u8> {
serde_json::to_vec(self).unwrap()
}

/// Convert a `Vec<u8>` into a `PackedEraBytecode`.
pub fn from_vec(input: &[u8]) -> Self {
serde_json::from_slice(input).unwrap()
}

/// Convert the `PackedEraBytecode` into a `Vec<u8>`.
pub fn bytecode(&self) -> Vec<u8> {
hex::decode(self.bytecode.clone()).unwrap()
}

/// Get the bytecode hash.
pub fn bytecode_hash(&self) -> H256 {
let h = hash_bytecode(&self.bytecode());
assert_eq!(h, H256::from_str(&self.hash).unwrap());
h
}

/// Get the factory deps.
pub fn factory_deps(&self) -> Vec<Vec<u8>> {
self.factory_deps
.iter()
.chain([&self.bytecode])
.map(|entry| hex::decode(entry).unwrap())
.collect()
}
}

fn ensure_chunkable(bytes: &[u8]) {
assert!(bytes.len() % 32 == 0, "Bytes must be divisible by 32 to split into chunks");
}

/// Convert bytes into 32 bytes chunks.
pub fn bytes_to_chunks(bytes: &[u8]) -> Vec<[u8; 32]> {
ensure_chunkable(bytes);
bytes
.chunks(32)
.map(|el| {
let mut chunk = [0u8; 32];
chunk.copy_from_slice(el);
chunk
})
.collect()
}
Loading