From 610262b9181309b833e860741f3ca9d49d67d86e Mon Sep 17 00:00:00 2001 From: Frank Yin Date: Fri, 15 Apr 2022 17:24:23 -0700 Subject: [PATCH 01/11] stable asset precompiles --- Cargo.lock | 1 + runtime/acala/src/lib.rs | 68 ++ runtime/acala/src/weights/mod.rs | 2 + .../src/weights/nutsfinance_stable_asset.rs | 131 ++++ runtime/common/Cargo.toml | 1 + runtime/common/src/lib.rs | 2 +- runtime/common/src/precompile/input.rs | 15 + runtime/common/src/precompile/mock.rs | 38 +- runtime/common/src/precompile/mod.rs | 10 + runtime/common/src/precompile/stable_asset.rs | 672 ++++++++++++++++++ 10 files changed, 938 insertions(+), 2 deletions(-) create mode 100644 runtime/acala/src/weights/nutsfinance_stable_asset.rs create mode 100644 runtime/common/src/precompile/stable_asset.rs diff --git a/Cargo.lock b/Cargo.lock index cb26ec0729..d97ce8b7f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10722,6 +10722,7 @@ dependencies = [ "module-support", "module-transaction-payment", "num_enum", + "nutsfinance-stable-asset", "orml-bencher", "orml-currencies", "orml-nft", diff --git a/runtime/acala/src/lib.rs b/runtime/acala/src/lib.rs index 675b6d4c01..b5ff518330 100644 --- a/runtime/acala/src/lib.rs +++ b/runtime/acala/src/lib.rs @@ -84,6 +84,7 @@ pub use sp_runtime::BuildStorage; pub use authority::AuthorityConfigImpl; pub use constants::{fee::*, time::*}; use module_support::mocks::MockStableAsset; +use module_support::ExchangeRateProvider; pub use primitives::{ define_combined_task, evm::{AccessListItem, EstimateResourcesRequest}, @@ -161,6 +162,7 @@ parameter_types! { // This Pallet is only used to payment fee pool, it's not added to whitelist by design. // because transaction payment pallet will ensure the accounts always have enough ED. pub const TransactionPaymentPalletId: PalletId = PalletId(*b"aca/fees"); + pub const StableAssetPalletId: PalletId = PalletId(*b"nuts/sta"); } pub fn get_all_module_accounts() -> Vec { @@ -176,6 +178,7 @@ pub fn get_all_module_accounts() -> Vec { TreasuryPalletId::get().into_account(), TreasuryReservePalletId::get().into_account(), UnreleasedNativeVaultAccountId::get(), + StableAssetPalletId::get().into_account(), ] } @@ -1499,6 +1502,68 @@ impl module_idle_scheduler::Config for Runtime { type DisableBlockThreshold = ConstU32<6>; } +pub struct EnsurePoolAssetId; +impl nutsfinance_stable_asset::traits::ValidateAssetId for EnsurePoolAssetId { + fn validate(currency_id: CurrencyId) -> bool { + matches!(currency_id, CurrencyId::StableAssetPoolToken(_)) + } +} + +pub struct ConvertBalanceHoma; +impl orml_tokens::ConvertBalance for ConvertBalanceHoma { + type AssetId = CurrencyId; + + fn convert_balance(balance: Balance, asset_id: CurrencyId) -> Balance { + match asset_id { + CurrencyId::Token(TokenSymbol::LKSM) => { + Homa::get_exchange_rate().checked_mul_int(balance).unwrap_or_default() + } + _ => balance, + } + } + + fn convert_balance_back(balance: Balance, asset_id: CurrencyId) -> Balance { + match asset_id { + CurrencyId::Token(TokenSymbol::LKSM) => Homa::get_exchange_rate() + .reciprocal() + .and_then(|x| x.checked_mul_int(balance)) + .unwrap_or_default(), + _ => balance, + } + } +} + +pub struct IsLiquidToken; +impl Contains for IsLiquidToken { + fn contains(currency_id: &CurrencyId) -> bool { + matches!(currency_id, CurrencyId::Token(TokenSymbol::LKSM)) + } +} + +type RebaseTokens = orml_tokens::Combiner< + AccountId, + IsLiquidToken, + orml_tokens::Mapper, + Tokens, +>; + +impl nutsfinance_stable_asset::Config for Runtime { + type Event = Event; + type AssetId = CurrencyId; + type Balance = Balance; + type Assets = RebaseTokens; + type PalletId = StableAssetPalletId; + + type AtLeast64BitUnsigned = u128; + type FeePrecision = ConstU128<10_000_000_000>; // 10 decimals + type APrecision = ConstU128<100>; // 2 decimals + type PoolAssetLimit = ConstU32<5>; + type SwapExactOverAmount = ConstU128<100>; + type WeightInfo = weights::nutsfinance_stable_asset::WeightInfo; + type ListingOrigin = EnsureRootOrHalfGeneralCouncil; + type EnsurePoolAssetId = EnsurePoolAssetId; +} + construct_runtime!( pub enum Runtime where Block = Block, @@ -1599,6 +1664,9 @@ construct_runtime!( EVMBridge: module_evm_bridge exclude_parts { Call } = 131, EvmAccounts: module_evm_accounts = 132, + // Stable asset + StableAsset: nutsfinance_stable_asset = 200, + // Parachain System, always put it at the end ParachainSystem: cumulus_pallet_parachain_system = 30, diff --git a/runtime/acala/src/weights/mod.rs b/runtime/acala/src/weights/mod.rs index b26b661b87..6cb5a57d0c 100644 --- a/runtime/acala/src/weights/mod.rs +++ b/runtime/acala/src/weights/mod.rs @@ -44,3 +44,5 @@ pub mod orml_authority; pub mod orml_oracle; pub mod orml_tokens; pub mod orml_vesting; + +pub mod nutsfinance_stable_asset; diff --git a/runtime/acala/src/weights/nutsfinance_stable_asset.rs b/runtime/acala/src/weights/nutsfinance_stable_asset.rs new file mode 100644 index 0000000000..1969f53246 --- /dev/null +++ b/runtime/acala/src/weights/nutsfinance_stable_asset.rs @@ -0,0 +1,131 @@ +// This file is part of Acala. + +// Copyright (C) 2020-2022 Acala Foundation. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Autogenerated weights for nutsfinance_stable_asset +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("karura-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/acala +// benchmark +// --chain=karura-dev +// --steps=50 +// --repeat=20 +// --pallet=* +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --template=./templates/runtime-weight-template.hbs +// --output=./runtime/karura/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for nutsfinance_stable_asset. +pub struct WeightInfo(PhantomData); +impl nutsfinance_stable_asset::WeightInfo for WeightInfo { + // Storage: StableAsset PoolCount (r:1 w:1) + // Storage: StableAsset Pools (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn create_pool() -> Weight { + (23_041_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: StableAsset Pools (r:1 w:1) + fn modify_a() -> Weight { + (16_092_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: StableAsset Pools (r:1 w:1) + // Storage: Tokens Accounts (r:6 w:6) + // Storage: System Account (r:2 w:2) + // Storage: Tokens TotalIssuance (r:1 w:1) + // Storage: AssetRegistry AssetMetadatas (r:1 w:0) + fn mint(u: u32, ) -> Weight { + (73_727_000 as Weight) + // Standard Error: 117_000 + .saturating_add((17_942_000 as Weight).saturating_mul(u as Weight)) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(u as Weight))) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(u as Weight))) + } + // Storage: StableAsset Pools (r:1 w:1) + // Storage: Tokens Accounts (r:5 w:5) + // Storage: System Account (r:1 w:0) + // Storage: Tokens TotalIssuance (r:1 w:1) + // Storage: AssetRegistry AssetMetadatas (r:1 w:0) + fn swap(u: u32, ) -> Weight { + (71_743_000 as Weight) + // Standard Error: 140_000 + .saturating_add((5_807_000 as Weight).saturating_mul(u as Weight)) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(u as Weight))) + .saturating_add(T::DbWeight::get().writes(7 as Weight)) + } + // Storage: StableAsset Pools (r:1 w:1) + // Storage: Tokens Accounts (r:6 w:6) + // Storage: System Account (r:1 w:0) + // Storage: AssetRegistry AssetMetadatas (r:1 w:0) + // Storage: Tokens TotalIssuance (r:1 w:1) + fn redeem_proportion(u: u32, ) -> Weight { + (81_025_000 as Weight) + // Standard Error: 699_000 + .saturating_add((13_663_000 as Weight).saturating_mul(u as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(u as Weight))) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(u as Weight))) + } + // Storage: StableAsset Pools (r:1 w:1) + // Storage: Tokens Accounts (r:5 w:4) + // Storage: AssetRegistry AssetMetadatas (r:1 w:0) + // Storage: System Account (r:1 w:0) + // Storage: Tokens TotalIssuance (r:1 w:1) + fn redeem_single(u: u32, ) -> Weight { + (89_436_000 as Weight) + // Standard Error: 819_000 + .saturating_add((2_425_000 as Weight).saturating_mul(u as Weight)) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(u as Weight))) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: StableAsset Pools (r:1 w:1) + // Storage: Tokens Accounts (r:6 w:6) + // Storage: AssetRegistry AssetMetadatas (r:1 w:0) + // Storage: System Account (r:1 w:0) + // Storage: Tokens TotalIssuance (r:1 w:1) + fn redeem_multi(u: u32, ) -> Weight { + (63_297_000 as Weight) + // Standard Error: 154_000 + .saturating_add((14_971_000 as Weight).saturating_mul(u as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(u as Weight))) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(u as Weight))) + } +} diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index f0b229ddc2..d3b89be410 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -57,6 +57,7 @@ module-evm-accounts = { path = "../../modules/evm-accounts", default-features = module-asset-registry = { path = "../../modules/asset-registry", default-features = false, optional = true } module-evm-bridge = { path = "../../modules/evm-bridge", default-features = false, optional = true } primitives = { package = "acala-primitives", path = "../../primitives", default-features = false } +nutsfinance-stable-asset = { version = "0.1.0", default-features = false, path = "../../ecosystem-modules/stable-asset/lib/stable-asset", package = "nutsfinance-stable-asset" } # orml orml-oracle = { path = "../../orml/oracle", default-features = false } diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 9ac50680e6..58851a0ef3 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -57,7 +57,7 @@ use module_evm::GenesisAccount; use orml_traits::GetByKey; pub use precompile::{ AllPrecompiles, DEXPrecompile, EVMPrecompile, MultiCurrencyPrecompile, NFTPrecompile, OraclePrecompile, - SchedulePrecompile, + SchedulePrecompile, StableAssetPrecompile, }; pub use primitives::{ currency::{TokenInfo, ACA, AUSD, BNC, DOT, KAR, KBTC, KINT, KSM, KUSD, LCDOT, LDOT, LKSM, PHA, RENBTC, VSKSM}, diff --git a/runtime/common/src/precompile/input.rs b/runtime/common/src/precompile/input.rs index bcdd699b53..ee30a582dc 100644 --- a/runtime/common/src/precompile/input.rs +++ b/runtime/common/src/precompile/input.rs @@ -217,6 +217,21 @@ impl Output { ethabi::encode(&[out]) } + pub fn encode_u128_array(&self, b: Vec) -> Vec { + let result: Vec = b.iter().map(|x| Token::Uint(U256::from(*x))).collect(); + let out = Token::FixedArray(result); + ethabi::encode(&[out]) + } + + pub fn encode_address_array(&self, b: Vec) -> Vec { + let result: Vec = b + .iter() + .map(|x| Token::Address(H160::from_slice(x.as_bytes()))) + .collect(); + let out = Token::FixedArray(result); + ethabi::encode(&[out]) + } + pub fn encode_bytes(&self, b: &[u8]) -> Vec { let out = Token::Bytes(b.to_vec()); ethabi::encode(&[out]) diff --git a/runtime/common/src/precompile/mock.rs b/runtime/common/src/precompile/mock.rs index 4b9ef65aa1..8989b8146d 100644 --- a/runtime/common/src/precompile/mock.rs +++ b/runtime/common/src/precompile/mock.rs @@ -375,6 +375,34 @@ impl module_dex::Config for Test { type OnLiquidityPoolUpdated = (); } +parameter_types! { + pub const StableAssetPalletId: PalletId = PalletId(*b"nuts/sta"); +} + +pub struct EnsurePoolAssetId; +impl nutsfinance_stable_asset::traits::ValidateAssetId for EnsurePoolAssetId { + fn validate(_currency_id: CurrencyId) -> bool { + true + } +} + +impl nutsfinance_stable_asset::Config for Test { + type Event = Event; + type AssetId = CurrencyId; + type Balance = Balance; + type Assets = Tokens; + type PalletId = StableAssetPalletId; + + type AtLeast64BitUnsigned = u128; + type FeePrecision = ConstU128<10_000_000_000>; // 10 decimals + type APrecision = ConstU128<100>; // 2 decimals + type PoolAssetLimit = ConstU32<5>; + type SwapExactOverAmount = ConstU128<100>; + type WeightInfo = (); + type ListingOrigin = EnsureSignedBy; + type EnsurePoolAssetId = EnsurePoolAssetId; +} + pub type AdaptedBasicCurrency = module_currencies::BasicCurrencyAdapter; pub type EvmErc20InfoMapping = module_asset_registry::EvmErc20InfoMapping; @@ -557,6 +585,7 @@ frame_support::construct_runtime!( EVMModule: module_evm, EvmAccounts: module_evm_accounts, IdleScheduler: module_idle_scheduler, + StableAsset: nutsfinance_stable_asset, } ); @@ -614,7 +643,14 @@ pub fn new_test_ext() -> sp_io::TestExternalities { Origin::root(), EvmAddressMapping::::get_account_id(&alice_evm_addr()), RENBTC, - 1_000 + 1_000_000_000 + )); + + assert_ok!(Currencies::update_balance( + Origin::root(), + EvmAddressMapping::::get_account_id(&alice_evm_addr()), + AUSD, + 1_000_000_000 )); }); ext diff --git a/runtime/common/src/precompile/mod.rs b/runtime/common/src/precompile/mod.rs index bb5079b3c7..7ecf2562ad 100644 --- a/runtime/common/src/precompile/mod.rs +++ b/runtime/common/src/precompile/mod.rs @@ -46,6 +46,7 @@ pub mod multicurrency; pub mod nft; pub mod oracle; pub mod schedule; +pub mod stable_asset; use crate::SystemContractsFilter; pub use dex::DEXPrecompile; @@ -54,6 +55,7 @@ pub use multicurrency::MultiCurrencyPrecompile; pub use nft::NFTPrecompile; pub use oracle::OraclePrecompile; pub use schedule::SchedulePrecompile; +pub use stable_asset::StableAssetPrecompile; pub const ECRECOVER: H160 = H160(hex!("0000000000000000000000000000000000000001")); pub const SHA256: H160 = H160(hex!("0000000000000000000000000000000000000002")); @@ -75,6 +77,7 @@ 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 const STABLE_ASSET: H160 = H160(hex!("0000000000000000000000000000000000000406")); pub fn target_gas_limit(target_gas: Option) -> Option { // srtool support rust 1.57.0 @@ -141,6 +144,7 @@ where ORACLE, // SCHEDULER, DEX, + STABLE_ASSET, ]), _marker: Default::default(), } @@ -169,6 +173,7 @@ where ORACLE, SCHEDULER, DEX, + STABLE_ASSET, ]), _marker: Default::default(), } @@ -183,6 +188,7 @@ where EVMPrecompile: Precompile, OraclePrecompile: Precompile, DEXPrecompile: Precompile, + StableAssetPrecompile: Precompile, SchedulePrecompile: Precompile, { fn execute( @@ -255,6 +261,10 @@ where Some(SchedulePrecompile::::execute(input, target_gas, context, is_static)) } else if address == DEX { Some(DEXPrecompile::::execute(input, target_gas, context, is_static)) + } else if address == STABLE_ASSET { + Some(StableAssetPrecompile::::execute( + input, target_gas, context, is_static, + )) } else { None } diff --git a/runtime/common/src/precompile/stable_asset.rs b/runtime/common/src/precompile/stable_asset.rs new file mode 100644 index 0000000000..e173fd6582 --- /dev/null +++ b/runtime/common/src/precompile/stable_asset.rs @@ -0,0 +1,672 @@ +// This file is part of Acala. + +// Copyright (C) 2020-2022 Acala Foundation. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use super::{ + input::{Input, InputT, Output}, + target_gas_limit, +}; +use crate::WeightToGas; +use frame_support::traits::Get; +use module_evm::{ + precompiles::Precompile, + runner::state::{PrecompileFailure, PrecompileOutput, PrecompileResult}, + Context, ExitError, ExitRevert, ExitSucceed, +}; +use module_support::Erc20InfoMapping; +use num_enum::{IntoPrimitive, TryFromPrimitive}; +use nutsfinance_stable_asset::traits::StableAsset; +use nutsfinance_stable_asset::WeightInfo; +use primitives::{Balance, CurrencyId}; +use sp_core::H160; +use sp_runtime::{traits::Convert, RuntimeDebug}; +use sp_std::{marker::PhantomData, prelude::*}; + +pub struct StableAssetPrecompile(PhantomData); + +#[module_evm_utility_macro::generate_function_selector] +#[derive(RuntimeDebug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] +#[repr(u32)] +pub enum Action { + GetStableAssetPoolPoolTokens = "getStableAssetPoolTokens(uint32)", + GetStableAssetPoolPoolTotalSupply = "getStableAssetPoolPoolTotalSupply(uint32)", + GetStableAssetPoolPoolPrecision = "getStableAssetPoolPoolPrecision(uint32)", + GetStableAssetPoolPoolMintFee = "getStableAssetPoolPoolMintFee(uint32)", + GetStableAssetPoolPoolSwapFee = "getStableAssetPoolPoolSwapFee(uint32)", + GetStableAssetPoolPoolRedeemFee = "getStableAssetPoolPoolRedeemFee(uint32)", + StableAssetSwap = "stableAssetSwap(address,uint32,uint32,uint32,uint256,uint256,uint32)", + StableAssetMint = "stableAssetMint(address,uint32,uint256[],uint256)", + StableAssetRedeem = "stableAssetRedeem(address,uint32,uint256,uint256[])", +} + +impl Precompile for StableAssetPrecompile +where + Runtime: module_evm::Config + nutsfinance_stable_asset::Config + module_prices::Config, + nutsfinance_stable_asset::Pallet: StableAsset< + AssetId = CurrencyId, + AtLeast64BitUnsigned = Balance, + Balance = Balance, + AccountId = Runtime::AccountId, + BlockNumber = Runtime::BlockNumber, + >, +{ + fn execute(input: &[u8], target_gas: Option, _context: &Context, _is_static: bool) -> PrecompileResult { + let input = Input::::new( + input, + target_gas_limit(target_gas), + ); + + let gas_cost = Pricer::::cost(&input)?; + + if let Some(gas_limit) = target_gas { + if gas_limit < gas_cost { + return Err(PrecompileFailure::Error { + exit_status: ExitError::OutOfGas, + }); + } + } + + let action = input.action()?; + + match action { + Action::GetStableAssetPoolPoolTokens => { + let pool_id = input.u32_at(1)?; + + let pool_info = + as StableAsset>::pool(pool_id).ok_or_else(|| { + PrecompileFailure::Revert { + exit_status: ExitRevert::Reverted, + output: "Pool not found".into(), + cost: target_gas_limit(target_gas).unwrap_or_default(), + } + })?; + let assets: Vec = pool_info + .assets + .iter() + .flat_map(|x| ::Erc20InfoMapping::encode_evm_address(*x)) + .collect(); + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: gas_cost, + output: Output::default().encode_address_array(assets), + logs: Default::default(), + }) + } + Action::GetStableAssetPoolPoolTotalSupply => { + let pool_id = input.u32_at(1)?; + + let pool_info = + as StableAsset>::pool(pool_id).ok_or_else(|| { + PrecompileFailure::Revert { + exit_status: ExitRevert::Reverted, + output: "Pool not found".into(), + cost: target_gas_limit(target_gas).unwrap_or_default(), + } + })?; + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: gas_cost, + output: Output::default().encode_u128(pool_info.total_supply), + logs: Default::default(), + }) + } + Action::GetStableAssetPoolPoolPrecision => { + let pool_id = input.u32_at(1)?; + + let pool_info = + as StableAsset>::pool(pool_id).ok_or_else(|| { + PrecompileFailure::Revert { + exit_status: ExitRevert::Reverted, + output: "Pool not found".into(), + cost: target_gas_limit(target_gas).unwrap_or_default(), + } + })?; + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: gas_cost, + output: Output::default().encode_u128(pool_info.precision), + logs: Default::default(), + }) + } + Action::GetStableAssetPoolPoolMintFee => { + let pool_id = input.u32_at(1)?; + + let pool_info = + as StableAsset>::pool(pool_id).ok_or_else(|| { + PrecompileFailure::Revert { + exit_status: ExitRevert::Reverted, + output: "Pool not found".into(), + cost: target_gas_limit(target_gas).unwrap_or_default(), + } + })?; + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: gas_cost, + output: Output::default().encode_u128(pool_info.mint_fee), + logs: Default::default(), + }) + } + Action::GetStableAssetPoolPoolSwapFee => { + let pool_id = input.u32_at(1)?; + + let pool_info = + as StableAsset>::pool(pool_id).ok_or_else(|| { + PrecompileFailure::Revert { + exit_status: ExitRevert::Reverted, + output: "Pool not found".into(), + cost: target_gas_limit(target_gas).unwrap_or_default(), + } + })?; + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: gas_cost, + output: Output::default().encode_u128(pool_info.swap_fee), + logs: Default::default(), + }) + } + Action::GetStableAssetPoolPoolRedeemFee => { + let pool_id = input.u32_at(1)?; + + let pool_info = + as StableAsset>::pool(pool_id).ok_or_else(|| { + PrecompileFailure::Revert { + exit_status: ExitRevert::Reverted, + output: "Pool not found".into(), + cost: target_gas_limit(target_gas).unwrap_or_default(), + } + })?; + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: gas_cost, + output: Output::default().encode_u128(pool_info.redeem_fee), + logs: Default::default(), + }) + } + Action::StableAssetSwap => { + let who = input.account_id_at(1)?; + let pool_id = input.u32_at(2)?; + let i = input.u32_at(3)?; + let j = input.u32_at(4)?; + let dx = input.balance_at(5)?; + let min_dy = input.balance_at(6)?; + let asset_length = input.u32_at(7)?; + + let (input, output) = as StableAsset>::swap( + &who, + pool_id, + i, + j, + dx, + min_dy, + asset_length, + ) + .map_err(|e| PrecompileFailure::Revert { + exit_status: ExitRevert::Reverted, + output: Into::<&str>::into(e).as_bytes().to_vec(), + cost: target_gas_limit(target_gas).unwrap_or_default(), + })?; + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: gas_cost, + output: Output::default().encode_u128_tuple(input, output), + logs: Default::default(), + }) + } + Action::StableAssetMint => { + let who = input.account_id_at(1)?; + let pool_id = input.u32_at(2)?; + // solidity abi enocde array will add an offset at input[3] + let min_mint_amount = input.balance_at(4)?; + let amount_len = input.u32_at(5)?; + let mut amounts = vec![]; + for i in 0..amount_len { + amounts.push(input.balance_at((6 + i) as usize)?); + } + + as StableAsset>::mint( + &who, + pool_id, + amounts, + min_mint_amount, + ) + .map_err(|e| PrecompileFailure::Revert { + exit_status: ExitRevert::Reverted, + output: Into::<&str>::into(e).as_bytes().to_vec(), + cost: target_gas_limit(target_gas).unwrap_or_default(), + })?; + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: gas_cost, + output: Output::default().encode_u8(0u8), + logs: Default::default(), + }) + } + Action::StableAssetRedeem => { + let who = input.account_id_at(1)?; + let pool_id = input.u32_at(2)?; + let redeem_amount = input.balance_at(3)?; + // solidity abi enocde array will add an offset at input[4] + let amount_len = input.u32_at(5)?; + let mut amounts = vec![]; + for i in 0..amount_len { + amounts.push(input.balance_at((6 + i) as usize)?); + } + + as StableAsset>::redeem_proportion( + &who, + pool_id, + redeem_amount, + amounts, + ) + .map_err(|e| PrecompileFailure::Revert { + exit_status: ExitRevert::Reverted, + output: Into::<&str>::into(e).as_bytes().to_vec(), + cost: target_gas_limit(target_gas).unwrap_or_default(), + })?; + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: gas_cost, + output: Output::default().encode_u8(0u8), + logs: Default::default(), + }) + } + } + } +} + +struct Pricer(PhantomData); + +impl Pricer +where + Runtime: module_evm::Config + nutsfinance_stable_asset::Config + module_prices::Config, +{ + const BASE_COST: u64 = 200; + + fn cost( + input: &Input< + Action, + Runtime::AccountId, + Runtime::AddressMapping, + ::Erc20InfoMapping, + >, + ) -> Result { + let action = input.action()?; + + let cost: u64 = match action { + Action::GetStableAssetPoolPoolTokens => { + let weight = ::DbWeight::get().reads(1); + Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) + } + Action::GetStableAssetPoolPoolTotalSupply => { + let weight = ::DbWeight::get().reads(1); + Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) + } + Action::GetStableAssetPoolPoolPrecision => { + let weight = ::DbWeight::get().reads(1); + Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) + } + Action::GetStableAssetPoolPoolMintFee => { + let weight = ::DbWeight::get().reads(1); + Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) + } + Action::GetStableAssetPoolPoolSwapFee => { + let weight = ::DbWeight::get().reads(1); + Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) + } + Action::GetStableAssetPoolPoolRedeemFee => { + let weight = ::DbWeight::get().reads(1); + Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) + } + Action::StableAssetSwap => { + let path_len = input.u32_at(7)?; + let weight = ::WeightInfo::swap(path_len); + Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) + } + Action::StableAssetMint => { + let path_len = input.u32_at(5)?; + let weight = ::WeightInfo::mint(path_len); + Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) + } + Action::StableAssetRedeem => { + let path_len = input.u32_at(5)?; + let weight = ::WeightInfo::redeem_proportion(path_len); + Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) + } + }; + Ok(cost) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::precompile::mock::{alice_evm_addr, new_test_ext, Origin, StableAsset, Test, ALICE, AUSD, RENBTC}; + use frame_support::assert_ok; + use hex_literal::hex; + + type StableAssetPrecompile = crate::StableAssetPrecompile; + + #[test] + fn get_stable_asset_pool_tokens_works() { + new_test_ext().execute_with(|| { + assert_ok!(StableAsset::create_pool( + Origin::signed(ALICE), + CurrencyId::StableAssetPoolToken(0), + vec![AUSD, RENBTC], + vec![1, 1], + 2u128, + 3u128, + 4u128, + 10000, + ALICE, + ALICE, + 1u128 + )); + let context = Context { + address: Default::default(), + caller: alice_evm_addr(), + apparent_value: Default::default(), + }; + let input = hex! {" + fb0f0f34 + 0000000000000000000000000000000000000000000000000000000000000000 + "}; + let resp = StableAssetPrecompile::execute(&input, None, &context, false).unwrap(); + let expected_output = hex! {" + 000000000000000000000000 + 000000000000000000010000 + 000000000000000100000000 + 000000000000000000000000 + 000000000001000000000000 + 00000014 + "}; + assert_eq!(resp.exit_status, ExitSucceed::Returned); + assert_eq!(resp.output, expected_output.to_vec()); + }); + } + + #[test] + fn get_stable_asset_total_supply_works() { + new_test_ext().execute_with(|| { + assert_ok!(StableAsset::create_pool( + Origin::signed(ALICE), + CurrencyId::StableAssetPoolToken(0), + vec![AUSD, RENBTC], + vec![1, 1], + 2u128, + 3u128, + 4u128, + 10000, + ALICE, + ALICE, + 1u128 + )); + let context = Context { + address: Default::default(), + caller: alice_evm_addr(), + apparent_value: Default::default(), + }; + let input = hex! {" + dc2306b5 + 0000000000000000000000000000000000000000000000000000000000000000 + "}; + let resp = StableAssetPrecompile::execute(&input, None, &context, false).unwrap(); + let expected_output = hex! {" + 000000000000000000000000 + 000000000000000000000000 + 0000000000000000 + "}; + assert_eq!(resp.exit_status, ExitSucceed::Returned); + assert_eq!(resp.output, expected_output.to_vec()); + }); + } + + #[test] + fn get_stable_asset_precision_works() { + new_test_ext().execute_with(|| { + assert_ok!(StableAsset::create_pool( + Origin::signed(ALICE), + CurrencyId::StableAssetPoolToken(0), + vec![AUSD, RENBTC], + vec![1, 1], + 2u128, + 3u128, + 4u128, + 10000, + ALICE, + ALICE, + 1u128 + )); + let context = Context { + address: Default::default(), + caller: alice_evm_addr(), + apparent_value: Default::default(), + }; + let input = hex! {" + 32d74a84 + 0000000000000000000000000000000000000000000000000000000000000000 + "}; + let resp = StableAssetPrecompile::execute(&input, None, &context, false).unwrap(); + let expected_output = hex! {" + 000000000000000000000000 + 000000000000000000000000 + 0000000000000001 + "}; + assert_eq!(resp.exit_status, ExitSucceed::Returned); + assert_eq!(resp.output, expected_output.to_vec()); + }); + } + + #[test] + fn get_stable_asset_mint_fee_works() { + new_test_ext().execute_with(|| { + assert_ok!(StableAsset::create_pool( + Origin::signed(ALICE), + CurrencyId::StableAssetPoolToken(0), + vec![AUSD, RENBTC], + vec![1, 1], + 2u128, + 3u128, + 4u128, + 10000, + ALICE, + ALICE, + 1u128 + )); + let context = Context { + address: Default::default(), + caller: alice_evm_addr(), + apparent_value: Default::default(), + }; + let input = hex! {" + 2ff9b99e + 0000000000000000000000000000000000000000000000000000000000000000 + "}; + let resp = StableAssetPrecompile::execute(&input, None, &context, false).unwrap(); + let expected_output = hex! {" + 000000000000000000000000 + 000000000000000000000000 + 0000000000000002 + "}; + assert_eq!(resp.exit_status, ExitSucceed::Returned); + assert_eq!(resp.output, expected_output.to_vec()); + }); + } + + #[test] + fn get_stable_asset_swap_fee_works() { + new_test_ext().execute_with(|| { + assert_ok!(StableAsset::create_pool( + Origin::signed(ALICE), + CurrencyId::StableAssetPoolToken(0), + vec![AUSD, RENBTC], + vec![1, 1], + 2u128, + 3u128, + 4u128, + 10000, + ALICE, + ALICE, + 1u128 + )); + let context = Context { + address: Default::default(), + caller: alice_evm_addr(), + apparent_value: Default::default(), + }; + let input = hex! {" + fcac2437 + 0000000000000000000000000000000000000000000000000000000000000000 + "}; + let resp = StableAssetPrecompile::execute(&input, None, &context, false).unwrap(); + let expected_output = hex! {" + 000000000000000000000000 + 000000000000000000000000 + 0000000000000003 + "}; + assert_eq!(resp.exit_status, ExitSucceed::Returned); + assert_eq!(resp.output, expected_output.to_vec()); + }); + } + + #[test] + fn get_stable_asset_redeem_fee_works() { + new_test_ext().execute_with(|| { + assert_ok!(StableAsset::create_pool( + Origin::signed(ALICE), + CurrencyId::StableAssetPoolToken(0), + vec![AUSD, RENBTC], + vec![1, 1], + 2u128, + 3u128, + 4u128, + 10000, + ALICE, + ALICE, + 1u128 + )); + let context = Context { + address: Default::default(), + caller: alice_evm_addr(), + apparent_value: Default::default(), + }; + let input = hex! {" + c155d42e + 0000000000000000000000000000000000000000000000000000000000000000 + "}; + let resp = StableAssetPrecompile::execute(&input, None, &context, false).unwrap(); + let expected_output = hex! {" + 000000000000000000000000 + 000000000000000000000000 + 0000000000000004 + "}; + assert_eq!(resp.exit_status, ExitSucceed::Returned); + assert_eq!(resp.output, expected_output.to_vec()); + }); + } + + #[test] + fn stable_asset_mint_and_redeem_works() { + new_test_ext().execute_with(|| { + assert_ok!(StableAsset::create_pool( + Origin::signed(ALICE), + CurrencyId::StableAssetPoolToken(0), + vec![AUSD, RENBTC], + vec![1, 1], + 2u128, + 3u128, + 4u128, + 10000, + ALICE, + ALICE, + 1u128 + )); + let context = Context { + address: Default::default(), + caller: alice_evm_addr(), + apparent_value: Default::default(), + }; + let mint_input = hex! {" + 2acdb2ec + 0000000000000000000000001000000000000000000000000000000000000001 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000080 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000002 + 00000000000000000000000000000000000000000000000000000000000f4240 + 00000000000000000000000000000000000000000000000000000000000f4240 + "}; + let mint_resp = StableAssetPrecompile::execute(&mint_input, None, &context, false).unwrap(); + assert_eq!(mint_resp.exit_status, ExitSucceed::Returned); + + let redeem_input = hex! {" + aa538d34 + 0000000000000000000000001000000000000000000000000000000000000001 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000007a120 + 0000000000000000000000000000000000000000000000000000000000000080 + 0000000000000000000000000000000000000000000000000000000000000002 + 0000000000000000000000000000000000000000000000000000000000000001 + 0000000000000000000000000000000000000000000000000000000000000002 + "}; + let redeem_resp = StableAssetPrecompile::execute(&redeem_input, None, &context, false).unwrap(); + assert_eq!(redeem_resp.exit_status, ExitSucceed::Returned); + }); + } + + #[test] + fn stable_asset_swap_works() { + new_test_ext().execute_with(|| { + assert_ok!(StableAsset::create_pool( + Origin::signed(ALICE), + CurrencyId::StableAssetPoolToken(0), + vec![AUSD, RENBTC], + vec![1, 1], + 2u128, + 3u128, + 4u128, + 10000, + ALICE, + ALICE, + 1u128 + )); + assert_ok!(StableAsset::mint( + Origin::signed(ALICE), + 0, + vec![1_000_000u128, 1_000_000u128], + 0u128 + )); + let context = Context { + address: Default::default(), + caller: alice_evm_addr(), + apparent_value: Default::default(), + }; + let input = hex! {" + ff9bc03c + 0000000000000000000000001000000000000000000000000000000000000001 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000001 + 000000000000000000000000000000000000000000000000000000000007a120 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000002 + "}; + let resp = StableAssetPrecompile::execute(&input, None, &context, false).unwrap(); + assert_eq!(resp.exit_status, ExitSucceed::Returned); + }); + } +} From 3424fc6f7823f5a0d3d722efe4bd431715029a65 Mon Sep 17 00:00:00 2001 From: Frank Yin Date: Wed, 4 May 2022 14:43:39 -0700 Subject: [PATCH 02/11] Update runtime/common/src/precompile/stable_asset.rs Co-authored-by: zjb0807 --- runtime/common/src/precompile/stable_asset.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/runtime/common/src/precompile/stable_asset.rs b/runtime/common/src/precompile/stable_asset.rs index e173fd6582..5e5b4c179f 100644 --- a/runtime/common/src/precompile/stable_asset.rs +++ b/runtime/common/src/precompile/stable_asset.rs @@ -42,12 +42,8 @@ pub struct StableAssetPrecompile(PhantomData); #[derive(RuntimeDebug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] #[repr(u32)] pub enum Action { - GetStableAssetPoolPoolTokens = "getStableAssetPoolTokens(uint32)", - GetStableAssetPoolPoolTotalSupply = "getStableAssetPoolPoolTotalSupply(uint32)", - GetStableAssetPoolPoolPrecision = "getStableAssetPoolPoolPrecision(uint32)", - GetStableAssetPoolPoolMintFee = "getStableAssetPoolPoolMintFee(uint32)", - GetStableAssetPoolPoolSwapFee = "getStableAssetPoolPoolSwapFee(uint32)", - GetStableAssetPoolPoolRedeemFee = "getStableAssetPoolPoolRedeemFee(uint32)", + GetStableAssetPoolTokens = "getStableAssetPoolTokens(uint32)", + GetStableAssetPoolTotalSupply = "getStableAssetPoolTotalSupply(uint32)", StableAssetSwap = "stableAssetSwap(address,uint32,uint32,uint32,uint256,uint256,uint32)", StableAssetMint = "stableAssetMint(address,uint32,uint256[],uint256)", StableAssetRedeem = "stableAssetRedeem(address,uint32,uint256,uint256[])", From 8598bdd555d6778aa538a0e7c07388348601d35d Mon Sep 17 00:00:00 2001 From: Frank Yin Date: Wed, 4 May 2022 14:43:45 -0700 Subject: [PATCH 03/11] Update runtime/acala/src/lib.rs Co-authored-by: zjb0807 --- runtime/acala/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/acala/src/lib.rs b/runtime/acala/src/lib.rs index b5ff518330..610c59a697 100644 --- a/runtime/acala/src/lib.rs +++ b/runtime/acala/src/lib.rs @@ -1515,7 +1515,7 @@ impl orml_tokens::ConvertBalance for ConvertBalanceHoma { fn convert_balance(balance: Balance, asset_id: CurrencyId) -> Balance { match asset_id { - CurrencyId::Token(TokenSymbol::LKSM) => { + CurrencyId::Token(TokenSymbol::LDOT) => { Homa::get_exchange_rate().checked_mul_int(balance).unwrap_or_default() } _ => balance, From 4f771785ed87ea6f65f3d15ba1ec0cc08d29ce71 Mon Sep 17 00:00:00 2001 From: Frank Yin Date: Wed, 4 May 2022 14:43:55 -0700 Subject: [PATCH 04/11] Update runtime/common/src/precompile/mod.rs Co-authored-by: zjb0807 --- runtime/common/src/precompile/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/runtime/common/src/precompile/mod.rs b/runtime/common/src/precompile/mod.rs index 7ecf2562ad..07b01fd904 100644 --- a/runtime/common/src/precompile/mod.rs +++ b/runtime/common/src/precompile/mod.rs @@ -144,7 +144,6 @@ where ORACLE, // SCHEDULER, DEX, - STABLE_ASSET, ]), _marker: Default::default(), } From 070dc6b24fb232467b5a483814ed8ef65c52c3e6 Mon Sep 17 00:00:00 2001 From: Frank Yin Date: Wed, 4 May 2022 14:45:16 -0700 Subject: [PATCH 05/11] Update lib.rs --- runtime/acala/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/acala/src/lib.rs b/runtime/acala/src/lib.rs index 610c59a697..8dc27545cf 100644 --- a/runtime/acala/src/lib.rs +++ b/runtime/acala/src/lib.rs @@ -1524,7 +1524,7 @@ impl orml_tokens::ConvertBalance for ConvertBalanceHoma { fn convert_balance_back(balance: Balance, asset_id: CurrencyId) -> Balance { match asset_id { - CurrencyId::Token(TokenSymbol::LKSM) => Homa::get_exchange_rate() + CurrencyId::Token(TokenSymbol::LDOT) => Homa::get_exchange_rate() .reciprocal() .and_then(|x| x.checked_mul_int(balance)) .unwrap_or_default(), @@ -1536,7 +1536,7 @@ impl orml_tokens::ConvertBalance for ConvertBalanceHoma { pub struct IsLiquidToken; impl Contains for IsLiquidToken { fn contains(currency_id: &CurrencyId) -> bool { - matches!(currency_id, CurrencyId::Token(TokenSymbol::LKSM)) + matches!(currency_id, CurrencyId::Token(TokenSymbol::LDOT)) } } From 38a785b7f864d9a08dad59e94e6ce523d3a60005 Mon Sep 17 00:00:00 2001 From: Frank Yin Date: Wed, 4 May 2022 15:35:53 -0700 Subject: [PATCH 06/11] Update lib.rs --- runtime/acala/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/acala/src/lib.rs b/runtime/acala/src/lib.rs index 8dc27545cf..df8ddf7a6b 100644 --- a/runtime/acala/src/lib.rs +++ b/runtime/acala/src/lib.rs @@ -1018,7 +1018,7 @@ where } parameter_types! { - pub CollateralCurrencyIds: Vec = vec![ACA, DOT, LCDOT, LDOT]; + pub CollateralCurrencyIds: Vec = vec![ACA, DOT, LCDOT, LDOT, CurrencyId::StableAssetPoolToken(0)]; pub DefaultLiquidationRatio: Ratio = Ratio::saturating_from_rational(150, 100); pub DefaultDebitExchangeRate: ExchangeRate = ExchangeRate::saturating_from_rational(1, 10); pub DefaultLiquidationPenalty: Rate = Rate::saturating_from_rational(8, 100); From 1c53c44314b319bac598ade47a75fdec36c357d0 Mon Sep 17 00:00:00 2001 From: Frank Yin Date: Wed, 4 May 2022 15:50:57 -0700 Subject: [PATCH 07/11] Revert "Update runtime/common/src/precompile/stable_asset.rs" This reverts commit 3424fc6f7823f5a0d3d722efe4bd431715029a65. --- runtime/common/src/precompile/stable_asset.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/runtime/common/src/precompile/stable_asset.rs b/runtime/common/src/precompile/stable_asset.rs index 5e5b4c179f..e173fd6582 100644 --- a/runtime/common/src/precompile/stable_asset.rs +++ b/runtime/common/src/precompile/stable_asset.rs @@ -42,8 +42,12 @@ pub struct StableAssetPrecompile(PhantomData); #[derive(RuntimeDebug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] #[repr(u32)] pub enum Action { - GetStableAssetPoolTokens = "getStableAssetPoolTokens(uint32)", - GetStableAssetPoolTotalSupply = "getStableAssetPoolTotalSupply(uint32)", + GetStableAssetPoolPoolTokens = "getStableAssetPoolTokens(uint32)", + GetStableAssetPoolPoolTotalSupply = "getStableAssetPoolPoolTotalSupply(uint32)", + GetStableAssetPoolPoolPrecision = "getStableAssetPoolPoolPrecision(uint32)", + GetStableAssetPoolPoolMintFee = "getStableAssetPoolPoolMintFee(uint32)", + GetStableAssetPoolPoolSwapFee = "getStableAssetPoolPoolSwapFee(uint32)", + GetStableAssetPoolPoolRedeemFee = "getStableAssetPoolPoolRedeemFee(uint32)", StableAssetSwap = "stableAssetSwap(address,uint32,uint32,uint32,uint256,uint256,uint32)", StableAssetMint = "stableAssetMint(address,uint32,uint256[],uint256)", StableAssetRedeem = "stableAssetRedeem(address,uint32,uint256,uint256[])", From 914df7d585985cefdcae967c10b377a51ff37f3a Mon Sep 17 00:00:00 2001 From: Frank Yin Date: Wed, 4 May 2022 15:52:20 -0700 Subject: [PATCH 08/11] add pegged --- runtime/acala/src/lib.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/runtime/acala/src/lib.rs b/runtime/acala/src/lib.rs index df8ddf7a6b..533ddcaaef 100644 --- a/runtime/acala/src/lib.rs +++ b/runtime/acala/src/lib.rs @@ -799,8 +799,12 @@ parameter_type_with_key! { } parameter_type_with_key! { - pub PricingPegged: |_currency_id: CurrencyId| -> Option { - None + pub PricingPegged: |currency_id: CurrencyId| -> Option { + match currency_id { + // taiKSM + CurrencyId::StableAssetPoolToken(0) => Some(DOT), + _ => None, + } }; } @@ -2152,8 +2156,8 @@ mod tests { fn check_call_size() { println!("{:?}", core::mem::size_of::()); assert!( - core::mem::size_of::() <= 240, - "size of Call is more than 240 bytes: some calls have too big arguments, use Box to \ + core::mem::size_of::() <= 280, + "size of Call is more than 280 bytes: some calls have too big arguments, use Box to \ reduce the size of Call. If the limit is too strong, maybe consider increasing the limit", ); From 2d93788009ef47c355e8b1803979f86d950b596c Mon Sep 17 00:00:00 2001 From: Frank Yin Date: Wed, 4 May 2022 17:33:15 -0700 Subject: [PATCH 09/11] fix test --- runtime/common/src/precompile/multicurrency.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/common/src/precompile/multicurrency.rs b/runtime/common/src/precompile/multicurrency.rs index 99f9fb5230..e34b886eb8 100644 --- a/runtime/common/src/precompile/multicurrency.rs +++ b/runtime/common/src/precompile/multicurrency.rs @@ -452,7 +452,7 @@ mod tests { // 1_000_000_000 let expected_output = hex! {" - 00000000000000000000000000000000 0000000000000000000000003b9aca00 + 00000000000000000000000000000000 00000000000000000000000077359400 "}; let resp = MultiCurrencyPrecompile::execute(&input, None, &context, false).unwrap(); From f50eef11473518fd2529a9d50fbcac485f78d5a9 Mon Sep 17 00:00:00 2001 From: Frank Yin Date: Thu, 5 May 2022 10:53:03 -0700 Subject: [PATCH 10/11] Fix function names --- runtime/common/src/precompile/stable_asset.rs | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/runtime/common/src/precompile/stable_asset.rs b/runtime/common/src/precompile/stable_asset.rs index e173fd6582..7397841124 100644 --- a/runtime/common/src/precompile/stable_asset.rs +++ b/runtime/common/src/precompile/stable_asset.rs @@ -42,12 +42,12 @@ pub struct StableAssetPrecompile(PhantomData); #[derive(RuntimeDebug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] #[repr(u32)] pub enum Action { - GetStableAssetPoolPoolTokens = "getStableAssetPoolTokens(uint32)", - GetStableAssetPoolPoolTotalSupply = "getStableAssetPoolPoolTotalSupply(uint32)", - GetStableAssetPoolPoolPrecision = "getStableAssetPoolPoolPrecision(uint32)", - GetStableAssetPoolPoolMintFee = "getStableAssetPoolPoolMintFee(uint32)", - GetStableAssetPoolPoolSwapFee = "getStableAssetPoolPoolSwapFee(uint32)", - GetStableAssetPoolPoolRedeemFee = "getStableAssetPoolPoolRedeemFee(uint32)", + GetStableAssetPoolTokens = "getStableAssetPoolTokens(uint32)", + GetStableAssetPoolTotalSupply = "getStableAssetPoolTotalSupply(uint32)", + GetStableAssetPoolPrecision = "getStableAssetPoolPrecision(uint32)", + GetStableAssetPoolMintFee = "getStableAssetPoolMintFee(uint32)", + GetStableAssetPoolSwapFee = "getStableAssetPoolSwapFee(uint32)", + GetStableAssetPoolRedeemFee = "getStableAssetPoolRedeemFee(uint32)", StableAssetSwap = "stableAssetSwap(address,uint32,uint32,uint32,uint256,uint256,uint32)", StableAssetMint = "stableAssetMint(address,uint32,uint256[],uint256)", StableAssetRedeem = "stableAssetRedeem(address,uint32,uint256,uint256[])", @@ -83,7 +83,7 @@ where let action = input.action()?; match action { - Action::GetStableAssetPoolPoolTokens => { + Action::GetStableAssetPoolTokens => { let pool_id = input.u32_at(1)?; let pool_info = @@ -106,7 +106,7 @@ where logs: Default::default(), }) } - Action::GetStableAssetPoolPoolTotalSupply => { + Action::GetStableAssetPoolTotalSupply => { let pool_id = input.u32_at(1)?; let pool_info = @@ -124,7 +124,7 @@ where logs: Default::default(), }) } - Action::GetStableAssetPoolPoolPrecision => { + Action::GetStableAssetPoolPrecision => { let pool_id = input.u32_at(1)?; let pool_info = @@ -142,7 +142,7 @@ where logs: Default::default(), }) } - Action::GetStableAssetPoolPoolMintFee => { + Action::GetStableAssetPoolMintFee => { let pool_id = input.u32_at(1)?; let pool_info = @@ -160,7 +160,7 @@ where logs: Default::default(), }) } - Action::GetStableAssetPoolPoolSwapFee => { + Action::GetStableAssetPoolSwapFee => { let pool_id = input.u32_at(1)?; let pool_info = @@ -178,7 +178,7 @@ where logs: Default::default(), }) } - Action::GetStableAssetPoolPoolRedeemFee => { + Action::GetStableAssetPoolRedeemFee => { let pool_id = input.u32_at(1)?; let pool_info = @@ -307,27 +307,27 @@ where let action = input.action()?; let cost: u64 = match action { - Action::GetStableAssetPoolPoolTokens => { + Action::GetStableAssetPoolTokens => { let weight = ::DbWeight::get().reads(1); Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) } - Action::GetStableAssetPoolPoolTotalSupply => { + Action::GetStableAssetPoolTotalSupply => { let weight = ::DbWeight::get().reads(1); Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) } - Action::GetStableAssetPoolPoolPrecision => { + Action::GetStableAssetPoolPrecision => { let weight = ::DbWeight::get().reads(1); Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) } - Action::GetStableAssetPoolPoolMintFee => { + Action::GetStableAssetPoolMintFee => { let weight = ::DbWeight::get().reads(1); Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) } - Action::GetStableAssetPoolPoolSwapFee => { + Action::GetStableAssetPoolSwapFee => { let weight = ::DbWeight::get().reads(1); Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) } - Action::GetStableAssetPoolPoolRedeemFee => { + Action::GetStableAssetPoolRedeemFee => { let weight = ::DbWeight::get().reads(1); Self::BASE_COST.saturating_add(WeightToGas::convert(weight)) } @@ -421,7 +421,7 @@ mod tests { apparent_value: Default::default(), }; let input = hex! {" - dc2306b5 + 7172c6aa 0000000000000000000000000000000000000000000000000000000000000000 "}; let resp = StableAssetPrecompile::execute(&input, None, &context, false).unwrap(); @@ -457,7 +457,7 @@ mod tests { apparent_value: Default::default(), }; let input = hex! {" - 32d74a84 + 9ccdcf91 0000000000000000000000000000000000000000000000000000000000000000 "}; let resp = StableAssetPrecompile::execute(&input, None, &context, false).unwrap(); @@ -493,7 +493,7 @@ mod tests { apparent_value: Default::default(), }; let input = hex! {" - 2ff9b99e + 62ff9875 0000000000000000000000000000000000000000000000000000000000000000 "}; let resp = StableAssetPrecompile::execute(&input, None, &context, false).unwrap(); @@ -529,7 +529,7 @@ mod tests { apparent_value: Default::default(), }; let input = hex! {" - fcac2437 + 68410f61 0000000000000000000000000000000000000000000000000000000000000000 "}; let resp = StableAssetPrecompile::execute(&input, None, &context, false).unwrap(); @@ -565,7 +565,7 @@ mod tests { apparent_value: Default::default(), }; let input = hex! {" - c155d42e + 7f2f11ca 0000000000000000000000000000000000000000000000000000000000000000 "}; let resp = StableAssetPrecompile::execute(&input, None, &context, false).unwrap(); From ed3c44cc11504a2fe3d00908f45bc232092e46a7 Mon Sep 17 00:00:00 2001 From: Frank Yin Date: Thu, 5 May 2022 18:00:14 -0700 Subject: [PATCH 11/11] Update runtime/common/src/precompile/multicurrency.rs Co-authored-by: zjb0807 --- runtime/common/src/precompile/multicurrency.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/common/src/precompile/multicurrency.rs b/runtime/common/src/precompile/multicurrency.rs index e34b886eb8..f11703d1c0 100644 --- a/runtime/common/src/precompile/multicurrency.rs +++ b/runtime/common/src/precompile/multicurrency.rs @@ -450,7 +450,7 @@ mod tests { // Token context.caller = ausd_evm_address(); - // 1_000_000_000 + // 2_000_000_000 let expected_output = hex! {" 00000000000000000000000000000000 00000000000000000000000077359400 "};