Using a vault
Deposit USDG or a Stock Token
USDG enters through UptickRouter.depositUsdg, which swaps to the Stock Token at the Chainlink-implied value less a slippage bound, then deposits.
What depositUsdg does
UptickRouter.depositUsdg(vault, usdgIn, minShares, receiver) is the USDG on-ramp for a StockVault. It is nonReentrant and returns the shares minted. The router holds no balances and leaves no allowances behind after any call.
| Step | Rule |
|---|---|
| Gate | Reads vault.health() first and reverts Unhealthy unless the status is Ok. |
| Quote | impliedStock = usdgIn * 10^(stockDecimals + feedDecimals) / (price * 10^usdgDecimals), matching StockVault._usdgToStock exactly. |
| Swap floor | minStock = impliedStock * (10,000 - slippageBps) / 10,000. |
| Swap | Pulls usdgIn with safeTransferFrom, approves the swap router, and calls exactInputSingle on the vault's own pool fee, then resets the allowance to zero. |
| Deposit | Checks stockReceived against minStock (MinStockOut), approves the vault, calls vault.deposit(stockReceived, receiver), and resets the allowance. |
| Shares | Reverts InsufficientShares when the vault mints fewer shares than minShares. |
What the web app does
The deposit panel quotes before it asks you to sign. It divides your USDG amount by the live Chainlink price and keeps a 1% cushion for the swap, then asks the vault what those shares are worth with previewDeposit. That preview is the minShares you send, so a worse fill reverts instead of silently giving you fewer shares.
When your USDG allowance to the router is below the amount, the panel sends one approval transaction first. That signature moves nothing. The deposit follows as a second transaction: depositUsdg(vault, amount, minShares, receiver).
The panel also checks the vault's remaining room under its size cap and disables the button when the deposit would exceed it, when your balance is too small, or when the quote is not ready. A reduced vault caps a single deposit at $25,000, converted at the live Chainlink price.
Error cases
| Error | What it means |
|---|---|
| Unhealthy | The price feed is not fresh. Deposits pause until it updates. |
| InsufficientShares | The price moved past your quote. Try again. |
| MinStockOut | The pool sat far below the oracle at swap time. The router refuses rather than depositing at a bad price. |
| ZeroAmount | The deposit was zero. |
Read the quote
The same quote the panel uses is one contract read away: previewDeposit on the vault, with the stock amount you expect the swap to return.
const minShares = await client.readContract({
address: vault,
abi: vaultAbi,
functionName: "previewDeposit",
args: [estimatedStock],
});Sources
contracts/src/UptickRouter.soldepositUsdg, _usdgToStock, the slippage floor and the custom errors.
web/components/deposit-panel.tsxThe quote, the 1% cushion, minShares from previewDeposit and the error mapping.