1ī¸Lending Core

The core entry of NAVI Protocol.

As a developer, your primary interactions with the NAVI Protocol will take place through the functions within the lending_core::incentive_v3 module. This module serves as the entry point for all write transactions, including deposits, withdrawals, borrowing, repayment, liquidations, and reward claims

Entry Functions

entry_deposit

This function allows a user to deposit a specified amount of a given coin type into a lending pool. The deposit amount is added to the pool's balance, and a deposit event is emitted.

public entry fun entry_deposit<CoinType>(
        clock: &Clock,
        storage: &mut Storage,
        pool: &mut Pool<CoinType>,
        asset: u8,
        deposit_coin: Coin<CoinType>,
        amount: u64,
        incentive_v2: &mut IncentiveV2,
        incentive_v3: &mut Incentive,
        ctx: &mut TxContext
    ) {}

example: https://suivision.xyz/txblock/246vdcrCLakVtHYzdv9Zgq61ahCBBCwgvtWCGCN6gpPw

entry_withdraw

This function allows a user to withdraw a specified amount from a lending pool. The withdrawal amount is deducted from the pool's balance, and a withdrawal event is emitted.

public entry fun entry_withdraw<CoinType>(
        clock: &Clock,
        oracle: &PriceOracle,
        storage: &mut Storage,
        pool: &mut Pool<CoinType>,
        asset: u8,
        amount: u64,
        incentive_v2: &mut IncentiveV2,
        incentive_v3: &mut Incentive,
        ctx: &mut TxContext
    ) {}

example: https://suivision.xyz/txblock/3o5hDDxtbw3iVxJu68C7Nnyhh5AWXiq5G4T3yWcz8XKV

entry_borrow

This function allows a user to borrow a specified amount from a lending pool. The borrowed amount is deducted from the pool's balance, and a borrow event is emitted.

public entry fun entry_borrow<CoinType>(
        clock: &Clock,
        oracle: &PriceOracle,
        storage: &mut Storage,
        pool: &mut Pool<CoinType>,
        asset: u8,
        amount: u64,
        incentive_v2: &mut IncentiveV2,
        incentive_v3: &mut Incentive,
        ctx: &mut TxContext
    ) {}

example: https://suivision.xyz/txblock/446CTVPAmvYFJjrWhLKigKDArQqgcd3xCfFCzURiTXMa

entry_repay

This function allows a user to repay a specified loan amount. The repayment amount is added to the pool's balance, and a repay event is emitted.

public entry fun entry_repay<CoinType>(
  clock: &Clock,
  oracle: &PriceOracle,
  storage: &mut Storage,
  pool: &mut Pool<CoinType>,
  asset: u8,
  repay_coin: Coin<CoinType>,
  amount: u64,
  incentive_v2: &mut IncentiveV2,
  incentive_v3: &mut Incentive,
  ctx: &mut TxContext
) {}

example: https://suivision.xyz/txblock/2TqWyBRoxRAk1t3Qq5yeHA7XrCaN7Dy8yXtwPeFPXv33

claim_reward_entry

This function allows users to claim rewards in a specified reward coin. Rewards are distributed from the bonus pool and a claim reward event is emitted.

public entry fun claim_reward_entry<RewardCoinType>(
clock: &Clock, 
incentive: &mut Incentive,
storage: &mut Storage, 
reward_fund: &mut RewardFund<RewardCoinType>,
coin_types: vector<String>,
rule_ids: vector<address>,
ctx: &mut TxContext
) {}

example: https://suivision.xyz/txblock/7JY13rhuhTDLLZJbpfRfoMrdJFwGySRrWCgESCodAFND

entry_liquidation

This function is used to liquidate a loan when a borrower's collateral is insufficient to cover their debt. The liquidation process repays the debt, returning any excess amount to the sender. A liquidation call event is emitted.

public entry fun entry_liquidation<DebtCoinType, CollateralCoinType>(
        clock: &Clock,
        oracle: &PriceOracle,
        storage: &mut Storage,
        debt_asset: u8,
        debt_pool: &mut Pool<DebtCoinType>,
        debt_coin: Coin<DebtCoinType>,
        collateral_asset: u8,
        collateral_pool: &mut Pool<CollateralCoinType>,
        liquidate_user: address,
        liquidate_amount: u64,
        incentive_v2: &mut IncentiveV2,
        incentive_v3: &mut Incentive,
        ctx: &mut TxContext
    ) {}

