Skip to content

Commit

Permalink
Merge pull request #65 from multiversx/composable-tasks-enable-swap-t…
Browse files Browse the repository at this point in the history
…okens-fixed-output

Composable tasks enable swap tokens fixed output
  • Loading branch information
CostinCarabas authored Mar 20, 2024
2 parents 8ddf417 + 017e135 commit 062d7f4
Show file tree
Hide file tree
Showing 7 changed files with 305 additions and 38 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
name: Contracts
uses: multiversx/mx-sc-actions/.github/workflows/contracts.yml@v2.3.1
with:
rust-toolchain: nightly-2023-05-26
vmtools-version: v1.4.60
rust-toolchain: nightly-2023-12-11
vmtools-version: v1.5.24
secrets:
token: ${{ secrets.GITHUB_TOKEN }}
2 changes: 1 addition & 1 deletion Cargo.lock

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

72 changes: 57 additions & 15 deletions composable-tasks/src/compose_tasks.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
use core::convert::TryFrom;

use crate::{external_sc_interactions, config::{SWAP_ARGS_LEN, ROUTER_SWAP_ARGS_LEN, SEND_TOKENS_ARGS_LEN}};
use router::multi_pair_swap::{
SWAP_TOKENS_FIXED_INPUT_FUNC_NAME, SWAP_TOKENS_FIXED_OUTPUT_FUNC_NAME,
};

use crate::{
config::{ROUTER_SWAP_ARGS_LEN, SEND_TOKENS_ARGS_LEN, SWAP_ARGS_LEN},
external_sc_interactions,
};

