1.000000
+0.00%
WonVault · TKRW share price · GIWA Sepolia 91342
§ 1

Why ERC-4626

The Ethereum tokenized-vault standard. Any wallet, aggregator, or yield router integrates with zero custom code.
Interface guarantees

ERC-4626 defines a complete bidirectional interface: deposit, withdraw, mint, redeem plus the accounting helpers convertToAssets, convertToShares, totalAssets, totalSupply. Any party that speaks ERC-4626 reads WonVault correctly without a custom adapter.

Our implementation extends OpenZeppelin v5's ERC4626, meaning the share-minting, asset-transfer, and accounting invariants ship from a thoroughly-audited library base — not hand-rolled math. The share-price mechanism is the yield mechanism: see §3.

Decimal offset override: we set _decimalsOffset() = 18, which inflates the virtual share supply by 1 × 10¹⁸ and adds a corresponding virtual asset unit. This neutralizes the first-depositor inflation attack (the exact bug that produced our 1.09 × 10²¹ share price on an earlier testnet build). The full security argument is in §5.

§ 2

Entry-fee schedule & calculator

Fee tier is read live from DojangScore.feeTierOf(user) at deposit time. Higher trust = lower friction.
Tier Basis points Entry fee % Source condition
PlatinumPlatinum 50 bps 0.50 % DojangScore ≥ 800
GoldGold 100 bps 1.00 % Score 500 – 799
SilverSilver 150 bps 1.50 % Score 200 – 499
StandardStandard 200 bps 2.00 % Score < 200
// on-chain deposit math (Solidity)
fee = floor(assets × bps / 10000);
net = assets − fee;
// OZ library: transferFrom(msg.sender, vault, net) then mint shares
shares = super.deposit(net, receiver);
// fee routes to treasury (separate transferFrom)
Interactive fee calculator
Tier Fee (TKRW) Net deposited Shares minted
PlatinumPlatinum 5.00 995.00 995.000
GoldGold 10.00 990.00 990.000
SilverSilver 15.00 985.00 985.000
StandardStandard 20.00 980.00 980.000
On a 1000 TKRW deposit — Platinum keeps 15.00 TKRW more at work than Standard.
§ 3

Strategy accrual — the engine

No new shares are minted when yield arrives. Assets grow; shares stay fixed; every share redeems for more.
// conceptual share price
sharePrice = totalAssets / totalSupply

// with _decimalsOffset()=18 (virtual units included)
sharePrice = (assets + 1) / (shares + 1018)

// yield = assets growing, shares constant → price rises
Interactive accrual simulator
New share price
1.025000
Position value (Platinum shares)
1020.13
P&L vs. entry
+20.13 TKRW
Harvest return (single period)
2.50%
Annualized APY
—
Harvests / year
Honest framing: The 6.00% APY shown in the live app is the target spec realized by the real mainnet strategy's harvest cadence. The testnet "▶ Run strategy tick" button deliberately injects ~2.5% per click so the accrual engine is visually legible on camera during a judge demo. These are two different things; neither is fabricated.
§ 4 · roadmap

Fee stack beyond entry

V2 adds management and performance fees. Labeled roadmap; not in the deployed testnet contract.
V2 — not yet deployed

Management fee: 1.00%/yr accrued continuously into the share price via a virtual assets increase per block — no discrete event, no depositor action required.

Performance fee: 15% of realized yield taken at each harvest and minted as shares to treasury (dilutive-by-design, per Yearn/Morpho standard).

perfFee_shares = floor(realizedYield_assets × 1500 / 10000)
// minted to treasury → dilutes existing holders by design
// this is the performance carry; entry+management fees are split
operatorSplit: perfFee → operator carry
ecosystemSplit: entry + management → 50 / 50 operator + GIWA treasury
Operator / protocol split policy: Performance fee is operator carry. Entry and management fees are shared with the GIWA ecosystem (proposed 50/50) so the protocol has a recurring revenue stake proportional to TVL activity — not a one-time listing fee.
§ 5 · most important

Security & trust model

Read this section before auditing, forking, or deploying to mainnet.

⚠ Simulation yield — testnet only

On testnet, the "yield source" is MockERC20's open mint(vault, amount). This is a simulation so judges can watch the accrual engine in a live demo. On mainnet, this open mint MUST be removed entirely. Value may enter the vault only through a role-gated harvest() called by a whitelisted strategy contract that has actually earned external yield (e.g. from a Dunamu-backed KRW yield source). No exceptions. The testnet build is not a mainnet reference.

Inflation / first-depositor / donation attack

Without the decimal offset, an attacker can deposit 1 wei to an empty vault, then donate a large amount directly to the vault's asset balance. This inflates totalAssets / totalSupply — so the next depositor's shares round to zero (the pathology that produced our 1.09 × 10²¹ share price in an earlier testnet build — we caught and patched it before any real money was at risk).

Fix: _decimalsOffset() = 18 makes the virtual supply 10¹⁸ × larger. An attacker must donate 10¹⁸ × the "attack capital" to move the price by 1 wei of shares — making the attack economically infeasible. This is the same defense used by Morpho, Euler v2, and OZ's own documentation.

// protected invariant with offset
virtualSupply = totalSupply + 1018
virtualAssets = totalAssets + 1
sharePrice = virtualAssets / virtualSupply

// attacker needs ≥ 10^18 TKRW donation to inflate by 1 wei
// ∴ attack cost >> any rational yield extraction

Oracle discipline

Any price the strategy trusts for rebalancing or yield calculation must be a TWAP, Chainlink feed, or Pyth pull oracle. Spot DEX quotes are manipulable within a single block — using them as an input to a harvest function is a known vector for flash-loan-driven bad debt. This is a mainnet checklist item, not a testnet constraint.

Roles & emergency brake

Access is managed via OpenZeppelin AccessControl with four roles: governor (governance), curator (parameter tuning), keeper (harvest calls), guardian (emergency). The guardian can pause or quarantine a strategy without a governance delay — providing a fast response path to a detected exploit. Owner and treasury keys are held in a Safe multisig.

The dashboard as a control surface

The live app clamps the displayed share price to a sanity band (0.5 – 5.0) and shows — / "degraded" when the price falls outside it. This is the same check that surfaced the 1e21 price before any user saw it. The UI is defense-in-depth: if the contract state is wrong, the dashboard renders wrong, not silently normal. This is not decoration.

§ 6

Trust assumptions summary

Freeze every new deposit today; holders still earn — because the yield is external. That test is the whole vault.
DojangScore Docs GIWASwap Docs Live App 0xEE4E6829EB6A7B79f826AD99E06d8Fb5629169F5 (Explorer)