Borrowing Function
Obligation
Before doing any borrowing related action, you need to have Obligation
object. Obligation
is an object to record your collateral and debt. So you need to create at least one to do any related borrowing action.
Each obligation isn’t related to another, so depositing collateral in one obligation doesn’t meant you can borrow an asset using another obligation - even you are the owner of both obligations.
Let’s learn how to create Obligation
object:
Open Obligation
public fun open_obligation(
version: &Version,
ctx: &mut TxContext,
): (Obligation, ObligationKey, ObligationHotPotato) { }
Parameters:
Name
Type
Description
version
Version
The version control object, contract version must match with this
Return Values
Obligation
Obligation
The obligation object which will be shared
Obligation Key
ObligationKey
This is an owned object that serves as proof of ownership of the obligation object.
ObligationHotPotato
ObligationHotPotato
Because open_obligation function used HotPotato pattern which this pattern is make it composable.
Return Obligation
public fun return_obligation(
version: &Version,
obligation: Obligation,
obligation_hot_potato: ObligationHotPotato,
ctx: &mut TxContext,
) { }
Parameters:
Name
Type
Description
version
Version
The version control object, contract version must match with this
obligation
Obligation
The obligation object created by open_obligation
.
obligation_hot_potato
ObligationHotPotato
HotPotato object generated by open_obligation
.
Example:
module protocol::foo {
use sui::coin::{Self, Coin};
use sui::clock::{Self, Clock};
use sui::tx_context::{Self ,TxContext};
use sui::transfer;
use scallop_protocol::obligation::open_obligation;
use scallop_protocol::obligation::return_obligation;
use scallop_protocol::Market as ScallopMarket;
use scallop_protocol::Version as ScallopVersion;
...
public fun doFoo(
scallop_version: &ScallopVersion,
clock: &Clock,
ctx: &mut TxContext
) {
let (obligation_id, obligation_key, obligation_hot_potato) = scallop_protocol::obligation::open_obligation(
scallop_version,
scallop_market,
coin,
clock,
ctx,
);
// ----------------
// Do other tx here
// ----------------
scallop_protocol::obligation::return_obligation(
scallop_version,
obligation_id,
obligation_hot_potato
);
transfer::transfer(obligation_key, ctx.sender());
}
}
Now, you are ready to do any borrowing related actions with your Obligation.
To be able to borrow, you need to have collateral. Let’s learn how to deposit collateral.
Collateral
Deposit Collateral
Allows deposit collateral to your obligation account. This function allow anyone to deposit collateral into other user obligation account. Why everyone can do it? Because this is fine if someone doing it for you. You will not loss anything if someone does it for you. So we open it for everyone.
public fun deposit_collateral<T>(
version: &Version,
obligation: &mut Obligation,
coin: Coin<T>,
ctx: &mut TxContext,
) { }
Parameters:
Name
Type
Description
version
Version
The version control object, contract version must match with this
obligation
Obligation
The id of obligation, it should be shared object.
coin
Coin
The base asset to be deposit to the collateral pool
Events:
CollateralDepositEvent is emmited when the collateral deposit tx success
Errors:
770: Means your current obligation is locked and need to unstake first from borrow incentive
73730: Means current collateral is not active yet.
1794: Invalid collateral type.
1796: Unable to deposited borrowed coin because the depositor try to deposit same asset as depositor borrowed.
Example:
module protocol::foo {
use sui::coin::{Self, Coin};
use sui::clock::{Self, Clock};
use sui::tx_context::{Self ,TxContext};
use sui::transfer;
use scallop_protocol::obligation::open_obligation;
use scallop_protocol::obligation::return_obligation;
use scallop_protocol::deposit_collateral::deposit_collateral;
use scallop_protocol::Market as ScallopMarket;
use scallop_protocol::Version as ScallopVersion;
use scallop_protocol::obligation::{Self, Obligation};
public fun doFoo<T>(
scallop_version: &ScallopVersion,
obligation: &mut Obligation,
coin: Coin<T>,
ctx: &mut TxContext
) {
let deposit_amount = coin::value(&coin);
let (obligation_id, obligation_key, obligation_hot_potato) = scallop_protocol::obligation::open_obligation(
scallop_version,
scallop_market,
coin,
clock,
ctx,
);
// ----------------
// Do other tx here
scallop_protocol::deposit_collateral::deposit_collateral(
scallop_version,
obligation_id,
deposit_amount,
ctx,
);
// ----------------
scallop_protocol::obligation::return_obligation(
scallop_version,
obligation_id,
obligation_hot_potato
);
transfer::transfer(obligation_key, ctx.sender());
}
}
Withdraw Collateral
Unlike depositing collateral, withdrawing collateral requires the ObligationKey
object, which is an owned object. This means that only the owner of the obligation account can withdraw collateral; another address cannot withdraw collateral from an obligation account it does not own.
public fun withdraw_collateral<T>(
version: &Version,
obligation: &mut Obligation,
obligation_key: &ObligationKey,
market: &mut Market,
coin_decimals_registry: &CoinDecimalsRegistry,
withdraw_amount: u64,
x_oracle: &XOracle,
clock: &Clock,
ctx: &mut TxContext,
): Coin<T> { }
Parameters:
Name
Type
Description
version
Version
The version control object, contract version must match with this
obligation
Obligation
The id of obligation, it should be shared object.
obligation_key
ObligationKey
The key to prove the ownership of the obligation
market
Market
The Scallop market object, it contains base assets, and related protocol configs
coin_decimal_registry
CoinDecimalsRegistry
The package that has decimal coin of base assets.
withdraw_amount
u64
The amount assets will withdraw from pool
x_orcale
XOracle
The x-oracle object which provides the price of assets
clock
Clock
The SUI system clock object
Return Value:
Coin
Coin
The withdrawed underlying asset
Events
CollateralWithdrawEvent is emmited when transaction success
Errors
770: Means your current obligation is locked and need to unstake first from borrow incentive
0: Not owner of obligation
1795: Withdraw collateral to much
Example
module protocol::foo {
use sui::coin::{Self, Coin};
use sui::clock::{Self, Clock};
use sui::tx_context::{Self ,TxContext};
use sui::transfer;
use scallop_protocol::withdraw_collateral::withdraw_collateral;
use scallop_protocol::Market as ScallopMarket;
use scallop_protocol::Version as ScallopVersion;
use scallop_protocol::obligation::{Self, Obligation, ObligationKey};
use scallop_protocol::coin_decimals_registry::CoinDecimalsRegistry;
use scallop_protocol::x_oracle::XOracle;
...
public fun doFoo<T>(
version: &ScallopVersion,
obligation: &mut Obligation,
obligation_key: &ObligationKey,
market: &mut ScallopMarket,
coin_decimals_registry: &CoinDecimalsRegistry,
withdraw_amount: u64,
x_oracle: &XOracle,
clock: &Clock,
ctx: &mut TxContext
) {
let withdrawed_coin = scallop_protocol::withdraw_collateral::withdraw_collateral(
scallop_version,
obligation_id,
obligation_key,
market,
coin_decimals_registry,
withdraw_amount,
x_oracle,
clock,
ctx,
);
transfer::transfer(withdrawed_coin, ctx.sender());
}
}
Check here the example how to do update price x_oracle
:
https://github.com/scallop-io/sui-scallop-sdk/blob/main/src/builders/oracle.ts
We recommend you to call this function using our Scallop SDK, so before calling any function related to withdraw Collateral, you need to call update price in the beginning of the PTB (Programmable Transaction Block).
Here what your PTB should looks like:
PTB for calling function that have withdraw collateral:
- update price (you get this from SDK)
- your function that call withdraw_collateral
Borrowing
Borrow
Allow user to borrow assets from borrowing pools againts collateral deposited by user.
public fun borrow<T>(
version: &Version,
obligation: &mut Obligation,
obligation_key: &ObligationKey,
market: &mut Market,
coin_decimals_registry: &CoinDecimalsRegistry,
borrow_amount: u64,
x_oracle: &XOracle,
clock: &Clock,
ctx: &mut TxContext,
): Coin<T> { }
Parameters:
version
Version
The version control object, contract version must match with this
obligation
Obligation
The id of obligation, it should be shared object.
obligation_key
ObligationKey
The key to prove the ownership of the obligation
market
Market
The Scallop market object, it contains base assets, and related protocol configs
coin_decimals_registry
CoinDecimalsRegistry
The package that has decimal coin of base assets.
borrow_amount
u64
The amount assets will borrow from pool
x_oracle
XOracle
The x-oracle object which provides the price of assets
clock
Clock
The SUI system clock object
Returns Value
coin
Coin
The borrowed underlying asset
Events:
BorrowEventV3 is emmited when transaction is success
Errors:
770: Means your current obligation is locked and need to unstake first from borrow incentive
0: Not owner of obligation
1284: Means unable to borrow a collateral coin
1282: Borrow to small
1281: Borrow to much
81924: Reserve not enough
Example:
module protocol::foo {
use sui::coin::{Self, Coin};
use sui::clock::{Self, Clock};
use sui::tx_context::{Self ,TxContext};
use sui::transfer;
use scallop_protocol::borrow::borrow;
use scallop_protocol::Market as ScallopMarket;
use scallop_protocol::Version as ScallopVersion;
use scallop_protocol::obligation::{Self, Obligation, ObligationKey};
use scallop_protocol::coin_decimals_registry::CoinDecimalsRegistry;
use scallop_protocol::x_oracle::XOracle;
...
public fun doFoo<T>(
version: &ScallopVersion,
obligation: &mut Obligation,
obligation_key: &ObligationKey,
market: &mut ScallopMarket,
coin_decimals_registry: &CoinDecimalsRegistry,
borrow_amount: u64,
x_oracle: &XOracle,
clock: &Clock,
ctx: &mut TxContext
) {
let borrowed_coin = scallop_protocol::borrow::borrow(
scallop_version,
obligation_id,
obligation_key,
market,
coin_decimals_registry,
borrow_amount,
x_oracle,
clock,
ctx,
);
transfer::transfer(borrowed_coin, ctx.sender());
}
}
Check here the example how to do update price x_oracle
:
https://github.com/scallop-io/sui-scallop-sdk/blob/main/src/builders/oracle.ts
We recommend you to call this function using our Scallop SDK, so before calling any function related to borrow, you need to call update price in the beginning of the PTB (Programmable Transaction Block).
Here what your PTB should looks like:
PTB for calling function that have borrow:
- update price (you get this from SDK)
- your function that call borrow
Repay
Enabled user to repay underlying assets without requiring the ObligationKey object. Therefore, users can repay the borrowing obligation using any account, not just the obligation owner’s account.
public entry fun repay<T>(
version: &Version,
obligation: &mut Obligation,
market: &mut Market,
user_coin: Coin<T>,
clock: &Clock,
ctx: &mut TxContext,
) { }
Parameters:
version
Version
The version control object, contract version must match with this
obligation
Obligation
The id of obligation, it should be shared object.
market
Market
The Scallop market object, it contains base assets, and related protocol configs
user_coin
Coin
The coin object used to repay borrowed underlying asset
clock
Clock
The SUI system clock object
Events:
RepayEventV3 is emmited when transaction is success
Errors:
770: Means your current obligation is locked and need to unstake first from borrow incentive
Example:
module protocol::foo {
use sui::coin::{Self, Coin};
use sui::clock::{Self, Clock};
use sui::tx_context::{Self ,TxContext};
use sui::transfer;
use scallop_protocol::repay::repay;
use scallop_protocol::Market as ScallopMarket;
use scallop_protocol::Version as ScallopVersion;
use scallop_protocol::obligation::{Self, Obligation};
use scallop_protocol::coin_decimals_registry::CoinDecimalsRegistry;
public fun doFoo<T>(
version: &ScallopVersion,
obligation: &mut Obligation,
market: &mut ScallopMarket,
user_coin: Coin<T>,
clock: &Clock,
ctx: &mut TxContext
) {
scallop_protocol::repay::repay(
scallop_version,
obligation_id,
market,
user_coin,
clock,
ctx,
);
}
}
Last updated
Was this helpful?