Skip to content
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
11 changes: 11 additions & 0 deletions prdoc/pr_10193.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
title: '[v2] pallet-revive: support uploading EVM bytecode via upload_code'
doc:
- audience: Runtime Dev
description: |-
Fixes https://github.com/paritytech/contract-issues/issues/182

Add support for EVM bytecode to the upload_code extrinsic.
Tests in issue https://github.com/paritytech/contract-issues/issues/182 send hardhat_setCode, which uses revive's upload_code API; this change makes that flow accept and store the EVM bytecode using upload_code extrinsic.
crates:
- name: pallet-revive
bump: patch
12 changes: 11 additions & 1 deletion substrate/frame/revive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1986,10 +1986,20 @@ impl<T: Config> Pallet<T> {
storage_deposit_limit: BalanceOf<T>,
) -> CodeUploadResult<BalanceOf<T>> {
let origin = T::UploadOrigin::ensure_origin(origin)?;

let bytecode_type = if code.starts_with(&polkavm_common::program::BLOB_MAGIC) {
BytecodeType::Pvm
} else {
if !T::AllowEVMBytecode::get() {
return Err(<Error<T>>::CodeRejected.into())
}
BytecodeType::Evm
};

let (module, deposit) = Self::try_upload_code(
origin,
code,
BytecodeType::Pvm,
bytecode_type,
storage_deposit_limit,
&ExecConfig::new_substrate_tx(),
)?;
Expand Down
43 changes: 40 additions & 3 deletions substrate/frame/revive/src/tests/sol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ use crate::{
tests::{
builder,
test_utils::{contract_base_deposit, ensure_stored, get_contract},
DebugFlag, ExtBuilder, Test,
AllowEvmBytecode, DebugFlag, ExtBuilder, RuntimeOrigin, Test,
},
Code, Config, Error, GenesisConfig, PristineCode,
Code, Config, Error, GenesisConfig, Pallet, PristineCode,
};
use alloy_core::sol_types::{SolCall, SolInterface};
use frame_support::{assert_err, assert_ok, traits::fungible::Mutate};
Expand Down Expand Up @@ -206,7 +206,6 @@ fn upload_evm_runtime_code_works() {
exec::Executable,
primitives::ExecConfig,
storage::{AccountInfo, ContractInfo},
Pallet,
};

let (runtime_code, _runtime_hash) =
Expand Down Expand Up @@ -242,6 +241,44 @@ fn upload_evm_runtime_code_works() {
});
}

#[test]
fn upload_and_remove_code_works_for_evm() {
let (code, code_hash) = compile_module_with_type("Dummy", FixtureType::SolcRuntime).unwrap();

ExtBuilder::default().build().execute_with(|| {
let _ = Pallet::<Test>::set_evm_balance(&ALICE_ADDR, 5_000_000_000u64.into());

// Ensure the code is not already stored.
assert!(!PristineCode::<Test>::contains_key(&code_hash));

// Upload the code.
assert_ok!(Pallet::<Test>::upload_code(RuntimeOrigin::signed(ALICE), code, 1000u64));

// Ensure the contract was stored.
ensure_stored(code_hash);

// Remove the code.
assert_ok!(Pallet::<Test>::remove_code(RuntimeOrigin::signed(ALICE), code_hash));

// Ensure the code is no longer stored.
assert!(!PristineCode::<Test>::contains_key(&code_hash));
});
}

#[test]
fn upload_fails_if_evm_bytecode_disabled() {
let (code, _) = compile_module_with_type("Dummy", FixtureType::SolcRuntime).unwrap();

AllowEvmBytecode::set(false); // Disable support for EVM bytecode.
ExtBuilder::default().build().execute_with(|| {
// Upload should fail since support for EVM bytecode is disabled.
assert_err!(
Pallet::<Test>::upload_code(RuntimeOrigin::signed(ALICE), code, 1000u64),
<Error<Test>>::CodeRejected
);
});
}

#[test_case(FixtureType::Solc)]
#[test_case(FixtureType::Resolc)]
fn dust_work_with_child_calls(fixture_type: FixtureType) {
Expand Down
Loading