Skip to content

Commit

Permalink
Merge pull request #805 from galacticcouncil/fix/evm-trade-insufficie…
Browse files Browse the repository at this point in the history
…nt-asset

fix: swaps of insufficient asset via evm
  • Loading branch information
mrq1911 authored Apr 17, 2024
2 parents 8abf856 + 403d955 commit 6cf5bb5
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 9 deletions.
6 changes: 3 additions & 3 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "runtime-integration-tests"
version = "1.20.1"
version = "1.20.2"
description = "Integration tests"
authors = ["GalacticCouncil"]
edition = "2021"
Expand Down
129 changes: 128 additions & 1 deletion integration-tests/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
use crate::{assert_balance, polkadot_test_net::*};
use fp_evm::{Context, Transfer};
use fp_rpc::runtime_decl_for_ethereum_runtime_rpc_api::EthereumRuntimeRPCApi;
use frame_support::storage::with_transaction;
use frame_support::{assert_ok, dispatch::GetDispatchInfo, sp_runtime::codec::Encode, traits::Contains};
use frame_system::RawOrigin;
use hex_literal::hex;
use hydradx_runtime::evm::ExtendedAddressMapping;
use hydradx_runtime::XYK;
use hydradx_runtime::{
evm::precompiles::{
addr,
Expand All @@ -17,12 +19,15 @@ use hydradx_runtime::{
AssetRegistry, Balances, CallFilter, Currencies, EVMAccounts, Omnipool, RuntimeCall, RuntimeOrigin, Tokens,
TransactionPause, EVM,
};
use hydradx_traits::AssetKind;
use hydradx_traits::Create;
use orml_traits::MultiCurrency;
use pallet_evm::*;
use pretty_assertions::assert_eq;
use primitives::{AssetId, Balance};
use sp_core::{blake2_256, H160, H256, U256};
use sp_runtime::{traits::SignedExtension, FixedU128, Permill};
use sp_runtime::TransactionOutcome;
use sp_runtime::{traits::SignedExtension, DispatchError, FixedU128, Permill};
use std::borrow::Cow;
use xcm_emulator::TestExt;

Expand Down Expand Up @@ -1119,6 +1124,103 @@ fn dispatch_should_work_with_transfer() {
});
}

#[test]
fn dispatch_should_work_with_buying_insufficient_asset() {
TestNet::reset();

Hydra::execute_with(|| {
//Set up to idle state where the chain is not utilized at all
pallet_transaction_payment::pallet::NextFeeMultiplier::<hydradx_runtime::Runtime>::put(
hydradx_runtime::MinimumMultiplier::get(),
);
assert_ok!(EVMAccounts::bind_evm_address(hydradx_runtime::RuntimeOrigin::signed(
ALICE.into()
)));

//Create inssufficient asset
let shitcoin = with_transaction::<u32, DispatchError, _>(|| {
let name = b"SHITCO".to_vec();
let shitcoin = AssetRegistry::register_insufficient_asset(
None,
Some(name.try_into().unwrap()),
AssetKind::External,
Some(1_000),
None,
None,
None,
None,
)
.unwrap();

TransactionOutcome::Commit(Ok(shitcoin))
})
.unwrap();

create_xyk_pool_with_amounts(shitcoin, 1000000 * UNITS, HDX, 1000000 * UNITS);
let evm_address = EVMAccounts::evm_address(&Into::<AccountId>::into(ALICE));
init_omnipool_with_oracle_for_block_10();

assert_ok!(hydradx_runtime::Currencies::update_balance(
hydradx_runtime::RuntimeOrigin::root(),
currency_precompile::alice_substrate_evm_addr().into(),
WETH,
(100 * UNITS * 1_000_000) as i128,
));
assert_ok!(hydradx_runtime::MultiTransactionPayment::set_currency(
hydradx_runtime::RuntimeOrigin::signed(ALICE.into()),
WETH,
));

let swap_route = vec![
Trade {
pool: PoolType::Omnipool,
asset_in: WETH,
asset_out: HDX,
},
Trade {
pool: PoolType::XYK,
asset_in: HDX,
asset_out: shitcoin,
},
];
let router_swap = RuntimeCall::Router(pallet_route_executor::Call::buy {
asset_in: WETH,
asset_out: shitcoin,
amount_out: 1 * UNITS,
max_amount_in: u128::MAX,
route: swap_route.clone(),
});

//Arrange
let data = router_swap.encode();
let (gas_price, _) = hydradx_runtime::DynamicEvmFee::min_gas_price();

hydradx_finalize_block(); //We do this to simulate that we don't have any prices in multi-payment-pallet, but the prices can be still calculated based on onchain route

let init_balance = Tokens::free_balance(shitcoin, &currency_precompile::alice_substrate_evm_addr());
assert_eq!(init_balance, 0);

// Act
assert_ok!(EVM::call(
evm_signed_origin(currency_precompile::alice_evm_addr()),
currency_precompile::alice_evm_addr(),
DISPATCH_ADDR,
data,
U256::from(0),
1000000,
gas_price * 10,
None,
Some(U256::zero()),
[].into()
));

//EVM call passes even when the substrate tx fails, so we need to check if the tx is executed
expect_hydra_events(vec![pallet_evm::Event::Executed { address: DISPATCH_ADDR }.into()]);
let new_balance = Tokens::free_balance(shitcoin, &currency_precompile::alice_substrate_evm_addr());
assert_eq!(new_balance, 1 * UNITS);
});
}

