Uptick

Connect a wallet

Uptick reads your balance and asks you to sign each transaction. It never holds your keys.

Docs ยท Deposit USDG or a Stock Token

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.

StepRule
GateReads vault.health() first and reverts Unhealthy unless the status is Ok.
QuoteimpliedStock = usdgIn * 10^(stockDecimals + feedDecimals) / (price * 10^usdgDecimals), matching StockVault._usdgToStock exactly.
Swap floorminStock = impliedStock * (10,000 - slippageBps) / 10,000.
SwapPulls usdgIn with safeTransferFrom, approves the swap router, and calls exactInputSingle on the vault's own pool fee, then resets the allowance to zero.
DepositChecks stockReceived against minStock (MinStockOut), approves the vault, calls vault.deposit(stockReceived, receiver), and resets the allowance.
SharesReverts InsufficientShares when the vault mints fewer shares than minShares.
The router refuses the swap when the oracle gate is not Ok, before any token moves.

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

ErrorWhat it means
UnhealthyThe price feed is not fresh. Deposits pause until it updates.
InsufficientSharesThe price moved past your quote. Try again.
MinStockOutThe pool sat far below the oracle at swap time. The router refuses rather than depositing at a bad price.
ZeroAmountThe deposit was zero.
The panel names the two errors a depositor can act on and shows the router's message for the rest.

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.

TypeScript, viem
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.