Skip to content

Commit

Permalink
split into modules
Browse files Browse the repository at this point in the history
  • Loading branch information
dorin-iancu committed May 8, 2024
1 parent 74d0ad9 commit d5c52e5
Show file tree
Hide file tree
Showing 11 changed files with 629 additions and 483 deletions.
484 changes: 11 additions & 473 deletions liquid-staking/src/lib.rs

Large diffs are not rendered by default.

83 changes: 83 additions & 0 deletions liquid-staking/src/user_actions/add_liquidity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use crate::{
delegation_proxy::ProxyTrait as _, user_actions::common::MIN_EGLD_TO_DELEGATE, StorageCache,
ERROR_BAD_PAYMENT_AMOUNT, ERROR_NOT_ACTIVE,
};

multiversx_sc::imports!();

#[multiversx_sc::module]
pub trait AddLiquidityModule:
crate::config::ConfigModule
+ crate::events::EventsModule
+ crate::delegation::DelegationModule
+ crate::liquidity_pool::LiquidityPoolModule
+ multiversx_sc_modules::ongoing_operation::OngoingOperationModule
+ multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule
+ super::common::CommonModule
{
#[payable("EGLD")]
#[endpoint(addLiquidity)]
fn add_liquidity(&self) {
self.blockchain().check_caller_is_user_account();

let storage_cache = StorageCache::new(self);
let caller = self.blockchain().get_caller();

let payment = self.call_value().egld_value().clone_value();
require!(
self.is_state_active(storage_cache.contract_state),
ERROR_NOT_ACTIVE
);
require!(payment >= MIN_EGLD_TO_DELEGATE, ERROR_BAD_PAYMENT_AMOUNT);

let delegation_contract = self.get_delegation_contract_for_delegate(&payment);
let gas_for_async_call = self.get_gas_for_async_call();

self.delegation_proxy_obj()
.contract(delegation_contract.clone())
.delegate()
.with_gas_limit(gas_for_async_call)
.with_egld_transfer(payment.clone())
.async_call()
.with_callback(AddLiquidityModule::callbacks(self).add_liquidity_callback(
caller,
delegation_contract,
payment,
))
.call_and_exit()
}

#[callback]
fn add_liquidity_callback(
&self,
caller: ManagedAddress,
delegation_contract: ManagedAddress,
staked_tokens: BigUint,
#[call_result] result: ManagedAsyncCallResult<()>,
) {
match result {
ManagedAsyncCallResult::Ok(()) => {
let mut storage_cache = StorageCache::new(self);
self.delegation_contract_data(&delegation_contract)
.update(|contract_data| {
contract_data.total_staked_from_ls_contract += &staked_tokens;
});

let ls_token_amount = self.pool_add_liquidity(&staked_tokens, &mut storage_cache);
let user_payment = self.mint_ls_token(ls_token_amount);
self.send().direct_esdt(
&caller,
&user_payment.token_identifier,
user_payment.token_nonce,
&user_payment.amount,
);

self.emit_add_liquidity_event(&storage_cache, &caller, user_payment.amount);
}
ManagedAsyncCallResult::Err(_) => {
self.send().direct_egld(&caller, &staked_tokens);
self.move_delegation_contract_to_back(delegation_contract);
}
}
}
}
82 changes: 82 additions & 0 deletions liquid-staking/src/user_actions/claim_rewards.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use multiversx_sc_modules::ongoing_operation::{
CONTINUE_OP, DEFAULT_MIN_GAS_TO_SAVE_PROGRESS, STOP_OP,
};

use crate::{
delegation::{ClaimStatus, ClaimStatusType},
delegation_proxy::ProxyTrait as _,
StorageCache, ERROR_NOT_ACTIVE, ERROR_NO_DELEGATION_CONTRACTS,
};

multiversx_sc::imports!();

pub const DEFAULT_GAS_TO_CLAIM_REWARDS: u64 = 6_000_000;

