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
45 changes: 45 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ pallet-commitments = { default-features = false, path = "../pallets/commitments"
fp-evm = { workspace = true }
fp-rpc = { workspace = true }
fp-self-contained = { workspace = true }
precompile-utils = { workspace = true }

# Frontier FRAME
pallet-base-fee = { workspace = true }
Expand Down Expand Up @@ -163,6 +164,7 @@ std = [
"pallet-scheduler/std",
"pallet-preimage/std",
"pallet-commitments/std",
"precompile-utils/std",
"sp-api/std",
"sp-block-builder/std",
"sp-consensus-aura/std",
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// `spec_version`, and `authoring_version` are the same between Wasm and native.
// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
// the compatible custom types.
spec_version: 239,
spec_version: 240,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down
64 changes: 22 additions & 42 deletions runtime/src/precompiles/balance_transfer.rs
Original file line number Diff line number Diff line change
@@ -1,60 +1,40 @@
use pallet_evm::{
BalanceConverter, ExitError, ExitSucceed, PrecompileHandle, PrecompileOutput, PrecompileResult,
};
use pallet_evm::PrecompileHandle;
use precompile_utils::EvmResult;
use sp_core::H256;
use sp_runtime::traits::UniqueSaturatedInto;
use sp_std::vec;

use crate::precompiles::{
contract_to_origin, get_method_id, get_pubkey, get_slice, try_dispatch_runtime_call,
};
use crate::precompiles::{contract_to_origin, parse_pubkey, PrecompileExt, PrecompileHandleExt};
use crate::Runtime;

pub const BALANCE_TRANSFER_INDEX: u64 = 2048;
// ss58 public key i.e., the contract sends funds it received to the destination address from the
// method parameter.
const CONTRACT_ADDRESS_SS58: [u8; 32] = [
0x07, 0xec, 0x71, 0x2a, 0x5d, 0x38, 0x43, 0x4d, 0xdd, 0x03, 0x3f, 0x8f, 0x02, 0x4e, 0xcd, 0xfc,
0x4b, 0xb5, 0x95, 0x1c, 0x13, 0xc3, 0x08, 0x5c, 0x39, 0x9c, 0x8a, 0x5f, 0x62, 0x93, 0x70, 0x5d,
];

pub struct BalanceTransferPrecompile;

impl BalanceTransferPrecompile {
pub fn execute(handle: &mut impl PrecompileHandle) -> PrecompileResult {
let txdata = handle.input();

// Match method ID: keccak256("transfer(bytes32)")
let method = get_slice(txdata, 0, 4)?;
if get_method_id("transfer(bytes32)") != method {
return Ok(PrecompileOutput {
exit_status: ExitSucceed::Returned,
output: vec![],
});
}

// Forward all received value to the destination address
let amount = handle.context().apparent_value;
impl PrecompileExt for BalanceTransferPrecompile {
const INDEX: u64 = 2048;
const ADDRESS_SS58: [u8; 32] = [
0x07, 0xec, 0x71, 0x2a, 0x5d, 0x38, 0x43, 0x4d, 0xdd, 0x03, 0x3f, 0x8f, 0x02, 0x4e, 0xcd,
0xfc, 0x4b, 0xb5, 0x95, 0x1c, 0x13, 0xc3, 0x08, 0x5c, 0x39, 0x9c, 0x8a, 0x5f, 0x62, 0x93,
0x70, 0x5d,
];
}

// Use BalanceConverter to convert EVM amount to Substrate balance
let amount_sub =
<Runtime as pallet_evm::Config>::BalanceConverter::into_substrate_balance(amount)
.ok_or(ExitError::OutOfFund)?;
#[precompile_utils::precompile]
impl BalanceTransferPrecompile {
#[precompile::public("transfer(bytes32)")]
#[precompile::payable]
fn transfer(handle: &mut impl PrecompileHandle, address: H256) -> EvmResult<()> {
let amount_sub = handle.try_convert_apparent_value()?;

if amount_sub.is_zero() {
return Ok(PrecompileOutput {
exit_status: ExitSucceed::Returned,
output: vec![],
});
return Ok(());
}

let address_bytes_dst = get_slice(txdata, 4, 36)?;
let (account_id_dst, _) = get_pubkey(address_bytes_dst)?;
let dest = parse_pubkey(address.as_bytes())?.0.into();

let call = pallet_balances::Call::<Runtime>::transfer_allow_death {
dest: account_id_dst.into(),
dest,
value: amount_sub.unique_saturated_into(),
};

try_dispatch_runtime_call(handle, call, contract_to_origin(&CONTRACT_ADDRESS_SS58)?)
handle.try_dispatch_runtime_call(call, contract_to_origin(&Self::ADDRESS_SS58)?)
}
}
14 changes: 9 additions & 5 deletions runtime/src/precompiles/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ extern crate alloc;

use alloc::vec::Vec;

use crate::precompiles::get_slice;
use ed25519_dalek::{Signature, Verifier, VerifyingKey};
use fp_evm::{ExitError, ExitSucceed, LinearCostPrecompile, PrecompileFailure};

pub const EDVERIFY_PRECOMPILE_INDEX: u64 = 1026;
use crate::precompiles::{parse_slice, PrecompileExt};

pub struct Ed25519Verify;

impl PrecompileExt for Ed25519Verify {
const INDEX: u64 = 1026;
const ADDRESS_SS58: [u8; 32] = [0; 32];
}

impl LinearCostPrecompile for Ed25519Verify {
const BASE: u64 = 15;
const WORD: u64 = 3;
Expand All @@ -23,13 +27,13 @@ impl LinearCostPrecompile for Ed25519Verify {

let mut buf = [0u8; 32];

let msg = get_slice(input, 4, 36)?;
let pk = VerifyingKey::try_from(get_slice(input, 36, 68)?).map_err(|_| {
let msg = parse_slice(input, 4, 36)?;
let pk = VerifyingKey::try_from(parse_slice(input, 36, 68)?).map_err(|_| {
PrecompileFailure::Error {
exit_status: ExitError::Other("Public key recover failed".into()),
}
})?;
let sig = Signature::try_from(get_slice(input, 68, 132)?).map_err(|_| {
let sig = Signature::try_from(parse_slice(input, 68, 132)?).map_err(|_| {
PrecompileFailure::Error {
exit_status: ExitError::Other("Signature recover failed".into()),
}
Expand Down
Loading
Loading