Skip to content

Commit 68f8294

Browse files
committed
Remove ADDRESS_SS58 from Precompile extension and clean up
1 parent b6bf2c6 commit 68f8294

File tree

9 files changed

+238
-232
lines changed

9 files changed

+238
-232
lines changed

precompiles/src/balance_transfer.rs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
use core::marker::PhantomData;
22

33
use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo};
4+
use frame_system::RawOrigin;
45
use pallet_evm::PrecompileHandle;
56
use precompile_utils::EvmResult;
67
use sp_core::{H256, U256};
78
use sp_runtime::traits::{Dispatchable, StaticLookup, UniqueSaturatedInto};
89

9-
use crate::parser::{contract_to_origin, parse_pubkey};
1010
use crate::{PrecompileExt, PrecompileHandleExt};
1111

1212
pub(crate) struct BalanceTransferPrecompile<R>(PhantomData<R>);
1313

14-
impl<R> PrecompileExt for BalanceTransferPrecompile<R>
14+
impl<R> PrecompileExt<R::AccountId> for BalanceTransferPrecompile<R>
1515
where
1616
R: frame_system::Config + pallet_balances::Config + pallet_evm::Config,
1717
R::AccountId: From<[u8; 32]>,
@@ -24,11 +24,6 @@ where
2424
<R as pallet_balances::Config>::Balance: TryFrom<U256>,
2525
{
2626
const INDEX: u64 = 2048;
27-
const ADDRESS_SS58: Option<[u8; 32]> = Some([
28-
0x07, 0xec, 0x71, 0x2a, 0x5d, 0x38, 0x43, 0x4d, 0xdd, 0x03, 0x3f, 0x8f, 0x02, 0x4e, 0xcd,
29-
0xfc, 0x4b, 0xb5, 0x95, 0x1c, 0x13, 0xc3, 0x08, 0x5c, 0x39, 0x9c, 0x8a, 0x5f, 0x62, 0x93,
30-
0x70, 0x5d,
31-
]);
3227
}
3328

3429
#[precompile_utils::precompile]
@@ -53,18 +48,13 @@ where
5348
return Ok(());
5449
}
5550

56-
let dest = parse_pubkey::<R::AccountId>(address.as_bytes())?.0.into();
51+
let dest = R::AccountId::from(address.0).into();
5752

5853
let call = pallet_balances::Call::<R>::transfer_allow_death {
5954
dest,
6055
value: amount_sub.unique_saturated_into(),
6156
};
6257

63-
handle.try_dispatch_runtime_call::<R, _>(
64-
call,
65-
contract_to_origin(
66-
&Self::ADDRESS_SS58.expect("ADDRESS_SS58 is defined for BalanceTransferPrecompile"),
67-
)?,
68-
)
58+
handle.try_dispatch_runtime_call::<R, _>(call, RawOrigin::Signed(Self::address_ss58()))
6959
}
7060
}

precompiles/src/ed25519.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
extern crate alloc;
22

33
use alloc::vec::Vec;
4+
use core::marker::PhantomData;
45

56
use ed25519_dalek::{Signature, Verifier, VerifyingKey};
67
use fp_evm::{ExitError, ExitSucceed, LinearCostPrecompile, PrecompileFailure};
78

89
use crate::PrecompileExt;
9-
use crate::parser::parse_slice;
1010

11-
pub(crate) struct Ed25519Verify;
11+
pub(crate) struct Ed25519Verify<A>(PhantomData<A>);
1212

