Skip to content

Commit

Permalink
Merge pull request #823 from multiversx/interface-hook
Browse files Browse the repository at this point in the history
example hook impl
  • Loading branch information
dorin-iancu authored Jan 31, 2024
2 parents 8474c5e + ade54d1 commit 34e75dc
Show file tree
Hide file tree
Showing 13 changed files with 739 additions and 7 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ members = [
"dex/pair-mock",
"dex/pair-mock/meta",

"dex/sample-hooks/pair-hooks-sample",
"dex/sample-hooks/pair-hooks-sample/meta",

"energy-integration/energy-factory-mock",
"energy-integration/energy-factory-mock/meta",
"energy-integration/energy-update",
Expand Down
4 changes: 2 additions & 2 deletions dex/pair/src/pair_actions/add_liq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub trait AddLiquidityModule:
(HookType::BeforeAddLiq, HookType::AfterAddLiq)
};
let payments_after_hook =
self.call_hook(hook_type_before, caller.clone(), payments_vec, args.clone());
self.call_hook(hook_type_before, caller.clone(), payments_vec, args);
let first_payment = payments_after_hook.get(0);
let second_payment = payments_after_hook.get(1);

Expand Down Expand Up @@ -133,7 +133,7 @@ pub trait AddLiquidityModule:
hook_type_after,
caller.clone(),
ManagedVec::from_single_item(lp_payment),
args,
ManagedVec::new(),
);
lp_payment = lp_payment_after_hook.get(0);

Expand Down
14 changes: 13 additions & 1 deletion dex/pair/src/pair_actions/remove_liq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::{
contexts::remove_liquidity::RemoveLiquidityContext, pair_hooks::hook_type::HookType,
StorageCache, SwapTokensOrder, ERROR_BAD_PAYMENT_TOKENS, ERROR_INVALID_ARGS,
ERROR_K_INVARIANT_FAILED, ERROR_LP_TOKEN_NOT_ISSUED, ERROR_NOT_ACTIVE, ERROR_NOT_WHITELISTED,
ERROR_SLIPPAGE_ON_REMOVE,
};

use super::common_result_types::RemoveLiquidityResultType;
Expand Down Expand Up @@ -74,7 +75,7 @@ pub trait RemoveLiquidityModule:
HookType::BeforeRemoveLiq,
caller.clone(),
ManagedVec::from_single_item(payment),
args.clone(),
ManagedVec::new(),
);
let payment = payments_after_hook.get(0);

Expand Down Expand Up @@ -105,6 +106,17 @@ pub trait RemoveLiquidityModule:
args,
);

let first_payment_after = output_payments_after_hook.get(0);
let second_payment_after = output_payments_after_hook.get(1);
require!(
first_payment_after.amount >= remove_liq_context.first_token_amount_min,
ERROR_SLIPPAGE_ON_REMOVE
);
require!(
second_payment_after.amount >= remove_liq_context.second_token_amount_min,
ERROR_SLIPPAGE_ON_REMOVE
);

self.send_multiple_tokens_if_not_zero(&caller, &output_payments_after_hook);

self.emit_remove_liquidity_event(&storage_cache, remove_liq_context);
Expand Down
15 changes: 11 additions & 4 deletions dex/pair/src/pair_actions/swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,6 @@ pub trait SwapModule:

let mut args = ManagedVec::new();
self.encode_arg_to_vec(&SwapType::FixedInput, &mut args);
self.encode_arg_to_vec(&token_out, &mut args);
self.encode_arg_to_vec(&amount_out_min, &mut args);

let payments_after_hook = self.call_hook(
HookType::BeforeSwap,
Expand All @@ -138,6 +136,9 @@ pub trait SwapModule:
);
let payment = payments_after_hook.get(0);

self.encode_arg_to_vec(&token_out, &mut args);
self.encode_arg_to_vec(&amount_out_min, &mut args);