#[test]
fn dispatch_transfer_should_not_work_with_insufficient_fees() {
TestNet::reset();
Expand Down Expand Up @@ -1500,6 +1602,8 @@ fn do_trade_to_populate_oracle(asset_1: AssetId, asset_2: AssetId, amount: Balan
}

use frame_support::traits::fungible::Mutate;
use hydradx_traits::router::{PoolType, Trade};

pub fn init_omnipol() {
let native_price = FixedU128::from_rational(29903049701668757, 73927734532192294158);
let dot_price = FixedU128::from_rational(103158291366950047, 4566210555614178);
Expand Down Expand Up @@ -1636,3 +1740,26 @@ impl PrecompileHandle for MockHandle {
None
}
}

fn create_xyk_pool_with_amounts(asset_a: u32, amount_a: u128, asset_b: u32, amount_b: u128) {
assert_ok!(Currencies::update_balance(
hydradx_runtime::RuntimeOrigin::root(),
DAVE.into(),
asset_a,
amount_a as i128,
));
assert_ok!(Currencies::update_balance(
hydradx_runtime::RuntimeOrigin::root(),
DAVE.into(),
asset_b,
amount_b as i128,
));

assert_ok!(XYK::create_pool(
RuntimeOrigin::signed(DAVE.into()),
asset_a,
amount_a,
asset_b,
amount_b,
));
}
10 changes: 10 additions & 0 deletions integration-tests/src/polkadot_test_net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,16 @@ pub fn hydradx_run_to_block(to: BlockNumber) {
}
}

pub fn hydradx_finalize_block() {
use frame_support::traits::OnFinalize;

let b = hydradx_runtime::System::block_number();

hydradx_runtime::System::on_finalize(b);
hydradx_runtime::EmaOracle::on_finalize(b);
hydradx_runtime::MultiTransactionPayment::on_finalize(b);
}

pub fn polkadot_run_to_block(to: BlockNumber) {
use frame_support::traits::OnFinalize;

Expand Down
2 changes: 1 addition & 1 deletion pallets/transaction-multi-payment/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pallet-transaction-multi-payment"
version = "9.5.0"
version = "9.6.0"
description = "Transaction multi currency payment support module"
authors = ["GalacticCoucil"]
edition = "2021"
Expand Down
4 changes: 3 additions & 1 deletion pallets/transaction-multi-payment/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,12 +522,14 @@ where
}

/// We provide an oracle for the price of all currencies accepted as fee payment.
/// In the else statement, first we try to get the price from cache, otherwise we calculate it
/// The price calculation based on onchain-route is mainly used by EVM dry run as in the dry run we dont have storage filled with prices, so calculation is needed
impl<T: Config> NativePriceOracle<AssetIdOf<T>, Price> for Pallet<T> {
fn price(currency: AssetIdOf<T>) -> Option<Price> {
if currency == T::NativeAssetId::get() {
Some(Price::one())
} else {
Pallet::<T>::currency_price(currency)
Pallet::<T>::currency_price(currency).or_else(|| Self::get_oracle_price(currency, T::NativeAssetId::get()))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/hydradx/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "hydradx-runtime"
version = "227.0.0"
version = "228.0.0"
authors = ["GalacticCouncil"]
edition = "2021"
license = "Apache 2.0"
Expand Down
2 changes: 1 addition & 1 deletion runtime/hydradx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("hydradx"),
impl_name: create_runtime_str!("hydradx"),
authoring_version: 1,
spec_version: 227,
spec_version: 228,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down

0 comments on commit 6cf5bb5

Please sign in to comment.