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:
Return Values
Return Obligation
public fun return_obligation( version: &Version, obligation: Obligation, obligation_hot_potato: ObligationHotPotato, ctx: &mut TxContext,) { }
Parameters:
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:
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:
Returns Value
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:
Events:
RepayEventV3 is emmited when transaction is success
Errors:
770: Means your current obligation is locked and need to unstake first from borrow incentive