mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 20:29:23 +00:00
Tidy the DEX pallet
This commit is contained in:
62
Cargo.lock
generated
62
Cargo.lock
generated
@@ -1478,9 +1478,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.47"
|
version = "1.2.48"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd405d82c84ff7f35739f175f67d8b9fb7687a0e84ccdc78bd3568839827cf07"
|
checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"find-msvc-tools",
|
"find-msvc-tools",
|
||||||
"jobserver",
|
"jobserver",
|
||||||
@@ -2203,7 +2203,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976"
|
checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"data-encoding",
|
"data-encoding",
|
||||||
"syn 1.0.109",
|
"syn 2.0.111",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4030,9 +4030,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.82"
|
version = "0.3.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65"
|
checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
@@ -7022,9 +7022,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-pki-types"
|
name = "rustls-pki-types"
|
||||||
version = "1.13.0"
|
version = "1.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a"
|
checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"web-time",
|
"web-time",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
@@ -8394,18 +8394,17 @@ dependencies = [
|
|||||||
name = "serai-dex-pallet"
|
name = "serai-dex-pallet"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"frame-benchmarking",
|
"borsh",
|
||||||
"frame-support",
|
"frame-support",
|
||||||
"frame-system",
|
"frame-system",
|
||||||
|
"pallet-timestamp",
|
||||||
"parity-scale-codec",
|
"parity-scale-codec",
|
||||||
"rand_core 0.6.4",
|
"serai-abi",
|
||||||
"serai-coins-pallet",
|
"serai-coins-pallet",
|
||||||
"serai-primitives",
|
"serai-core-pallet",
|
||||||
"sp-api",
|
|
||||||
"sp-core",
|
"sp-core",
|
||||||
"sp-io",
|
"sp-io",
|
||||||
"sp-runtime",
|
"substrate-median",
|
||||||
"sp-std",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -9049,6 +9048,7 @@ dependencies = [
|
|||||||
"serai-abi",
|
"serai-abi",
|
||||||
"serai-coins-pallet",
|
"serai-coins-pallet",
|
||||||
"serai-core-pallet",
|
"serai-core-pallet",
|
||||||
|
"serai-dex-pallet",
|
||||||
"serai-signals-pallet",
|
"serai-signals-pallet",
|
||||||
"serai-validator-sets-pallet",
|
"serai-validator-sets-pallet",
|
||||||
"sp-api",
|
"sp-api",
|
||||||
@@ -10592,9 +10592,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.41"
|
version = "0.1.43"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
|
checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
@@ -10646,9 +10646,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-subscriber"
|
name = "tracing-subscriber"
|
||||||
version = "0.3.20"
|
version = "0.3.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"
|
checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"matchers",
|
"matchers",
|
||||||
"nu-ansi-term",
|
"nu-ansi-term",
|
||||||
@@ -10940,9 +10940,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.105"
|
version = "0.2.106"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60"
|
checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@@ -10953,9 +10953,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.105"
|
version = "0.2.106"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2"
|
checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
@@ -10963,9 +10963,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.105"
|
version = "0.2.106"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc"
|
checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -10976,9 +10976,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.105"
|
version = "0.2.106"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76"
|
checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@@ -11233,9 +11233,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.82"
|
version = "0.3.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1"
|
checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
@@ -11764,18 +11764,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.30"
|
version = "0.8.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4ea879c944afe8a2b25fef16bb4ba234f47c694565e97383b36f3a878219065c"
|
checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy-derive",
|
"zerocopy-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "zerocopy-derive"
|
||||||
version = "0.8.30"
|
version = "0.8.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf955aa904d6040f70dc8e9384444cb1030aed272ba3cb09bbc4ab9e7c1f34f5"
|
checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|||||||
@@ -8,21 +8,26 @@ use serai_primitives::{
|
|||||||
balance::{Amount, ExternalBalance, Balance},
|
balance::{Amount, ExternalBalance, Balance},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The address used for a liquidity pool by the DEX.
|
||||||
|
pub fn address(coin: ExternalCoin) -> SeraiAddress {
|
||||||
|
SeraiAddress::system(borsh::to_vec(&(b"DEX", coin)).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
/// A call to the DEX.
|
/// A call to the DEX.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
|
#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
|
||||||
pub enum Call {
|
pub enum Call {
|
||||||
/// Add liquidity.
|
/// Add liquidity.
|
||||||
add_liquidity {
|
add_liquidity {
|
||||||
/// The coin to add liquidity for.
|
/// The pool to add liquidity to, specified by its external coin.
|
||||||
coin: ExternalCoin,
|
external_coin: ExternalCoin,
|
||||||
/// The intended amount of SRI to add as liquidity.
|
/// The intended amount of SRI to add as liquidity.
|
||||||
sri_intended: Amount,
|
sri_intended: Amount,
|
||||||
/// The intended amount of the coin to add as liquidity.
|
/// The intended amount of the coin to add as liquidity.
|
||||||
coin_intended: Amount,
|
external_coin_intended: Amount,
|
||||||
/// The minimum amount of SRI to add as liquidity.
|
/// The minimum amount of SRI to add as liquidity.
|
||||||
sri_minimum: Amount,
|
sri_minimum: Amount,
|
||||||
/// The minimum amount of the coin to add as liquidity.
|
/// The minimum amount of the coin to add as liquidity.
|
||||||
coin_minimum: Amount,
|
external_coin_minimum: Amount,
|
||||||
},
|
},
|
||||||
/// Transfer these liquidity tokens to the specified address.
|
/// Transfer these liquidity tokens to the specified address.
|
||||||
transfer_liquidity {
|
transfer_liquidity {
|
||||||
@@ -40,17 +45,17 @@ pub enum Call {
|
|||||||
/// The minimum amount of SRI to receive.
|
/// The minimum amount of SRI to receive.
|
||||||
sri_minimum: Amount,
|
sri_minimum: Amount,
|
||||||
/// The minimum amount of the coin to receive.
|
/// The minimum amount of the coin to receive.
|
||||||
coin_minimum: Amount,
|
external_coin_minimum: Amount,
|
||||||
},
|
},
|
||||||
/// Swap an exact amount of coins.
|
/// Swap an exact amount of coins.
|
||||||
swap_exact {
|
swap {
|
||||||
/// The coins to swap.
|
/// The coins to swap.
|
||||||
coins_to_swap: Balance,
|
coins_to_swap: Balance,
|
||||||
/// The minimum balance to receive.
|
/// The minimum balance to receive.
|
||||||
minimum_to_receive: Balance,
|
minimum_to_receive: Balance,
|
||||||
},
|
},
|
||||||
/// Swap for an exact amount of coins.
|
/// Swap for an exact amount of coins.
|
||||||
swap_for_exact {
|
swap_for {
|
||||||
/// The coins to receive.
|
/// The coins to receive.
|
||||||
coins_to_receive: Balance,
|
coins_to_receive: Balance,
|
||||||
/// The maximum amount to swap.
|
/// The maximum amount to swap.
|
||||||
@@ -64,8 +69,8 @@ impl Call {
|
|||||||
Call::add_liquidity { .. } |
|
Call::add_liquidity { .. } |
|
||||||
Call::transfer_liquidity { .. } |
|
Call::transfer_liquidity { .. } |
|
||||||
Call::remove_liquidity { .. } |
|
Call::remove_liquidity { .. } |
|
||||||
Call::swap_exact { .. } |
|
Call::swap { .. } |
|
||||||
Call::swap_for_exact { .. } => true,
|
Call::swap_for { .. } => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,7 +89,7 @@ pub enum Event {
|
|||||||
/// The amount of liquidity tokens which were minted.
|
/// The amount of liquidity tokens which were minted.
|
||||||
liquidity_tokens_minted: Amount,
|
liquidity_tokens_minted: Amount,
|
||||||
/// The amount of the coin which was added to the pool's liquidity.
|
/// The amount of the coin which was added to the pool's liquidity.
|
||||||
coin_amount: Amount,
|
external_coin_amount: Amount,
|
||||||
/// The amount of SRI which was added to the pool's liquidity.
|
/// The amount of SRI which was added to the pool's liquidity.
|
||||||
sri_amount: Amount,
|
sri_amount: Amount,
|
||||||
},
|
},
|
||||||
@@ -98,7 +103,7 @@ pub enum Event {
|
|||||||
/// The mount of liquidity tokens which were burnt.
|
/// The mount of liquidity tokens which were burnt.
|
||||||
liquidity_tokens_burnt: Amount,
|
liquidity_tokens_burnt: Amount,
|
||||||
/// The amount of the coin which was removed from the pool's liquidity.
|
/// The amount of the coin which was removed from the pool's liquidity.
|
||||||
coin_amount: Amount,
|
external_coin_amount: Amount,
|
||||||
/// The amount of SRI which was removed from the pool's liquidity.
|
/// The amount of SRI which was removed from the pool's liquidity.
|
||||||
sri_amount: Amount,
|
sri_amount: Amount,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ version = "0.1.0"
|
|||||||
description = "Coins pallet for Serai"
|
description = "Coins pallet for Serai"
|
||||||
license = "AGPL-3.0-only"
|
license = "AGPL-3.0-only"
|
||||||
repository = "https://github.com/serai-dex/serai/tree/develop/substrate/coins"
|
repository = "https://github.com/serai-dex/serai/tree/develop/substrate/coins"
|
||||||
authors = ["Akil Demir <akildemir72@gmail.com>"]
|
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.85"
|
rust-version = "1.85"
|
||||||
|
|
||||||
|
|||||||
@@ -227,6 +227,13 @@ mod pallet {
|
|||||||
Self::emit_event(Event::Transfer { from: from.into(), to: to.into(), coins });
|
Self::emit_event(Event::Transfer { from: from.into(), to: to.into(), coins });
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Burn `coins` from `from`.
|
||||||
|
pub fn burn_fn(from: Public, coins: Balance) -> Result<(), Error<T, I>> {
|
||||||
|
Self::burn_internal(from, coins)?;
|
||||||
|
Self::emit_event(Event::Burn { from: from.into(), coins });
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pallet::call]
|
#[pallet::call]
|
||||||
@@ -245,8 +252,7 @@ mod pallet {
|
|||||||
#[pallet::weight((0, DispatchClass::Normal))] // TODO
|
#[pallet::weight((0, DispatchClass::Normal))] // TODO
|
||||||
pub fn burn(origin: OriginFor<T>, coins: Balance) -> DispatchResult {
|
pub fn burn(origin: OriginFor<T>, coins: Balance) -> DispatchResult {
|
||||||
let from = ensure_signed(origin)?;
|
let from = ensure_signed(origin)?;
|
||||||
Self::burn_internal(from, coins)?;
|
Self::burn_fn(from, coins)?;
|
||||||
Self::emit_event(Event::Burn { from: from.into(), coins });
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! Test environment for Coins pallet.
|
//! Test environment for the Coins pallet.
|
||||||
|
|
||||||
use borsh::BorshDeserialize;
|
use borsh::BorshDeserialize;
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ version = "0.1.0"
|
|||||||
description = "DEX pallet for Serai"
|
description = "DEX pallet for Serai"
|
||||||
license = "AGPL-3.0-only"
|
license = "AGPL-3.0-only"
|
||||||
repository = "https://github.com/serai-dex/serai/tree/develop/substrate/dex"
|
repository = "https://github.com/serai-dex/serai/tree/develop/substrate/dex"
|
||||||
authors = ["Parity Technologies <admin@parity.io>, Akil Demir <akildemir72@gmail.com>"]
|
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.85"
|
rust-version = "1.85"
|
||||||
|
|
||||||
@@ -12,61 +12,61 @@ rust-version = "1.85"
|
|||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
[package.metadata.cargo-machete]
|
|
||||||
ignored = ["scale"]
|
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
scale = { package = "parity-scale-codec", version = "3.6.1", default-features = false }
|
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
sp-std = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc", default-features = false }
|
|
||||||
sp-io = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc", default-features = false }
|
|
||||||
sp-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc", default-features = false }
|
|
||||||
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc", default-features = false }
|
|
||||||
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc", default-features = false }
|
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc", default-features = false }
|
||||||
|
|
||||||
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc", default-features = false }
|
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc", default-features = false }
|
||||||
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc", default-features = false }
|
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc", default-features = false }
|
||||||
frame-benchmarking = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc", default-features = false, optional = true }
|
|
||||||
|
|
||||||
coins-pallet = { package = "serai-coins-pallet", path = "../coins", default-features = false }
|
substrate-median = { path = "../median", default-features = false }
|
||||||
|
|
||||||
serai-primitives = { path = "../primitives", default-features = false }
|
serai-abi = { path = "../abi", default-features = false, features = ["substrate"] }
|
||||||
|
serai-core-pallet = { path = "../core", default-features = false }
|
||||||
|
serai-coins-pallet = { path = "../coins", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand_core = { version = "0.6", default-features = false, features = ["getrandom"] }
|
borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] }
|
||||||
|
|
||||||
|
sp-io = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc", default-features = false, features = ["std"] }
|
||||||
|
|
||||||
|
pallet-timestamp = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc", default-features = false, features = ["std"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
|
||||||
std = [
|
std = [
|
||||||
"scale/std",
|
"scale/std",
|
||||||
|
|
||||||
"sp-std/std",
|
|
||||||
"sp-io/std",
|
|
||||||
"sp-api/std",
|
|
||||||
"sp-runtime/std",
|
|
||||||
"sp-core/std",
|
"sp-core/std",
|
||||||
|
|
||||||
"serai-primitives/std",
|
|
||||||
|
|
||||||
"frame-system/std",
|
"frame-system/std",
|
||||||
"frame-support/std",
|
"frame-support/std",
|
||||||
"frame-benchmarking?/std",
|
|
||||||
|
|
||||||
"coins-pallet/std",
|
"substrate-median/std",
|
||||||
]
|
|
||||||
runtime-benchmarks = [
|
|
||||||
"sp-runtime/runtime-benchmarks",
|
|
||||||
|
|
||||||
"frame-system/runtime-benchmarks",
|
"serai-abi/std",
|
||||||
"frame-support/runtime-benchmarks",
|
"serai-core-pallet/std",
|
||||||
"frame-benchmarking/runtime-benchmarks",
|
"serai-coins-pallet/std",
|
||||||
]
|
]
|
||||||
|
|
||||||
try-runtime = [
|
try-runtime = [
|
||||||
"sp-runtime/try-runtime",
|
|
||||||
|
|
||||||
"frame-system/try-runtime",
|
"frame-system/try-runtime",
|
||||||
"frame-support/try-runtime",
|
"frame-support/try-runtime",
|
||||||
|
|
||||||
|
"serai-abi/try-runtime",
|
||||||
|
"serai-core-pallet/try-runtime",
|
||||||
|
"serai-coins-pallet/try-runtime",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
runtime-benchmarks = [
|
||||||
|
"frame-system/runtime-benchmarks",
|
||||||
|
"frame-support/runtime-benchmarks",
|
||||||
|
|
||||||
|
"serai-core-pallet/runtime-benchmarks",
|
||||||
|
"serai-coins-pallet/runtime-benchmarks",
|
||||||
|
]
|
||||||
|
|
||||||
|
default = ["std"]
|
||||||
|
|||||||
@@ -1,211 +0,0 @@
|
|||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
NOTE
|
|
||||||
|
|
||||||
Individual files contain the following tag instead of the full license
|
|
||||||
text.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
This enables machine processing of license information based on the SPDX
|
|
||||||
License Identifiers that are here available: http://spdx.org/licenses/
|
|
||||||
3
substrate/dex/README.md
Normal file
3
substrate/dex/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# DEX Pallet
|
||||||
|
|
||||||
|
Pallet implementing the necessary DEX logic for the Serai protocol.
|
||||||
@@ -1,230 +0,0 @@
|
|||||||
// This file was originally:
|
|
||||||
|
|
||||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// It has been forked into a crate distributed under the AGPL 3.0.
|
|
||||||
// Please check the current distribution for up-to-date copyright and licensing information.
|
|
||||||
|
|
||||||
//! Dex pallet benchmarking.
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
use frame_benchmarking::{benchmarks, whitelisted_caller};
|
|
||||||
use frame_support::{assert_ok, storage::bounded::BoundedVec};
|
|
||||||
use frame_system::RawOrigin as SystemOrigin;
|
|
||||||
|
|
||||||
use sp_runtime::traits::StaticLookup;
|
|
||||||
use sp_std::{ops::Div, prelude::*};
|
|
||||||
|
|
||||||
use serai_primitives::{Amount, Balance};
|
|
||||||
|
|
||||||
use crate::Pallet as Dex;
|
|
||||||
use coins_pallet::Pallet as Coins;
|
|
||||||
|
|
||||||
const INITIAL_COIN_BALANCE: u64 = 1_000_000_000;
|
|
||||||
type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;
|
|
||||||
|
|
||||||
type LiquidityTokens<T> = coins_pallet::Pallet<T, coins_pallet::Instance1>;
|
|
||||||
|
|
||||||
fn create_coin<T: Config>(coin: &ExternalCoin) -> (T::AccountId, AccountIdLookupOf<T>) {
|
|
||||||
let caller: T::AccountId = whitelisted_caller();
|
|
||||||
let caller_lookup = T::Lookup::unlookup(caller);
|
|
||||||
assert_ok!(Coins::<T>::mint(
|
|
||||||
caller,
|
|
||||||
Balance { coin: Coin::native(), amount: Amount(SubstrateAmount::MAX.div(1000u64)) }
|
|
||||||
));
|
|
||||||
assert_ok!(Coins::<T>::mint(
|
|
||||||
caller,
|
|
||||||
Balance { coin: (*coin).into(), amount: Amount(INITIAL_COIN_BALANCE) }
|
|
||||||
));
|
|
||||||
(caller, caller_lookup)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_coin_and_pool<T: Config>(
|
|
||||||
coin: &ExternalCoin,
|
|
||||||
) -> (ExternalCoin, T::AccountId, AccountIdLookupOf<T>) {
|
|
||||||
let (caller, caller_lookup) = create_coin::<T>(coin);
|
|
||||||
assert_ok!(Dex::<T>::create_pool(*coin));
|
|
||||||
|
|
||||||
(*coin, caller, caller_lookup)
|
|
||||||
}
|
|
||||||
|
|
||||||
benchmarks! {
|
|
||||||
add_liquidity {
|
|
||||||
let coin1 = Coin::native();
|
|
||||||
let coin2 = ExternalCoin::Bitcoin;
|
|
||||||
let (lp_token, caller, _) = create_coin_and_pool::<T>(&coin2);
|
|
||||||
let add_amount: u64 = 1000;
|
|
||||||
}: _(
|
|
||||||
SystemOrigin::Signed(caller),
|
|
||||||
coin2,
|
|
||||||
1000u64,
|
|
||||||
add_amount,
|
|
||||||
0u64,
|
|
||||||
0u64,
|
|
||||||
caller
|
|
||||||
)
|
|
||||||
verify {
|
|
||||||
let pool_id = Dex::<T>::get_pool_id(coin1, coin2.into()).unwrap();
|
|
||||||
let lp_minted = Dex::<T>::calc_lp_amount_for_zero_supply(
|
|
||||||
add_amount,
|
|
||||||
1000u64,
|
|
||||||
).unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
LiquidityTokens::<T>::balance(caller, lp_token.into()).0,
|
|
||||||
lp_minted
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Coins::<T>::balance(Dex::<T>::get_pool_account(pool_id), Coin::native()).0,
|
|
||||||
add_amount
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Coins::<T>::balance(
|
|
||||||
Dex::<T>::get_pool_account(pool_id),
|
|
||||||
ExternalCoin::Bitcoin.into(),
|
|
||||||
).0,
|
|
||||||
1000
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_liquidity {
|
|
||||||
let coin1 = Coin::native();
|
|
||||||
let coin2 = ExternalCoin::Monero;
|
|
||||||
let (lp_token, caller, _) = create_coin_and_pool::<T>(&coin2);
|
|
||||||
let add_amount: u64 = 100;
|
|
||||||
let lp_minted = Dex::<T>::calc_lp_amount_for_zero_supply(
|
|
||||||
add_amount,
|
|
||||||
1000u64
|
|
||||||
).unwrap();
|
|
||||||
let remove_lp_amount: u64 = lp_minted.checked_div(10).unwrap();
|
|
||||||
|
|
||||||
Dex::<T>::add_liquidity(
|
|
||||||
SystemOrigin::Signed(caller).into(),
|
|
||||||
coin2,
|
|
||||||
1000u64,
|
|
||||||
add_amount,
|
|
||||||
0u64,
|
|
||||||
0u64,
|
|
||||||
caller,
|
|
||||||
)?;
|
|
||||||
let total_supply = LiquidityTokens::<T>::supply(Coin::from(lp_token));
|
|
||||||
}: _(
|
|
||||||
SystemOrigin::Signed(caller),
|
|
||||||
coin2,
|
|
||||||
remove_lp_amount,
|
|
||||||
0u64,
|
|
||||||
0u64,
|
|
||||||
caller
|
|
||||||
)
|
|
||||||
verify {
|
|
||||||
let new_total_supply = LiquidityTokens::<T>::supply(Coin::from(lp_token));
|
|
||||||
assert_eq!(
|
|
||||||
new_total_supply,
|
|
||||||
total_supply - remove_lp_amount
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
swap_exact_tokens_for_tokens {
|
|
||||||
let native = Coin::native();
|
|
||||||
let coin1 = ExternalCoin::Bitcoin;
|
|
||||||
let coin2 = ExternalCoin::Ether;
|
|
||||||
let (_, caller, _) = create_coin_and_pool::<T>(&coin1);
|
|
||||||
let (_, _) = create_coin::<T>(&coin2);
|
|
||||||
|
|
||||||
Dex::<T>::add_liquidity(
|
|
||||||
SystemOrigin::Signed(caller).into(),
|
|
||||||
coin1,
|
|
||||||
200u64,
|
|
||||||
// TODO: this call otherwise fails with `InsufficientLiquidityMinted` if we don't multiply
|
|
||||||
// with 3. Might be again related to their expectance on ed being > 1.
|
|
||||||
100 * 3,
|
|
||||||
0u64,
|
|
||||||
0u64,
|
|
||||||
caller,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let swap_amount = 100u64;
|
|
||||||
|
|
||||||
// since we only allow the native-coin pools, then the worst case scenario would be to swap
|
|
||||||
// coin1-native-coin2
|
|
||||||
Dex::<T>::create_pool(coin2)?;
|
|
||||||
Dex::<T>::add_liquidity(
|
|
||||||
SystemOrigin::Signed(caller).into(),
|
|
||||||
coin2,
|
|
||||||
1000u64,
|
|
||||||
500,
|
|
||||||
0u64,
|
|
||||||
0u64,
|
|
||||||
caller,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let path = vec![Coin::from(coin1), native, Coin::from(coin2)];
|
|
||||||
let path = BoundedVec::<_, T::MaxSwapPathLength>::try_from(path).unwrap();
|
|
||||||
let native_balance = Coins::<T>::balance(caller, native).0;
|
|
||||||
let coin1_balance = Coins::<T>::balance(caller, ExternalCoin::Bitcoin.into()).0;
|
|
||||||
}: _(SystemOrigin::Signed(caller), path, swap_amount, 1u64, caller)
|
|
||||||
verify {
|
|
||||||
let ed_bump = 2u64;
|
|
||||||
let new_coin1_balance = Coins::<T>::balance(caller, ExternalCoin::Bitcoin.into()).0;
|
|
||||||
assert_eq!(new_coin1_balance, coin1_balance - 100u64);
|
|
||||||
}
|
|
||||||
|
|
||||||
swap_tokens_for_exact_tokens {
|
|
||||||
let native = Coin::native();
|
|
||||||
let coin1 = ExternalCoin::Bitcoin;
|
|
||||||
let coin2 = ExternalCoin::Ether;
|
|
||||||
let (_, caller, _) = create_coin_and_pool::<T>(&coin1);
|
|
||||||
let (_, _) = create_coin::<T>(&coin2);
|
|
||||||
|
|
||||||
Dex::<T>::add_liquidity(
|
|
||||||
SystemOrigin::Signed(caller).into(),
|
|
||||||
coin1,
|
|
||||||
500u64,
|
|
||||||
1000,
|
|
||||||
0u64,
|
|
||||||
0u64,
|
|
||||||
caller,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// since we only allow the native-coin pools, then the worst case scenario would be to swap
|
|
||||||
// coin1-native-coin2
|
|
||||||
Dex::<T>::create_pool(coin2)?;
|
|
||||||
Dex::<T>::add_liquidity(
|
|
||||||
SystemOrigin::Signed(caller).into(),
|
|
||||||
coin2,
|
|
||||||
1000u64,
|
|
||||||
500,
|
|
||||||
0u64,
|
|
||||||
0u64,
|
|
||||||
caller,
|
|
||||||
)?;
|
|
||||||
let path = vec![Coin::from(coin1), native, Coin::from(coin2)];
|
|
||||||
|
|
||||||
let path: BoundedVec<_, T::MaxSwapPathLength> = BoundedVec::try_from(path).unwrap();
|
|
||||||
let coin2_balance = Coins::<T>::balance(caller, ExternalCoin::Ether.into()).0;
|
|
||||||
}: _(
|
|
||||||
SystemOrigin::Signed(caller),
|
|
||||||
path.clone(),
|
|
||||||
100u64,
|
|
||||||
1000,
|
|
||||||
caller
|
|
||||||
)
|
|
||||||
verify {
|
|
||||||
let new_coin2_balance = Coins::<T>::balance(caller, ExternalCoin::Ether.into()).0;
|
|
||||||
assert_eq!(new_coin2_balance, coin2_balance + 100u64);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_benchmark_test_suite!(Dex, crate::mock::new_test_ext(), crate::mock::Test);
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,126 +1,62 @@
|
|||||||
// This file was originally:
|
//! Test environment for the DEX pallet.
|
||||||
|
|
||||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
use borsh::BorshDeserialize;
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
use frame_support::{sp_runtime::BuildStorage, derive_impl, construct_runtime};
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// It has been forked into a crate distributed under the AGPL 3.0.
|
use serai_coins_pallet::{CoinsInstance, LiquidityTokensInstance};
|
||||||
// Please check the current distribution for up-to-date copyright and licensing information.
|
|
||||||
|
|
||||||
//! Test environment for Dex pallet.
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
use crate as dex;
|
use crate as dex;
|
||||||
|
|
||||||
use frame_support::{
|
|
||||||
construct_runtime,
|
|
||||||
traits::{ConstU16, ConstU32, ConstU64},
|
|
||||||
};
|
|
||||||
|
|
||||||
use sp_core::{H256, sr25519::Public};
|
|
||||||
use sp_runtime::{
|
|
||||||
traits::{BlakeTwo256, IdentityLookup},
|
|
||||||
BuildStorage,
|
|
||||||
};
|
|
||||||
|
|
||||||
use serai_primitives::{Coin, Balance, Amount, system_address};
|
|
||||||
|
|
||||||
pub use coins_pallet as coins;
|
|
||||||
|
|
||||||
type Block = frame_system::mocking::MockBlock<Test>;
|
|
||||||
|
|
||||||
pub const MEDIAN_PRICE_WINDOW_LENGTH: u16 = 10;
|
|
||||||
|
|
||||||
construct_runtime!(
|
construct_runtime!(
|
||||||
pub enum Test
|
pub enum Test
|
||||||
{
|
{
|
||||||
System: frame_system,
|
System: frame_system,
|
||||||
CoinsPallet: coins,
|
Timestamp: pallet_timestamp,
|
||||||
LiquidityTokens: coins::<Instance1>::{Pallet, Call, Storage, Event<T>},
|
Core: serai_core_pallet,
|
||||||
|
Coins: serai_coins_pallet::<CoinsInstance>,
|
||||||
|
LiquidityTokens: serai_coins_pallet::<LiquidityTokensInstance>,
|
||||||
Dex: dex,
|
Dex: dex,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = frame_support::traits::Everything;
|
type AccountId = sp_core::sr25519::Public;
|
||||||
type BlockWeights = ();
|
type Lookup = frame_support::sp_runtime::traits::IdentityLookup<Self::AccountId>;
|
||||||
type BlockLength = ();
|
type Block = frame_system::mocking::MockBlock<Test>;
|
||||||
type RuntimeOrigin = RuntimeOrigin;
|
|
||||||
type RuntimeCall = RuntimeCall;
|
|
||||||
type Nonce = u64;
|
|
||||||
type Hash = H256;
|
|
||||||
type Hashing = BlakeTwo256;
|
|
||||||
type AccountId = Public;
|
|
||||||
type Lookup = IdentityLookup<Self::AccountId>;
|
|
||||||
type Block = Block;
|
|
||||||
type RuntimeEvent = RuntimeEvent;
|
|
||||||
type BlockHashCount = ConstU64<250>;
|
|
||||||
type DbWeight = ();
|
|
||||||
type Version = ();
|
|
||||||
type PalletInfo = PalletInfo;
|
|
||||||
type AccountData = ();
|
|
||||||
type OnNewAccount = ();
|
|
||||||
type OnKilledAccount = ();
|
|
||||||
type SystemWeightInfo = ();
|
|
||||||
type SS58Prefix = ();
|
|
||||||
type OnSetCode = ();
|
|
||||||
type MaxConsumers = ConstU32<16>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl coins::Config for Test {
|
#[derive_impl(pallet_timestamp::config_preludes::TestDefaultConfig)]
|
||||||
type RuntimeEvent = RuntimeEvent;
|
impl pallet_timestamp::Config for Test {}
|
||||||
type AllowMint = ();
|
|
||||||
|
impl serai_core_pallet::Config for Test {}
|
||||||
|
|
||||||
|
impl serai_coins_pallet::Config<CoinsInstance> for Test {
|
||||||
|
type AllowMint = serai_coins_pallet::AlwaysAllowMint;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl coins::Config<coins::Instance1> for Test {
|
impl serai_coins_pallet::Config<LiquidityTokensInstance> for Test {
|
||||||
type RuntimeEvent = RuntimeEvent;
|
type AllowMint = serai_coins_pallet::AlwaysAllowMint;
|
||||||
type AllowMint = ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config for Test {
|
impl crate::Config for Test {}
|
||||||
type RuntimeEvent = RuntimeEvent;
|
|
||||||
|
|
||||||
type WeightInfo = ();
|
|
||||||
type LPFee = ConstU32<3>; // means 0.3%
|
|
||||||
type MaxSwapPathLength = ConstU32<4>;
|
|
||||||
|
|
||||||
type MedianPriceWindowLength = ConstU16<{ MEDIAN_PRICE_WINDOW_LENGTH }>;
|
|
||||||
|
|
||||||
// 100 is good enough when the main currency has 12 decimals.
|
|
||||||
type MintMinLiquidity = ConstU64<100>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
|
pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
|
||||||
let mut t = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
let mut storage = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
||||||
|
|
||||||
let accounts: Vec<Public> = vec![
|
serai_coins_pallet::GenesisConfig::<Test, CoinsInstance> {
|
||||||
system_address(b"account1").into(),
|
accounts: vec![],
|
||||||
system_address(b"account2").into(),
|
_instance: Default::default(),
|
||||||
system_address(b"account3").into(),
|
|
||||||
system_address(b"account4").into(),
|
|
||||||
];
|
|
||||||
coins::GenesisConfig::<Test> {
|
|
||||||
accounts: accounts
|
|
||||||
.into_iter()
|
|
||||||
.map(|a| (a, Balance { coin: Coin::Serai, amount: Amount(1 << 60) }))
|
|
||||||
.collect(),
|
|
||||||
_ignore: Default::default(),
|
|
||||||
}
|
}
|
||||||
.assimilate_storage(&mut t)
|
.assimilate_storage(&mut storage)
|
||||||
|
.unwrap();
|
||||||
|
serai_coins_pallet::GenesisConfig::<Test, LiquidityTokensInstance> {
|
||||||
|
accounts: vec![],
|
||||||
|
_instance: Default::default(),
|
||||||
|
}
|
||||||
|
.assimilate_storage(&mut storage)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut ext = sp_io::TestExternalities::new(t);
|
storage.into()
|
||||||
ext.execute_with(|| System::set_block_number(1));
|
|
||||||
ext
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,54 +0,0 @@
|
|||||||
// This file was originally:
|
|
||||||
|
|
||||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// It has been forked into a crate distributed under the AGPL 3.0.
|
|
||||||
// Please check the current distribution for up-to-date copyright and licensing information.
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
/// Trait for providing methods to swap between the various coin classes.
|
|
||||||
pub trait Swap<AccountId, Balance, MultiCoinId> {
|
|
||||||
/// Swap exactly `amount_in` of coin `path[0]` for coin `path[1]`.
|
|
||||||
/// If an `amount_out_min` is specified, it will return an error if it is unable to acquire
|
|
||||||
/// the amount desired.
|
|
||||||
///
|
|
||||||
/// Withdraws the `path[0]` coin from `sender`, deposits the `path[1]` coin to `send_to`,
|
|
||||||
///
|
|
||||||
/// If successful, returns the amount of `path[1]` acquired for the `amount_in`.
|
|
||||||
fn swap_exact_tokens_for_tokens(
|
|
||||||
sender: AccountId,
|
|
||||||
path: Vec<MultiCoinId>,
|
|
||||||
amount_in: Balance,
|
|
||||||
amount_out_min: Option<Balance>,
|
|
||||||
send_to: AccountId,
|
|
||||||
) -> Result<Balance, DispatchError>;
|
|
||||||
|
|
||||||
/// Take the `path[0]` coin and swap some amount for `amount_out` of the `path[1]`. If an
|
|
||||||
/// `amount_in_max` is specified, it will return an error if acquiring `amount_out` would be
|
|
||||||
/// too costly.
|
|
||||||
///
|
|
||||||
/// Withdraws `path[0]` coin from `sender`, deposits `path[1]` coin to `send_to`,
|
|
||||||
///
|
|
||||||
/// If successful returns the amount of the `path[0]` taken to provide `path[1]`.
|
|
||||||
fn swap_tokens_for_exact_tokens(
|
|
||||||
sender: AccountId,
|
|
||||||
path: Vec<MultiCoinId>,
|
|
||||||
amount_out: Balance,
|
|
||||||
amount_in_max: Option<Balance>,
|
|
||||||
send_to: AccountId,
|
|
||||||
) -> Result<Balance, DispatchError>;
|
|
||||||
}
|
|
||||||
@@ -1,259 +0,0 @@
|
|||||||
// This file was originally:
|
|
||||||
|
|
||||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// It has been forked into a crate distributed under the AGPL 3.0.
|
|
||||||
// Please check the current distribution for up-to-date copyright and licensing information.
|
|
||||||
|
|
||||||
//! Autogenerated weights for Dex Pallet.
|
|
||||||
//!
|
|
||||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
|
||||||
//! DATE: 2023-07-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
|
||||||
//! WORST CASE MAP SIZE: `1000000`
|
|
||||||
//! HOSTNAME: `runner-gghbxkbs-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz`
|
|
||||||
//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024`
|
|
||||||
|
|
||||||
// Executed Command:
|
|
||||||
// target/production/substrate
|
|
||||||
// benchmark
|
|
||||||
// pallet
|
|
||||||
// --steps=50
|
|
||||||
// --repeat=20
|
|
||||||
// --extrinsic=*
|
|
||||||
// --wasm-execution=compiled
|
|
||||||
// --heap-pages=4096
|
|
||||||
// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json
|
|
||||||
// --pallet=serai_dex_pallet
|
|
||||||
// --chain=dev
|
|
||||||
// --header=./HEADER-APACHE2
|
|
||||||
// --output=./substrate/dex/pallet/src/weights.rs
|
|
||||||
// --template=./.maintain/frame-weight-template.hbs
|
|
||||||
|
|
||||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
|
||||||
#![allow(unused_parens)]
|
|
||||||
#![allow(unused_imports)]
|
|
||||||
#![allow(missing_docs)]
|
|
||||||
|
|
||||||
use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
|
|
||||||
use core::marker::PhantomData;
|
|
||||||
|
|
||||||
/// Weight functions needed for Dex Pallet.
|
|
||||||
pub trait WeightInfo {
|
|
||||||
fn create_pool() -> Weight;
|
|
||||||
fn add_liquidity() -> Weight;
|
|
||||||
fn remove_liquidity() -> Weight;
|
|
||||||
fn swap_exact_tokens_for_tokens() -> Weight;
|
|
||||||
fn swap_tokens_for_exact_tokens() -> Weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Weights for Dex Pallet using the Substrate node and recommended hardware.
|
|
||||||
pub struct SubstrateWeight<T>(PhantomData<T>);
|
|
||||||
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
|
||||||
/// Storage: `DexPallet::Pools` (r:1 w:1)
|
|
||||||
/// Proof: `DexPallet::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `System::Account` (r:2 w:2)
|
|
||||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Account` (r:1 w:1)
|
|
||||||
/// Proof: `Coins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Coin` (r:1 w:1)
|
|
||||||
/// Proof: `Coins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `DexPallet::NextPoolCoinId` (r:1 w:1)
|
|
||||||
/// Proof: `DexPallet::NextPoolCoinId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `PoolCoins::Coin` (r:1 w:1)
|
|
||||||
/// Proof: `PoolCoins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `PoolCoins::Account` (r:1 w:1)
|
|
||||||
/// Proof: `PoolCoins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
fn create_pool() -> Weight {
|
|
||||||
// Proof Size summary in bytes:
|
|
||||||
// Measured: `729`
|
|
||||||
// Estimated: `6196`
|
|
||||||
// Minimum execution time: 131_688_000 picoseconds.
|
|
||||||
Weight::from_parts(134_092_000, 6196)
|
|
||||||
.saturating_add(T::DbWeight::get().reads(8_u64))
|
|
||||||
.saturating_add(T::DbWeight::get().writes(8_u64))
|
|
||||||
}
|
|
||||||
/// Storage: `DexPallet::Pools` (r:1 w:0)
|
|
||||||
/// Proof: `DexPallet::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `System::Account` (r:1 w:1)
|
|
||||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Coin` (r:1 w:1)
|
|
||||||
/// Proof: `Coins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Account` (r:2 w:2)
|
|
||||||
/// Proof: `Coins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `PoolCoins::Coin` (r:1 w:1)
|
|
||||||
/// Proof: `PoolCoins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `PoolCoins::Account` (r:2 w:2)
|
|
||||||
/// Proof: `PoolCoins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
fn add_liquidity() -> Weight {
|
|
||||||
// Proof Size summary in bytes:
|
|
||||||
// Measured: `1382`
|
|
||||||
// Estimated: `6208`
|
|
||||||
// Minimum execution time: 157_310_000 picoseconds.
|
|
||||||
Weight::from_parts(161_547_000, 6208)
|
|
||||||
.saturating_add(T::DbWeight::get().reads(8_u64))
|
|
||||||
.saturating_add(T::DbWeight::get().writes(7_u64))
|
|
||||||
}
|
|
||||||
/// Storage: `DexPallet::Pools` (r:1 w:0)
|
|
||||||
/// Proof: `DexPallet::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `System::Account` (r:1 w:1)
|
|
||||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Coin` (r:1 w:1)
|
|
||||||
/// Proof: `Coins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Account` (r:2 w:2)
|
|
||||||
/// Proof: `Coins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `PoolCoins::Coin` (r:1 w:1)
|
|
||||||
/// Proof: `PoolCoins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `PoolCoins::Account` (r:1 w:1)
|
|
||||||
/// Proof: `PoolCoins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
fn remove_liquidity() -> Weight {
|
|
||||||
// Proof Size summary in bytes:
|
|
||||||
// Measured: `1371`
|
|
||||||
// Estimated: `6208`
|
|
||||||
// Minimum execution time: 142_769_000 picoseconds.
|
|
||||||
Weight::from_parts(145_139_000, 6208)
|
|
||||||
.saturating_add(T::DbWeight::get().reads(7_u64))
|
|
||||||
.saturating_add(T::DbWeight::get().writes(6_u64))
|
|
||||||
}
|
|
||||||
/// Storage: `System::Account` (r:1 w:1)
|
|
||||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Coin` (r:3 w:3)
|
|
||||||
/// Proof: `Coins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Account` (r:6 w:6)
|
|
||||||
/// Proof: `Coins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
fn swap_exact_tokens_for_tokens() -> Weight {
|
|
||||||
// Proof Size summary in bytes:
|
|
||||||
// Measured: `1738`
|
|
||||||
// Estimated: `16644`
|
|
||||||
// Minimum execution time: 213_186_000 picoseconds.
|
|
||||||
Weight::from_parts(217_471_000, 16644)
|
|
||||||
.saturating_add(T::DbWeight::get().reads(10_u64))
|
|
||||||
.saturating_add(T::DbWeight::get().writes(10_u64))
|
|
||||||
}
|
|
||||||
/// Storage: `Coins::Coin` (r:3 w:3)
|
|
||||||
/// Proof: `Coins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Account` (r:6 w:6)
|
|
||||||
/// Proof: `Coins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `System::Account` (r:1 w:1)
|
|
||||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
|
||||||
fn swap_tokens_for_exact_tokens() -> Weight {
|
|
||||||
// Proof Size summary in bytes:
|
|
||||||
// Measured: `1738`
|
|
||||||
// Estimated: `16644`
|
|
||||||
// Minimum execution time: 213_793_000 picoseconds.
|
|
||||||
Weight::from_parts(218_584_000, 16644)
|
|
||||||
.saturating_add(T::DbWeight::get().reads(10_u64))
|
|
||||||
.saturating_add(T::DbWeight::get().writes(10_u64))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// For backwards compatibility and tests.
|
|
||||||
impl WeightInfo for () {
|
|
||||||
/// Storage: `DexPallet::Pools` (r:1 w:1)
|
|
||||||
/// Proof: `DexPallet::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `System::Account` (r:2 w:2)
|
|
||||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Account` (r:1 w:1)
|
|
||||||
/// Proof: `Coins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Coin` (r:1 w:1)
|
|
||||||
/// Proof: `Coins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `DexPallet::NextPoolCoinId` (r:1 w:1)
|
|
||||||
/// Proof: `DexPallet::NextPoolCoinId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `PoolCoins::Coin` (r:1 w:1)
|
|
||||||
/// Proof: `PoolCoins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `PoolCoins::Account` (r:1 w:1)
|
|
||||||
/// Proof: `PoolCoins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
fn create_pool() -> Weight {
|
|
||||||
// Proof Size summary in bytes:
|
|
||||||
// Measured: `729`
|
|
||||||
// Estimated: `6196`
|
|
||||||
// Minimum execution time: 131_688_000 picoseconds.
|
|
||||||
Weight::from_parts(134_092_000, 6196)
|
|
||||||
.saturating_add(RocksDbWeight::get().reads(8_u64))
|
|
||||||
.saturating_add(RocksDbWeight::get().writes(8_u64))
|
|
||||||
}
|
|
||||||
/// Storage: `DexPallet::Pools` (r:1 w:0)
|
|
||||||
/// Proof: `DexPallet::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `System::Account` (r:1 w:1)
|
|
||||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Coin` (r:1 w:1)
|
|
||||||
/// Proof: `Coins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Account` (r:2 w:2)
|
|
||||||
/// Proof: `Coins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `PoolCoins::Coin` (r:1 w:1)
|
|
||||||
/// Proof: `PoolCoins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `PoolCoins::Account` (r:2 w:2)
|
|
||||||
/// Proof: `PoolCoins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
fn add_liquidity() -> Weight {
|
|
||||||
// Proof Size summary in bytes:
|
|
||||||
// Measured: `1382`
|
|
||||||
// Estimated: `6208`
|
|
||||||
// Minimum execution time: 157_310_000 picoseconds.
|
|
||||||
Weight::from_parts(161_547_000, 6208)
|
|
||||||
.saturating_add(RocksDbWeight::get().reads(8_u64))
|
|
||||||
.saturating_add(RocksDbWeight::get().writes(7_u64))
|
|
||||||
}
|
|
||||||
/// Storage: `DexPallet::Pools` (r:1 w:0)
|
|
||||||
/// Proof: `DexPallet::Pools` (`max_values`: None, `max_size`: Some(30), added: 2505, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `System::Account` (r:1 w:1)
|
|
||||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Coin` (r:1 w:1)
|
|
||||||
/// Proof: `Coins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Account` (r:2 w:2)
|
|
||||||
/// Proof: `Coins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `PoolCoins::Coin` (r:1 w:1)
|
|
||||||
/// Proof: `PoolCoins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `PoolCoins::Account` (r:1 w:1)
|
|
||||||
/// Proof: `PoolCoins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
fn remove_liquidity() -> Weight {
|
|
||||||
// Proof Size summary in bytes:
|
|
||||||
// Measured: `1371`
|
|
||||||
// Estimated: `6208`
|
|
||||||
// Minimum execution time: 142_769_000 picoseconds.
|
|
||||||
Weight::from_parts(145_139_000, 6208)
|
|
||||||
.saturating_add(RocksDbWeight::get().reads(7_u64))
|
|
||||||
.saturating_add(RocksDbWeight::get().writes(6_u64))
|
|
||||||
}
|
|
||||||
/// Storage: `System::Account` (r:1 w:1)
|
|
||||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Coin` (r:3 w:3)
|
|
||||||
/// Proof: `Coins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Account` (r:6 w:6)
|
|
||||||
/// Proof: `Coins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
fn swap_exact_tokens_for_tokens() -> Weight {
|
|
||||||
// Proof Size summary in bytes:
|
|
||||||
// Measured: `1738`
|
|
||||||
// Estimated: `16644`
|
|
||||||
// Minimum execution time: 213_186_000 picoseconds.
|
|
||||||
Weight::from_parts(217_471_000, 16644)
|
|
||||||
.saturating_add(RocksDbWeight::get().reads(10_u64))
|
|
||||||
.saturating_add(RocksDbWeight::get().writes(10_u64))
|
|
||||||
}
|
|
||||||
/// Storage: `Coins::Coin` (r:3 w:3)
|
|
||||||
/// Proof: `Coins::Coin` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `Coins::Account` (r:6 w:6)
|
|
||||||
/// Proof: `Coins::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
|
|
||||||
/// Storage: `System::Account` (r:1 w:1)
|
|
||||||
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
|
|
||||||
fn swap_tokens_for_exact_tokens() -> Weight {
|
|
||||||
// Proof Size summary in bytes:
|
|
||||||
// Measured: `1738`
|
|
||||||
// Estimated: `16644`
|
|
||||||
// Minimum execution time: 213_793_000 picoseconds.
|
|
||||||
Weight::from_parts(218_584_000, 16644)
|
|
||||||
.saturating_add(RocksDbWeight::get().reads(10_u64))
|
|
||||||
.saturating_add(RocksDbWeight::get().writes(10_u64))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
use core::cmp::Ord;
|
use core::cmp::Ord;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
use scale::FullCodec;
|
use scale::FullCodec;
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![no_std]
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
extern crate std;
|
||||||
|
|
||||||
use scale::{EncodeLike, FullCodec};
|
use scale::{EncodeLike, FullCodec};
|
||||||
use frame_support::storage::*;
|
use frame_support::storage::*;
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ impl SeraiAddress {
|
|||||||
/// logarithm for a point whose representation has a known Blake2b-256 preimage.
|
/// logarithm for a point whose representation has a known Blake2b-256 preimage.
|
||||||
// The alternative would be to massage this until its not a valid point, which isn't worth the
|
// The alternative would be to massage this until its not a valid point, which isn't worth the
|
||||||
// computational expense as this should be a hard problem for outputs which happen to be points.
|
// computational expense as this should be a hard problem for outputs which happen to be points.
|
||||||
pub fn system(label: &[u8]) -> Self {
|
pub fn system(label: impl AsRef<[u8]>) -> Self {
|
||||||
Self(sp_core::blake2_256(label))
|
Self(sp_core::blake2_256(label.as_ref()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
184
substrate/primitives/src/dex.rs
Normal file
184
substrate/primitives/src/dex.rs
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
use alloc::{vec, vec::Vec};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
coin::{ExternalCoin, Coin},
|
||||||
|
balance::Amount,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// An error incurred with the DEX.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
/// An arithmetic overflow occurred.
|
||||||
|
Overflow,
|
||||||
|
/// An arithmetic underflow occured.
|
||||||
|
Underflow,
|
||||||
|
/// The `x * y = k` invariant was violated.
|
||||||
|
KInvariant,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The premise of a swap.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
|
pub enum Premise {
|
||||||
|
/// A swap to SRI.
|
||||||
|
ToSerai {
|
||||||
|
/// The coin swapped from.
|
||||||
|
from: ExternalCoin,
|
||||||
|
},
|
||||||
|
/// A swap from SRI.
|
||||||
|
FromSerai {
|
||||||
|
/// The coin swapped to.
|
||||||
|
to: ExternalCoin,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Premise {
|
||||||
|
/// Establish the premise of a swap.
|
||||||
|
///
|
||||||
|
/// This will return `None` if not exactly one coin is `Coin::Serai`.
|
||||||
|
pub fn establish(coin_in: Coin, coin_out: Coin) -> Option<Self> {
|
||||||
|
if !((coin_in == Coin::Serai) ^ (coin_out == Coin::Serai)) {
|
||||||
|
None?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(match coin_in {
|
||||||
|
Coin::Serai => match coin_out {
|
||||||
|
Coin::Serai => unreachable!("prior checked exactly one was `Coin::Serai`"),
|
||||||
|
Coin::External(coin) => Premise::FromSerai { to: coin },
|
||||||
|
},
|
||||||
|
Coin::External(coin) => Premise::ToSerai { from: coin },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establish the route for a swap.
|
||||||
|
///
|
||||||
|
/// This will return `None` if the coin from is the coin to.
|
||||||
|
pub fn route(coin_in: Coin, coin_out: Coin) -> Option<Vec<Self>> {
|
||||||
|
if coin_in == coin_out {
|
||||||
|
None?;
|
||||||
|
}
|
||||||
|
Some(if (coin_in == Coin::Serai) ^ (coin_out == Coin::Serai) {
|
||||||
|
vec![Self::establish(coin_in, coin_out).expect("sri ^ sri")]
|
||||||
|
} else {
|
||||||
|
// Since they aren't both `Coin::Serai`, and not just one is, neither are
|
||||||
|
vec![
|
||||||
|
Self::establish(coin_in, Coin::Serai).expect("sri ^ sri #1"),
|
||||||
|
Self::establish(Coin::Serai, coin_out).expect("sri ^ sri #2"),
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch the coin _in_ for the swap.
|
||||||
|
pub fn r#in(self) -> Coin {
|
||||||
|
match self {
|
||||||
|
Premise::ToSerai { from } => from.into(),
|
||||||
|
Premise::FromSerai { .. } => Coin::Serai,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch the coin _out_ from the swap.
|
||||||
|
pub fn out(self) -> Coin {
|
||||||
|
match self {
|
||||||
|
Premise::ToSerai { .. } => Coin::Serai,
|
||||||
|
Premise::FromSerai { to } => to.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch the external coin present within the swap.
|
||||||
|
pub fn external_coin(self) -> ExternalCoin {
|
||||||
|
match self {
|
||||||
|
Premise::ToSerai { from: external_coin } | Premise::FromSerai { to: external_coin } => {
|
||||||
|
external_coin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The reserves for a liquidity pool.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
|
pub struct Reserves {
|
||||||
|
/// The amount of SRI already present.
|
||||||
|
pub sri: Amount,
|
||||||
|
/// The amount of the external coin already present.
|
||||||
|
pub external_coin: Amount,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Reserves {
|
||||||
|
/// The product of two amounts.
|
||||||
|
///
|
||||||
|
/// This is intended to be used as the famous `x * y = k` formula's implementation.
|
||||||
|
fn product(x: u64, y: u64) -> u128 {
|
||||||
|
u128::from(x) * u128::from(y)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decompose this into `(in_reserve, out_reserve)` given the direction for a swap.
|
||||||
|
fn as_in_out(self, premise: Premise) -> (u64, u64) {
|
||||||
|
match premise {
|
||||||
|
Premise::ToSerai { .. } => (self.external_coin.0, self.sri.0),
|
||||||
|
Premise::FromSerai { .. } => (self.sri.0, self.external_coin.0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Premise {
|
||||||
|
/// Validate the following swap may be performed.
|
||||||
|
///
|
||||||
|
/// Validation of the amounts occur via the `x * y = k` formula popularized with Uniswap V2,
|
||||||
|
/// itself licensed under the GPL.
|
||||||
|
///
|
||||||
|
/// For more information, please see the following links:
|
||||||
|
///
|
||||||
|
/// <https://docs.uniswap.org/contracts/v2/concepts/protocol-overview/how-uniswap-works>
|
||||||
|
///
|
||||||
|
/// <https://github.com/Uniswap/v2-core/blob/4dd59067c76dea4a0e8e4bfdda41877a6b16dedc>
|
||||||
|
fn validate(
|
||||||
|
self,
|
||||||
|
reserves: Reserves,
|
||||||
|
amount_in: Amount,
|
||||||
|
amount_out: Amount,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let (in_reserve, out_reserve) = reserves.as_in_out(self);
|
||||||
|
let current_k = Reserves::product(in_reserve, out_reserve);
|
||||||
|
let proposed_k = Reserves::product(
|
||||||
|
in_reserve.checked_add(amount_in.0).ok_or(Error::Overflow)?,
|
||||||
|
out_reserve.checked_sub(amount_out.0).ok_or(Error::Underflow)?,
|
||||||
|
);
|
||||||
|
if proposed_k < current_k {
|
||||||
|
Err(Error::KInvariant)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Quote a swap for an amount in.
|
||||||
|
pub fn quote_for_in(self, reserves: Reserves, amount_in: Amount) -> Result<Amount, Error> {
|
||||||
|
let (in_reserve, out_reserve) = reserves.as_in_out(self);
|
||||||
|
let current_k = Reserves::product(in_reserve, out_reserve);
|
||||||
|
let proposed_in_reserve = u128::from(in_reserve) + u128::from(amount_in.0);
|
||||||
|
let required_proposed_out_reserve = current_k.div_ceil(proposed_in_reserve);
|
||||||
|
// If this does not fit in a `u64`, the following substraction would have underflowed
|
||||||
|
let required_proposed_out_reserve =
|
||||||
|
u64::try_from(required_proposed_out_reserve).map_err(|_| Error::Underflow)?;
|
||||||
|
let amount_out =
|
||||||
|
Amount(out_reserve.checked_sub(required_proposed_out_reserve).ok_or(Error::Underflow)?);
|
||||||
|
|
||||||
|
// Ensure this passes validation using a consistent, traditionally presented function
|
||||||
|
self.validate(reserves, amount_in, amount_out)?;
|
||||||
|
|
||||||
|
Ok(amount_out)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Quote a swap for an amount out.
|
||||||
|
pub fn quote_for_out(self, reserves: Reserves, amount_out: Amount) -> Result<Amount, Error> {
|
||||||
|
let (in_reserve, out_reserve) = reserves.as_in_out(self);
|
||||||
|
let current_k = Reserves::product(in_reserve, out_reserve);
|
||||||
|
let proposed_out_reserve = out_reserve.checked_sub(amount_out.0).ok_or(Error::Underflow)?;
|
||||||
|
let required_proposed_in_reserve = current_k.div_ceil(u128::from(proposed_out_reserve));
|
||||||
|
let required_proposed_in_reserve =
|
||||||
|
u64::try_from(required_proposed_in_reserve).map_err(|_| Error::Overflow)?;
|
||||||
|
let amount_in =
|
||||||
|
Amount(required_proposed_in_reserve.checked_sub(in_reserve).ok_or(Error::Overflow)?);
|
||||||
|
|
||||||
|
self.validate(reserves, amount_in, amount_out)?;
|
||||||
|
|
||||||
|
Ok(amount_in)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,6 +38,9 @@ pub mod network_id;
|
|||||||
/// Types for identifying and working with validator sets.
|
/// Types for identifying and working with validator sets.
|
||||||
pub mod validator_sets;
|
pub mod validator_sets;
|
||||||
|
|
||||||
|
/// Types for the DEX.
|
||||||
|
pub mod dex;
|
||||||
|
|
||||||
/// Types for signaling.
|
/// Types for signaling.
|
||||||
pub mod signals;
|
pub mod signals;
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ serai-core-pallet = { path = "../core", default-features = false }
|
|||||||
serai-coins-pallet = { path = "../coins", default-features = false }
|
serai-coins-pallet = { path = "../coins", default-features = false }
|
||||||
serai-validator-sets-pallet = { path = "../validator-sets", default-features = false }
|
serai-validator-sets-pallet = { path = "../validator-sets", default-features = false }
|
||||||
serai-signals-pallet = { path = "../signals", default-features = false }
|
serai-signals-pallet = { path = "../signals", default-features = false }
|
||||||
|
serai-dex-pallet = { path = "../dex", default-features = false }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
substrate-wasm-builder = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc" }
|
substrate-wasm-builder = { git = "https://github.com/serai-dex/patch-polkadot-sdk", rev = "8c36534bb0bd5a02979f94bb913d11d55fe7eadc" }
|
||||||
@@ -88,6 +89,7 @@ std = [
|
|||||||
"serai-coins-pallet/std",
|
"serai-coins-pallet/std",
|
||||||
"serai-validator-sets-pallet/std",
|
"serai-validator-sets-pallet/std",
|
||||||
"serai-signals-pallet/std",
|
"serai-signals-pallet/std",
|
||||||
|
"serai-dex-pallet/std",
|
||||||
]
|
]
|
||||||
|
|
||||||
try-runtime = [
|
try-runtime = [
|
||||||
@@ -107,6 +109,7 @@ try-runtime = [
|
|||||||
"serai-coins-pallet/try-runtime",
|
"serai-coins-pallet/try-runtime",
|
||||||
"serai-validator-sets-pallet/try-runtime",
|
"serai-validator-sets-pallet/try-runtime",
|
||||||
"serai-signals-pallet/try-runtime",
|
"serai-signals-pallet/try-runtime",
|
||||||
|
"serai-dex-pallet/try-runtime",
|
||||||
]
|
]
|
||||||
|
|
||||||
runtime-benchmarks = [
|
runtime-benchmarks = [
|
||||||
@@ -123,6 +126,7 @@ runtime-benchmarks = [
|
|||||||
"serai-coins-pallet/runtime-benchmarks",
|
"serai-coins-pallet/runtime-benchmarks",
|
||||||
"serai-validator-sets-pallet/runtime-benchmarks",
|
"serai-validator-sets-pallet/runtime-benchmarks",
|
||||||
"serai-signals-pallet/runtime-benchmarks",
|
"serai-signals-pallet/runtime-benchmarks",
|
||||||
|
"serai-dex-pallet/runtime-benchmarks",
|
||||||
]
|
]
|
||||||
|
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
|
|||||||
@@ -93,6 +93,9 @@ mod runtime {
|
|||||||
#[runtime::pallet_index(5)]
|
#[runtime::pallet_index(5)]
|
||||||
pub type LiquidityTokens = serai_coins_pallet::Pallet<Runtime, LiquidityTokensInstance>;
|
pub type LiquidityTokens = serai_coins_pallet::Pallet<Runtime, LiquidityTokensInstance>;
|
||||||
|
|
||||||
|
#[runtime::pallet_index(6)]
|
||||||
|
pub type Dex = serai_dex_pallet::Pallet<Runtime>;
|
||||||
|
|
||||||
#[runtime::pallet_index(0xfd)]
|
#[runtime::pallet_index(0xfd)]
|
||||||
#[runtime::disable_inherent]
|
#[runtime::disable_inherent]
|
||||||
pub type Timestamp = pallet_timestamp::Pallet<Runtime>;
|
pub type Timestamp = pallet_timestamp::Pallet<Runtime>;
|
||||||
@@ -171,6 +174,7 @@ impl serai_signals_pallet::Config for Runtime {
|
|||||||
impl serai_coins_pallet::Config<LiquidityTokensInstance> for Runtime {
|
impl serai_coins_pallet::Config<LiquidityTokensInstance> for Runtime {
|
||||||
type AllowMint = serai_coins_pallet::AlwaysAllowMint;
|
type AllowMint = serai_coins_pallet::AlwaysAllowMint;
|
||||||
}
|
}
|
||||||
|
impl serai_dex_pallet::Config for Runtime {}
|
||||||
|
|
||||||
impl pallet_timestamp::Config for Runtime {
|
impl pallet_timestamp::Config for Runtime {
|
||||||
type Moment = u64;
|
type Moment = u64;
|
||||||
@@ -292,16 +296,35 @@ impl From<serai_abi::Call> for RuntimeCall {
|
|||||||
serai_abi::Call::Dex(call) => {
|
serai_abi::Call::Dex(call) => {
|
||||||
use serai_abi::dex::Call;
|
use serai_abi::dex::Call;
|
||||||
match call {
|
match call {
|
||||||
|
Call::add_liquidity {
|
||||||
|
external_coin,
|
||||||
|
sri_intended,
|
||||||
|
external_coin_intended,
|
||||||
|
sri_minimum,
|
||||||
|
external_coin_minimum,
|
||||||
|
} => RuntimeCall::Dex(serai_dex_pallet::Call::add_liquidity {
|
||||||
|
external_coin,
|
||||||
|
sri_intended,
|
||||||
|
external_coin_intended,
|
||||||
|
sri_minimum,
|
||||||
|
external_coin_minimum,
|
||||||
|
}),
|
||||||
Call::transfer_liquidity { to, liquidity_tokens } => {
|
Call::transfer_liquidity { to, liquidity_tokens } => {
|
||||||
RuntimeCall::LiquidityTokens(serai_coins_pallet::Call::transfer {
|
RuntimeCall::Dex(serai_dex_pallet::Call::transfer_liquidity { to, liquidity_tokens })
|
||||||
to: to.into(),
|
}
|
||||||
coins: liquidity_tokens.into(),
|
Call::remove_liquidity { liquidity_tokens, sri_minimum, external_coin_minimum } => {
|
||||||
|
RuntimeCall::Dex(serai_dex_pallet::Call::remove_liquidity {
|
||||||
|
liquidity_tokens,
|
||||||
|
sri_minimum,
|
||||||
|
external_coin_minimum,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Call::add_liquidity { .. } |
|
Call::swap { coins_to_swap, minimum_to_receive } => {
|
||||||
Call::remove_liquidity { .. } |
|
RuntimeCall::Dex(serai_dex_pallet::Call::swap { coins_to_swap, minimum_to_receive })
|
||||||
Call::swap_exact { .. } |
|
}
|
||||||
Call::swap_for_exact { .. } => todo!("TODO"),
|
Call::swap_for { coins_to_receive, maximum_to_swap } => {
|
||||||
|
RuntimeCall::Dex(serai_dex_pallet::Call::swap_for { coins_to_receive, maximum_to_swap })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
serai_abi::Call::GenesisLiquidity(call) => {
|
serai_abi::Call::GenesisLiquidity(call) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user