let mut swap_context = SwapContext::new(
payment.token_identifier,
payment.amount,
Expand Down Expand Up @@ -167,6 +168,11 @@ pub trait SwapModule:
let output_payments_after_hook =
self.call_hook(HookType::AfterSwap, caller.clone(), output_payments, args);

require!(
output_payments_after_hook.get(0).amount >= swap_context.output_token_amount,
ERROR_SLIPPAGE_EXCEEDED
);

self.send_multiple_tokens_if_not_zero(&caller, &output_payments_after_hook);

self.emit_swap_event(&storage_cache, swap_context);
Expand Down Expand Up @@ -209,8 +215,6 @@ pub trait SwapModule:

let mut args = ManagedVec::new();
self.encode_arg_to_vec(&SwapType::FixedOutput, &mut args);
self.encode_arg_to_vec(&token_out, &mut args);
self.encode_arg_to_vec(&amount_out, &mut args);

let payments_after_hook = self.call_hook(
HookType::BeforeSwap,
Expand All @@ -220,6 +224,9 @@ pub trait SwapModule:
);
let payment = payments_after_hook.get(0);

self.encode_arg_to_vec(&token_out, &mut args);
self.encode_arg_to_vec(&amount_out, &mut args);

let mut swap_context = SwapContext::new(
payment.token_identifier,
payment.amount,
Expand Down
65 changes: 65 additions & 0 deletions dex/pair/src/pair_hooks/hook_type.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::pair_actions::swap::SwapType;

multiversx_sc::imports!();
multiversx_sc::derive_imports!();

Expand All @@ -21,3 +23,66 @@ pub struct Hook<M: ManagedTypeApi> {
pub dest_address: ManagedAddress<M>,
pub endpoint_name: ManagedBuffer<M>,
}

pub trait PairHook {
type Sc: ContractBase;

fn before_add_initial_liq(
sc: &Self::Sc,
first_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
second_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
);

fn after_add_initial_liq(
sc: &Self::Sc,
lp_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
);

fn before_add_liq(
sc: &Self::Sc,
first_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
second_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
first_token_amount_min: BigUint<<Self::Sc as ContractBase>::Api>,
second_token_amount_min: BigUint<<Self::Sc as ContractBase>::Api>,
);

fn after_add_liq(
sc: &Self::Sc,
lp_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
);

fn before_remove_liq(
sc: &Self::Sc,
lp_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
);

fn after_remove_liq(
sc: &Self::Sc,
first_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
second_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
first_token_amount_min: BigUint<<Self::Sc as ContractBase>::Api>,
second_token_amount_min: BigUint<<Self::Sc as ContractBase>::Api>,
);

fn before_swap(
sc: &Self::Sc,
payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
swap_type: SwapType,
);

fn after_swap(
sc: &Self::Sc,
payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
swap_type: SwapType,
token_out: TokenIdentifier<<Self::Sc as ContractBase>::Api>,
amount_out: BigUint<<Self::Sc as ContractBase>::Api>,
);
}
21 changes: 21 additions & 0 deletions dex/sample-hooks/pair-hooks-sample/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "pair-hooks-sample"
version = "0.0.0"
authors = ["you"]
edition = "2021"
publish = false

[lib]
path = "src/lib.rs"

[dependencies.multiversx-sc]
version = "=0.46.1"

[dependencies.pair]
path = "../../pair"

[dev-dependencies]
num-bigint = "0.4.2"

[dev-dependencies.multiversx-sc-scenario]
version = "=0.46.1"
12 changes: 12 additions & 0 deletions dex/sample-hooks/pair-hooks-sample/meta/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "pair-hooks-sample-meta"
version = "0.0.0"
edition = "2021"
publish = false

[dependencies.pair-hooks-sample]
path = ".."

[dependencies.multiversx-sc-meta]
version = "=0.46.1"
default-features = false
3 changes: 3 additions & 0 deletions dex/sample-hooks/pair-hooks-sample/meta/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
multiversx_sc_meta::cli_main::<pair_hooks_sample::AbiProvider>();
}
3 changes: 3 additions & 0 deletions dex/sample-hooks/pair-hooks-sample/multiversx.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"language": "rust"
}
140 changes: 140 additions & 0 deletions dex/sample-hooks/pair-hooks-sample/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#![no_std]

