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.
It’s possible to have multiple obligation.
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.
Understanding Obligation
Obligation is a shared object, instead of owning Obligation object in your wallet - you will hold an ObligationKey in your wallet. This ObligationKey is a proof you own a particularObligation that connected to this ObligationKey. So what you will see in your wallet is an NFT of ObligationKey.
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
Name
Type
Description
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 .
You might be wondering why we implement the HotPotato pattern in the open_obligation function. The reason is that the Obligation is a shared object. If we directly return the object, it will be shared, and we won’t be able to combine this transaction with another function for borrowing in a single PTB (Programmable Transaction Block).
By using this methodology, we can combine the open obligation transaction with a deposit collateral transaction in one PTB. Also to make the Obligation shared, we also need to include the return_obligation function to transaction to make the Obligation object become shared.
import { getFullnodeUrl, SuiClient, } from'@mysten/sui.js/client';import { SUI_CLOCK_OBJECT_ID } from'@mysten/sui.js/utils';import { Ed25519Keypair } from'@mysten/sui/keypairs/ed25519';constkeypair=newEd25519Keypair();constaddress=keypair.getPublicKey().toSuiAddress();constrpcUrl=getFullnodeUrl('mainnet');constclient=newSuiClient({ url: rpcUrl });constSCALLOP_MARKET_OBJECT="0xa757975255146dc9686aa823b7838b507f315d704f428cbadad2f4ea061939d9";constSCALLOP_VERSION_OBJECT="0x07871c4b3c847a0f674510d4978d5cf6f960452795e8ff6f189fd2088a3f6ac7";consttxb=newTransactionBlock();txb.setSender();const [obligationId,obligationKey,obligationHotPotato] =txb.moveCall({ target:"0xa45b8ffca59e5b44ec7c04481a04cb620b0e07b2b183527bca4e5f32372c5f1a::obligation::open_obligation", arguments: [txb.object(SCALLOP_VERSION_OBJECT), ], typeArguments: [],});// You can do another stuff here before return the obligation// Example like deposit collateral then borrowtxb.moveCall({ target:"0xa45b8ffca59e5b44ec7c04481a04cb620b0e07b2b183527bca4e5f32372c5f1a::obligation::open_obligation", arguments: [txb.object(SCALLOP_VERSION_OBJECT), obligationId, obligationHotPotato ], typeArguments: []});txb.transferObjects([obligationKey],txb.pure(address));awaitclient.signAndExecuteTransaction({ signer:getKeyPair(keypair), transaction: txb, requestType:'WaitForLocalExecution', options: { showEffects:true, },});
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.
See how composable Sui is—you can execute two transactions with just one approval. We'll explore more examples of Sui's composability in programmable transaction blocks (PTBs) within the Scallop protocol.
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.
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:&mutObligation, obligation_key:&ObligationKey, market:&mutMarket, coin_decimals_registry:&CoinDecimalsRegistry, borrow_amount:u64, x_oracle:&XOracle, clock:&Clock, ctx:&mutTxContext,):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_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
Name
Type
Description
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
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:&mutObligation, market:&mutMarket, user_coin:Coin<T>, clock:&Clock, ctx:&mutTxContext,) { }
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.
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