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
2 changes: 1 addition & 1 deletion primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ authors = ["Acala Developers"]
edition = "2021"

[dependencies]
hex-literal = "0.3.1"
bstringify = "0.1.2"
serde = { version = "1.0.124", optional = true }
codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false, features = ["max-encoded-len"] }
Expand All @@ -27,7 +28,6 @@ nutsfinance-stable-asset = { version = "0.1.0", default-features = false, path =

[dev-dependencies]
serde_json = { version = "1.0.68" }
hex-literal = "0.3.1"

[features]
default = ["std"]
Expand Down
8 changes: 4 additions & 4 deletions primitives/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::{
};
use codec::{Decode, Encode};
use core::ops::Range;
use hex_literal::hex;
pub use module_evm_utiltity::{
ethereum::{AccessListItem, Log, TransactionAction},
evm::ExitReason,
Expand Down Expand Up @@ -106,12 +107,11 @@ pub struct EthereumTransactionMessage {
/// 0 - 0x0000000000000000000000000000000000000400
/// Acala precompiles
/// 0x0000000000000000000000000000000000000400 - 0x0000000000000000000000000000000000000800
pub const PRECOMPILE_ADDRESS_START: EvmAddress = H160([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0]);
pub const PRECOMPILE_ADDRESS_START: EvmAddress = H160(hex!("0000000000000000000000000000000000000400"));
/// Predeployed system contracts (except Mirrored ERC20)
/// 0x0000000000000000000000000000000000000800 - 0x0000000000000000000000000000000000001000
pub const PREDEPLOY_ADDRESS_START: EvmAddress = H160([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0]);
pub const MIRRORED_TOKENS_ADDRESS_START: EvmAddress =
H160([0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
pub const PREDEPLOY_ADDRESS_START: EvmAddress = H160(hex!("0000000000000000000000000000000000000800"));
pub const MIRRORED_TOKENS_ADDRESS_START: EvmAddress = H160(hex!("0000000000000000000100000000000000000000"));
pub const MIRRORED_NFT_ADDRESS_START: u64 = 0x2000000;
/// System contract address prefix
pub const SYSTEM_CONTRACT_ADDRESS_PREFIX: [u8; 9] = [0u8; 9];
Expand Down
2 changes: 1 addition & 1 deletion runtime/acala/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1355,7 +1355,7 @@ parameter_types! {
pub NetworkContractSource: H160 = H160::from_low_u64_be(0);
pub DeveloperDeposit: Balance = 100 * dollar(ACA);
pub PublicationFee: Balance = 10000 * dollar(ACA);
pub PrecompilesValue: AllPrecompiles<Runtime> = AllPrecompiles::<_>::new();
pub PrecompilesValue: AllPrecompiles<Runtime> = AllPrecompiles::<_>::acala();
}

#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)]
Expand Down
2 changes: 1 addition & 1 deletion runtime/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ authors = ["Acala Developers"]
edition = "2021"

[dependencies]
hex-literal = "0.3.1"
static_assertions = "1.1.0"
num_enum = { version = "0.5.1", default-features = false }
serde = { version = "1.0.124", optional = true, default-features = false }
Expand Down Expand Up @@ -43,7 +44,6 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "releas

[dev-dependencies]
serde_json = "1.0.68"
hex-literal = "0.3.1"

sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" }
Expand Down
2 changes: 1 addition & 1 deletion runtime/common/src/precompile/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ pub type EvmErc20InfoMapping = module_asset_registry::EvmErc20InfoMapping<Test>;

parameter_types! {
pub NetworkContractSource: H160 = alice_evm_addr();
pub PrecompilesValue: AllPrecompiles<Test> = AllPrecompiles::<_>::new();
pub PrecompilesValue: AllPrecompiles<Test> = AllPrecompiles::<_>::mandala();
}

ord_parameter_types! {
Expand Down
181 changes: 133 additions & 48 deletions runtime/common/src/precompile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ mod mock;
mod tests;

use frame_support::log;
use hex_literal::hex;
use module_evm::{
precompiles::{
Blake2F, Bn128Add, Bn128Mul, Bn128Pairing, ECRecover, ECRecoverPublicKey, Identity, IstanbulModexp, Modexp,
Expand All @@ -34,9 +35,8 @@ use module_evm::{
Context, ExitRevert,
};
use module_support::PrecompileCallerFilter as PrecompileCallerFilterT;
use primitives::evm::PRECOMPILE_ADDRESS_START;
use sp_core::H160;
use sp_std::marker::PhantomData;
use sp_std::{collections::btree_set::BTreeSet, marker::PhantomData};

pub mod dex;
pub mod evm;
Expand All @@ -54,39 +54,118 @@ pub use nft::NFTPrecompile;
pub use oracle::OraclePrecompile;
pub use schedule::SchedulePrecompile;

#[derive(Default)]
pub struct AllPrecompiles<R>(PhantomData<R>);
pub const ECRECOVER: H160 = H160(hex!("0000000000000000000000000000000000000001"));
pub const SHA256: H160 = H160(hex!("0000000000000000000000000000000000000002"));
pub const RIPEMD: H160 = H160(hex!("0000000000000000000000000000000000000003"));
pub const IDENTITY: H160 = H160(hex!("0000000000000000000000000000000000000004"));
pub const MODEXP: H160 = H160(hex!("0000000000000000000000000000000000000005"));
pub const BN_ADD: H160 = H160(hex!("0000000000000000000000000000000000000006"));
pub const BN_MUL: H160 = H160(hex!("0000000000000000000000000000000000000007"));
pub const BN_PAIRING: H160 = H160(hex!("0000000000000000000000000000000000000008"));
pub const BLAKE2F: H160 = H160(hex!("0000000000000000000000000000000000000009"));

pub const ECRECOVER_PUBLICKEY: H160 = H160(hex!("0000000000000000000000000000000000000080"));
pub const SHA3_256: H160 = H160(hex!("0000000000000000000000000000000000000081"));
pub const SHA3_512: H160 = H160(hex!("0000000000000000000000000000000000000082"));

pub const MULTI_CURRENCY: H160 = H160(hex!("0000000000000000000000000000000000000400"));
pub const NFT: H160 = H160(hex!("0000000000000000000000000000000000000401"));
pub const EVM: H160 = H160(hex!("0000000000000000000000000000000000000402"));
pub const ORACLE: H160 = H160(hex!("0000000000000000000000000000000000000403"));
pub const SCHEDULER: H160 = H160(hex!("0000000000000000000000000000000000000404"));
pub const DEX: H160 = H160(hex!("0000000000000000000000000000000000000405"));

pub struct AllPrecompiles<R> {
active: BTreeSet<H160>,
_marker: PhantomData<R>,
}

impl<R> AllPrecompiles<R>
where
R: module_evm::Config,
{
pub fn new() -> Self {
Self(Default::default())
pub fn acala() -> Self {
Self {
active: BTreeSet::from([
ECRECOVER,
SHA256,
RIPEMD,
IDENTITY,
MODEXP,
BN_ADD,
BN_MUL,
BN_PAIRING,
BLAKE2F,
// Non-standard precompile starts with 128
ECRECOVER_PUBLICKEY,
SHA3_256,
SHA3_512,
// Acala precompile
MULTI_CURRENCY,
NFT,
EVM,
ORACLE,
// SCHEDULER,
DEX,
]),
_marker: Default::default(),
}
}

pub fn karura() -> Self {
Self {
active: BTreeSet::from([
ECRECOVER,
SHA256,
RIPEMD,
IDENTITY,
MODEXP,
BN_ADD,
BN_MUL,
BN_PAIRING,
BLAKE2F,
// Non-standard precompile starts with 128
ECRECOVER_PUBLICKEY,
SHA3_256,
SHA3_512,
// Acala precompile
MULTI_CURRENCY,
NFT,
EVM,
ORACLE,
// SCHEDULER,
DEX,
]),
_marker: Default::default(),
}
}
pub fn used_addresses() -> sp_std::vec::Vec<H160> {
sp_std::vec![
H160::from_low_u64_be(1),
H160::from_low_u64_be(2),
H160::from_low_u64_be(3),
H160::from_low_u64_be(4),
H160::from_low_u64_be(5),
H160::from_low_u64_be(6),
H160::from_low_u64_be(7),
H160::from_low_u64_be(8),
H160::from_low_u64_be(9),
// Non-standard precompile starts with 128
H160::from_low_u64_be(128),
H160::from_low_u64_be(129),
H160::from_low_u64_be(130),
// Acala precompile
PRECOMPILE_ADDRESS_START,
PRECOMPILE_ADDRESS_START | H160::from_low_u64_be(1),
PRECOMPILE_ADDRESS_START | H160::from_low_u64_be(2),
PRECOMPILE_ADDRESS_START | H160::from_low_u64_be(3),
PRECOMPILE_ADDRESS_START | H160::from_low_u64_be(4),
PRECOMPILE_ADDRESS_START | H160::from_low_u64_be(5),
]

pub fn mandala() -> Self {
Self {
active: BTreeSet::from([
ECRECOVER,
SHA256,
RIPEMD,
IDENTITY,
MODEXP,
BN_ADD,
BN_MUL,
BN_PAIRING,
BLAKE2F,
// Non-standard precompile starts with 128
ECRECOVER_PUBLICKEY,
SHA3_256,
SHA3_512,
// Acala precompile
MULTI_CURRENCY,
NFT,
EVM,
ORACLE,
SCHEDULER,
DEX,
]),
_marker: Default::default(),
}
}
}

Expand Down Expand Up @@ -114,35 +193,35 @@ where
log::trace!(target: "evm", "Precompile begin, address: {:?}, input: {:?}, target_gas: {:?}, context: {:?}", address, input, target_gas, context);

// https://github.com/ethereum/go-ethereum/blob/9357280fce5c5d57111d690a336cca5f89e34da6/core/vm/contracts.go#L83
let result = if address == H160::from_low_u64_be(1) {
let result = if address == ECRECOVER {
Some(ECRecover::execute(input, target_gas, context, is_static))
} else if address == H160::from_low_u64_be(2) {
} else if address == SHA256 {
Some(Sha256::execute(input, target_gas, context, is_static))
} else if address == H160::from_low_u64_be(3) {
} else if address == RIPEMD {
Some(Ripemd160::execute(input, target_gas, context, is_static))
} else if address == H160::from_low_u64_be(4) {
} else if address == IDENTITY {
Some(Identity::execute(input, target_gas, context, is_static))
} else if address == H160::from_low_u64_be(5) {
} else if address == MODEXP {
if R::config().increase_state_access_gas {
Some(Modexp::execute(input, target_gas, context, is_static))
} else {
Some(IstanbulModexp::execute(input, target_gas, context, is_static))
}
} else if address == H160::from_low_u64_be(6) {
} else if address == BN_ADD {
Some(Bn128Add::execute(input, target_gas, context, is_static))
} else if address == H160::from_low_u64_be(7) {
} else if address == BN_MUL {
Some(Bn128Mul::execute(input, target_gas, context, is_static))
} else if address == H160::from_low_u64_be(8) {
} else if address == BN_PAIRING {
Some(Bn128Pairing::execute(input, target_gas, context, is_static))
} else if address == H160::from_low_u64_be(9) {
} else if address == BLAKE2F {
Some(Blake2F::execute(input, target_gas, context, is_static))
}
// Non-standard precompile starts with 128
else if address == H160::from_low_u64_be(128) {
else if address == ECRECOVER_PUBLICKEY {
Some(ECRecoverPublicKey::execute(input, target_gas, context, is_static))
} else if address == H160::from_low_u64_be(129) {
} else if address == SHA3_256 {
Some(Sha3FIPS256::execute(input, target_gas, context, is_static))
} else if address == H160::from_low_u64_be(130) {
} else if address == SHA3_512 {
Some(Sha3FIPS512::execute(input, target_gas, context, is_static))
}
// Acala precompile
Expand All @@ -156,19 +235,19 @@ where
}));
}

if address == PRECOMPILE_ADDRESS_START {
if address == MULTI_CURRENCY {
Some(MultiCurrencyPrecompile::<R>::execute(
input, target_gas, context, is_static,
))
} else if address == PRECOMPILE_ADDRESS_START | H160::from_low_u64_be(1) {
} else if address == NFT {
Some(NFTPrecompile::<R>::execute(input, target_gas, context, is_static))
} else if address == PRECOMPILE_ADDRESS_START | H160::from_low_u64_be(2) {
} else if address == EVM {
Some(EVMPrecompile::<R>::execute(input, target_gas, context, is_static))
} else if address == PRECOMPILE_ADDRESS_START | H160::from_low_u64_be(3) {
} else if address == ORACLE {
Some(OraclePrecompile::<R>::execute(input, target_gas, context, is_static))
} else if address == PRECOMPILE_ADDRESS_START | H160::from_low_u64_be(4) {
} else if address == SCHEDULER {
Some(SchedulePrecompile::<R>::execute(input, target_gas, context, is_static))
} else if address == PRECOMPILE_ADDRESS_START | H160::from_low_u64_be(5) {
} else if address == DEX {
Some(DEXPrecompile::<R>::execute(input, target_gas, context, is_static))
} else {
None
Expand All @@ -183,6 +262,12 @@ where
}

fn is_precompile(&self, address: H160) -> bool {
Self::used_addresses().contains(&address)
self.active.contains(&address)
}
}

#[test]
fn ensure_precompile_address_start() {
use primitives::evm::PRECOMPILE_ADDRESS_START;
assert_eq!(PRECOMPILE_ADDRESS_START, MULTI_CURRENCY);
}
2 changes: 1 addition & 1 deletion runtime/karura/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1365,7 +1365,7 @@ parameter_types! {
pub NetworkContractSource: H160 = H160::from_low_u64_be(0);
pub DeveloperDeposit: Balance = 100 * dollar(KAR);
pub PublicationFee: Balance = 10000 * dollar(KAR);
pub PrecompilesValue: AllPrecompiles<Runtime> = AllPrecompiles::<_>::new();
pub PrecompilesValue: AllPrecompiles<Runtime> = AllPrecompiles::<_>::karura();
}

#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)]
Expand Down
2 changes: 1 addition & 1 deletion runtime/mandala/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1488,7 +1488,7 @@ impl ecosystem_compound_cash::Config for Runtime {
parameter_types! {
pub const ChainId: u64 = 595;
pub NetworkContractSource: H160 = H160::from_low_u64_be(0);
pub PrecompilesValue: AllPrecompiles<Runtime> = AllPrecompiles::<_>::new();
pub PrecompilesValue: AllPrecompiles<Runtime> = AllPrecompiles::<_>::mandala();
}

#[cfg(feature = "with-ethereum-compatibility")]
Expand Down