use core::marker::PhantomData;

use pair::pair_hooks::hook_type::PairHook;

multiversx_sc::imports!();

#[multiversx_sc::contract]
pub trait PairHooksSample {
#[init]
fn init(&self, known_pairs: MultiValueEncoded<ManagedAddress>) {
let mapper = self.known_pairs();
for pair in known_pairs {
mapper.add(&pair);
}
}

#[payable("*")]
#[endpoint(beforeAddInitialLiqHook)]
fn before_add_initial_liq_hook(&self, original_caller: ManagedAddress) {
self.require_known_pair();

let [first_payment, second_payment] = self.call_value().multi_esdt();
Wrapper::<Self>::before_add_initial_liq(
self,
first_payment,
second_payment,
original_caller,
);
}

#[payable("*")]
#[endpoint(afterAddInitialLiqHook)]
fn after_add_initial_liq_hook(&self, original_caller: ManagedAddress) {
self.require_known_pair();

let lp_payment = self.call_value().single_esdt();
Wrapper::<Self>::after_add_initial_liq(self, lp_payment, original_caller);
}

fn require_known_pair(&self) {
let caller = self.blockchain().get_caller();
require!(
self.known_pairs().contains(&caller),
"Only known pairs may call this endpoint"
);
}

#[storage_mapper("knownPairs")]
fn known_pairs(&self) -> WhitelistMapper<ManagedAddress>;
}

pub struct Wrapper<T: PairHooksSample> {
_phantom: PhantomData<T>,
}

impl<T: PairHooksSample> PairHook for Wrapper<T> {
type Sc = T;

fn before_add_initial_liq(
sc: &Self::Sc,
first_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
second_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
_original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
) {
let caller = sc.blockchain().get_caller();
sc.send()
.direct_non_zero_esdt_payment(&caller, &first_payment);
sc.send()
.direct_non_zero_esdt_payment(&caller, &second_payment);
}

fn after_add_initial_liq(
sc: &Self::Sc,
lp_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
_original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
) {
let caller = sc.blockchain().get_caller();
sc.send().direct_non_zero_esdt_payment(&caller, &lp_payment);
}

fn before_add_liq(
_sc: &Self::Sc,
_first_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
_second_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
_original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
_first_token_amount_min: BigUint<<Self::Sc as ContractBase>::Api>,
_second_token_amount_min: BigUint<<Self::Sc as ContractBase>::Api>,
) {
todo!()
}

fn after_add_liq(
_sc: &Self::Sc,
_lp_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
_original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
) {
todo!()
}

fn before_remove_liq(
_sc: &Self::Sc,
_lp_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
_original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
) {
todo!()
}

fn after_remove_liq(
_sc: &Self::Sc,
_first_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
_second_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
_original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
_first_token_amount_min: BigUint<<Self::Sc as ContractBase>::Api>,
_second_token_amount_min: BigUint<<Self::Sc as ContractBase>::Api>,
) {
todo!()
}

fn before_swap(
_sc: &Self::Sc,
_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
_original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
_swap_type: pair::pair_actions::swap::SwapType,
) {
todo!()
}

fn after_swap(
_sc: &Self::Sc,
_payment: EsdtTokenPayment<<Self::Sc as ContractBase>::Api>,
_original_caller: ManagedAddress<<Self::Sc as ContractBase>::Api>,
_swap_type: pair::pair_actions::swap::SwapType,
_token_out: TokenIdentifier<<Self::Sc as ContractBase>::Api>,
_amount_out: BigUint<<Self::Sc as ContractBase>::Api>,
) {
todo!()
}
}
Loading

0 comments on commit 34e75dc

Please sign in to comment.