Skip to content

Commit

Permalink
Merge pull request #825 from multiversx/pair-hooks
Browse files Browse the repository at this point in the history
pair hooks again
  • Loading branch information
dorin-iancu authored Feb 7, 2024
2 parents e227609 + 04890fe commit c791e7f
Show file tree
Hide file tree
Showing 26 changed files with 1,101 additions and 26 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
15 changes: 15 additions & 0 deletions common/modules/banned_addresses/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "banned_addresses"
version = "0.0.0"
authors = ["Dorin Iancu <[email protected]>"]
edition = "2021"

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

[dependencies.multiversx-sc]
version = "=0.46.1"
features = ["esdt-token-payment-legacy-decode"]

[dependencies.permissions_module]
path = "../permissions_module"
36 changes: 36 additions & 0 deletions common/modules/banned_addresses/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#![no_std]

multiversx_sc::imports!();

#[multiversx_sc::module]
pub trait BannedAddressModule: permissions_module::PermissionsModule {
#[endpoint(addBannedAddress)]
fn add_banned_address(&self, addresses: MultiValueEncoded<ManagedAddress>) {
self.require_caller_has_owner_or_admin_permissions();

let mapper = self.banned_addresses();
for address in addresses {
mapper.add(&address);
}
}

#[endpoint(removeBannedAddress)]
fn remove_banned_address(&self, addresses: MultiValueEncoded<ManagedAddress>) {
self.require_caller_has_owner_or_admin_permissions();

let mapper = self.banned_addresses();
for address in addresses {
mapper.remove(&address);
}
}

fn require_not_banned_address(&self, address: &ManagedAddress) {
require!(
!self.banned_addresses().contains(address),
"Cannot add hook for this address"
);
}

#[storage_mapper("bannedAddresses")]
fn banned_addresses(&self) -> WhitelistMapper<ManagedAddress>;
}
3 changes: 3 additions & 0 deletions dex/pair/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ path = "../../energy-integration/fees-collector"
[dependencies.utils]
path = "../../common/modules/utils"

[dependencies.banned_addresses]
path = "../../common/modules/banned_addresses"

[dependencies.itertools]
version = "0.10.1"
default-features = false
Expand Down
7 changes: 7 additions & 0 deletions dex/pair/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub mod fee;
mod liquidity_pool;
pub mod locking_wrapper;
pub mod pair_actions;
pub mod pair_hooks;
pub mod safe_price;
pub mod safe_price_view;

Expand Down Expand Up @@ -45,6 +46,9 @@ pub trait Pair<ContractReader>:
+ pair_actions::swap::SwapModule
+ pair_actions::views::ViewsModule
+ pair_actions::common_methods::CommonMethodsModule
+ pair_hooks::change_hooks::ChangeHooksModule
+ pair_hooks::call_hook::CallHookModule
+ banned_addresses::BannedAddressModule
+ utils::UtilsModule
{
#[init]
Expand Down Expand Up @@ -97,6 +101,9 @@ pub trait Pair<ContractReader>:
);
self.add_permissions_for_all(admins, Permissions::ADMIN);
};

let sc_address = self.blockchain().get_sc_address();
self.banned_addresses().add(&sc_address);
}

#[endpoint]
Expand Down
40 changes: 36 additions & 4 deletions dex/pair/src/pair_actions/add_liq.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
contexts::add_liquidity::AddLiquidityContext, StorageCache, ERROR_BAD_PAYMENT_TOKENS,
ERROR_INITIAL_LIQUIDITY_NOT_ADDED, ERROR_INVALID_ARGS, ERROR_K_INVARIANT_FAILED,
ERROR_LP_TOKEN_NOT_ISSUED, ERROR_NOT_ACTIVE,
contexts::add_liquidity::AddLiquidityContext, pair_hooks::hook_type::PairHookType,
StorageCache, ERROR_BAD_PAYMENT_TOKENS, ERROR_INITIAL_LIQUIDITY_NOT_ADDED, ERROR_INVALID_ARGS,
ERROR_K_INVARIANT_FAILED, ERROR_LP_TOKEN_NOT_ISSUED, ERROR_NOT_ACTIVE,
};

use super::common_result_types::AddLiquidityResultType;
Expand All @@ -21,6 +21,9 @@ pub trait AddLiquidityModule:
+ permissions_module::PermissionsModule
+ pausable::PausableModule
+ super::common_methods::CommonMethodsModule
+ crate::pair_hooks::change_hooks::ChangeHooksModule
+ crate::pair_hooks::call_hook::CallHookModule
+ banned_addresses::BannedAddressModule
+ utils::UtilsModule
{
#[payable("*")]
Expand Down Expand Up @@ -62,6 +65,28 @@ pub trait AddLiquidityModule:
ERROR_INITIAL_LIQUIDITY_NOT_ADDED
);

let mut payments_vec = ManagedVec::new();
payments_vec.push(first_payment);
payments_vec.push(second_payment);

let mut args = ManagedVec::new();

let (hook_type_before, hook_type_after) = if storage_cache.lp_token_supply == 0 {
(
PairHookType::BeforeAddInitialLiq,
PairHookType::AfterAddInitialLiq,
)
} else {
self.encode_arg_to_vec(&first_token_amount_min, &mut args);
self.encode_arg_to_vec(&second_token_amount_min, &mut args);

(PairHookType::BeforeAddLiq, PairHookType::AfterAddLiq)
};
let payments_after_hook =
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);

