Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Satoshi Lending Protocol Workflow

This document outlines the high-level workflows and terminology for the Satoshi Lending protocol.

Terminology

TermDefinition
CollateralAny non-USDC asset deposited to secure a loan.
LendersUsers who supply assets to the pool to earn interest.
BorrowersUsers who provide collateral to take loans from the pool.
LTV (Loan to Value)A metric used to assess the health of a borrower’s position. Formula: total_borrow_value.div(total_collateral_value)
Insurance Allocation Rate(Also known as Reserve Factor) The percentage of the liquidation penalty diverted to the protocol’s Insurance Fund.
Liquidation PenaltyThe amount deducted and sent to the liquidation account when a liquidation occurs.

System Assumptions & Constraints

  • Asset Types:
    • Lending and borrowing are restricted to USDC.
    • Collateral deposits are restricted to non-USDC assets.
  • Contracts:
    • There is a single USDC contract for deposits.
    • There are currently three non-USDC contracts for collateral deposits.
    • The Near intents contract is used exclusively for liquidation.
  • Account Roles: A single account cannot function as both a lender and a borrower simultaneously.

Workflows

Lender Actions

Lending (Supply)

Involves the deposit of USDC into the protocol by a lender.

Unlending (Withdraw)

The withdrawal of principal USDC along with any accrued interest by the lender.

Borrower Actions

Collateral Deposit

A borrower deposits non-USDC assets to enable borrowing of USDC.

Repay

The repayment of borrowed USDC along with accrued interest by the borrower.

Withdraw Collateral

The withdrawal of deposited collateral by the borrower.

Borrow

The act of borrowing USDC from the protocol, secured by the deposited collateral.

Parameters of the protocol

This document outlines the key configurable parameters of the LendingProtocol. These values are critical for managing risk and defining the economic model of the protocol.

Interest Rate Model Parameters

These parameters define the interest rate model for USDC borrowing. The borrow rate is calculated based on the utilization of available liquidity.

usdc_base_borrow_rate

  • Description: The base borrow rate for USDC, representing the minimum annual percentage rate (APR) when there are zero borrows (0% utilization).

usdc_rate_multiplier

  • Description: A multiplier that determines how steeply the borrow rate increases as the utilization ratio increases. The formula is: borrow_rate = usdc_base_borrow_rate + (utilization_ratio * usdc_rate_multiplier).

Liquidation Parameters

These parameters govern the process of liquidation for undercollateralized loans.

liquidation_penalty

  • Description: The percentage fee applied to the value of collateral seized during a liquidation event. This penalty covers potential losses.

insurance_allocation_rate

  • Description: The portion of the liquidation_penalty that is allocated to the protocol’s insurance fund. The remaining portion of the penalty is paid to the liquidator as a fee.

Loan-to-Value (LTV) Ratio Parameters

LTV ratios are fundamental risk parameters that determine how much can be borrowed against collateral and when a position is considered risky.

Formula: total_borrow_value.div(total_collateral_value)

borrow_threshold

  • Description: The maximum Loan-to-Value (LTV) ratio for initiating a new borrow. For example, a value of 0.75 means a user can borrow up to 75% of their collateral’s value.

