Skip to main content

Bonder Contract

Handles bonding of OP20 assets and LP tokens for discounted SLOHM.

Storage

// Bond info per user
bondPayout: AddressMemoryMap // SLOHM owed
bondVesting: AddressMemoryMap // Blocks remaining
bondLastBlock: AddressMemoryMap // Last interaction

// Global
totalDebt: StoredU256 // Outstanding unvested SLOHM
bcv: StoredU256 // Bond Control Variable
vestingBlocks: StoredU256 // Default: 720 blocks
lpCaps: AddressMemoryMap // Max bondable per LP

Key Methods

bond(asset, amount, maxPrice)

function bond(asset, amount, maxPrice): void {
// Verify asset is approved
require(treasury.isApproved(asset));

// Check LP cap if applicable
if (isLP(asset)) {
require(lpBonded[asset] + amount <= lpCaps[asset]);
}

// Pull asset to treasury
asset.transferFrom(sender, treasury, amount);

// Calculate value and discount
const value = isLP(asset) ? calculateRFV(asset, amount) : getAssetValue(asset, amount);
const price = value × (1 + debtRatio × BCV);
require(price <= maxPrice, "Slippage");

// Calculate and record payout
const payout = value / price;
bonds[sender].payout += payout;
bonds[sender].vesting = vestingBlocks;
totalDebt += payout;
}

claim()

function claim(): void {
// Calculate vested amount
const elapsed = block.number - bond.lastBlock;
const percentVested = elapsed / bond.vesting;
const payout = bond.payout × percentVested;

// Mint vested SLOHM
Treasury.mintForBond(sender, payout);

// Update records
bond.payout -= payout;
totalDebt -= payout;
}

RFV Calculation

function calculateRFV(lp, amount): u256 {
const (reserve0, reserve1) = pool.getReserves();
const totalLP = lp.totalSupply();
// RFV = 2 × sqrt(reserve0 × reserve1) × (amount / totalLP)
return 2 × sqrt(reserve0 × reserve1) × amount / totalLP;
}

View Functions

  • pendingPayout(user) - Total SLOHM owed
  • claimable(user) - Vested SLOHM available
  • bondPrice(asset) - Current bond price