Non-entry Functions

deposit_with_account_cap

This function is similar to a standard deposit but includes an account cap limitation. The deposit amount is added to the pool's balance, and a deposit event is emitted.

public fun deposit_with_account_cap<T>(
clock: &Clock, 
storage: &mut Storage,
pool: &mut Pool<T>, 
asset: u8,
deposit_coin: Coin<CoinType>,
incentive_v2: &mut IncentiveV2,
incentive_v3: &mut Incentive,
account_cap: &AccountCap
) {}

withdraw

This function allows other contracts to withdraw a specified amount from a lending pool. The balance object is returned, and a withdrawal event is emitted.

public fun withdraw<CoinType>(
        clock: &Clock,
        oracle: &PriceOracle,
        storage: &mut Storage,
        pool: &mut Pool<CoinType>,
        asset: u8,
        amount: u64,
        incentive_v2: &mut IncentiveV2,
        incentive_v3: &mut Incentive,
        ctx: &mut TxContext
    ): Balance<CoinType> {}

withdraw_with_account_cap

This function is similar to a standard withdraw but includes an account cap limitation. The balance object is returned, and a withdrawal event is emitted.

public fun withdraw_with_account_cap<CoinType>(
        clock: &Clock,
        oracle: &PriceOracle,
        storage: &mut Storage,
        pool: &mut Pool<CoinType>,
        asset: u8,
        amount: u64,
        incentive_v2: &mut IncentiveV2,
        incentive_v3: &mut Incentive,
        account_cap: &AccountCap
    ): Balance<CoinType> {}

borrow

This function allows other contracts to borrow a specified amount from a lending pool. The balance object is returned, and a borrow event is emitted.

public fun borrow<CoinType>(
        clock: &Clock,
        oracle: &PriceOracle,
        storage: &mut Storage,
        pool: &mut Pool<CoinType>,
        asset: u8,
        amount: u64,
        incentive_v2: &mut IncentiveV2,
        incentive_v3: &mut Incentive,
        ctx: &mut TxContext
    ): Balance<CoinType> {}

borrow_with_account_cap

This function is similar to a standard borrow but includes an account cap limitation. The balance object is returned, and the borrow event is emitted.

public fun borrow_with_account_cap<CoinType>(
        clock: &Clock,
        oracle: &PriceOracle,
        storage: &mut Storage,
        pool: &mut Pool<CoinType>,
        asset: u8,
        amount: u64,
        incentive_v2: &mut IncentiveV2,
        incentive_v3: &mut Incentive,
        account_cap: &AccountCap
    ): Balance<CoinType> {}

repay

This function allows other contracts to repay a specified amount of a loan. The balance object is returned, and a repay event is emitted.

public fun repay<CoinType>(
        clock: &Clock,
        oracle: &PriceOracle,
        storage: &mut Storage,
        pool: &mut Pool<CoinType>,
        asset: u8,
        repay_coin: Coin<CoinType>,
        amount: u64,
        incentive_v2: &mut IncentiveV2,
        incentive_v3: &mut Incentive,
        ctx: &mut TxContext
    ): Balance<CoinType> {}

repay_with_account_cap

This function is similar to a standard repay but includes an account cap limitation. The balance object is returned, and a repay event is emitted.

public fun repay_with_account_cap<CoinType>(
        clock: &Clock,
        oracle: &PriceOracle,
        storage: &mut Storage,
        pool: &mut Pool<CoinType>,
        asset: u8,
        repay_coin: Coin<CoinType>,
        amount: u64,
        incentive_v2: &mut IncentiveV2,
        incentive_v3: &mut Incentive,
        account_cap: &AccountCap
    ): Balance<CoinType> {}

claim_reward

Quick Reward Claiming Using the SDK

We recommend using the SDK to claim rewards because the SDK will automatically claim all available rewards and perform off-chain indexing to optimize gas usage.

SDK Benefits:

  • Off-chain indexing: Retrieves relevant rules without incurring on-chain gas costs.

  • Optimized filtering: Selects only the necessary rule IDs before executing on-chain transactions.

For users who want to implement customized and native reward claiming, we provide the following instructions:

Step-by-Step Process

  1. Retrieve Claimable Rewards

  • Use get_user_claimable_rewards to fetch claimable reward information.

  • Parse the response using parse_claimable_rewardsto determine RewardCoinType, coin_types, and rule_ids

get_user_claimable_rewards

This function retrieves the claimable rewards for a user, returning detailed reward information.

struct ClaimableReward has copy, drop {
    asset_coin_type: String,
    reward_coin_type: String,
    user_claimable_reward: u256,
    user_claimed_reward: u256,
    rule_ids: vector<address>,
}

public fun get_user_claimable_rewards<RewardCoinType>(
    clock: &Clock, 
    storage: &mut Storage, 
    incentive: &mut Incentive,
    user: address
) vector<ClaimableReward> {}

parse_claimable_rewards

This function parses the claimable rewards to return the asset coin types, reward coin types, user total rewards, user claimed rewards, and rule ids.

public fun parse_claimable_rewards(claimable_rewards: vector<ClaimableReward>)
(
    vector<String>, // asset coin types
    vector<String>, // reward coin types
    vector<u256>,   // user total rewards
    vector<u256>,   // user claimed rewards
    vector<vector<address>> // rule ids
)
  • The coin_types are derived from the asset tokens involved.

  • The rule_ids are extracted from the parsed claimable rewards.

  1. Execute

// Reward Fund IDs
VSUI: 0x7093cf7549d5e5b35bfde2177223d1050f71655c7f676a5e610ee70eb4d93b5c
NAVX: 0x1a3f9fcfdfac10e92c99220203f7c4bb502558692f0be0f2cb5f788b4e12a6b5
SUINS: 0xc6b14b4eda9015ca69ec5f6a9688faa4f760259ce285dafe902ebe6700f5838f
DEEP: 0xc889d78b634f954979e80e622a2ae0fece824c0f6d9590044378a2563035f32f
FDUSD: 0x958dd7ad70755b10f96693bcd591d7a2cb9830a6c523baf43b3b5897664aa788

claim_reward

public entry fun claim_reward<RewardCoinType>(
    clock: &Clock, 
    incentive: &mut Incentive,
    storage: &mut Storage, 
    reward_fund: &mut RewardFund<RewardCoinType>,
    coin_types: vector<String>,
    rule_ids: vector<address>,
    ctx: &mut TxContext
) {}

claim_reward_with_account_cap

This function is similar to a standard claim rewards but includes an account cap limitation. Rewards are distributed from the bonus pool, and a claim reward event is emitted.

public fun claim_reward_with_account_cap<RewardCoinType>(
clock: &Clock, 
incentive: &mut Incentive,
storage: &mut Storage, 
reward_fund: &mut RewardFund<RewardCoinType>,
coin_types: vector<String>,
rule_ids: vector<address>,
account_cap: &AccountCap) Balance<RewardCoinType> {}
  • Sample: Provide the appropriate parameters:

// To claim rewards, we need to gather the same reward coin types
// and then pass the corresponding asset coin types and rule IDs.
// The expected function call should look like this:
claim_reward<VSUI>(
    ...,  // Additional parameters (e.g., clock, incentive, storage, etc.)
    coin_types: <SUI, SUI, BLUE, BLUE>,  // Expand asset types to match rule mappings
    rule_ids: <rule1, rule2, rule3, rule4>  // Flattened list of rule IDs
);

let user_a_rewards = incentive_v3::get_user_claimable_rewards(
    &clock,           
    &mut storage,     
    &mut incentive,   
    USER_A            
);
​
// Parse the retrieved claimable rewards into structured vectors
let (
    asset_coin_types,       // List of asset coin types
    reward_coin_types,      // List of corresponding reward coin types
    user_claimable_rewards, // Total claimable rewards per asset
    user_claimed_rewards,   // Already claimed rewards per asset
    rule_ids                // Associated rule IDs for each asset
) = incentive_v3::parse_claimable_rewards(user_a_rewards);
// Parse the retrieved claimable rewards into structured vectors
// Example output structure after parsing:
// (
//   <SUI, BLUE>,         // Unique asset coin types
//   <VSUI, VSUI>,        // Corresponding reward coin types
//   <claimable1, claimable2>, // Claimable rewards amounts
//   <claimed1, claimed2>, // Already claimed amounts
//   <<rule1, rule2>, <rule3, rule4>> // Rule IDs grouped by asset type
// )