withdraw_threshold

  • Description: The maximum Loan-to-Value (LTV) ratio permitted after a collateral withdrawal. This prevents users from withdrawing collateral if it would leave their position undercollateralized. It is often set to the same value as `borrow_threshold

liquidation_threshold

  • Description: The Loan-to-Value (LTV) ratio at which a user’s position becomes eligible for liquidation. This value must be higher than the borrow_threshold to provide a safety buffer for borrowers.

Oracle Parameters

oracle_price_staleness_secs

  • Description: The maximum age (in seconds) of an asset price from an oracle before it is considered stale and no longer valid for protocol operations. This is a critical safety feature to prevent acting on outdated price information.

Off-Chain Liquidation Process

Introduction

This document outlines the off-chain liquidation process for the protocol. It details the interaction between a liquidation bot and the smart contracts to manage under-collateralized loans, ensuring the solvency of the protocol by efficiently liquidating risky positions.

Core Principles and Assumptions

  • Immutable Process: Once a position is marked for liquidation, the process will complete, regardless of any subsequent price movements that might improve the user’s Loan-to-Value (LTV) ratio.
  • Account Lock: While a user’s position is being liquidated, they cannot perform any other actions like depositing, withdrawing, or borrowing.
  • Full Liquidation: The entire position, including all types of collateral, is liquidated.
  • Socialized Loss (v1): In the initial version, the protocol does not use an insurance fund. Any bad debt resulting from a liquidation is socialized among lenders by adjusting the supply index. This is v1 requirement arising from the PRD.

Data Structure Changes

To support the liquidation process, the following changes are made to the smart contract’s state.

The main contract state is updated with:

#![allow(unused)]
fn main() {
    /// Account designated to handle collateral swaps.
    pub liquidator_account: AccountId,
    /// State of any ongoing liquidation.
    pub liquidation: Option<LiquidationInfo>,
	/// Tracks pending liquidations
    pub pending_liquidations: Vector<UserId>
}

The InFlightOperation enum is extended to include liquidation states:

#![allow(unused)]
fn main() {
pub enum InFlightOperation {
    Borrowing,
    WithdrawingUsdc,
    WithdrawingCollateral,
    Liquidation
	LiquidationFinal(Usdc)
}
}

A new LiquidationInfo struct tracks the state of an ongoing liquidation:

#![allow(unused)]
fn main() {
#[derive(Debug, Clone, PartialEq, Default)]
pub struct LiquidationInfo {
    /// The user whose position is being liquidated.
    pub user: UserId,
    /// The current state of the liquidation process.
    pub liquidation_state: LiquidationState,
}
}

The LiquidationState enum tracks the sub-steps within the collateral transfer phase:

#![allow(unused)]
fn main() {
pub enum LiquidationState {
    #[default]
    MarkedForLiquidation,
    OngoingTransfer,
    TransferSuccess,
    TransferFailure(Vec<CollateralContract>),
}
}

Swap and Hold Account

The protocol uses a “Swap and Hold Account” during the liquidation process. This is a standard NEAR Account ID and does not require any special smart contract code.

This account is used to store the user’s collateral in an intents contract, which facilitates the swap from the collateral asset to USDC.

End-to-End Liquidation Flow

The liquidation process is a multi-stage operation orchestrated by an off-chain bot interacting with the main smart contract.

Stage 1: Position Flagging

  1. Monitor LTV: The bot continuously monitors each user’s LTV ratio off-chain.
  2. Initiate Liquidation: If a user’s LTV exceeds the liquidation threshold, the bot calls liquidate_position(user_id) on the smart contract. This function marks the user for liquidation, records their current borrow value, and locks their account from further operations.

Stage 2: Collateral Transfer

  1. Iterate and Transfer: The smart contract initiates all collateral transfers at once. The bot calls perform_transfer_for_liquidation(contracts: Option<Vec<CollateralContract>>) to initiate it..
  2. On-Chain Transfer: This contract call initiates an async transfer of the specified collateral from the protocol to the designated liquidator_account. The contract updates the state to OngoingTransfer.
  3. Handle Callbacks: The contract handles the async transfer’s callback:
    • On success, the state is updated to TransferSuccess.
    • On failure, the state is updated to TransferFailure with the collateral info, signaling the bot to retry the transfer for that specific asset.

Stage 3: Asset Swapping (Off-Chain)

  1. Swap to USDC: Once the collateral is in the liquidator_account, the bot uses an external service (e.g., 1Click API) to swap each collateral asset for USDC.
  2. Hold Funds: The resulting USDC is temporarily held in a “Swap & Hold” contract controlled by the liquidator.

Stage 4: USDC Repatriation

  1. Transfer Back: After all collateral has been swapped, the bot triggers a transfer of the total accumulated USDC from the “Swap & Hold” contract back to the main protocol contract.
  2. Record Value: The main contract recognizes the incoming transfer is from the liquidator_account and records the amount in the swapped_collateral_value field of the user’s LiquidationInfo.

Stage 5: Finalizing Liquidation

  1. Finalize: With the USDC returned, the bot calls finalize_liquidation().
  2. Settle Account: This function performs the final accounting: it repays the user’s debt, calculates and distributes liquidation fees, and handles any surplus or deficit. The user’s account is then unlocked.

Smart Contract Interface

liquidate_account(user_id)

Marks a user’s position for liquidation.

  • Authorization: Can only be called by a permissioned liquidator bot account.
  • Checks: Verifies that the user’s position is indeed eligible for liquidation based on their LTV.
  • Actions:
    • Creates a LiquidationInfo struct for the user.
    • Sets liquidation_state to MarkedForLiquidation.
    • Stores the user’s current borrow value.
    • Sets the user’s in_flight_operation to Liquidation, preventing other actions.

transfer_collateral_for_liquidation(ft_contract)

Transfers a specific collateral asset from the user’s position to the liquidator_account.

  • Authorization: Callable by any account, allowing for permissionless retries.
  • Pre-conditions:
    • The user must be in a liquidation state (MarkedForLiquidation or TransferFailure).
    • If the state is TransferFailure(failed_contract), the ft_contract parameter must match failed_contract.
    • The user must have a balance of the specified collateral (ft_contract).
  • Actions:
    • Initiates an async transfer of the user’s full balance of ft_contract to the liquidator_account.
    • Sets the liquidation_state to OngoingTransfer(ft_contract).
    • The callback updates the state to TransferSuccess or TransferFailure based on the outcome.

finalize_liquidation()

Settles the user’s account after collateral has been swapped and USDC has been returned to the contract.

  • Authorization: Callable by any account, allowing for permissionless retries.
  • Pre-conditions:
    • Asserts that all of the user’s collateral has been transferred out (collateral balances are zero).
    • Asserts that swapped_collateral_value is greater than zero.
  • Actions:
    • Repay Debt: The user’s borrowed shares are deducted from the protocol’s total.
    • Calculate Fees: A liquidation penalty is calculated from swapped_collatal_value and split into liquidator and protocol fees.
    • Calculate Final Balance: net_collateral = swapped_collateral_value - liquidator_fee - protocol_fee final_balance = net_collateral - user_borrow_value
  • Settlement:
    • Surplus (final_balance > 0): Fees are paid, and the remaining surplus is sent to the liquidated user.
    • Bad Debt (final_balance < 0): Fees are paid from the swapped collateral. The shortfall is socialized among lenders by reducing the supply index.
  • Cleanup: The user’s in_flight_operation is cleared and the LiquidationInfo is removed.

Security Considerations

  • A 1 yoctoNEAR deposit should be required for these calls to prevent call-based attacks (see NEAR documentation).

System Architecture

Introduction

This document provides a high-level overview of the Satoshi Lending Protocol’s architecture. For terminology and general workflow definitions, please refer to the Workflow Document.

Core Infrastructure

Oracle and Price Feeds

We utilize the Pyth Oracle to obtain real-time price information for collateral assets. Accurate price data is critical for the following operations:

  • Borrowing
  • Withdrawing collateral
  • Liquidation

Note: User operations (and bots during liquidation) accept optional price data to update collateral prices before execution. Providing this data is highly recommended to prevent transaction failures due to stale prices.

Intents Contract

  • Purpose: Exclusively handles asset swaps during the liquidation process.
  • Interaction: The frontend should not interact with the Intents contract directly.

Frontend Workflows

This section details the interaction flows between the user/frontend and the smart contracts.

General Requirements

  • Security Deposit: Most state-changing methods require attaching 1 yoctoNEAR as a security deposit.
  • Storage Balance: Before interacting, ensure the user has a sufficient storage_balance registered on the relevant contract (Satoshi contract or Fungible Token contract).

1. Deposit (Lending & Collateral)

Deposits of USDC (lending) and non-USDC assets (collateral) are initiated directly via the Fungible Token (FT) contract.

Workflow:

  1. Check Storage: Verify the user has a valid storage_balance on the Satoshi contract. If not, prompt the user to call storage_deposit.
  2. Verify Registration: Confirm the user is registered.
  3. External Deposit: User issues a deposit transaction on the deposit address of the external (non-Near) blockchain.
  4. Poll Transaction: The system polls the external transaction until it is confirmed successful. This is a two-step process: you have to poll that the external transaction succeeds, and poll that the bridging action occurs on the Near side. However, OmniBridge may provide a single endpoint to query for both.
  5. Contract Deposit: Once the external transaction is confirmed, the user initiates the deposit to the Satoshi contract.
  6. Update UI: Poll the transaction about it’s status and if was success/failure.

2. Unlending (Withdraw USDC)

Lenders can withdraw their USDC principal and accrued interest directly to their Near account.

Workflow:

  1. Check Storage: Verify the user has a valid storage_balance on the USDC Fungible Token contract. Register if necessary.
  2. Execute Withdraw: Invoke the withdrawal method on the Satoshi contract (attach 1 yocto).
  3. Handle Result: Parse the transaction result (success or failure, e.g., insufficient liquidity) and display it to the user.

3. Borrow USDC / Withdraw Collateral

Borrowers can withdraw borrowed USDC or their deposited collateral.

Key Considerations:

  • Price Freshness: It is mandatory to submit off-chain hex-encoded Pyth price feed data with the transaction. Failure to do so can cause the transaction to fail.
  • Price Update: All price feeds for all collateral assets must be updated during this transaction.

Workflow:

  1. Check Storage: Verify the user has a valid storage_balance on the destination Fungible Token contract. Register if necessary.
  2. Execute Transaction: Invoke the borrow or withdraw collateral method on the Satoshi contract (attach 1 yocto).
  3. Handle Result: Parse the transaction result and display it to the user.

4. Repay Loan

Borrowers can repay borrowed USDC plus accrued interest.

Key Considerations:

  • Overpayment Strategy: The frontend should perform a slight overpayment. Since interest compounds continuously and the exact transaction timestamp is unknown, this ensures the entire debt is covered.
  • Excess Refund: Any excess USDC provided beyond the actual debt amount is automatically returned to the borrower.

Workflow:

  1. Execute Repay: Invoke the repayment method on the Satoshi contract (attach 1 yocto).
  2. Handle Result: Parse the transaction result and display it to the user.

Off-Chain Services

Bot

The bot handles automated maintenance tasks for the protocol. Responsibilities:

  • Monitoring: Track Near token balance of Liquidation bot and raise alerts if they fall below a defined threshold.
  • Simulation & Marking: Perform off-chain simulations to identify and “mark” unhealthy positions. This involves calculating:
    • Total Borrow Value: Adjusted for continuously accruing interest.
    • Total Collateral Value: Based on the latest real-time Pyth price information.
  • Liquidation: Execute liquidation on marked users, including passing the necessary off-chain Pyth price data.

Querier

Status: Pending input. (Responsibilities to be defined)

Indexer

Status: Pending input. (Responsibilities to be defined)

Indexer REST API

Status: Pending input. (Responsibilities to be defined)

Integration & Porting Guide

This document outlines the steps required to port the frontend from the old architecture to the new smart contract system.

Goals & Scope

The primary goal is to reach a functional state suitable for audit. The frontend must support the following workflows:

  1. User Actions:
    • USDC Deposit
    • Collateral Deposit
    • Borrow USDC
    • Withdraw USDC
    • Withdraw Collateral
    • Repayment of USDC
  2. State Display:
    • Show current protocol state information.

Core Smart Contract Methods

To retrieve data, you will primarily interact with two view-only methods. It is essential to understand the data structures they return.

1. get_config

Returns ContractConfigView, which contains protocol configuration parameters.

#![allow(unused)]
fn main() {
pub struct ContractConfigView {
    pub owner_id: AccountId,
    pub liquidation_threshold: Decimal,
    pub borrow_threshold: Decimal,
    pub withdraw_threshold: Decimal,
    pub liquidation_penalty: Decimal,
    pub pyth_oracle_contract: AccountId,
    pub usdc_base_borrow_rate: Decimal,
    pub usdc_rate_multiplier: Decimal,
    pub insurance_allocation_rate: Decimal,
    pub liquidator_account: AccountId,
    pub intents_contract: AccountId,
    pub oracle_price_staleness_secs: u64,
    pub supported_collaterals: HashMap<CollateralContract, CollateralMetadata>,
    pub supported_usdc_token: Option<UsdcTokenView>,
    pub pyth_required_deposit: NearToken,
}
}

2. get_contract_state

Returns ContractState, which contains the dynamic state of the protocol (liquidity, shares, indexes, etc.).

#![allow(unused)]
fn main() {
pub struct ContractState {
    /// Protocol's cash-on-hand (available for withdrawal/borrowing).
    pub usdc_liquidity: Usdc,
    pub collateral_liquidity: IterableMap<CollateralContract, RawAmount>,
    /// Total lending shares for USDC.
    pub total_supplied_usdc_shares: LendingShare,
    /// Total borrow shares for USDC.
    pub total_borrowed_usdc_shares: BorrowShare,
    /// User data
    pub users: near_sdk::store::IterableMap<UserId, User>,
    /// Index to track interest accrued for USDC suppliers.
    /// User supply balance = `supplied_usdc_shares` * `usdc_supply_index`.
    pub usdc_supply_index: LendingIndex,
    /// Index to track interest accrued on USDC borrows.
    /// User borrow balance = `borrowed_usdc_shares` * `usdc_borrow_index`.
    pub usdc_borrow_index: BorrowIndex,
    /// Timestamp of the last interest accrual.
    pub last_interest_accrual_timestamp: Timestamp,
    /// Protocol's accumulated bad debt in USDC.
    pub bad_debt_usdc: Usdc,
    /// Protocol's insurance fund.
    pub insurance_fund: Usdc,
    /// Oracle Prices.
    pub prices: LookupMap<UsdPythIdentifier, PythPrice>,
    /// State of any ongoing liquidation.
    pub liquidation: Option<LiquidationInfo>,
    /// Tracks pending liquidations.
    pub pending_liquidations: Vector<UserId>,
    /// Unpaid fees to be paid to the liquidator.
    pub unpaid_liquidator_fee: Usdc,
    /// Unpaid surplus amounts to be transferred to users after liquidation.
    pub pending_surplus_transfers: LookupMap<UserId, Usdc>,
    /// The number of users registered with the contract.
    pub user_count: u64,
}
}

3. get_user(user_id: UserId)

Returns the User struct, containing specific data for a single user.

#![allow(unused)]
fn main() {
pub struct User {
    // Amounts of non-USDC collateral.
    pub collateral: HashMap<CollateralContract, RawAmount>,
    // User's position in the USDC market (supplier, borrower, or neither).
    pub usdc_position: UsdcPosition,
    // The current in-flight operation for this user, if any.
    pub in_flight_operation: Option<InFlightOperation>,
    /// Storage balance
    pub storage_balance: NearToken,
}

pub enum UsdcPosition {
    #[default]
    None,
    Supplied(LendingShare),
    Borrowed(BorrowShare),
}
}

Backend API Migration (Indexer & Querier)

This section maps old backend endpoints to the new logic using ContractState and ContractConfigView.

Summary Table

Old QueryEndpointNew Logic Summary
transactionsQuery/transactions/account/{accountId}Deferred to V2 (Indexer API).
indexerTotalBorrowedQuery/borrows/total_borrowedtotal_borrowed_usdc_shares * usdc_borrow_index
indexerTotalFeesQuery/fees/total/interest_and_penaltiesinsurance_fund + Liquidator Account Balance
indexerAccountsQuery/accountsuser_count
indexerProtocolLtvQuery/dashboard/ltvTotal Borrowed / Total Collateral Value
indexerTokenCollateralQuery/dashboard/token_collateralSum of all collateral values (USD).
indexerTotalStablecoinDepositedQuery/token_transfers/stablecoin/total_depositedusdc_liquidity
indexerTotalCollateralDepositedQuery/token_transfers/collateral/total_depositedSame as indexerTokenCollateralQuery.
querierUtilizationRatioQuery/utilization_ratioTotal Borrowed / Total Supplied
querierLendableQuery/lendableusdc_liquidity

Detailed Porting Guide

indexerTotalBorrowedQuery

Represents the total USDC lent out by the protocol.

  • Source: ContractState
  • Formula: total_borrowed_usdc_shares * usdc_borrow_index

indexerTotalFeesQuery

Represents total liquidator and insurance fees collected.

  • Source: ContractState (for insurance fund) & ContractConfigView (for liquidator account ID).
  • Formula: insurance_fund + (USDC balance of liquidator_account)

indexerAccountsQuery

Total number of registered users.

  • Source: ContractState
  • Formula: user_count

indexerProtocolLtvQuery

Protocol Loan-to-Value ratio.

  • Formula: Total Borrowed Value / Total Collateral Value
    • Total Borrowed Value: See indexerTotalBorrowedQuery.
    • Total Collateral Value:
      1. Get collateral_liquidity from ContractState.
      2. Fetch USD prices using Hermes.
      3. Normalize amounts based on token decimals.
      4. Sum: (Amount * USD Price) for all collateral types.

indexerTokenCollateralQuery & indexerTotalCollateralDepositedQuery

Total collateral present in the protocol (in USD).

  • Formula: Same calculation as Total Collateral Value in indexerProtocolLtvQuery.

indexerTotalStablecoinDepositedQuery

Total USDC present in the protocol.

  • Source: ContractState
  • Formula: usdc_liquidity

querierUtilizationRatioQuery

  • Source: ContractState
  • Formula: Total Borrowed / Total Supplied
    • Total Borrowed: total_borrowed_usdc_shares * usdc_borrow_index
    • Total Supplied: total_supplied_usdc_shares * usdc_supply_index

querierLendableQuery

Available USDC for lending.

  • Source: ContractState
  • Formula: usdc_liquidity

Contract View Query Migration

This section maps old smart contract view methods to the new logic.

Summary Table

Old QueryOld MethodNew Logic Summary
spBalanceOfCollateralQuerybalance_of_collateralUser.collateral (converted to USD).
spBalanceOfBorrowQuerybalance_of_borrowUser.usdc_position (Borrowed) * usdc_borrow_index.
spGetUserUnlentQueryget_user_unlentUser.usdc_position (Supplied) * usdc_supply_index.
spGetUserLentQueryget_user_lentDeprecated. (All deposits are now fully lent/supplied).
spGetBorrowThresholdQueryget_borrow_thresholdContractConfigView.borrow_threshold.
spGetWithdrawThresholdQueryget_withdraw_thresholdContractConfigView.withdraw_threshold.
spGetLiquidationThresholdQueryget_liquidation_thresholdContractConfigView.liquidation_threshold.
spGetLiquidationWarningThresholdQueryget_liquidation_warning_thresholdDeprecated. Hardcode in frontend.
spGetMaximumWithdrawableQueryget_maximum_withdrawableClient-side calculation (Collateral - Borrowed/Threshold).
spGetCollateralValueQueryget_collateral_valueUser.collateral * Prices.
spCalculateLtvQuerycalculate_ltvUser Borrowed Value / User Collateral Value.
spGetAccumulatedInterestQueryget_accumulated_interestDeferred to V2 Indexer.
spGetAnnualPercentageRateQueryget_annual_percentage_rateContractConfigView.usdc_base_borrow_rate.
spGetAnnualPercentageYieldQueryget_annual_percentage_yieldNot Applicable.
spGetMinimumBorrowableQueryget_smaller_operations_amountHardcode in frontend.
spGetMaximumBorrowableAmountQuerycomposedBorrowing Power - Current Borrow Value.
spBalanceOfAllMainCollateralsQuerycomposedAggregate User.collateral values.
spIsAccountAtRiskQueryis_account_at_riskClient-side check: Current LTV > Hardcoded Limit.
spGetAccountPendingLiquidationNotificationsQueryDeprecated.

Detailed Integration Guide

spBalanceOfCollateralQuery

Represents the collateral deposited by a User.

  • Source: User struct (collateral field).
  • Logic: Iterate through the map. Use Hermes API to convert amounts to USD if total value is needed.

spBalanceOfBorrowQuery

Represents the amount borrowed by a User (including accrued interest).

  • Source: User struct (usdc_position) & ContractState (usdc_borrow_index).
  • Formula:
    • If usdc_position is Borrowed(shares): shares * usdc_borrow_index.

spGetUserUnlentQuery

Represents the total USDC supplied by the lender that can be withdrawn.

  • Source: User struct (usdc_position) & ContractState (usdc_supply_index).
  • Formula:
    • If usdc_position is Supplied(shares): shares * usdc_supply_index.

spGetBorrowThresholdQuery, spGetWithdrawThresholdQuery, spGetLiquidationThresholdQuery

  • Source: ContractConfigView fields:
    • borrow_threshold
    • withdraw_threshold
    • liquidation_threshold

spGetMaximumWithdrawableQuery

Maximum amount (USDC) that can be withdrawn. Do note that this is an approximation of the maximum appoint since the current price fluctuating and interest also gets accumulated as seconds pass.

  • Logic (USDC):
    1. Fetch Pyth/Hermes data.
    2. Perform client-side interest accrual (refer to Liquidator bot implementation for logic).
    3. Calculate total supplied balance (like spGetUserUnlentQuery).
  • Logic (Collateral - returned in USDC value):
    1. Fetch Pyth/Hermes data.
    2. Perform client-side interest accrual.
    3. Compute Total Borrow Value of user.
    4. Compute Total Collateral Value of user.
    5. Formula: Total Collateral Value - (Total Borrow Value / withdraw_threshold)

spGetMaximumBorrowableAmountQuery

Maximum additional amount that can be borrowed.

  • Formula: Borrowing Power - Current Borrow Value
    • Borrowing Power: Total Collateral Value * borrow_threshold
    • Current Borrow Value: User Borrow Shares * Borrow Index

spGetAnnualPercentageRateQuery

Borrow rate at zero utilization.

  • Source: ContractConfigView.usdc_base_borrow_rate

User Actions (Transactions)

These are the write operations performed by the user.

Deposit

  1. USDC: Use ft_transfer_call on the USDC token contract, passing the protocol contract as the receiver.
  2. Collateral: Use ft_transfer_call on the specific collateral token contract.

Withdraw

  1. USDC: Call withdraw_usdc on the protocol contract.
  2. Collateral: Call withdraw_collateral on the protocol contract.

Borrow USDC

Call borrow_usdc on the protocol contract.

Repay USDC

Send USDC using ft_transfer_call on the USDC token contract to the protocol contract. The contract will automatically interpret this as a repayment.