multiversx_sc::imports!();
multiversx_sc::derive_imports!();
Expand Down Expand Up @@ -42,14 +49,19 @@ pub trait TaskCall:
payment_for_next_task = match task_type {
TaskType::WrapEGLD => self.wrap_egld(payment_for_current_task),
TaskType::UnwrapEGLD => self.unwrap_egld(payment_for_current_task),
TaskType::Swap => self.swap(payment_for_current_task, args),
TaskType::Swap => {
self.swap(payment_for_current_task, &mut payments_to_return, args)
}
TaskType::RouterSwap => {
self.router_swap(payment_for_current_task, &mut payments_to_return, args)
}
TaskType::SendEgldOrEsdt => {
require!(args.len() == SEND_TOKENS_ARGS_LEN, "Invalid number of arguments!");
let new_destination =
ManagedAddress::try_from(args.get(0).clone_value()).unwrap_or_else(|err| sc_panic!(err));
require!(
args.len() == SEND_TOKENS_ARGS_LEN,
"Invalid number of arguments!"
);
let new_destination = ManagedAddress::try_from(args.get(0).clone_value())
.unwrap_or_else(|err| sc_panic!(err));

dest_addr = new_destination;
break;
Expand All @@ -67,6 +79,7 @@ pub trait TaskCall:
fn swap(
&self,
payment_for_current_task: EgldOrEsdtTokenPayment,
payments_to_return: &mut PaymentsVec<Self::Api>,
args: ManagedVec<ManagedBuffer>,
) -> EgldOrEsdtTokenPayment {
require!(
Expand All @@ -75,18 +88,47 @@ pub trait TaskCall:
);
let payment_in = payment_for_current_task.unwrap_esdt();

require!(args.len() == SWAP_ARGS_LEN, "Incorrect arguments for swap task!");
require!(
args.len() == SWAP_ARGS_LEN,
"Incorrect arguments for swap task!"
);

let function_in_out = args.get(0).clone_value();
let token_out = TokenIdentifier::from(args.get(1).clone_value());
let min_amount_out = BigUint::from(args.get(2).clone_value());

let token_out = TokenIdentifier::from(args.get(0).clone_value());
let min_amount_out = BigUint::from(args.get(1).clone_value());
// if function_in_out
let swap_tokens_fixed_input_function =
ManagedBuffer::from(SWAP_TOKENS_FIXED_INPUT_FUNC_NAME);
let swap_tokens_fixed_output_function =
ManagedBuffer::from(SWAP_TOKENS_FIXED_OUTPUT_FUNC_NAME);
require!(
function_in_out == swap_tokens_fixed_input_function
|| function_in_out == swap_tokens_fixed_output_function,
"Invalid function name for swap"
);

self.perform_tokens_swap(
payment_in.token_identifier,
payment_in.amount,
token_out,
min_amount_out,
)
.into()
let payment_out = if function_in_out == swap_tokens_fixed_input_function {
self.perform_swap_tokens_fixed_input(
payment_in.token_identifier,
payment_in.amount,
token_out,
min_amount_out,
)
} else {
let returned_payments_by_pair = self.perform_swap_tokens_fixed_output(
payment_in.token_identifier,
payment_in.amount,
token_out,
min_amount_out,
);
let payment_out = returned_payments_by_pair.get(0);
let payment_in_leftover = returned_payments_by_pair.get(1);
payments_to_return.push(payment_in_leftover);
payment_out
};

payment_out.into()
}

fn router_swap(
Expand Down
5 changes: 4 additions & 1 deletion composable-tasks/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ multiversx_sc::imports!();

use crate::external_sc_interactions;

pub const SWAP_ARGS_LEN: usize = 2;
pub const SWAP_ARGS_LEN: usize = 3;
pub const ROUTER_SWAP_ARGS_LEN: usize = 4;
pub const SEND_TOKENS_ARGS_LEN: usize = 1;
pub const SWAP_TOKENS_FIXED_INPUT_FUNC_NAME: &[u8] = b"swapTokensFixedInput";
pub const SWAP_TOKENS_FIXED_OUTPUT_FUNC_NAME: &[u8] = b"swapTokensFixedOutput";


#[multiversx_sc::module]
pub trait ConfigModule:
Expand Down
49 changes: 37 additions & 12 deletions composable-tasks/src/external_sc_interactions/pair_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl<M: ManagedTypeApi> PairAddressForTokens<M> {

#[multiversx_sc::module]
pub trait PairActionsModule: router_actions::RouterActionsModule {
fn perform_tokens_swap(
fn perform_swap_tokens_fixed_input(
&self,
from_tokens: TokenIdentifier,
from_amount: BigUint,
Expand All @@ -36,20 +36,45 @@ pub trait PairActionsModule: router_actions::RouterActionsModule {
let pair_address = self.get_pair(from_tokens.clone(), to_tokens.clone());
let payment = EsdtTokenPayment::new(from_tokens, 0, from_amount);

self.call_pair_swap(pair_address, payment, to_tokens, min_amount_out)
self.pair_proxy(pair_address)
.swap_tokens_fixed_input(to_tokens, min_amount_out)
.with_esdt_transfer(payment)
.execute_on_dest_context()
}

fn call_pair_swap(
fn perform_swap_tokens_fixed_output(
&self,
pair_address: ManagedAddress,
input_tokens: EsdtTokenPayment,
requested_token_id: TokenIdentifier,
min_amount_out: BigUint,
) -> EsdtTokenPayment {
self.pair_proxy(pair_address)
.swap_tokens_fixed_input(requested_token_id, min_amount_out)
.with_esdt_transfer(input_tokens)
.execute_on_dest_context()
from_token_id: TokenIdentifier,
from_amount: BigUint,
to_token_id: TokenIdentifier,
amount_out: BigUint,
) -> ManagedVec<EsdtTokenPayment> {
if from_token_id == to_token_id {
return ManagedVec::from_single_item(EsdtTokenPayment::new(
from_token_id,
0,
from_amount,
));
}

let pair_address = self.get_pair(from_token_id.clone(), to_token_id.clone());
let payment = EsdtTokenPayment::new(from_token_id, 0, from_amount);

let ((), back_transfers) = self
.pair_proxy(pair_address)
.swap_tokens_fixed_output(to_token_id.clone(), amount_out)
.with_esdt_transfer(payment)
.execute_on_dest_context_with_back_transfers();

require!(
back_transfers.esdt_payments.len() <= 2,
"Swap tokens fixed output: Back transfers expected maximum 2 payments"
);

let payment_out = back_transfers.esdt_payments.get(0);
require!(payment_out.token_identifier == to_token_id, "Wrong returned token identifier!");

back_transfers.esdt_payments
}

#[proxy]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ type SwapOperationType<M> =
use core::convert::TryFrom;

use router::{factory::ProxyTrait as _, multi_pair_swap::ProxyTrait as _};
pub const SWAP_TOKENS_FIXED_INPUT_FUNC_NAME: &[u8] = b"swapTokensFixedInput";

#[multiversx_sc::module]
pub trait RouterActionsModule {
Expand Down
Loading

0 comments on commit 062d7f4

Please sign in to comment.