Full Claim Contract Demo

use lending_core::incentive_v3::{Self, Incentive as IncentiveV3, RewardFund};
use lending_core::storage::Storage;
use std::ascii::String;
use std::type_name;
use std::vector;
use sui::balance::{Balance};
use sui::coin::{Self};
use sui::clock::{Clock};
use sui::transfer::{Self};
use sui::tx_context::{Self, TxContext};

/// This function is used to claim reward with one coin type
/// It runs fully onchain without offchain indexing.
/// This practice is not gas optimized, and claiming reward though SDK with is recommended.
/// Params objectIds will be available on the gitbook.
    public fun claim_reward<RewardCoinType>(
        clock: &Clock,
        incentive: &mut IncentiveV3,
        storage: &mut Storage,
        reward_fund: &mut RewardFund<RewardCoinType>,
        ctx: &mut TxContext,
    ): Balance<RewardCoinType> {
        let (
            asset_coin_types,
            reward_coin_types,
            user_total_rewards,
            user_claimed_rewards,
            rule_ids,
        ) = incentive_v3::parse_claimable_rewards(
            incentive_v3::get_user_claimable_rewards(
                clock,
                storage,
                incentive,
                tx_context::sender(ctx),
            ),
        );

        let target_coin_type = &type_name::into_string(type_name::get<RewardCoinType>());

        let input_coin_types = vector::empty<String>();
        let input_rule_ids = vector::empty<address>();

        let i = 0;
        while (i < vector::length(&asset_coin_types)) {
            let asset_coin_type = vector::borrow(&asset_coin_types, i);
            let reward_coin_type = vector::borrow(&reward_coin_types, i);
            let user_total_reward = *vector::borrow(&user_total_rewards, i);
            let user_claimed_reward = *vector::borrow(&user_claimed_rewards, i);
            let rule_id = vector::borrow(&rule_ids, i);

            if (user_total_reward > user_claimed_reward && reward_coin_type == target_coin_type) {
                vector::push_back(&mut input_coin_types, *asset_coin_type);
                vector::append(&mut input_rule_ids, *rule_id);
            };

            i = i + 1;
        };

        incentive_v3::claim_reward<RewardCoinType>(
            clock,
            incentive,
            storage,
            reward_fund,
            input_coin_types,
            input_rule_ids,
            ctx,
        )
    }

    public entry fun claim_reward_entry<RewardCoinType>(
        clock: &Clock,
        incentive: &mut IncentiveV3,
        storage: &mut Storage,
        reward_fund: &mut RewardFund<RewardCoinType>,
        recipient: address,
        ctx: &mut TxContext,
    ) {
        let (
            asset_coin_types,
            reward_coin_types,
            user_total_rewards,
            user_claimed_rewards,
            rule_ids,
        ) = incentive_v3::parse_claimable_rewards(
            incentive_v3::get_user_claimable_rewards(
                clock,
                storage,
                incentive,
                tx_context::sender(ctx),
            ),
        );

        let target_coin_type = &type_name::into_string(type_name::get<RewardCoinType>());

        let input_coin_types = vector::empty<String>();
        let input_rule_ids = vector::empty<address>();

        let i = 0;
        while (i < vector::length(&asset_coin_types)) {
            let asset_coin_type = vector::borrow(&asset_coin_types, i);
            let reward_coin_type = vector::borrow(&reward_coin_types, i);
            let user_total_reward = *vector::borrow(&user_total_rewards, i);
            let user_claimed_reward = *vector::borrow(&user_claimed_rewards, i);
            let rule_id = vector::borrow(&rule_ids, i);

            if (user_total_reward > user_claimed_reward && reward_coin_type == target_coin_type) {
                vector::push_back(&mut input_coin_types, *asset_coin_type);
                vector::append(&mut input_rule_ids, *rule_id);
            };

            i = i + 1;
        };

        let balance = incentive_v3::claim_reward<RewardCoinType>(
            clock,
            incentive,
            storage,
            reward_fund,
            input_coin_types,
            input_rule_ids,
            ctx,
        );

        transfer::public_transfer(coin::from_balance(balance, ctx), recipient)
    }

example: https://suivision.xyz/txblock/5Nr7nkQg8GGLepEPVRmZ2CamkUgsSoNMqDyhNGbVqjjW

Last updated