#[multiversx_sc::module]
pub trait ClaimRewardsModule:
crate::config::ConfigModule
+ crate::events::EventsModule
+ crate::delegation::DelegationModule
+ crate::liquidity_pool::LiquidityPoolModule
+ multiversx_sc_modules::ongoing_operation::OngoingOperationModule
+ multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule
+ super::common::CommonModule
{
#[endpoint(claimRewards)]
fn claim_rewards(&self) {
let storage_cache = StorageCache::new(self);

require!(
self.is_state_active(storage_cache.contract_state),
ERROR_NOT_ACTIVE
);

let delegation_addresses_mapper = self.delegation_addresses_list();
require!(
!delegation_addresses_mapper.is_empty(),
ERROR_NO_DELEGATION_CONTRACTS
);
let claim_status_mapper = self.delegation_claim_status();
let old_claim_status = claim_status_mapper.get();
let current_epoch = self.blockchain().get_block_epoch();
let mut current_claim_status = self.load_operation::<ClaimStatus<Self::Api>>();

self.check_claim_operation(&current_claim_status, old_claim_status, current_epoch);
self.prepare_claim_operation(&mut current_claim_status, current_epoch);

let run_result = self.run_while_it_has_gas(DEFAULT_MIN_GAS_TO_SAVE_PROGRESS, || {
let delegation_address_node = delegation_addresses_mapper
.get_node_by_id(current_claim_status.current_node)
.unwrap();
let next_node = delegation_address_node.get_next_node_id();
let delegation_address = delegation_address_node.into_value();

self.delegation_proxy_obj()
.contract(delegation_address)
.claim_rewards()
.with_gas_limit(DEFAULT_GAS_TO_CLAIM_REWARDS)
.transfer_execute();

if next_node == 0 {
claim_status_mapper.set(current_claim_status.clone());
return STOP_OP;
} else {
current_claim_status.current_node = next_node;
}

CONTINUE_OP
});

match run_result {
OperationCompletionStatus::InterruptedBeforeOutOfGas => {
self.save_progress(&current_claim_status);
}
OperationCompletionStatus::Completed => {
claim_status_mapper.update(|claim_status| {
claim_status.status = ClaimStatusType::Finished;
claim_status.last_claim_block = self.blockchain().get_block_nonce();
});
}
};
}
}
44 changes: 44 additions & 0 deletions liquid-staking/src/user_actions/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use crate::{delegation_proxy, StorageCache, ERROR_INSUFFICIENT_GAS};

multiversx_sc::imports!();

pub const MIN_GAS_FOR_CALLBACK: u64 = 12_000_000;
pub const MIN_GAS_FOR_ASYNC_CALL: u64 = 12_000_000;
pub const MIN_EGLD_TO_DELEGATE: u64 = 1_000_000_000_000_000_000;

#[multiversx_sc::module]
pub trait CommonModule:
crate::config::ConfigModule
+ crate::liquidity_pool::LiquidityPoolModule
+ multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule
{
// views
#[view(getLsValueForPosition)]
fn get_ls_value_for_position(&self, ls_token_amount: BigUint) -> BigUint {
let storage_cache = StorageCache::new(self);
self.get_egld_amount(&ls_token_amount, &storage_cache)
}

fn get_gas_for_async_call(&self) -> u64 {
let gas_left = self.blockchain().get_gas_left();
require!(
gas_left > MIN_GAS_FOR_ASYNC_CALL + MIN_GAS_FOR_CALLBACK,
ERROR_INSUFFICIENT_GAS
);

gas_left - MIN_GAS_FOR_CALLBACK
}

fn send_back_unbond_nft(&self, caller: &ManagedAddress, unstake_token_nonce: u64) {
let unstake_token_id = self.unstake_token().get_token_id();
self.send().direct_esdt(
caller,
&unstake_token_id,
unstake_token_nonce,
&BigUint::from(1u64),
)
}

#[proxy]
fn delegation_proxy_obj(&self) -> delegation_proxy::Proxy<Self::Api>;
}
77 changes: 77 additions & 0 deletions liquid-staking/src/user_actions/delegate_rewards.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use crate::{
delegation::ClaimStatusType, delegation_proxy::ProxyTrait as _, StorageCache,
ERROR_CLAIM_REDELEGATE, ERROR_NOT_ACTIVE,
};

multiversx_sc::imports!();

