Ethereum Stablecoin (Managed Single-Asset (yield via STRC credit exposure))
Saturn Credit
Audited 04/15/2026 · 3w ago Automated Pipeline (V1.2.3) Tier: Simple Framework V1.2.3
Deal Breaker Gate
FAIL
3 of 23 deal breakers failed
Score
0 /100
Grade F
Risk Level
Critical
Aggregate finding
Re-check Cadence
N/A
Suggested for next assessment
Findings
Three of four core upgradeable contracts can be unilaterally upgraded by a single EOA with no timelock, multisig, or governance oversight. The sUSDat vault, which holds all deposited user funds, is directly exposed; a compromised key would enable instant fund drainage. The deal-breaker gate fails on EOA upgrade control, EOA fund control, and timelock backdoors.
- ▸ Single EOA controls upgrades on 3/4 core contracts (USDat, sUSDat, WithdrawalQueueERC721)
- ▸ No timelock on StrcPriceOracle.updateOracle() — oracle can be redirected instantly
- ▸ 20% toleranceBps on USDat<->STRC conversions is wide and processor-controlled
- ▸ PROCESSOR_ROLE is a trusted off-chain actor with no on-chain rate limits
- ▸ No public bug bounty program (Immunefi page returns 404)
Technical findings only — not financial advice.
Trust Surfaces
Who can move funds, and how fast| Surface | Controller | Type | Min Delay | Worst Case |
|---|---|---|---|---|
| USDat — Proxy upgrade | 0x610182581C93687Ca03F4a8E7f124f8cEC616820 ↗ | EOA | Instant | Replace USDat implementation — instant token redirection or freeze |
| USDat — DEFAULT_ADMIN_ROLE | 0x610182581C93687Ca03F4a8E7f124f8cEC616820 ↗ | EOA | Instant | Grant/revoke any role on USDat (compliance, whitelist) |
| sUSDat — UUPS upgrade & DEFAULT_ADMIN_ROLE | 0x610182581C93687Ca03F4a8E7f124f8cEC616820 ↗ | EOA | Instant | Replace vault implementation — full drainage of deposited USDat |
| Withdraw — UUPS upgrade & DEFAULT_ADMIN_ROLE | 0x610182581C93687Ca03F4a8E7f124f8cEC616820 ↗ | EOA | Instant | Replace withdrawal queue — redirect funds in flight |
| StrcPriceOracle — DEFAULT_ADMIN_ROLE | 0x610182581C93687Ca03F4a8E7f124f8cEC616820 ↗ | EOA | Instant | Redirect oracle to attacker feed — instant NAV manipulation |
| Mint/Redeem (SwapFacility) — Proxy upgrade | 0x23CA665c8a73292Fc7AC2cC4493d2cE883BBA468 ↗ | Timelock | 72h | Mint/Redeem upgrade — 72h public delay before exposure |
| Chainlink STRC Feed — Owner | 0x21f73D42Eb58Ba49dDB685dc29D3bF5c0f0373CA ↗ | Multisig 4/9 | Instant | Replace Chainlink STRC price feed implementation |
USDat — Proxy upgrade
EOA Controller 0x6101…6820 ↗
Min delay Instant
Worst case Replace USDat implementation — instant token redirection or freeze
USDat — DEFAULT_ADMIN_ROLE
EOA Controller 0x6101…6820 ↗
Min delay Instant
Worst case Grant/revoke any role on USDat (compliance, whitelist)
sUSDat — UUPS upgrade & DEFAULT_ADMIN_ROLE
EOA Controller 0x6101…6820 ↗
Min delay Instant
Worst case Replace vault implementation — full drainage of deposited USDat
Withdraw — UUPS upgrade & DEFAULT_ADMIN_ROLE
EOA Controller 0x6101…6820 ↗
Min delay Instant
Worst case Replace withdrawal queue — redirect funds in flight
StrcPriceOracle — DEFAULT_ADMIN_ROLE
EOA Controller 0x6101…6820 ↗
Min delay Instant
Worst case Redirect oracle to attacker feed — instant NAV manipulation
Mint/Redeem (SwapFacility) — Proxy upgrade
Timelock Controller 0x23CA…A468 ↗
Min delay 72h
Worst case Mint/Redeem upgrade — 72h public delay before exposure
Chainlink STRC Feed — Owner
Multisig 4/9 Controller 0x21f7…73CA ↗
Min delay Instant
Worst case Replace Chainlink STRC price feed implementation
Deal Breaker Matrix
PASS 12 FAIL 3 N/A 5 Inconclusive 3
Access Control & Governance
| Item | Status | Evidence |
|---|---|---|
| EOA Upgrade Control | FAIL | Single EOA (0x6101...6820) controls proxy upgrades on USDat, sUSDat, and WithdrawalQueueERC721. Code size = 0 confirms EOA. |
| EOA Fund Control | FAIL | Same EOA holds DEFAULT_ADMIN_ROLE on sUSDat (ERC4626 vault). Via UUPS upgrade, complete fund extraction is possible in a single transaction. |
| >60% Governance Centralization | N/A | No governance token. |
| Governance Mechanism Bypass | N/A | No governance voting mechanism. |
| Timelock Backdoors | FAIL | Zero timelock on USDat, sUSDat, Withdraw, StrcPriceOracle admin ops. Only SwapFacility has 72h TimelockController. updateOracle() can instantly redirect price feed. |
| No Emergency Controls | PASS | Pause/unpause implemented via COMPLIANCE_ROLE (pause) and DEFAULT_ADMIN_ROLE (unpause). |
Oracle & Price Integrity
| Item | Status | Evidence |
|---|---|---|
| Direct Pool Price Oracle | PASS | Uses Chainlink STRC feed wrapped by StrcPriceOracle with staleness check (26h) and price bounds ($20-$150). Not a DEX spot price. |
| Manual Price Control | PASS | Admin cannot set prices directly, but can call updateOracle() to change the oracle contract address — flagged as aggravating factor. |
Smart Contract Architecture
| Item | Status | Evidence |
|---|---|---|
| Known Compiler Bugs | PASS | Solidity 0.8.20 and 0.8.26. 198 files pass, 0 fail. |
| No Reentrancy Protection | PASS | ReentrancyGuard on StakedUSDat and Withdraw; custom transient-storage lock on SwapFacility. |
| Unlimited Minting | PASS | USDat minting controlled by underlying M token wrapping (1:1 backed). No unbacked path. |
| Unsafe Delegatecall | PASS | No delegatecall or unvalidated .call{} in Saturn contracts (only OZ proxy infrastructure). |
| Uninitialized Implementation | PASS | All 5 implementations call _disableInitializers() in constructor. |
| Unprotected Initializer | PASS | All initialize() use initializer modifier; SwapFacility uses reinitializer(2) for V2. |
Audit & Verification
| Item | Status | Evidence |
|---|---|---|
| No Audit + High TVL | PASS | 3 audits completed (Three Sigma, 2× Certora). TVL unknown (not on DeFiLlama). |
| Unverified Contracts | PASS | 10/10 contracts verified on Etherscan. |
| Critical Unfixed Issues | Inconclusive | Detailed audit findings not reviewed (pipeline halted at deal breaker gate). |
Economic & Liquidity
| Item | Status | Evidence |
|---|---|---|
| Zero Flash Loan Protection | Inconclusive | Internal balance tracking used (usdatBalance, strcBalance); deeper flash-loan analysis not performed. |
| Broken Tokenomics | Inconclusive | 11%+ yield from STRC credit; revenue source not independently verified. Vesting caps reward distribution at 2.5% of totalAssets per cycle. |
| No Slippage Protection | PASS | depositWithMinShares, mintWithMaxAssets, requestRedeem(minUsdatReceived). processRequests validates against oracle within toleranceBps. |
Cross-Chain & Bridges
| Item | Status | Evidence |
|---|---|---|
| Centralized Bridge | N/A | Single chain (Ethereum only). |
| No Transfer Limits | N/A | Not a bridge. |
| No Token Verification | N/A | Not a bridge. |
Open Issues
P0: 2P1: 2P2: 2
- P0 Critical · Access Control Timeline: ImmediateSingle EOA controls upgrades on 3/4 core contractsImpact: Complete fund drainage via malicious upgradeRecommendation: Migrate admin authority to a multisig (≥3/5) behind a TimelockController (≥48h)
- P0 High · Oracle Timeline: ImmediateNo timelock on StrcPriceOracle.updateOracle()Impact: Instant oracle substitution could manipulate NAV and conversion ratesRecommendation: Add timelock to all oracle admin operations (updateOracle, setStaleness, setBounds)
- P1 Medium · Oracle Timeline: 1 month20% toleranceBps on USDat<->STRC conversionsImpact: Wide tolerance allows significant price deviation during processor settlementRecommendation: Reduce toleranceBps to 5–10% or implement dynamic tolerance bounded by oracle volatility
- P1 Medium · Operations Timeline: 1 monthNo public bug bounty programImpact: Reduces incentive for responsible vulnerability disclosureRecommendation: Establish an Immunefi program with $100K+ max bounty
- P2 Medium · Access Control Timeline: 3 monthsPROCESSOR_ROLE is a trusted off-chain actorImpact: Processor controls STRC conversions and withdrawal processing without on-chain boundsRecommendation: Implement on-chain rate limits and per-cycle caps on processor actions
- P2 Low · Transparency Timeline: 1 monthProtocol not tracked on DeFiLlamaImpact: Reduces independent TVL monitoring capabilityRecommendation: Submit DeFiLlama listing and maintain adapter
Contract Inventory
USDat (Proxy)
0x23238f20b894f29041f48D88eE91131C395Aaa71 ↗ Verified Proxy
Compiler: 0.8.26
USDat (Impl)
0x17cac25c6d6bbcb592837fea083a5c8eb4d1e52e ↗ Verified
Compiler: 0.8.26
sUSDat (Proxy)
0xD166337499E176bbC38a1FBd113Ab144e5bd2Df7 ↗ Verified Proxy
Compiler: 0.8.20
sUSDat (Impl)
0x2005e0ca201a37694125ff267ae57872bea0a0ce ↗ Verified
Compiler: 0.8.20
Mint/Redeem (Proxy)
0xB6807116b3B1B321a390594e31ECD6e0076f6278 ↗ Verified Proxy
Compiler: 0.8.26
Mint/Redeem (Impl)
0x45bf08d042a8958f01f8e8319b791e4584550da8 ↗ Verified
Compiler: 0.8.26
Withdraw (Proxy)
0x4Bc9FEC04F0F95e9b42a3EF18F3C96fB57923D2e ↗ Verified Proxy
Compiler: 0.8.20
Withdraw (Impl)
0x256fa0ba1b6dfb50ee883955c5a99d3c1b017fd5 ↗ Verified
Compiler: 0.8.20
StrcPriceOracle
0x5f7eCD0D045c393da6cb6c933c671AC305A871BF ↗ Verified
Compiler: 0.8.20
Chainlink STRC Feed
0xf4d2076277fff631EFC4385Ab36b1f7734218d23 ↗ Verified Proxy
Compiler: 0.6.6
Audit History
Operations
Bug Bounty: None detected
All role assignments (11)
| Contract | Role | Holder | Powers |
|---|---|---|---|
| USDat | DEFAULT_ADMIN_ROLE | 0x6101...6820 (EOA) | Grant/revoke roles, full admin |
| USDat | WHITELIST_MANAGER_ROLE | Compliance address | Enable/disable whitelist, add/remove addresses |
| sUSDat | DEFAULT_ADMIN_ROLE | 0x6101...6820 (EOA) | Upgrade, vesting, fees, tolerance, unpause, rescueTokens, redistributeLockedAmount |
| sUSDat | PROCESSOR_ROLE | Processor address | Convert USDat<->STRC, distribute rewards |
| sUSDat | COMPLIANCE_ROLE | Compliance address | Blacklist/unblacklist, pause |
| Withdraw | DEFAULT_ADMIN_ROLE | 0x6101...6820 (EOA) | Upgrade, unpause |
| Withdraw | PROCESSOR_ROLE | Processor address | Lock/unlock/process withdrawal requests |
| Withdraw | COMPLIANCE_ROLE | Compliance address | Seize requests, seize funds, pause |
| Withdraw | STAKED_USDAT_ROLE | sUSDat proxy | Add requests, claim on behalf of users |
| StrcPriceOracle | DEFAULT_ADMIN_ROLE | 0x6101...6820 (EOA) | Update oracle, set staleness, set price bounds |
| SwapFacility | DEFAULT_ADMIN_ROLE | Set at init (unconfirmed) | Set permissioned extensions/swappers |