Paboxo

Borrow shares and fees

How debt is recorded as shares, which way each conversion rounds, and the two fees on every borrow.

Supply has no shares — a market's supply is simply the Earn vault's claim, 1:1 in USDG (LendingPoolRouter). Debt does: each borrower holds borrow shares, and interest raises what every share is worth. The narrative is on how it works.

Minting shares on a borrow

smint={aTBS=0⌊a⋅TBSTBA⌋otherwisesmint=0⇒ZeroSharess_{\text{mint}} = \begin{cases} a & \text{TBS} = 0 \\[1mm] \left\lfloor \dfrac{a \cdot \text{TBS}}{\text{TBA}} \right\rfloor & \text{otherwise} \end{cases} \qquad s_{\text{mint}} = 0 \Rightarrow \texttt{ZeroShares}

Where:

  • aa — the amount borrowed, USDG base units.
  • TBA\text{TBA}, TBS\text{TBS} — totalBorrowAssets and totalBorrowShares after accrual.

Source: LendingPoolRouter. There are no virtual shares on the borrow side. Rounding down favours the borrower: their recorded debt can start up to one share's worth (TBA/TBS\text{TBA}/\text{TBS} base units) below aa, and that gap is carried by everyone else's shares. A borrow so small it would mint zero shares reverts.

Debt behind shares

d(s)=⌊s⋅TBATBS⌋d(s) = \left\lfloor \frac{s \cdot \text{TBA}}{\text{TBS}} \right\rfloor

This is what health checks value (IsHealthy · 0x9259…F9a1) and what a repayment of ss shares pulls (LendingPoolRouter) — rounded down, in the repayer's favour. A request for more shares than you hold is capped at your balance (LendingPoolRouter), so type(uint256).max repays everything and cannot be made to revert by someone repaying a share first; InsufficientShares fires only when you hold none.

Liquidation and bad debt round the other way, in the lenders' favour:

d↑(s)=min⁡(⌈s⋅TBATBS⌉, TBA)d_{\uparrow}(s) = \min\left(\left\lceil \frac{s \cdot \text{TBA}}{\text{TBS}} \right\rceil,\ \text{TBA}\right)

Source: LendingPoolRouter, LendingPoolRouter.

Fees

Every borrow pays two fees, taken out of what the borrower receives. The debt booked is the full amount.

fp=⌊a ϕp1018⌋,fc=⌊a ϕc1018⌋,received=a−fp−fc,debt booked=af_p = \left\lfloor \frac{a\,\phi_p}{10^{18}} \right\rfloor, \qquad f_c = \left\lfloor \frac{a\,\phi_c}{10^{18}} \right\rfloor, \qquad \text{received} = a - f_p - f_c, \qquad \text{debt booked} = a

Where:

  • ϕp\phi_p — the protocol fee, getProtocolFee(borrowToken). It is set per borrow token, not per market, and a stored 0 means 0.1% (1e15).
  • ϕc\phi_c — the creator fee, creatorFee(router), per market. A stored 0 means 0.01% (1e14). Live on every market: 1 (1e-18), which is off.

Source: LendingPoolRouter, LendingPoolRouter, LendingPoolFactory · 0x7a2b…b1C6; paid out in LendingPool.

Each fee is capped at MAX_BORROW_FEE = 10% (1e17) when set (LendingPoolFactory · 0x7a2b…b1C6, LendingPoolFactory · 0x7a2b…b1C6). And because a stored 0 restores the default, neither fee can be set to zero. To switch the creator fee off, the owner sets it to 1 instead (factory.setCreatorFee(router, 1)): 1 wei-WAD of any borrow under 10¹⁸ base units — a trillion USDG — floors to 0. The protocol fee goes to the factory's protocol() address, the creator fee to the market's creator. protocol() is a 2-of-4 Safe. The protocol fee is at its 0.1% default and the creator fee is 1 (off) on all three launch markets (read at block 86868761, and again at block 92690105), on all five at block 94915008, on MSFT/USDG and AAPL/USDG at block 99393260, and on QQQ/USDG, GOOGL/USDG and AMD/USDG at block 113204091.

Worked example: borrowing 1,000 USDG

In the illustrative market, before accrual: TBA=\text{TBA} = 20010000000, TBS=\text{TBS} = 20000000000.

Shares:

smint=⌊1000000000×2000000000020010000000⌋=999500249s_{\text{mint}} = \left\lfloor \frac{1000000000 \times 20000000000}{20010000000} \right\rfloor = 999500249

After the borrow, TBA=\text{TBA} = 21010000000 and TBS=\text{TBS} = 20999500249. Those 999,500,249 shares are worth 999999999 (999.999999 USDG) rounded down and 1000000000 (1,000.000000 USDG) rounded up — the borrower's recorded debt starts one base unit below what they borrowed.

Fees:

RawUSDG
Borrowed, debt booked aa10000000001,000.000000
Protocol fee fpf_p (0.1%)10000001.000000
Creator fee fcf_c (ϕc=1\phi_c = 1, off)00.000000
Received999000000999.000000

So the borrower walks away with 999.00 USDG and owes 1,000 — an effective upfront cost of 0.10% before any interest. Health and LTV are checked against the full 1,000 of debt, not the 999.00 received. (At the creator fee's 0.01% default, a stored 0, fcf_c would be 100000 and the borrower would receive 998.90.)

(In practice the borrow accrues first, so TBA\text{TBA} would include the pending 9.117741 USDG of interest from accrual and the share count would be slightly lower. The arithmetic is the same.)

On this page