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
9 changes: 9 additions & 0 deletions prdoc/pr_9617.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
title: '[pallet-revive] Add setting evm balance'
doc:
- audience: Runtime User
description: |-
Adds a balance setter in EVM for pallet-revive.

crates:
- name: pallet-revive
bump: minor
42 changes: 30 additions & 12 deletions substrate/frame/revive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,9 @@ pub mod pallet {
#[pallet::genesis_build]
impl<T: Config> BuildGenesisConfig for GenesisConfig<T>
where
BalanceOf<T>: Into<U256> + TryFrom<U256>,
BalanceOf<T>: Into<U256> + TryFrom<U256> + Bounded,
MomentOf<T>: Into<U256>,
T::Hash: frame_support::traits::IsType<H256>,
{
fn build(&self) {
use crate::{exec::Key, vm::ContractBlob};
Expand All @@ -602,17 +604,8 @@ pub mod pallet {
let owner = Pallet::<T>::account_id();

for genesis::Account { address, balance, nonce, contract_data } in &self.accounts {
let Ok(balance_with_dust) =
BalanceWithDust::<BalanceOf<T>>::from_value::<T>(*balance).inspect_err(|err| {
log::error!(target: LOG_TARGET, "Failed to convert balance for {address:?}: {err:?}");
})
else {
continue;
};
let account_id = T::AddressMapper::to_account_id(address);
let (value, dust) = balance_with_dust.deconstruct();

let _ = T::Currency::set_balance(&account_id, value);
frame_system::Account::<T>::mutate(&account_id, |info| {
info.nonce = (*nonce).into();
});
Expand All @@ -621,7 +614,7 @@ pub mod pallet {
None => {
AccountInfoOf::<T>::insert(
address,
AccountInfo { account_type: AccountType::EOA, dust },
AccountInfo { account_type: AccountType::EOA, dust: 0 },
);
},
Some(genesis::ContractData { code, storage }) => {
Expand Down Expand Up @@ -650,7 +643,7 @@ pub mod pallet {

AccountInfoOf::<T>::insert(
address,
AccountInfo { account_type: info.clone().into(), dust },
AccountInfo { account_type: info.clone().into(), dust: 0 },
);

<PristineCode<T>>::insert(blob.code_hash(), code);
Expand All @@ -662,6 +655,10 @@ pub mod pallet {
}
},
}

let _ = Pallet::<T>::set_evm_balance(address, *balance).inspect_err(|err| {
log::error!(target: LOG_TARGET, "Failed to set EVM balance for {address:?}: {err:?}");
});
}
}
}
Expand Down Expand Up @@ -1539,11 +1536,32 @@ where
}

/// Get the balance with EVM decimals of the given `address`.
///
/// Returns the spendable balance excluding the existential deposit.
pub fn evm_balance(address: &H160) -> U256 {
let balance = AccountInfo::<T>::balance((*address).into());
Self::convert_native_to_evm(balance)
}

/// Set the EVM balance of an account.
///
/// The account's total balance becomes the EVM value plus the existential deposit,
/// consistent with `evm_balance` which returns the spendable balance excluding the existential
/// deposit.
pub fn set_evm_balance(address: &H160, evm_value: U256) -> Result<(), Error<T>> {
let ed = T::Currency::minimum_balance();
let balance_with_dust = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(evm_value)
.map_err(|_| <Error<T>>::BalanceConversionFailed)?;
let (value, dust) = balance_with_dust.deconstruct();
let account_id = T::AddressMapper::to_account_id(&address);
T::Currency::set_balance(&account_id, ed.saturating_add(value));
AccountInfoOf::<T>::mutate(address, |account| {
account.as_mut().map(|a| a.dust = dust);
});

Ok(())
}

/// Get the nonce for the given `address`.
pub fn evm_nonce(address: &H160) -> u32
where
Expand Down
4 changes: 2 additions & 2 deletions substrate/frame/revive/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ impl Default for Origin<Test> {
fn ext_builder_with_genesis_config_works() {
let pvm_contract = Account {
address: BOB_ADDR,
balance: U256::from(100),
balance: U256::from(100_000_100),
nonce: 42,
contract_data: Some(ContractData {
code: compile_module("dummy").unwrap().0,
Expand All @@ -470,7 +470,7 @@ fn ext_builder_with_genesis_config_works() {

let evm_contract = Account {
address: CHARLIE_ADDR,
balance: U256::from(100),
balance: U256::from(1_000_00_100),
nonce: 43,
contract_data: Some(ContractData {
code: vec![revm::bytecode::opcode::RETURN],
Expand Down
16 changes: 16 additions & 0 deletions substrate/frame/revive/src/tests/pvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,22 @@ fn eth_call_transfer_with_dust_works() {
});
}

#[test]
fn set_evm_balance_works() {
let (binary, _) = compile_module("dummy").unwrap();
ExtBuilder::default().existential_deposit(200).build().execute_with(|| {
let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000);
let Contract { addr, .. } =
builder::bare_instantiate(Code::Upload(binary)).build_and_unwrap_contract();
let native_with_dust = BalanceWithDust::new_unchecked::<Test>(100, 10);
let evm_value = Pallet::<Test>::convert_native_to_evm(native_with_dust);

assert_ok!(Pallet::<Test>::set_evm_balance(&addr, evm_value));

assert_eq!(Pallet::<Test>::evm_balance(&addr), evm_value);
});
}

#[test]
fn contract_call_transfer_with_dust_works() {
let (binary_caller, _code_hash_caller) = compile_module("call_with_value").unwrap();
Expand Down
Loading