From 993baa761191be37af12f7200e95f6bc25921cab Mon Sep 17 00:00:00 2001 From: pgherveou Date: Thu, 5 Feb 2026 06:15:48 +0000 Subject: [PATCH 1/3] Add revive substrate runtime-api integration tests for call & instantiate --- prdoc/pr_10919.prdoc | 22 ++++ .../frame/revive/dev-node/runtime/src/lib.rs | 16 ++- substrate/frame/revive/rpc/src/tests.rs | 103 +++++++++++++++--- 3 files changed, 123 insertions(+), 18 deletions(-) create mode 100644 prdoc/pr_10919.prdoc diff --git a/prdoc/pr_10919.prdoc b/prdoc/pr_10919.prdoc new file mode 100644 index 0000000000000..14276a1c03840 --- /dev/null +++ b/prdoc/pr_10919.prdoc @@ -0,0 +1,22 @@ +title: Add revive substrate runtime-api integration tests for call & instantiate +doc: +- audience: Runtime Dev + description: |- + ## Summary + - Add integration tests for revive runtime API + - Test Fibonacci contract deployment and execution via substrate APIs + + ## Changes + - Add test for Fibonacci contract call via runtime API + - Add test to verify large Fibonacci values run out of gas as expected + - Update dev-node runtime configuration for testing + + ## Test plan + - Run new integration tests + - Verify runtime API correctly handles contract deployment + - Verify gas limits are enforced correctly +crates: +- name: revive-dev-runtime + bump: patch +- name: pallet-revive-eth-rpc + bump: patch diff --git a/substrate/frame/revive/dev-node/runtime/src/lib.rs b/substrate/frame/revive/dev-node/runtime/src/lib.rs index 086b4b3a77f69..6b795a534c919 100644 --- a/substrate/frame/revive/dev-node/runtime/src/lib.rs +++ b/substrate/frame/revive/dev-node/runtime/src/lib.rs @@ -64,11 +64,12 @@ pub mod currency { pub mod genesis_config_presets { use super::*; use crate::{ - currency::DOLLARS, sp_keyring::Sr25519Keyring, Balance, BalancesConfig, + currency::DOLLARS, sp_keyring::Sr25519Keyring, Balance, BalancesConfig, ReviveConfig, RuntimeGenesisConfig, SudoConfig, }; use alloc::{vec, vec::Vec}; + use pallet_revive::is_eth_derived; use serde_json::Value; pub const ENDOWMENT: Balance = 10_000_000_000_001 * DOLLARS; @@ -103,14 +104,23 @@ pub mod genesis_config_presets { /// Returns a development genesis config preset. pub fn development_config_genesis() -> Value { + let endowed_accounts = well_known_accounts(); frame_support::build_struct_json_patch!(RuntimeGenesisConfig { balances: BalancesConfig { - balances: well_known_accounts() - .into_iter() + balances: endowed_accounts + .iter() + .cloned() .map(|id| (id, ENDOWMENT)) .collect::>(), }, sudo: SudoConfig { key: Some(Sr25519Keyring::Alice.to_account_id()) }, + revive: ReviveConfig { + mapped_accounts: endowed_accounts + .iter() + .filter(|x| !is_eth_derived(x)) + .cloned() + .collect(), + }, }) } diff --git a/substrate/frame/revive/rpc/src/tests.rs b/substrate/frame/revive/rpc/src/tests.rs index a11ddcf2a1736..09d847af58ab9 100644 --- a/substrate/frame/revive/rpc/src/tests.rs +++ b/substrate/frame/revive/rpc/src/tests.rs @@ -302,7 +302,7 @@ async fn run_all_eth_rpc_tests_inner() -> anyhow::Result<()> { } run_tests!( - test_fibonacci_large_value_runs_out_of_gas, + test_fibonacci_call_via_runtime_api, test_transfer, test_deploy_and_call, test_runtime_api_dry_run_addr_works, @@ -832,31 +832,104 @@ async fn test_runtime_pallets_address_upload_code() -> anyhow::Result<()> { Ok(()) } -async fn test_fibonacci_large_value_runs_out_of_gas() -> anyhow::Result<()> { +/// Test that deploys and calls the Fibonacci contract via Substrate APIs works +async fn test_fibonacci_call_via_runtime_api() -> anyhow::Result<()> { use pallet_revive::precompiles::alloy::sol_types::SolCall; use pallet_revive_fixtures::Fibonacci; - let client = Arc::new(SharedResources::client().await); let (bytes, _) = pallet_revive_fixtures::compile_module_with_type( "Fibonacci", pallet_revive_fixtures::FixtureType::Solc, )?; - let account = Account::default(); - let nonce = client.get_transaction_count(account.address(), BlockTag::Latest.into()).await?; - let tx = TransactionBuilder::new(client.clone()).input(bytes.to_vec()).send().await?; - let receipt = tx.wait_for_receipt().await?; - let contract_address = create1(&account.address(), nonce.try_into().unwrap()); - assert_eq!(Some(contract_address), receipt.contract_address); + let node_client = + OnlineClient::::from_url(SharedResources::node_rpc_url()).await?; + let signer = subxt_signer::sr25519::dev::alice(); + let origin: [u8; 32] = signer.public_key().0; - let result = TransactionBuilder::new(client.clone()) - .to(contract_address) - .input(Fibonacci::fibCall { n: 100u64 }.abi_encode()) - .eth_call() + // Deploy the Fibonacci contract via Substrate API + log::trace!(target: LOG_TARGET, "Deploying Fibonacci contract via Substrate API"); + let dry_run_result = node_client + .runtime_api() + .at_latest() + .await? + .call(subxt_client::apis().revive_api().instantiate( + subxt::utils::AccountId32(origin), + 0u128, // value + None, // gas_limit + None, // storage_deposit_limit + subxt_client::src_chain::runtime_types::pallet_revive::primitives::Code::Upload( + bytes.clone(), + ), + vec![], // data (constructor args) + None, // salt + )) .await; - let err = result.expect_err("fib(100) should run out of gas"); - assert!(err.to_string().contains("OutOfGas"), "expected OutOfGas error, got: {err}"); + assert!(dry_run_result.is_ok(), "Dry-run instantiate failed: {dry_run_result:?}"); + let dry_run = dry_run_result.unwrap(); + let instantiate_result = dry_run.result.expect("Dry-run should succeed"); + + log::trace!( + target: LOG_TARGET, + "Dry-run succeeded: address: {:?}, gas_consumed: {:?}, weight_required: {:?}", + instantiate_result.addr, + dry_run.gas_consumed, + dry_run.weight_required + ); + + // Now submit the actual instantiate extrinsic + let events = node_client + .tx() + .sign_and_submit_then_watch_default( + &subxt_client::tx().revive().instantiate_with_code( + 0u128, // value + dry_run.weight_required, // weight_limit from dry-run + u128::MAX, // storage_deposit_limit + bytes, // code + vec![], // data + None, // salt + ), + &subxt_signer::sr25519::dev::alice(), + ) + .await? + .wait_for_finalized_success() + .await?; + + // Extract the contract address from the Instantiated event + let instantiated_event = events + .find_first::()? + .expect("Instantiated event should be present"); + + let contract_address = instantiated_event.contract; + log::trace!(target: LOG_TARGET, "Contract deployed via Substrate at: {contract_address:?}"); + + // Verify that the dry-run predicted address matches the actual deployed address + assert_eq!( + instantiate_result.addr, contract_address, + "Dry-run predicted address should match actual deployed address" + ); + + // Call the deployed contract using runtime API + let call_data = Fibonacci::fibCall { n: 3u64 }.abi_encode(); + let call_payload = subxt_client::apis().revive_api().call( + subxt::utils::AccountId32(origin), + contract_address, + 0u128, // value + None, // gas_limit + None, // storage_deposit_limit + call_data, + ); + + let result = node_client.runtime_api().at_latest().await?.call(call_payload).await; + + assert!(result.is_ok(), "Contract call failed: {result:?}"); + let call_result = result.unwrap(); + let exec_result = call_result.result.expect("fib(3) should succeed"); + + let decoded = Fibonacci::fibCall::abi_decode_returns(&exec_result.data) + .expect("Failed to decode return value"); + assert_eq!(decoded, 2u64, "fib(3) should return 2"); Ok(()) } From 9916515aec58dddd458862b7a29e451deb6050fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=B3nica=20Jin?= Date: Mon, 16 Feb 2026 18:09:08 +0100 Subject: [PATCH 2/3] add oog assertion to fib test --- substrate/frame/revive/rpc/src/tests.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/substrate/frame/revive/rpc/src/tests.rs b/substrate/frame/revive/rpc/src/tests.rs index b70cf54bf21ce..9bfadd1446d7b 100644 --- a/substrate/frame/revive/rpc/src/tests.rs +++ b/substrate/frame/revive/rpc/src/tests.rs @@ -932,5 +932,22 @@ async fn test_fibonacci_call_via_runtime_api() -> anyhow::Result<()> { .expect("Failed to decode return value"); assert_eq!(decoded, 2u64, "fib(3) should return 2"); + // Verify that large Fibonacci values run out of gas + let call_data = Fibonacci::fibCall { n: 100u64 }.abi_encode(); + let call_payload = subxt_client::apis().revive_api().call( + subxt::utils::AccountId32(origin), + contract_address, + 0u128, // value + None, // gas_limit + None, // storage_deposit_limit + call_data, + ); + + let result = node_client.runtime_api().at_latest().await?.call(call_payload).await; + assert!(result.is_ok(), "Runtime API call failed: {result:?}"); + let call_result = result.unwrap(); + assert!(call_result.result.is_err(), "fib(100) should run out of gas"); + Ok(()) } + From b6b714b24265ef6251ed9fb070c141acbdfeaf6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=B3nica=20Jin?= Date: Mon, 16 Feb 2026 18:41:22 +0100 Subject: [PATCH 3/3] fmt test --- substrate/frame/revive/rpc/src/tests.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/substrate/frame/revive/rpc/src/tests.rs b/substrate/frame/revive/rpc/src/tests.rs index 9bfadd1446d7b..9153bce67384b 100644 --- a/substrate/frame/revive/rpc/src/tests.rs +++ b/substrate/frame/revive/rpc/src/tests.rs @@ -950,4 +950,3 @@ async fn test_fibonacci_call_via_runtime_api() -> anyhow::Result<()> { Ok(()) } -