13-
impl PrecompileExt for Ed25519Verify {
13+
impl<A> PrecompileExt<A> for Ed25519Verify<A>
14+
where
15+
A: From<[u8; 32]>,
16+
{
1417
const INDEX: u64 = 1026;
15-
const ADDRESS_SS58: Option<[u8; 32]> = None;
1618
}
1719

18-
impl LinearCostPrecompile for Ed25519Verify {
20+
impl<A> LinearCostPrecompile for Ed25519Verify<A>
21+
where
22+
A: From<[u8; 32]>,
23+
{
1924
const BASE: u64 = 15;
2025
const WORD: u64 = 3;
2126

@@ -47,3 +52,21 @@ impl LinearCostPrecompile for Ed25519Verify {
4752
Ok((ExitSucceed::Returned, buf.to_vec()))
4853
}
4954
}
55+
56+
/// Takes a slice from bytes with PrecompileFailure as Error
57+
fn parse_slice(data: &[u8], from: usize, to: usize) -> Result<&[u8], PrecompileFailure> {
58+
let maybe_slice = data.get(from..to);
59+
if let Some(slice) = maybe_slice {
60+
Ok(slice)
61+
} else {
62+
log::error!(
63+
"fail to get slice from data, {:?}, from {}, to {}",
64+
&data,
65+
from,
66+
to
67+
);
68+
Err(PrecompileFailure::Error {
69+
exit_status: ExitError::InvalidRange,
70+
})
71+
}
72+
}

precompiles/src/extensions.rs

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
extern crate alloc;
2+
3+
use alloc::format;
4+
use core::marker::PhantomData;
5+
6+
use frame_support::dispatch::{GetDispatchInfo, Pays, PostDispatchInfo};
7+
use frame_system::RawOrigin;
8+
use pallet_evm::{
9+
AddressMapping, BalanceConverter, ExitError, GasWeightMapping, IsPrecompileResult, Precompile,
10+
PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet,
11+
};
12+
use pallet_evm_precompile_modexp::Modexp;
13+
use pallet_evm_precompile_sha3fips::Sha3FIPS256;
14+
use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256};
15+
use precompile_utils::EvmResult;
16+
use sp_core::{H160, U256, blake2_256, crypto::ByteArray};
17+
use sp_runtime::traits::Dispatchable;
18+
use sp_runtime::traits::StaticLookup;
19+
use subtensor_runtime_common::ProxyType;
20+
21+
use pallet_admin_utils::{PrecompileEnable, PrecompileEnum};
22+
23+
pub(crate) trait PrecompileHandleExt: PrecompileHandle {
24+
fn caller_account_id<R>(&self) -> R::AccountId
25+
where
26+
R: frame_system::Config + pallet_evm::Config,
27+
<R as pallet_evm::Config>::AddressMapping: AddressMapping<R::AccountId>,
28+
{
29+
<R as pallet_evm::Config>::AddressMapping::into_account_id(self.context().caller)
30+
}
31+
32+
fn try_convert_apparent_value<R>(&self) -> EvmResult<U256>
33+
where
34+
R: pallet_evm::Config,
35+
{
36+
let amount = self.context().apparent_value;
37+
<R as pallet_evm::Config>::BalanceConverter::into_substrate_balance(amount).ok_or(
38+
PrecompileFailure::Error {
39+
exit_status: ExitError::Other(
40+
"error converting balance from ETH to subtensor".into(),
41+
),
42+
},
43+
)
44+
}
45+
46+
/// Dispatches a runtime call, but also checks and records the gas costs.
47+
fn try_dispatch_runtime_call<R, Call>(
48+
&mut self,
49+
call: Call,
50+
origin: RawOrigin<R::AccountId>,
51+
) -> EvmResult<()>
52+
where
53+
R: frame_system::Config + pallet_evm::Config,
54+
R::RuntimeCall: From<Call>,
55+
R::RuntimeCall: GetDispatchInfo + Dispatchable<PostInfo = PostDispatchInfo>,
56+
R::RuntimeOrigin: From<RawOrigin<R::AccountId>>,
57+
{
58+
let call = R::RuntimeCall::from(call);
59+
let info = GetDispatchInfo::get_dispatch_info(&call);
60+
61+
let target_gas = self.gas_limit();
62+
if let Some(gas) = target_gas {
63+
let valid_weight =
64+
<R as pallet_evm::Config>::GasWeightMapping::gas_to_weight(gas, false).ref_time();
65+
if info.weight.ref_time() > valid_weight {
66+
return Err(PrecompileFailure::Error {
67+
exit_status: ExitError::OutOfGas,
68+
});
69+
}
70+
}
71+
72+
self.record_external_cost(
73+
Some(info.weight.ref_time()),
74+
Some(info.weight.proof_size()),
75+
None,
76+
)?;
77+
78+
match call.dispatch(R::RuntimeOrigin::from(origin)) {
79+
Ok(post_info) => {
80+
if post_info.pays_fee(&info) == Pays::Yes {
81+
let actual_weight = post_info.actual_weight.unwrap_or(info.weight);
82+
let cost =
83+
<R as pallet_evm::Config>::GasWeightMapping::weight_to_gas(actual_weight);
84+
self.record_cost(cost)?;
85+
86+
self.refund_external_cost(
87+
Some(
88+
info.weight
89+
.ref_time()
90+
.saturating_sub(actual_weight.ref_time()),
91+
),
92+
Some(
93+
info.weight
94+
.proof_size()
95+
.saturating_sub(actual_weight.proof_size()),
96+
),
97+
);
98+
}
99+
100+
log::info!("Dispatch succeeded. Post info: {:?}", post_info);
101+
102+
Ok(())
103+
}
104+
Err(e) => {
105+
log::error!("Dispatch failed. Error: {:?}", e);
106+
log::warn!("Returning error PrecompileFailure::Error");
107+
Err(PrecompileFailure::Error {
108+
exit_status: ExitError::Other(
109+
format!("dispatch execution failed: {}", <&'static str>::from(e)).into(),
110+
),
111+
})
112+
}
113+
}
114+
}
115+
}
116+
117+
impl<T> PrecompileHandleExt for T where T: PrecompileHandle {}
118+
119+
pub(crate) trait PrecompileExt<AccountId: From<[u8; 32]>> {
120+
const INDEX: u64;
121+
122+
// ss58 public key i.e., the contract sends funds it received to the destination address from
123+
// the method parameter.
124+
fn address_ss58() -> AccountId {
125+
let hash = H160::from_low_u64_be(Self::INDEX);
126+
let address_bytes: [u8; 20] = hash.into();
127+
128+
let prefix = b"evm:";
129+
130+
// Concatenate prefix and ethereum address
131+
let mut combined = Vec::with_capacity(prefix.len().saturating_add(address_bytes.len()));
132+
combined.extend_from_slice(prefix);
133+
combined.extend_from_slice(&address_bytes);
134+
135+
let hash = blake2_256(&combined);
136+
137+
hash.into()
138+
}
139+
}
140+
141+
#[cfg(test)]
142+
mod test {
143+
use super::*;
144+
145+
use sp_core::crypto::AccountId32;
146+
147+
#[test]
148+
fn ss58_address_from_index_works() {
149+
assert_eq!(
150+
TestPrecompile::address_ss58(),
151+
AccountId32::from([
152+
0x3a, 0x86, 0x18, 0xfb, 0xbb, 0x1b, 0xbc, 0x47, 0x86, 0x64, 0xff, 0x53, 0x46, 0x18,
153+
0x0c, 0x35, 0xd0, 0x9f, 0xac, 0x26, 0xf2, 0x02, 0x70, 0x85, 0xb3, 0x1c, 0x56, 0xc1,
154+
0x06, 0x3c, 0x1c, 0xd3,
155+
])
156+
);
157+
}
158+
159+
struct TestPrecompile;
160+
161+
impl PrecompileExt<AccountId32> for TestPrecompile {
162+
const INDEX: u64 = 2051;
163+
}
164+
}

0 commit comments

Comments
 (0)