RobinSplitVault is a UUPS-upgradeable ERC-4626 vault (rsvUSDC, asset USDC.e) that deploys deposits into equal YES+NO conditional-token pairs on a single manager-selected Polymarket market enrolled in Polymarket’s holder-rewards programme. The market must be a Conditional Tokens Framework (v1) market; the vault cannot hold Protocol V2 positions. A pair always merges back to exactly 1 USDC.e, so withdrawals are instant and at par. The staking vault supplies all merged USDC.e here; anyone else can deposit USDC.e directly.
Addresses are on the contracts overview.
Accounting
The vault only ever reads its own books, never live balances, when pricing shares:trackedAssets— net deposits plus every yield tranche recognized so far.totalAssets()—trackedAssetsminus the still-vesting remainder (unvestedProfit()). This is what ERC-4626 conversions use.pendingYield()— everything the vault holds abovetrackedAssets(PolyUSD at par, idle USDC.e, extra pairs). Invisible to the share price until the nextcompound().
compound() folds pending yield into a linear vesting schedule. A tranche vests over the period it accrued, clamped to [baseVestingDuration, 30 days] (base is 24h on mainnet, floor 8h); it is blended by amount with whatever is still vesting. Net effect: the share price never jumps, yield drips at roughly its earn rate, and neither a daily payout nor a compound backlog can be sniped by a short-lived deposit.
Share decimals are
12 (6 asset decimals + a virtual offset of 6). Yield is
only recognized while at least 1e12 shares (1 USDC.e at genesis price)
exist; below that it stays pending (YieldPending) rather than accruing to
virtual shares.Functions
Keeper: calling compound
compound() is permissionless and idempotent. Robin runs it daily after Polymarket’s payout; anyone may call it more often. If the offramp is paused the PolyUSD leg is skipped and UnwrapFailed is emitted — USDC.e and pair yield are still recognized, and the accrual clock stays frozen until an unwrap succeeds so the backlog cannot later drip faster than it was earned.
Direct deposits from a DepositWallet
Polymarket DepositWallets cannot callapprove, so they cannot use deposit directly. RobinPushDepositRouter is a stateless, unowned periphery for that case. Batch atomically:
USDC.e.transfer(router, assets)router.depositFor(splitVault, assets, wallet)— mintsrsvUSDCtowallet. Passtype(uint256).maxto use the router’s whole balance.
redeem with owner == msg.sender).
Events
Roles
Next steps
Capacity
The Split Vault’s headroom is the staking vault’s tier-2 deposit limit.
Architecture
How the staking vault routes merged USDC.e into the Split Vault.