From 2257634bf4889a1edea98ca9f71dbf332989f6ac Mon Sep 17 00:00:00 2001 From: pgherveou Date: Wed, 28 Jan 2026 07:36:55 +0100 Subject: [PATCH 1/4] revive runtime-api integration tests --- .../frame/revive/dev-node/runtime/src/lib.rs | 16 ++- substrate/frame/revive/rpc/src/tests.rs | 132 ++++++++++++++++++ 2 files changed, 145 insertions(+), 3 deletions(-) diff --git a/substrate/frame/revive/dev-node/runtime/src/lib.rs b/substrate/frame/revive/dev-node/runtime/src/lib.rs index 176d6b91a13c3..bcf2128dc8082 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 269dffb8c7572..7d6b2400864fe 100644 --- a/substrate/frame/revive/rpc/src/tests.rs +++ b/substrate/frame/revive/rpc/src/tests.rs @@ -284,6 +284,8 @@ async fn run_all_eth_rpc_tests() -> anyhow::Result<()> { } run_tests!( + test_fibonacci_call_via_runtime_api, + test_fibonacci_large_value_runs_out_of_gas, test_transfer, test_deploy_and_call, test_runtime_api_dry_run_addr_works, @@ -790,3 +792,133 @@ async fn test_runtime_pallets_address_upload_code(client: Arc) -> anyh Ok(()) } + +async fn test_fibonacci_large_value_runs_out_of_gas(client: Arc) -> anyhow::Result<()> { + use pallet_revive::precompiles::alloy::sol_types::SolCall; + use pallet_revive_fixtures::Fibonacci; + + 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).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 result = TransactionBuilder::new(&client) + .to(contract_address) + .input(Fibonacci::fibCall { n: 100u64 }.abi_encode()) + .eth_call() + .await; + + let err = result.expect_err("fib(100) should run out of gas"); + assert!(err.to_string().contains("OutOfGas"), "expected OutOfGas error, got: {err}"); + + Ok(()) +} + +/// Test that deploys and calls the Fibonacci contract via Substrate APIs works +async fn test_fibonacci_call_via_runtime_api(_client: Arc) -> anyhow::Result<()> { + use pallet_revive::precompiles::alloy::sol_types::SolCall; + use pallet_revive_fixtures::Fibonacci; + + let (bytes, _) = pallet_revive_fixtures::compile_module_with_type( + "Fibonacci", + pallet_revive_fixtures::FixtureType::Solc, + )?; + + 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; + + // 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; + + 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 42903147d1894c07c670eed9fd36134fab7dd933 Mon Sep 17 00:00:00 2001 From: pgherveou Date: Wed, 28 Jan 2026 09:54:25 +0100 Subject: [PATCH 2/4] Remove test_fibonacci_large_value_runs_out_of_gas (moved to dry-run-limit branch) --- substrate/frame/revive/rpc/src/tests.rs | 29 ------------------------- 1 file changed, 29 deletions(-) diff --git a/substrate/frame/revive/rpc/src/tests.rs b/substrate/frame/revive/rpc/src/tests.rs index 7d6b2400864fe..ccb1622402537 100644 --- a/substrate/frame/revive/rpc/src/tests.rs +++ b/substrate/frame/revive/rpc/src/tests.rs @@ -285,7 +285,6 @@ async fn run_all_eth_rpc_tests() -> anyhow::Result<()> { run_tests!( test_fibonacci_call_via_runtime_api, - test_fibonacci_large_value_runs_out_of_gas, test_transfer, test_deploy_and_call, test_runtime_api_dry_run_addr_works, @@ -793,34 +792,6 @@ async fn test_runtime_pallets_address_upload_code(client: Arc) -> anyh Ok(()) } -async fn test_fibonacci_large_value_runs_out_of_gas(client: Arc) -> anyhow::Result<()> { - use pallet_revive::precompiles::alloy::sol_types::SolCall; - use pallet_revive_fixtures::Fibonacci; - - 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).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 result = TransactionBuilder::new(&client) - .to(contract_address) - .input(Fibonacci::fibCall { n: 100u64 }.abi_encode()) - .eth_call() - .await; - - let err = result.expect_err("fib(100) should run out of gas"); - assert!(err.to_string().contains("OutOfGas"), "expected OutOfGas error, got: {err}"); - - Ok(()) -} - /// Test that deploys and calls the Fibonacci contract via Substrate APIs works async fn test_fibonacci_call_via_runtime_api(_client: Arc) -> anyhow::Result<()> { use pallet_revive::precompiles::alloy::sol_types::SolCall; From b6eaf285a8fa4c0ebc547b793ecd079d2641fef2 Mon Sep 17 00:00:00 2001 From: "cmd[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 Jan 2026 09:00:45 +0000 Subject: [PATCH 3/4] Update from github-actions[bot] running command 'prdoc --audience runtime_dev --bump patch' --- prdoc/pr_10919.prdoc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) 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 From 428e599f73acee51ed8da7dd67ad88e5821ec10f Mon Sep 17 00:00:00 2001 From: pgherveou Date: Wed, 28 Jan 2026 14:31:49 +0000 Subject: [PATCH 4/4] Fix test_fibonacci_call_via_runtime_api signature Remove unused client parameter from test function to match the test macro which calls tests without arguments. Co-Authored-By: Claude Opus 4.5 --- substrate/frame/revive/rpc/src/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/revive/rpc/src/tests.rs b/substrate/frame/revive/rpc/src/tests.rs index ccb1622402537..35e0e61e1f1aa 100644 --- a/substrate/frame/revive/rpc/src/tests.rs +++ b/substrate/frame/revive/rpc/src/tests.rs @@ -793,7 +793,7 @@ async fn test_runtime_pallets_address_upload_code(client: Arc) -> anyh } /// Test that deploys and calls the Fibonacci contract via Substrate APIs works -async fn test_fibonacci_call_via_runtime_api(_client: Arc) -> anyhow::Result<()> { +async fn test_fibonacci_call_via_runtime_api() -> anyhow::Result<()> { use pallet_revive::precompiles::alloy::sol_types::SolCall; use pallet_revive_fixtures::Fibonacci;