diff --git a/Cargo.lock b/Cargo.lock index 3424f3319..b40684741 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4619,7 +4619,7 @@ dependencies = [ [[package]] name = "hydradx-runtime" -version = "207.0.0" +version = "208.0.0" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", @@ -4675,7 +4675,11 @@ dependencies = [ "pallet-ethereum", "pallet-evm", "pallet-evm-chain-id", + "pallet-evm-precompile-blake2", + "pallet-evm-precompile-bn128", "pallet-evm-precompile-dispatch", + "pallet-evm-precompile-modexp", + "pallet-evm-precompile-simple", "pallet-genesis-history", "pallet-identity", "pallet-lbp", @@ -6569,6 +6573,20 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.4" @@ -6609,6 +6627,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-rational" version = "0.4.1" @@ -7622,6 +7651,24 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "pallet-evm-precompile-blake2" +version = "2.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?rev=bf5885a982041cc744ecbb62a2afc13d56d464dc#bf5885a982041cc744ecbb62a2afc13d56d464dc" +dependencies = [ + "fp-evm", +] + +[[package]] +name = "pallet-evm-precompile-bn128" +version = "2.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?rev=bf5885a982041cc744ecbb62a2afc13d56d464dc#bf5885a982041cc744ecbb62a2afc13d56d464dc" +dependencies = [ + "fp-evm", + "sp-core", + "substrate-bn", +] + [[package]] name = "pallet-evm-precompile-dispatch" version = "2.0.0-dev" @@ -7634,6 +7681,25 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "pallet-evm-precompile-modexp" +version = "2.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?rev=bf5885a982041cc744ecbb62a2afc13d56d464dc#bf5885a982041cc744ecbb62a2afc13d56d464dc" +dependencies = [ + "fp-evm", + "num", +] + +[[package]] +name = "pallet-evm-precompile-simple" +version = "2.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?rev=bf5885a982041cc744ecbb62a2afc13d56d464dc#bf5885a982041cc744ecbb62a2afc13d56d464dc" +dependencies = [ + "fp-evm", + "ripemd", + "sp-io", +] + [[package]] name = "pallet-fast-unstake" version = "4.0.0-dev" @@ -11042,6 +11108,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "rlp" version = "0.5.2" @@ -11227,7 +11302,7 @@ dependencies = [ [[package]] name = "runtime-integration-tests" -version = "1.17.3" +version = "1.17.4" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", @@ -11240,6 +11315,7 @@ dependencies = [ "cumulus-primitives-utility", "cumulus-test-relay-sproof-builder", "fp-evm", + "fp-rpc", "frame-benchmarking", "frame-executive", "frame-remote-externalities", @@ -14261,6 +14337,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "substrate-bn" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" +dependencies = [ + "byteorder", + "crunchy", + "lazy_static", + "rand 0.8.5", + "rustc-hex", +] + [[package]] name = "substrate-build-script-utils" version = "3.0.0" diff --git a/Cargo.toml b/Cargo.toml index a094fa340..d53f2f3c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ members = [ log = "0.4.20" async-trait = "0.1" futures = "0.3.25" +hex-literal = "0.4.1" hydra-dx-math = { path = "math", default-features = false } hydradx = { path = "node", default-features = false } hydradx-traits = { path = "traits", default-features = false } @@ -237,6 +238,10 @@ pallet-ethereum = { git = "https://github.com/moonbeam-foundation/frontier", rev pallet-evm = { git = "https://github.com/moonbeam-foundation/frontier", rev = "bf5885a982041cc744ecbb62a2afc13d56d464dc", default-features = false } pallet-evm-chain-id = { git = "https://github.com/moonbeam-foundation/frontier", rev = "bf5885a982041cc744ecbb62a2afc13d56d464dc", default-features = false } pallet-evm-precompile-dispatch = { git = "https://github.com/moonbeam-foundation/frontier", rev = "bf5885a982041cc744ecbb62a2afc13d56d464dc", default-features = false } +pallet-evm-precompile-simple = { git = "https://github.com/moonbeam-foundation/frontier", rev = "bf5885a982041cc744ecbb62a2afc13d56d464dc", default-features = false } +pallet-evm-precompile-modexp = { git = "https://github.com/moonbeam-foundation/frontier", rev = "bf5885a982041cc744ecbb62a2afc13d56d464dc", default-features = false } +pallet-evm-precompile-bn128 = { git = "https://github.com/moonbeam-foundation/frontier", rev = "bf5885a982041cc744ecbb62a2afc13d56d464dc", default-features = false } +pallet-evm-precompile-blake2 = { git = "https://github.com/moonbeam-foundation/frontier", rev = "bf5885a982041cc744ecbb62a2afc13d56d464dc", default-features = false } # EVM from acala module-evm-utility-macro = { path = "runtime/hydradx/src/evm/evm-utility/macro", default-features = false} diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 4455fa67e..268ef868a 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "runtime-integration-tests" -version = "1.17.3" +version = "1.17.4" description = "Integration tests" authors = ["GalacticCouncil"] edition = "2021" @@ -9,6 +9,7 @@ license = "Apache 2.0" repository = "https://github.com/galacticcouncil/HydraDX-node" [dependencies] +hex-literal = { workspace = true } frame-remote-externalities = { workspace = true } tokio = { version = "1", features = ["macros", "rt-multi-thread"] } scraper = { workspace = true } @@ -63,6 +64,7 @@ orml-unknown-tokens = { workspace = true } # Evm pallet-evm = { workspace = true } fp-evm = { workspace = true } +fp-rpc = { workspace = true } # Cumulus dependencies cumulus-pallet-aura-ext = { workspace = true } cumulus-pallet-parachain-system = { workspace = true } @@ -125,7 +127,6 @@ polkadot-runtime-parachains = { workspace = true } polkadot-runtime = { workspace = true } [dev-dependencies] -hex-literal = "0.4.1" pretty_assertions = "1.2.1" xcm-emulator = { workspace = true } diff --git a/integration-tests/src/evm.rs b/integration-tests/src/evm.rs index f60a6eb6e..0740c1f83 100644 --- a/integration-tests/src/evm.rs +++ b/integration-tests/src/evm.rs @@ -24,6 +24,212 @@ use xcm_emulator::TestExt; const TREASURY_ACCOUNT_INIT_BALANCE: Balance = 1000 * UNITS; +mod standard_precompiles { + use super::*; + use pretty_assertions::assert_eq; + use sp_runtime::traits::UniqueSaturatedInto; + + fn evm_runner_call( + to: EvmAddress, + data: Vec, + ) -> Result>> { + ::Runner::call( + evm_address(), + to, + data, + U256::from(1000u64), + U256::from(1000000u64).unique_saturated_into(), + None, + None, + None, + Default::default(), + false, + true, + None, + None, + ::config(), + ) + } + + #[test] + fn ecrecover_precompile() { + TestNet::reset(); + + Hydra::execute_with(|| { + //Arrange + let input = hex! {" + 18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c + 000000000000000000000000000000000000000000000000000000000000001c + 73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f + eeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549 + "} + .to_vec(); + let expected_output = hex!("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b").to_vec(); + + //Act + let execution_result = evm_runner_call(hydradx_runtime::evm::precompiles::ECRECOVER, input).unwrap(); + + //Assert + assert_eq!(execution_result.exit_reason, ExitReason::Succeed(ExitSucceed::Returned),); + assert_eq!(execution_result.value, expected_output); + }); + } + + #[test] + fn sha256_precompile() { + TestNet::reset(); + + Hydra::execute_with(|| { + //Arrange + let input = "HydraDX".as_bytes().to_vec(); + let expected_output = hex!("61e6380e10376b3479838d623b2b1faeaa2afafcfaff2840a6df2f41161488da").to_vec(); + + //Act + let execution_result = evm_runner_call(hydradx_runtime::evm::precompiles::SHA256, input).unwrap(); + + //Assert + assert_eq!(execution_result.exit_reason, ExitReason::Succeed(ExitSucceed::Returned),); + assert_eq!(execution_result.value, expected_output); + }); + } + + #[test] + fn ripemd160_precompile() { + TestNet::reset(); + + Hydra::execute_with(|| { + //Arrange + let input = "HydraDX".as_bytes().to_vec(); + let mut expected_output = [0u8; 32]; + expected_output[12..32].copy_from_slice(&hex!("8883ba5c203439408542b87526c113426ce94742")); + + //Act + let execution_result = evm_runner_call(hydradx_runtime::evm::precompiles::RIPEMD, input).unwrap(); + + //Assert + assert_eq!(execution_result.exit_reason, ExitReason::Succeed(ExitSucceed::Returned),); + assert_eq!(execution_result.value, expected_output); + }); + } + + #[test] + fn identity_precompile() { + TestNet::reset(); + + Hydra::execute_with(|| { + //Arrange + let input = "HydraDX".as_bytes().to_vec(); + + //Act + let execution_result = evm_runner_call(hydradx_runtime::evm::precompiles::IDENTITY, input.clone()).unwrap(); + + //Assert + assert_eq!(execution_result.exit_reason, ExitReason::Succeed(ExitSucceed::Returned),); + assert_eq!(execution_result.value, input); + }); + } + + #[test] + fn modexp_precompile() { + TestNet::reset(); + + Hydra::execute_with(|| { + //Arrange + let input = hex!( + " + 0000000000000000000000000000000000000000000000000000000000000001 + 0000000000000000000000000000000000000000000000000000000000000001 + 0000000000000000000000000000000000000000000000000000000000000001 + 03 + 05 + 07 + " + ) + .to_vec(); + let expected_output = vec![5]; + + //Act + let execution_result = evm_runner_call(hydradx_runtime::evm::precompiles::MODEXP, input).unwrap(); + + //Assert + assert_eq!(execution_result.exit_reason, ExitReason::Succeed(ExitSucceed::Returned),); + assert_eq!(execution_result.value, expected_output); + }); + } + + #[test] + fn bn128add_precompile() { + TestNet::reset(); + + Hydra::execute_with(|| { + //Arrange + let input = hex!("089142debb13c461f61523586a60732d8b69c5b38a3380a74da7b2961d867dbf2d5fc7bbc013c16d7945f190b232eacc25da675c0eb093fe6b9f1b4b4e107b3625f8c89ea3437f44f8fc8b6bfbb6312074dc6f983809a5e809ff4e1d076dd5850b38c7ced6e4daef9c4347f370d6d8b58f4b1d8dc61a3c59d651a0644a2a27cf").to_vec(); + let expected_output = hex!("0a6678fd675aa4d8f0d03a1feb921a27f38ebdcb860cc083653519655acd6d79172fd5b3b2bfdd44e43bcec3eace9347608f9f0a16f1e184cb3f52e6f259cbeb").to_vec(); + + //Act + let execution_result = evm_runner_call(hydradx_runtime::evm::precompiles::BN_ADD, input).unwrap(); + + //Assert + assert_eq!(execution_result.exit_reason, ExitReason::Succeed(ExitSucceed::Returned),); + assert_eq!(execution_result.value, expected_output); + }); + } + + #[test] + fn bn128mul_precompile() { + TestNet::reset(); + + Hydra::execute_with(|| { + //Arrange + let input = hex!("089142debb13c461f61523586a60732d8b69c5b38a3380a74da7b2961d867dbf2d5fc7bbc013c16d7945f190b232eacc25da675c0eb093fe6b9f1b4b4e107b36ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").to_vec(); + let expected_output = hex!("0bf982b98a2757878c051bfe7eee228b12bc69274b918f08d9fcb21e9184ddc10b17c77cbf3c19d5d27e18cbd4a8c336afb488d0e92c18d56e64dd4ea5c437e6").to_vec(); + + //Act + let execution_result = evm_runner_call(hydradx_runtime::evm::precompiles::BN_MUL, input).unwrap(); + + //Assert + assert_eq!(execution_result.exit_reason, ExitReason::Succeed(ExitSucceed::Returned),); + assert_eq!(execution_result.value, expected_output); + }); + } + + #[test] + fn bn128pairing_precompile() { + TestNet::reset(); + + Hydra::execute_with(|| { + //Arrange + let input = hex!("089142debb13c461f61523586a60732d8b69c5b38a3380a74da7b2961d867dbf2d5fc7bbc013c16d7945f190b232eacc25da675c0eb093fe6b9f1b4b4e107b3629f2c1dbcc614745f242077001ec9edd475acdab9ab435770d456bd22bbd2abf268683f9b1be0bde4508e2e25e51f6b44da3546e87524337d506fd03c4ff7ce01851abe58ef4e08916bec8034ca62c04cd08340ab6cc525e61706340926221651b71422869c92e49465200ca19033a8aa425f955be3d8329c4475503e45c00e1").to_vec(); + let expected_output = hex!("0000000000000000000000000000000000000000000000000000000000000000").to_vec(); + + //Act + let execution_result = evm_runner_call(hydradx_runtime::evm::precompiles::BN_PAIRING, input).unwrap(); + + //Assert + assert_eq!(execution_result.exit_reason, ExitReason::Succeed(ExitSucceed::Returned),); + assert_eq!(execution_result.value, expected_output); + }); + } + + #[test] + fn blake2f_precompile() { + TestNet::reset(); + + Hydra::execute_with(|| { + //Arrange + let input = hex!("0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001").to_vec(); + let expected_output = hex!("ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923").to_vec(); + + //Act + let execution_result = evm_runner_call(hydradx_runtime::evm::precompiles::BLAKE2F, input).unwrap(); + + //Assert + assert_eq!(execution_result.exit_reason, ExitReason::Succeed(ExitSucceed::Returned),); + assert_eq!(execution_result.value, expected_output); + }); + } +} + mod currency_precompile { use super::*; use pretty_assertions::assert_eq; @@ -42,8 +248,8 @@ mod currency_precompile { let mut handle = MockHandle { input: data, context: Context { - address: evm_address(), - caller: native_asset_ethereum_address(), + address: native_asset_ethereum_address(), + caller: evm_address(), apparent_value: U256::from(0), }, core_address: native_asset_ethereum_address(), @@ -78,8 +284,8 @@ mod currency_precompile { let mut handle = MockHandle { input: data, context: Context { - address: evm_address(), - caller: native_asset_ethereum_address(), + address: H160::from(hex!("00000000000000000000000000000001ffffffff")), + caller: evm_address(), apparent_value: U256::from(0), }, core_address: H160::from(hex!("00000000000000000000000000000001ffffffff")), diff --git a/runtime/hydradx/Cargo.toml b/runtime/hydradx/Cargo.toml index 038c7086b..11db86bab 100644 --- a/runtime/hydradx/Cargo.toml +++ b/runtime/hydradx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hydradx-runtime" -version = "207.0.0" +version = "208.0.0" authors = ["GalacticCouncil"] edition = "2021" license = "Apache 2.0" @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] substrate-wasm-builder = { workspace = true } [dependencies] -hex-literal = "0.4.1" +hex-literal = { workspace = true } serde = { features = ["derive"], optional = true, version = "1.0.136" } codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false, features = ["derive"] } scale-info = { version = "2.3.1", default-features = false, features = ["derive"] } @@ -141,6 +141,10 @@ pallet-ethereum = { workspace = true } pallet-evm = { workspace = true } pallet-evm-chain-id = { workspace = true } pallet-evm-precompile-dispatch = { workspace = true } +pallet-evm-precompile-simple = { workspace = true } +pallet-evm-precompile-modexp = { workspace = true } +pallet-evm-precompile-bn128 = { workspace = true } +pallet-evm-precompile-blake2 = { workspace = true } module-evm-utility-macro = { workspace = true } ethabi = { version = "18.0.0", default-features = false } @@ -284,6 +288,10 @@ std = [ "pallet-evm/std", "pallet-evm-chain-id/std", "pallet-evm-precompile-dispatch/std", + "pallet-evm-precompile-simple/std", + "pallet-evm-precompile-modexp/std", + "pallet-evm-precompile-bn128/std", + "pallet-evm-precompile-blake2/std", "pallet-xyk/std", "pallet-referrals/std", ] diff --git a/runtime/hydradx/src/evm/precompiles/mod.rs b/runtime/hydradx/src/evm/precompiles/mod.rs index 132fd4993..da6e90596 100644 --- a/runtime/hydradx/src/evm/precompiles/mod.rs +++ b/runtime/hydradx/src/evm/precompiles/mod.rs @@ -28,10 +28,15 @@ use pallet_evm::{ ExitError, ExitRevert, ExitSucceed, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileOutput, PrecompileResult, PrecompileSet, }; +use pallet_evm_precompile_blake2::Blake2F; +use pallet_evm_precompile_bn128::{Bn128Add, Bn128Mul, Bn128Pairing}; +use pallet_evm_precompile_modexp::Modexp; +use pallet_evm_precompile_simple::{ECRecover, Identity, Ripemd160, Sha256}; use sp_runtime::traits::Dispatchable; use codec::alloc; use ethabi::Token; +use hex_literal::hex; use primitive_types::{H160, U256}; use sp_std::{borrow::ToOwned, vec::Vec}; @@ -80,6 +85,22 @@ impl HydraDXPrecompiles { // https://docs.moonbeam.network/builders/pallets-precompiles/precompiles/overview/#precompiled-contract-addresses const DISPATCH_ADDR: H160 = addr(1025); +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 ETH_PRECOMPILE_END: H160 = BLAKE2F; + +fn is_standard_precompile(address: H160) -> bool { + !address.is_zero() && address <= ETH_PRECOMPILE_END +} + impl PrecompileSet for HydraDXPrecompiles where R: pallet_evm::Config + pallet_currencies::Config, @@ -88,9 +109,36 @@ where MultiCurrencyPrecompile: Precompile, { fn execute(&self, handle: &mut impl PrecompileHandle) -> Option { + let context = handle.context(); let address = handle.code_address(); - if address == DISPATCH_ADDR { + // Filter known precompile addresses except Ethereum officials + if address > ETH_PRECOMPILE_END && context.address != address { + return Some(Err(PrecompileFailure::Revert { + exit_status: ExitRevert::Reverted, + output: "cannot be called with DELEGATECALL or CALLCODE".into(), + })); + } + + if address == ECRECOVER { + Some(ECRecover::execute(handle)) + } else if address == SHA256 { + Some(Sha256::execute(handle)) + } else if address == RIPEMD { + Some(Ripemd160::execute(handle)) + } else if address == IDENTITY { + Some(Identity::execute(handle)) + } else if address == MODEXP { + Some(Modexp::execute(handle)) + } else if address == BN_ADD { + Some(Bn128Add::execute(handle)) + } else if address == BN_MUL { + Some(Bn128Mul::execute(handle)) + } else if address == BN_PAIRING { + Some(Bn128Pairing::execute(handle)) + } else if address == BLAKE2F { + Some(Blake2F::execute(handle)) + } else if address == DISPATCH_ADDR { Some(pallet_evm_precompile_dispatch::Dispatch::::execute(handle)) } else if is_asset_address(address) { Some(MultiCurrencyPrecompile::::execute(handle)) @@ -100,7 +148,7 @@ where } fn is_precompile(&self, address: H160, _remaining_gas: u64) -> IsPrecompileResult { - let is_precompile = address == DISPATCH_ADDR || is_asset_address(address); + let is_precompile = address == DISPATCH_ADDR || is_asset_address(address) || is_standard_precompile(address); IsPrecompileResult::Answer { is_precompile, extra_cost: 0, diff --git a/runtime/hydradx/src/lib.rs b/runtime/hydradx/src/lib.rs index 0da8bf6ab..b4e80b0dc 100644 --- a/runtime/hydradx/src/lib.rs +++ b/runtime/hydradx/src/lib.rs @@ -107,7 +107,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("hydradx"), impl_name: create_runtime_str!("hydradx"), authoring_version: 1, - spec_version: 207, + spec_version: 208, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1,