Scope: ARU.sol, ARUMintRedeemManager.sol, ARUPriceOracle.sol and the off-chain actors that operate them.
┌─────────────────┐ ┌─────────────────────┐ ┌────────────────┐
│ APs (external) │──────▶│ Manager │──────▶│ ARU (token) │
│ submit requests │ │ (MANAGER_ADMIN) │ │ (owner/minter) │
└─────────────────┘ └─────────────────────┘ └────────────────┘
▲ ▲
│ reads price off-chain │
┌────────┴────────┐ │
│ ARUPriceOracle │ │
│ (ADMIN/UPDATER) │ │
└─────────────────┘ │
│
┌─────────────────┐ │
│ Treasury (EOA/Safe) ◀── USDC ── │
└─────────────────┘ │
│
48h timelocked minter ──────┘
Every arrow crossing a box is a trust boundary. Actors inside a box are trusted per the roles table below.
| Role | Holder | Powers | Misuse impact |
|---|---|---|---|
ARU.owner |
Cold multisig (2-of-3 recommended) | Propose minter change (48h timelock), transfer ownership (48h timelock), cancel pending changes | Misuse bounded by 48h window — community can observe and mitigate |
ARU.minter |
Initially owner → rotates to Manager after 48h timelock | mint(to, amount), burn(amount) (via ERC20Burnable) |
Unlimited inflation if compromised. This is the crown-jewel key. |
Manager.MANAGER_ADMIN |
Operational multisig (2-of-3 recommended) | Add/remove APs, pause/unpause, freeze (irreversible), settle epochs with arbitrary price, set treasury, set minimums | Can settle at adversarial price, freeze the contract, mis-route collateral |
Oracle.ADMIN_ROLE |
Same operational multisig or separate | Set maxPriceChangeBps, minUpdateInterval, stalenessThreshold, feedId, grant/revoke roles |
Can silently disable rate-of-change guard or staleness enforcement |
Oracle.PRICE_UPDATER |
Redstone relayer (hot hardware) | setPrice(newPrice) subject to rate-of-change + interval |
Can push adversarial prices within the rate-of-change window; cumulative attack over hours could drift NAV meaningfully |
| Treasury | EOA or Safe holding USDC | Signs safeTransferFrom approvals that let Manager refund APs |
If treasury drains or refuses approvals, refunds + redemptions stall |
MANAGER_ADMIN keyCapability: anything MANAGER_ADMIN can do.
Worst case (post-fix):
Mitigations currently in place:
MANAGER_ADMIN must already be an AP-curated multisig. Enforce 2-of-3 or higher, hardware keys.Residual risk: high if signing ceremony breaks down. Accepted only under strict multisig policy (see Deployment Ceremony). Consider a settlement timelock (e.g., 6h between price announcement and execution) as a future hardening step.
ARU.minter key (after timelock rotation)Capability: unlimited mint/burn.
Why this is the worst key: no timelock between compromise and exploitation; one transaction drains the protocol.
Mitigations:
MANAGER_ADMIN (T-1).Residual risk: equal to T-1 by construction.
Oracle.ADMIN_ROLE keyCapability: reconfigure safety parameters.
Worst case:
maxPriceChangeBps = 10_000 (100%) → rate-of-change guard disabled, next setPrice can be arbitrary.stalenessThreshold = type(uint256).max → latestRoundDataStrict() never reverts, all staleness monitoring goes blind.Mitigations:
Recommended hardening: add 24h timelock on setMaxPriceChangeBps and setStalenessThreshold. Lower-risk setters (setMinUpdateInterval, setFeedId) can stay immediate.
Residual risk: high until setters are timelocked.
Oracle.PRICE_UPDATER (hot relayer)Capability: push prices within the rate-of-change window.
Worst case: sustained 3%/hour attack could drift NAV arbitrarily over ~24h. Paired with a T-1 attacker who settles at the drifted price, this is exploitable.
Mitigations:
maxPriceChangeBps caps single-update magnitude (default 3%).minUpdateInterval caps update frequency (default 1h).Recommended hardening: second-oracle cross-check — the Redstone price is acceptable only if within X% of a secondary source (e.g., Chainlink gold feed + FX). Either enforce on-chain with two feeds or via an off-chain circuit-breaker that pauses subscriptions.
Residual risk: medium. The combination of rate-of-change + AP-based issuance (rather than open mint) makes point-in-time attacks expensive, but it's not cost-free.
Capability: revoke USDC approval to Manager, or drain the EOA.
Worst case:
safeTransferFrom reverts).Mitigations:
setTreasuryAddress exists on Manager — admin can rotate to a new Safe if the old one is compromised.Residual risk: medium. Rotation requires Manager admin cooperation; pairs badly with T-1.
Capability: attacker serves adversarial UI or RPC responses to APs.
Worst case: AP submits requestMint with parameters that look right in the UI but have different calldata on-chain (classic phishing).
Mitigations:
minimumMintAmount / minimumRedeemAmount cap the blast radius of a single bad request.Residual risk: low (bounded by single-epoch request) but worth the guide.
Capability: AP submits many tiny requests to bloat epoch state.
Mitigations:
minimumMintAmount / minimumRedeemAmount enforce floors.Residual risk: negligible under current design.
Capability: observe an admin's pending settlement tx and reorder/react.
Worst case: admin submits settlement with price P; attacker front-runs with a (legitimate) setPrice that shifts the oracle before settlement indexes from it. Post-fix, settlement reads its price parameter, not the oracle — so front-running the oracle doesn't help. Front-running the settlement itself requires MANAGER_ADMIN role → reduces to T-1.
Residual risk: low.
| Risk | Why accepted | Revisit trigger |
|---|---|---|
| Manual price submission at settlement | Operational flexibility; automation would create circular dependencies | If settlement ops prove consistent over 6 months, consider oracle-coupled settlement |
| Oracle admin setters without timelock | Simplicity at launch; T-3 attack requires multisig breach | Add timelocks after first 3 months of operation |
Irreversible freeze() |
Intended for clean migration | Keep — controlled migration pattern |
| AP list not paginated on-chain | Would require substantial state/gas overhead | If AP count exceeds ~200, revisit with a paginated iteration pattern |
Unbounded aps[] / refundees[] arrays in settlement |
Admin controls input; gas ceiling is the natural bound | Add explicit cap (e.g., 500) as a conservative fence |
latestRoundDataStrict() will revert for integrators until admin pushes a manual price; accept and monitor.These are not enforced on-chain; they are operator responsibilities:
addAP has passed KYC and signed the AP agreement.Violation of any of these is a governance failure, not a smart-contract failure.