The full protocol surface — vault, stable, oracle, account factory — verified on the Robinhood Chain explorer. Every function, every event, every storage slot is below. Audits and source are linked next to each address.
Custodies pledged equity tokens, mints USDG against them, enforces LTV bands, and exposes the public liquidate() entrypoint. All accounting denominated in 1e18 USD.
| Signature | Description | Access |
|---|---|---|
| pledgeAndBorrow(address token, uint256 amount, uint256 borrowUsd) | Locks `amount` of `token` as collateral and mints `borrowUsd` of USDG to msg.sender in a single transaction. Reverts ExceedsLtv if LTV cap breached. | EXTERNAL |
| liquidate(address user, address token, uint256 debtUsdToRepay) | Repays up to 50% of `user`'s debt with caller's USDG, seizes `debtUsdToRepay × 1.05` worth of `token` to caller. Reverts PositionHealthy if HF ≥ 1. | EXTERNAL |
| repay(uint256 amountUsd) | Burns `amountUsd` USDG from msg.sender and decrements their debt. Use `repayMax()` to settle in full. | EXTERNAL |
| withdraw(address token, uint256 amount) | Unpledges collateral. Reverts if withdrawal would push HF below 1. | EXTERNAL |
| register(uint256 amount) · withdrawLp(uint256 shares) | LP deposit and redemption. Tokenized as ERC-4626 shares against pooled USDG plus accrued borrow yield. | EXTERNAL |
| positionOf(address user) → (collateralUsd, borrowedUsd, health) | Aggregated read used by all UI components. `health` is scaled 1e18 (1e18 = HF 1.000). | VIEW |
| healthFactor(address user) → uint256 | Same as positionOf().health. Returns type(uint256).max for zero-debt accounts. | VIEW |
| setBorrowRateBps(uint256 newRate) | Adjusts the protocol borrow APY in basis points. Caps at 5000 bps (50%). | OWNER |
| setReserveFactorBps(uint256 newBps) | Portion of borrow interest routed to protocolReserves. Default 1000 bps. | OWNER |
| claimReserves(uint256 amountUsd) | Transfers accrued reserves to the configured treasury address. | OWNER |
| Slot | Layout | Notes |
|---|---|---|
| 0 | mapping(address => Position) | Per-user collateral (per token) and outstanding USDG debt. |
| 1 | mapping(address => Asset) | Per-token LTV / liqThreshold / staleAfter / priceFeed. |
| 2 | address[] | listedAssets enumeration. |
| 3 | uint256 | totalBorrowedUsd (1e18). |
| 4 | uint256 | borrowRateBps (current APR). |
| 5 | uint256 + uint256 | reserveFactorBps + protocolReserves. |
| 6 | address | treasury sink for reserves. |
Initial vault + USDGStable + Pyth adapter pinned to Robinhood Chain Testnet. 8 stock feeds listed.
Vault becomes a yield vault: register() / withdrawLp() / sharePriceUsd added. Borrow-rate accrual moved to per-block.
First batch of EIP-7702 delegations enabled. Pledge flow drops from 3 popups to 1.
reserveFactorBps and protocolReserves accounting introduced. setTreasury() guarded behind 72h timelock.
Two fixes shipped: ExceedsLtv now reverts before token pull; liquidator close-factor capped at 50% on-chain.
PythPriceAdapter switched to lastObservation() fallback. Vault default borrow rate adjusted to 4.50% APR.
All state lives here. pledgeAndBorrow() is the canonical entry. Read its preconditions before anything else.
USDGStable.mint() is unreachable except via the vault. Grep mint() to confirm — there is exactly one call site.
Every quote is bounded by staleAfter. Liquidators must call updateAndPriceUsd() to refresh before claiming.
The protocol works with plain EOAs. EquiSmartAccountFactory exists so the UI can bundle approve + pledge into one signature.