#[multiversx_sc::module]
pub trait DelegateRewardsModule:
crate::config::ConfigModule
+ crate::events::EventsModule
+ crate::delegation::DelegationModule
+ crate::liquidity_pool::LiquidityPoolModule
+ multiversx_sc_modules::ongoing_operation::OngoingOperationModule
+ multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule
+ super::common::CommonModule
{
#[endpoint(delegateRewards)]
fn delegate_rewards(&self) {
let mut storage_cache = StorageCache::new(self);
let claim_status = self.delegation_claim_status().get();
require!(
self.is_state_active(storage_cache.contract_state),
ERROR_NOT_ACTIVE
);
require!(
claim_status.status == ClaimStatusType::Delegable,
ERROR_CLAIM_REDELEGATE
);

let rewards_reserve = storage_cache.rewards_reserve.clone();
storage_cache.rewards_reserve = BigUint::zero();
let delegation_contract = self.get_delegation_contract_for_delegate(&rewards_reserve);
let gas_for_async_call = self.get_gas_for_async_call();

self.delegation_proxy_obj()
.contract(delegation_contract.clone())
.delegate()
.with_gas_limit(gas_for_async_call)
.with_egld_transfer(rewards_reserve.clone())
.async_call()
.with_callback(
DelegateRewardsModule::callbacks(self)
.delegate_rewards_callback(delegation_contract, rewards_reserve),
)
.call_and_exit()
}

#[callback]
fn delegate_rewards_callback(
&self,
delegation_contract: ManagedAddress,
staked_tokens: BigUint,
#[call_result] result: ManagedAsyncCallResult<()>,
) {
let mut storage_cache = StorageCache::new(self);
match result {
ManagedAsyncCallResult::Ok(()) => {
self.delegation_contract_data(&delegation_contract)
.update(|contract_data| {
contract_data.total_staked_from_ls_contract += &staked_tokens;
});

self.delegation_claim_status()
.update(|claim_status| claim_status.status = ClaimStatusType::Redelegated);

storage_cache.virtual_egld_reserve += &staked_tokens;
let sc_address = self.blockchain().get_sc_address();
self.emit_add_liquidity_event(&storage_cache, &sc_address, BigUint::zero());
}
ManagedAsyncCallResult::Err(_) => {
storage_cache.rewards_reserve = staked_tokens;
self.move_delegation_contract_to_back(delegation_contract);
}
}
}
}
7 changes: 7 additions & 0 deletions liquid-staking/src/user_actions/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub mod add_liquidity;
pub mod claim_rewards;
pub mod common;
pub mod delegate_rewards;
pub mod recompute_token_reserve;
pub mod remove_liquidity;
pub mod unbond;
61 changes: 61 additions & 0 deletions liquid-staking/src/user_actions/recompute_token_reserve.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use crate::{
delegation::ClaimStatusType, user_actions::common::MIN_EGLD_TO_DELEGATE, StorageCache,
ERROR_NOT_ACTIVE, ERROR_RECOMPUTE_RESERVES, ERROR_RECOMPUTE_TOO_SOON,
};

multiversx_sc::imports!();

pub const RECOMPUTE_BLOCK_OFFSET: u64 = 10;

#[multiversx_sc::module]
pub trait RecomputeTokenReserveModule:
crate::config::ConfigModule
+ crate::events::EventsModule
+ crate::delegation::DelegationModule
+ crate::liquidity_pool::LiquidityPoolModule
+ multiversx_sc_modules::ongoing_operation::OngoingOperationModule
+ multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule
+ super::common::CommonModule
{
#[endpoint(recomputeTokenReserve)]
fn recompute_token_reserve(&self) {
let mut storage_cache = StorageCache::new(self);
let claim_status_mapper = self.delegation_claim_status();
let mut claim_status = claim_status_mapper.get();

require!(
self.is_state_active(storage_cache.contract_state),
ERROR_NOT_ACTIVE
);
require!(
claim_status.status == ClaimStatusType::Finished,
ERROR_RECOMPUTE_RESERVES
);

let current_block = self.blockchain().get_block_nonce();
require!(
current_block >= claim_status.last_claim_block + RECOMPUTE_BLOCK_OFFSET,
ERROR_RECOMPUTE_TOO_SOON
);

let current_egld_balance = self
.blockchain()
.get_sc_balance(&EgldOrEsdtTokenIdentifier::egld(), 0);
if current_egld_balance
> &storage_cache.total_withdrawn_egld + &claim_status.starting_token_reserve
{
let rewards = &current_egld_balance
- &storage_cache.total_withdrawn_egld
- &claim_status.starting_token_reserve;
storage_cache.rewards_reserve += rewards;
}

if storage_cache.rewards_reserve >= MIN_EGLD_TO_DELEGATE {
claim_status.status = ClaimStatusType::Delegable;
} else {
claim_status.status = ClaimStatusType::Insufficient;
}

claim_status_mapper.set(claim_status);
}
}
Loading

0 comments on commit d5c52e5

Please sign in to comment.