Integrate with a pool

All position changes go through one entrypoint, which takes a list of requests and applies them in one transaction.

Submitting requests

fn submit(
    e: Env,
    from: Address,      // whose positions change
    spender: Address,   // who sends tokens to the pool
    to: Address,        // who receives tokens from the pool
    requests: Vec<Request>,
) -> Positions;

pub struct Request {
    pub request_type: u32,
    pub address: Address, // asset address, or the user being liquidated
    pub amount: i128,
}

submit_with_allowance takes the same arguments and uses transfer_from to collect tokens from spender.

Type Request address amount
0 Supply Asset Underlying tokens
1 Withdraw Asset Underlying tokens
2 Supply collateral Asset Underlying tokens
3 Withdraw collateral Asset Underlying tokens
4 Borrow Asset Underlying tokens
5 Repay Asset Underlying tokens
6 Fill user liquidation auction User being liquidated Percent to fill, 1 to 100
9 Delete liquidation auction Ignored, always your own auction Ignored

Types 7 and 8 are reserved for bad-debt and interest auction fills. Precept rejects them.

Reading state

Function Returns
get_config() Oracle, bstop_rate, status, max_positions, min_collateral
get_admin() Admin address
get_reserve_list() Reserve asset addresses, in index order
get_reserve(asset) The reserve's config and live data, including b_rate, d_rate, b_supply and d_supply
get_positions(address) An account's liabilities, collateral and supply, keyed by reserve index
get_auction(auction_type, user) An open auction's base terms. Only type 0 is supported

Position balances are in b-tokens and d-tokens, not underlying tokens. Multiply by b_rate or d_rate and divide by 10^12 to convert. Check decimals on each reserve rather than assuming 7.

Liquidating

fn new_auction(
    e: Env,
    auction_type: u32,   // must be 0, user liquidation
    user: Address,       // the position being liquidated
    bid: Vec<Address>,   // debts the filler will repay
    lot: Vec<Address>,   // collateral the filler will receive
    percent: u32,        // share of the position, 15 means 15%
) -> AuctionData;

Then fill with a type 6 request. A partial liquidation must leave the borrower between 1.03 and 1.15 health. Timing, pricing and stale-auction behaviour are covered in Liquidation auctions.

bad_debt(user) settles a position that has no collateral value left, and reverts while an auction is open for that user. del_auction(auction_type, user) removes an auction that is at least 500 blocks old. Anyone can call either one.

Entrypoints that always fail

These remain in the contract interface, but they are switched off:

  • Pool: flash_loan, update_pool, gulp_emissions, claim and the emission configuration functions.
  • Backstop: distribute, gulp_emissions, add_reward, remove_reward, claim and drop.

An integration that assumes rewards, flash loans or backstop-funded bad debt needs changing, even though the function names still resolve.

Handling prices

Prices have 7 decimals, and the pool refuses a price that is missing, dated in the future, more than 24 hours old or not positive. The proxy can apply a shorter limit per asset. A refused price makes the call fail rather than falling back to an old value, so handle InvalidPrice as an expected outcome. What stops when a price is stale lists which actions are affected.

Events to index

Beyond position and auction events, Precept emits loss events: debt_setoff, defaulted_debt, collateral_orphaned and orphan_settled. A lender-facing product should watch defaulted_debt, because it marks a drop in b_rate. See When there is nothing left to bid.