Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Cargo.lock

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

15 changes: 15 additions & 0 deletions crates/bridge-pot-currency-swap/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "bridge-pot-currency-swap"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
primitives-currency-swap = { version = "0.1", path = "../primitives-currency-swap", default-features = false }

frame-support = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "locked/polkadot-v0.9.38" }

[features]
default = ["std"]
std = ["frame-support/std", "primitives-currency-swap/std"]
try-runtime = ["frame-support/try-runtime", "primitives-currency-swap/try-runtime"]
37 changes: 37 additions & 0 deletions crates/bridge-pot-currency-swap/src/existence_optional.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! An implementation that does not require pot account existence and can potentially kill the
//! pot account by withdrawing all the funds from it.

use frame_support::{
sp_runtime::{traits::Convert, DispatchError},
traits::{Currency, ExistenceRequirement, Get, Imbalance, WithdrawReasons},
};

use super::{Config, CurrencySwap};

/// A marker type for the implementation that does not require pot accounts existence.
pub enum Marker {}

impl<T: Config> primitives_currency_swap::CurrencySwap<T::AccountIdFrom, T::AccountIdTo>
for CurrencySwap<T, Marker>
{
type From = T::CurrencyFrom;
type To = T::CurrencyTo;
type Error = DispatchError;

fn swap(
imbalance: <Self::From as Currency<T::AccountIdFrom>>::NegativeImbalance,
) -> Result<<Self::To as Currency<T::AccountIdTo>>::NegativeImbalance, Self::Error> {
let amount = imbalance.peek();

T::CurrencyFrom::resolve_creating(&T::PotFrom::get(), imbalance);

let imbalance = T::CurrencyTo::withdraw(
&T::PotTo::get(),
T::BalanceCoverter::convert(amount),
WithdrawReasons::TRANSFER,
ExistenceRequirement::AllowDeath,
)?;

Ok(imbalance)
}
}
57 changes: 57 additions & 0 deletions crates/bridge-pot-currency-swap/src/existence_required.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//! An implementation that requires and ensures pot account existence.

use frame_support::{
sp_runtime::{traits::Convert, DispatchError},
traits::{Currency, ExistenceRequirement, Get, Imbalance, WithdrawReasons},
};

use super::{Config, CurrencySwap};

/// A marker type for the implementation that requires pot accounts existence.
pub enum Marker {}

/// An error that can occur while doing the swap operation.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Error<ImbalanceFrom> {
/// Unable to resolve the incoming balance into the corresponding pot.
ResolvingIncomingImbalance(ImbalanceFrom),
/// Unable to withdraw the outpoing balance from the corresponding pot.
IssuingOutgoingImbalance(DispatchError),
}

impl<T> From<Error<T>> for DispatchError {
fn from(value: Error<T>) -> Self {
match value {
Error::ResolvingIncomingImbalance(_) => DispatchError::NoProviders,
Error::IssuingOutgoingImbalance(err) => err,
}
}
}

impl<T: Config> primitives_currency_swap::CurrencySwap<T::AccountIdFrom, T::AccountIdTo>
for CurrencySwap<T, Marker>
{
type From = T::CurrencyFrom;
type To = T::CurrencyTo;
type Error =
Error<<<T as Config>::CurrencyFrom as Currency<T::AccountIdFrom>>::NegativeImbalance>;

fn swap(
imbalance: <Self::From as Currency<T::AccountIdFrom>>::NegativeImbalance,
) -> Result<<Self::To as Currency<T::AccountIdTo>>::NegativeImbalance, Self::Error> {
let amount = imbalance.peek();

T::CurrencyFrom::resolve_into_existing(&T::PotFrom::get(), imbalance)
.map_err(Error::ResolvingIncomingImbalance)?;

let imbalance = T::CurrencyTo::withdraw(
&T::PotTo::get(),
T::BalanceCoverter::convert(amount),
WithdrawReasons::TRANSFER,
ExistenceRequirement::KeepAlive,
)
.map_err(Error::IssuingOutgoingImbalance)?;

Ok(imbalance)
}
}
48 changes: 48 additions & 0 deletions crates/bridge-pot-currency-swap/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Bridge pot currency swap implementation.

// Either generate code at stadard mode, or `no_std`, based on the `std` feature presence.
#![cfg_attr(not(feature = "std"), no_std)]

use frame_support::{
sp_runtime::traits::Convert,
sp_std::marker::PhantomData,
traits::{Currency, Get},
};

pub mod existence_optional;
pub mod existence_required;

pub use existence_optional::Marker as ExistenceOptional;
pub use existence_required::Marker as ExistenceRequired;

/// The config for the generic bridge pot currency swap logic.
pub trait Config {
/// The type representing the account key for the currency to swap from.
type AccountIdFrom;

/// The type representing the account key for the currency to swap to.
type AccountIdTo;

/// The currency to swap from.
type CurrencyFrom: Currency<Self::AccountIdFrom>;

/// The currency to swap to.
type CurrencyTo: Currency<Self::AccountIdTo>;

/// The converter to determine how the balance amount should be converted from one currency to
/// another.
type BalanceCoverter: Convert<
<Self::CurrencyFrom as Currency<Self::AccountIdFrom>>::Balance,
<Self::CurrencyTo as Currency<Self::AccountIdTo>>::Balance,
>;

/// The account to land the balances to when receiving the funds as part of the swap operation.
type PotFrom: Get<Self::AccountIdFrom>;

/// The account to take the balances from when sending the funds as part of the swap operation.
type PotTo: Get<Self::AccountIdTo>;
}

/// A [`primitives_currency_swap::CurrencySwap`] implementation that does the swap using two
/// "pot" accounts for each of end swaped currencies.
pub struct CurrencySwap<T: Config, ExistenceRequirement>(PhantomData<(T, ExistenceRequirement)>);