diff --git a/Cargo.lock b/Cargo.lock index f882991..91f6899 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5657,6 +5657,7 @@ dependencies = [ "semver 1.0.26", "serde", "serde_json", + "subxt 0.44.0", "tokio", "tracing", "tracing-appender", diff --git a/assets/revive_metadata.scale b/assets/revive_metadata.scale index 68c0a1e..461d071 100644 Binary files a/assets/revive_metadata.scale and b/assets/revive_metadata.scale differ diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 63c8275..2b0f76f 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -37,6 +37,7 @@ schemars = { workspace = true } semver = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } +subxt = { workspace = true } [lints] workspace = true diff --git a/crates/core/src/differential_benchmarks/driver.rs b/crates/core/src/differential_benchmarks/driver.rs index 1d13b69..5dcc2fb 100644 --- a/crates/core/src/differential_benchmarks/driver.rs +++ b/crates/core/src/differential_benchmarks/driver.rs @@ -127,6 +127,8 @@ where .inspect_err(|err| error!(?err, "Pre-linking compilation failed")) .context("Failed to produce the pre-linking compiled contracts")?; + let deployer_address = self.test_definition.case.deployer_address(); + let mut deployed_libraries = None::>; let mut contract_sources = self .test_definition @@ -159,23 +161,6 @@ where let code = alloy::hex::decode(code)?; - // Getting the deployer address from the cases themselves. This is to ensure - // that we're doing the deployments from different accounts and therefore we're - // not slowed down by the nonce. - let deployer_address = self - .test_definition - .case - .steps - .iter() - .filter_map(|step| match step { - Step::FunctionCall(input) => input.caller.as_address().copied(), - Step::BalanceAssertion(..) => None, - Step::StorageEmptyAssertion(..) => None, - Step::Repeat(..) => None, - Step::AllocateAccount(..) => None, - }) - .next() - .unwrap_or(FunctionCallStep::default_caller_address()); let tx = TransactionBuilder::::with_deploy_code( TransactionRequest::default().from(deployer_address), code, diff --git a/crates/core/src/differential_tests/driver.rs b/crates/core/src/differential_tests/driver.rs index cffc74d..d7fdcef 100644 --- a/crates/core/src/differential_tests/driver.rs +++ b/crates/core/src/differential_tests/driver.rs @@ -8,7 +8,7 @@ use alloy::{ hex, json_abi::JsonAbi, network::{Ethereum, TransactionBuilder}, - primitives::{Address, TxHash, U256}, + primitives::{Address, TxHash, U256, address}, rpc::types::{ TransactionReceipt, TransactionRequest, trace::geth::{ @@ -18,9 +18,9 @@ use alloy::{ }, }; use anyhow::{Context as _, Result, bail}; -use futures::TryStreamExt; +use futures::{TryStreamExt, future::try_join_all}; use indexmap::IndexMap; -use revive_dt_common::types::{PlatformIdentifier, PrivateKeyAllocator}; +use revive_dt_common::types::{PlatformIdentifier, PrivateKeyAllocator, VmIdentifier}; use revive_dt_format::{ metadata::{ContractInstance, ContractPathAndIdent}, steps::{ @@ -30,6 +30,7 @@ use revive_dt_format::{ }, traits::ResolutionContext, }; +use subxt::{ext::codec::Decode, metadata::Metadata, tx::Payload}; use tokio::sync::Mutex; use tracing::{error, info, instrument}; @@ -198,6 +199,8 @@ where }) .context("Failed to produce the pre-linking compiled contracts")?; + let deployer_address = test_definition.case.deployer_address(); + let mut deployed_libraries = None::>; let mut contract_sources = test_definition .metadata @@ -232,22 +235,6 @@ where let code = alloy::hex::decode(code)?; - // Getting the deployer address from the cases themselves. This is to ensure - // that we're doing the deployments from different accounts and therefore we're - // not slowed down by the nonce. - let deployer_address = test_definition - .case - .steps - .iter() - .filter_map(|step| match step { - Step::FunctionCall(input) => input.caller.as_address().copied(), - Step::BalanceAssertion(..) => None, - Step::StorageEmptyAssertion(..) => None, - Step::Repeat(..) => None, - Step::AllocateAccount(..) => None, - }) - .next() - .unwrap_or(FunctionCallStep::default_caller_address()); let tx = TransactionBuilder::::with_deploy_code( TransactionRequest::default().from(deployer_address), code, @@ -295,6 +282,51 @@ where }) .context("Failed to compile the post-link contracts")?; + // Factory contracts on the PVM refer to the code that they're instantiating by hash rather + // than including the actual bytecode. This creates a problem where a factory contract could + // be deployed but the code it's supposed to create is not on chain. Therefore, we upload + // all the code to the chain prior to running any transactions on the driver. + if platform_information.platform.vm_identifier() == VmIdentifier::PolkaVM { + #[subxt::subxt(runtime_metadata_path = "../../assets/revive_metadata.scale")] + pub mod revive {} + + let metadata_bytes = include_bytes!("../../../../assets/revive_metadata.scale"); + let metadata = Metadata::decode(&mut &metadata_bytes[..]) + .context("Failed to decode the revive metadata")?; + + const RUNTIME_PALLET_ADDRESS: Address = + address!("0x6d6f646c70792f70616464720000000000000000"); + + let code_upload_tasks = compiler_output + .contracts + .values() + .flat_map(|item| item.values()) + .map(|(code_string, _)| { + let metadata = metadata.clone(); + async move { + let code = alloy::hex::decode(code_string) + .context("Failed to hex-decode the post-link code. This is a bug")?; + let payload = revive::tx().revive().upload_code(code, u128::MAX); + let encoded_payload = payload + .encode_call_data(&metadata) + .context("Failed to encode the upload code payload")?; + + let tx_request = TransactionRequest::default() + .from(deployer_address) + .to(RUNTIME_PALLET_ADDRESS) + .input(encoded_payload.into()); + platform_information + .node + .execute_transaction(tx_request) + .await + .context("Failed to execute transaction") + } + }); + try_join_all(code_upload_tasks) + .await + .context("Code upload failed")?; + } + Ok(ExecutionState::new( compiler_output.contracts, deployed_libraries.unwrap_or_default(), diff --git a/crates/format/src/case.rs b/crates/format/src/case.rs index 44639dd..19114a9 100644 --- a/crates/format/src/case.rs +++ b/crates/format/src/case.rs @@ -1,3 +1,4 @@ +use alloy::primitives::Address; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -107,6 +108,20 @@ impl Case { None => Mode::all().cloned().collect(), } } + + pub fn deployer_address(&self) -> Address { + self.steps + .iter() + .filter_map(|step| match step { + Step::FunctionCall(input) => input.caller.as_address().copied(), + Step::BalanceAssertion(..) => None, + Step::StorageEmptyAssertion(..) => None, + Step::Repeat(..) => None, + Step::AllocateAccount(..) => None, + }) + .next() + .unwrap_or(FunctionCallStep::default_caller_address()) + } } define_wrapper_type!(