self.update_safe_price(
&storage_cache.first_token_reserve,
&storage_cache.second_token_reserve,
Expand Down Expand Up @@ -103,11 +128,18 @@ pub trait AddLiquidityModule:
self.send()
.esdt_local_mint(&storage_cache.lp_token_id, 0, &add_liq_context.liq_added);

let lp_payment = EsdtTokenPayment::new(
let mut lp_payment = EsdtTokenPayment::new(
storage_cache.lp_token_id.clone(),
0,
add_liq_context.liq_added.clone(),
);
let lp_payment_after_hook = self.call_hook(
hook_type_after,
caller.clone(),
ManagedVec::from_single_item(lp_payment),
ManagedVec::new(),
);
lp_payment = lp_payment_after_hook.get(0);

let mut output_payments =
self.build_add_liq_output_payments(&storage_cache, &add_liq_context);
Expand Down
29 changes: 26 additions & 3 deletions dex/pair/src/pair_actions/initial_liq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use common_errors::ERROR_PERMISSION_DENIED;
use pausable::State;

use crate::{
contexts::add_liquidity::AddLiquidityContext, StorageCache, ERROR_ACTIVE,
ERROR_BAD_PAYMENT_TOKENS, ERROR_INITIAL_LIQUIDITY_ALREADY_ADDED,
contexts::add_liquidity::AddLiquidityContext, pair_hooks::hook_type::PairHookType,
StorageCache, ERROR_ACTIVE, ERROR_BAD_PAYMENT_TOKENS, ERROR_INITIAL_LIQUIDITY_ALREADY_ADDED,
};

use super::common_result_types::AddLiquidityResultType;
Expand All @@ -22,6 +22,9 @@ pub trait InitialLiquidityModule:
+ permissions_module::PermissionsModule
+ pausable::PausableModule
+ super::common_methods::CommonMethodsModule
+ crate::pair_hooks::change_hooks::ChangeHooksModule
+ crate::pair_hooks::call_hook::CallHookModule
+ banned_addresses::BannedAddressModule
+ utils::UtilsModule
{
#[payable("*")]
Expand Down Expand Up @@ -55,6 +58,19 @@ pub trait InitialLiquidityModule:
ERROR_INITIAL_LIQUIDITY_ALREADY_ADDED
);

let mut payments_vec = ManagedVec::new();
payments_vec.push(first_payment);
payments_vec.push(second_payment);

let payments_after_hook = self.call_hook(
PairHookType::BeforeAddInitialLiq,
caller.clone(),
payments_vec,
ManagedVec::new(),
);
let first_payment = payments_after_hook.get(0);
let second_payment = payments_after_hook.get(1);

let first_token_optimal_amount = &first_payment.amount;
let second_token_optimal_amount = &second_payment.amount;
let liq_added = self.pool_add_initial_liquidity(
Expand All @@ -66,8 +82,15 @@ pub trait InitialLiquidityModule:
self.send()
.esdt_local_mint(&storage_cache.lp_token_id, 0, &liq_added);

let lp_payment =
let mut lp_payment =
EsdtTokenPayment::new(storage_cache.lp_token_id.clone(), 0, liq_added.clone());
let lp_payment_after_hook = self.call_hook(
PairHookType::AfterAddInitialLiq,
caller.clone(),
ManagedVec::from_single_item(lp_payment),
ManagedVec::new(),
);
lp_payment = lp_payment_after_hook.get(0);

self.send()
.direct_non_zero_esdt_payment(&caller, &lp_payment);
Expand Down
36 changes: 29 additions & 7 deletions dex/pair/src/pair_actions/remove_liq.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::{
contexts::remove_liquidity::RemoveLiquidityContext, 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,
contexts::remove_liquidity::RemoveLiquidityContext, pair_hooks::hook_type::PairHookType,
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 All @@ -22,6 +23,9 @@ pub trait RemoveLiquidityModule:
+ permissions_module::PermissionsModule
+ pausable::PausableModule
+ super::common_methods::CommonMethodsModule
+ crate::pair_hooks::change_hooks::ChangeHooksModule
+ crate::pair_hooks::call_hook::CallHookModule
+ banned_addresses::BannedAddressModule
+ utils::UtilsModule
{
#[payable("*")]
Expand Down Expand Up @@ -63,6 +67,18 @@ pub trait RemoveLiquidityModule:
&storage_cache.second_token_reserve,
);

let mut args = ManagedVec::new();
self.encode_arg_to_vec(&first_token_amount_min, &mut args);
self.encode_arg_to_vec(&second_token_amount_min, &mut args);

let payments_after_hook = self.call_hook(
PairHookType::BeforeRemoveLiq,
caller.clone(),
ManagedVec::from_single_item(payment),
ManagedVec::new(),
);
let payment = payments_after_hook.get(0);

let mut remove_liq_context = RemoveLiquidityContext::new(
payment.amount,
first_token_amount_min,
Expand All @@ -83,9 +99,15 @@ pub trait RemoveLiquidityModule:

let output_payments =
self.build_remove_liq_output_payments(&storage_cache, &remove_liq_context);
let output_payments_after_hook = self.call_hook(
PairHookType::AfterRemoveLiq,
caller.clone(),
output_payments,
args,
);

let first_payment_after = output_payments.get(0);
let second_payment_after = output_payments.get(1);
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
Expand All @@ -95,11 +117,11 @@ pub trait RemoveLiquidityModule:
ERROR_SLIPPAGE_ON_REMOVE
);

self.send_multiple_tokens_if_not_zero(&caller, &output_payments);
self.send_multiple_tokens_if_not_zero(&caller, &output_payments_after_hook);

self.emit_remove_liquidity_event(&storage_cache, remove_liq_context);

self.build_remove_liq_results(output_payments)
self.build_remove_liq_results(output_payments_after_hook)
}

#[payable("*")]
Expand Down
Loading

0 comments on commit c791e7f

Please sign in to comment.