Skip to content

Latest commit

 

History

History
74 lines (51 loc) · 3.96 KB

File metadata and controls

74 lines (51 loc) · 3.96 KB

Security Model

Summary

Wield is not trustless. It is bounded-trust: an off-chain agent decides allocations, but the vault constrains what any allocation may do. Deposits and withdrawals never require agent cooperation.

What the agent can and cannot do

The agent signs an Intent:

struct Intent {
    uint256 nonce;
    uint256 deadline;
    Allocation[] allocations;
}

The digest binds chainid and the vault address, so a signature is valid for exactly one vault on one chain.

Can: shift capital between whitelisted underlyings, within caps, within slippage, using fresh oracle prices.

Cannot:

  • send funds to an address of its choosing
  • add a new underlying (owner-only)
  • exceed a concentration cap
  • swap at worse than maxSlippageBps
  • act on a price older than oracleStaleAfter
  • replay an intent (nonce) or use an expired one (deadline)
  • withdraw a user's shares

If the agent key is compromised, the attacker can churn the portfolio between approved assets and burn value through repeated swaps, bounded by the slippage cap each time. It cannot exfiltrate funds.

Owner powers

Power Effect
setPaused Blocks new deposits. Withdrawals stay open.
addUnderlying / deactivate Changes the whitelist and its price feed
setDexRouter, setMaxSlippageBps, setOracleStaleAfter Execution parameters
emergencyWithdrawAll Unwinds every underlying back to USDG inside the vault

The owner cannot transfer user funds out of the vault. Emergency withdraw converts positions to USDG in place; shares remain redeemable by their holders.

Owner keys are operationally the highest-value target in the system.

Oracle assumptions

  • Prices come from Chainlink tokenized-equity feeds, 8 decimals.
  • Feeds update on price movement during US market hours (24-5), not on a heartbeat.
  • oracleStaleAfter is 48 hours so that a normal weekend does not brick redemptions. This is a deliberate trade of freshness for availability.
  • The feed answer already contains Robinhood's split multiplier. Applying it again inflates value after a corporate action. See deployed-addresses.md.

Execution assumptions

  • Swaps route through Uniswap V3 SwapRouter02 at the 0.30% fee tier.
  • A rebalance leg that cannot fill within 1.00% slippage reverts. Failing loudly is preferred over filling badly.
  • Robinhood Chain uses legacy gas pricing.

Known accepted risks

These are real, currently unmitigated, and disclosed on purpose.

  1. No third-party audit. The contracts are live and used in production, but have not been formally audited.
  2. Basket vaults launched unseeded. No dead seed position guards against first-depositor share inflation. Mitigation is OpenZeppelin v5 ERC-4626 virtual shares and decimals offset, which makes the classic donation attack unprofitable but is not the same as a seed.
  3. BlendManager has lighter test coverage than the vault. Specifically missing: a reentrancy-attacker test, an exit-after-removeBasket test, and a double-exit test. The contract uses nonReentrant on exit() and burns before paying out, but the negative-path tests are not yet written.
  4. Flagship vault multiplier bug. The original vault applies the feed multiplier a second time in a valuation view. Bytecode is immutable, so it is documented rather than patched. Basket vaults deployed after the fix are unaffected.
  5. Centralized keeper. There is one agent and one keeper. If they stop, allocations go stale - but user withdrawals continue to work, which is the property that matters.
  6. Tokenized-equity issuer risk. The tokens themselves are third-party instruments. Wield inherits whatever redemption, custody, and regulatory risk their issuer carries.

Reporting a vulnerability

Do not open a public issue. Use the GitHub Security tab on the affected repository, or email security@usewield.io. See SECURITY.md in each repo for response targets and safe-harbour terms.