TL;DR
On March 22, 2026, an attacker exploited Resolv Labs' USR stablecoin by compromising the off-chain signing infrastructure that authorized minting. With a $200K USDC deposit, they minted ~80 million unbacked USR tokens, swapped them across DEXes, and walked away with ~$25M in ETH. USR de-pegged to $0.025. The root cause wasn't the delta-neutral strategy — it was a missing on-chain mint cap combined with single-point-of-failure key management.
This article breaks down the attack step-by-step, reconstructs the vulnerability, and provides concrete defense patterns every stablecoin protocol should implement.
The Protocol: Resolv Labs and Delta-Neutral USR
Resolv Labs built USR as a delta-neutral stablecoin — maintaining its peg through hedged positions rather than pure overcollateralization. The architecture:
- Collateral Deposit: Users deposit USDC/USDT into the protocol
- Off-Chain Oracle + Signer: An off-chain service calculates the appropriate USR mint amount based on hedging positions and collateral value
- Mint Authorization: The off-chain signer produces a signature authorizing the smart contract to mint USR
- On-Chain Mint: The contract verifies the signature and mints tokens
The delta-neutral strategy itself was sound. The problem was in step 3.
The Vulnerability: Trust Without Verification
The USR minting contract had a critical design flaw:
// Simplified reconstruction of the vulnerable pattern
function mintUSR(
uint256 amount,
uint256 collateralDeposited,
bytes memory signature
) external {
// ✅ Verifies signature is from authorized signer
require(verifySignature(amount, collateralDeposited, signature), "Invalid signature");
// ❌ NO maximum mint-to-collateral ratio check
// ❌ NO per-epoch mint cap
// ❌ NO time-delay for large mints
// ❌ NO multi-sig requirement above threshold
_mint(msg.sender, amount);
}
The contract's only validation was signature verification. If you had a valid signature, you could mint any amount. The contract trusted the off-chain signer completely — a textbook single point of failure.
What Was Missing
| Defense Layer | Status | Impact |
|---|---|---|
| Signature verification | ✅ Present | Checked signer identity |
| Mint-to-collateral ratio | ❌ Missing | No sanity check on amounts |
| Per-block/epoch mint cap | ❌ Missing | Unlimited minting in one tx |
| Timelock for large mints | ❌ Missing | No delay for suspicious amounts |
| Multi-sig above threshold | ❌ Missing | Single key controlled all minting |
| Circuit breaker | ❌ Missing | No automatic pause on anomaly |
The Attack: Step by Step
Phase 1: Infrastructure Compromise
The attacker gained access to the off-chain signing service's private key. The exact vector remains under investigation, but Chainalysis reports suggest either:
- Direct compromise of the key management server
- Exploitation of the signing service's API
- Social engineering of an infrastructure operator
Phase 2: Seed Deposit
The attacker deposited approximately $200,000 in USDC into the protocol — just enough to appear legitimate and create a valid collateral record.
Phase 3: The Mint
Using the compromised signing key, the attacker authorized the minting of ~80 million USR tokens against their $200K deposit. The on-chain contract happily obliged — the signature was valid, and no other checks existed.
Deposit: $200,000 USDC
Minted: 80,000,000 USR ($80M face value)
Ratio: 400x leverage — pure counterfeit
Phase 4: The Dump
The attacker immediately began swapping USR across multiple DEXes:
- Curve Finance: Large USR → USDC swaps
- Uniswap V3: USR → USDT conversions
- 1inch Aggregator: Optimized routing for remaining tokens
- Final conversion: All proceeds → ETH
The selling pressure was catastrophic. USR's price collapsed from $1.00 to $0.025 — a 97.5% crash.
Phase 5: Extraction
The attacker converted approximately $25 million worth of stablecoins into ETH before liquidity dried up. The remaining ~$55M in minted USR became worthless as the peg collapsed.
Why the Delta-Neutral Strategy Was Irrelevant
Many initial reports blamed Resolv's delta-neutral approach. This is incorrect. The attack bypassed the entire hedging mechanism:
- The delta-neutral strategy determines how much USR should be minted for a given collateral deposit
- The vulnerability was that the contract didn't enforce that determination
- Even a simple overcollateralized stablecoin with the same signing architecture would have been equally vulnerable
The lesson: your economic model is only as secure as your enforcement layer.
The Five Defense Patterns Every Stablecoin Needs
1. On-Chain Mint Ratio Enforcement
Never trust off-chain infrastructure alone for mint authorization:
uint256 public constant MAX_MINT_RATIO = 1.05e18; // 105% max
function mintUSR(uint256 amount, uint256 collateral, bytes memory sig) external {
require(verifySignature(amount, collateral, sig), "Bad sig");
// On-chain sanity check — even if signer is compromised
uint256 ratio = (amount * 1e18) / collateral;
require(ratio <= MAX_MINT_RATIO, "Mint ratio exceeded");
_mint(msg.sender, amount);
}
2. Epoch-Based Mint Caps
Limit total minting per time window:
uint256 public constant EPOCH_MINT_CAP = 10_000_000e18; // 10M per epoch
uint256 public constant EPOCH_DURATION = 1 hours;
mapping(uint256 => uint256) public epochMinted;
function currentEpoch() public view returns (uint256) {
return block.timestamp / EPOCH_DURATION;
}
function mintWithCap(uint256 amount) internal {
uint256 epoch = currentEpoch();
epochMinted[epoch] += amount;
require(epochMinted[epoch] <= EPOCH_MINT_CAP, "Epoch cap exceeded");
_mint(msg.sender, amount);
}
3. Timelocked Large Mints
For mints above a threshold, enforce a delay:
uint256 public constant LARGE_MINT_THRESHOLD = 1_000_000e18;
uint256 public constant TIMELOCK_DELAY = 6 hours;
struct PendingMint {
address recipient;
uint256 amount;
uint256 executeAfter;
bool executed;
bool cancelled;
}
mapping(bytes32 => PendingMint) public pendingMints;
function requestLargeMint(uint256 amount) external returns (bytes32) {
require(amount > LARGE_MINT_THRESHOLD, "Use standard mint");
bytes32 id = keccak256(abi.encode(msg.sender, amount, block.timestamp));
pendingMints[id] = PendingMint({
recipient: msg.sender,
amount: amount,
executeAfter: block.timestamp + TIMELOCK_DELAY,
executed: false,
cancelled: false
});
emit LargeMintRequested(id, msg.sender, amount);
return id;
}
4. Multi-Sig Above Threshold
Require multiple signers for large operations:
uint256 public constant MULTISIG_THRESHOLD = 5_000_000e18;
uint8 public constant REQUIRED_SIGNERS = 3;
function mintWithMultiSig(
uint256 amount,
bytes[] memory signatures
) external {
if (amount > MULTISIG_THRESHOLD) {
require(signatures.length >= REQUIRED_SIGNERS, "Need more signatures");
_verifyMultiSig(amount, signatures);
}
_mint(msg.sender, amount);
}
5. Automated Circuit Breaker
Pause on anomalous activity:
uint256 public constant SUPPLY_CHANGE_LIMIT = 10; // 10% max supply change
uint256 public lastSupplySnapshot;
uint256 public lastSnapshotTime;
function checkCircuitBreaker(uint256 mintAmount) internal {
if (block.timestamp > lastSnapshotTime + 1 hours) {
lastSupplySnapshot = totalSupply();
lastSnapshotTime = block.timestamp;
}
uint256 changePercent = (mintAmount * 100) / lastSupplySnapshot;
if (changePercent > SUPPLY_CHANGE_LIMIT) {
_pause();
emit CircuitBreakerTriggered(mintAmount, changePercent);
revert("Circuit breaker: anomalous mint");
}
}
The Broader Pattern: Off-Chain Trust in On-Chain Systems
The Resolv exploit joins a growing list of attacks that target the seam between off-chain infrastructure and on-chain contracts:
| Incident | Off-Chain Weakness | On-Chain Missing Check |
|---|---|---|
| Resolv USR (Mar 2026) | Compromised signing key | No mint ratio cap |
| Ronin Bridge (2022) | Compromised validator keys | Insufficient multi-sig threshold |
| Harmony Bridge (2022) | Compromised 2-of-5 multi-sig | Low signer threshold |
| Wormhole (2022) | Guardian set manipulation | Missing validation |
The pattern is clear: off-chain components get compromised. Your on-chain contracts must be defensive even against your own infrastructure.
Audit Checklist: Off-Chain Signer Dependencies
If your protocol uses off-chain signing for authorization, verify:
- [ ] On-chain bounds checking — Does the contract enforce maximum values regardless of signature validity?
- [ ] Mint/withdrawal rate limiting — Are there per-epoch caps?
- [ ] Multi-sig for large operations — Is a single key compromise insufficient to cause catastrophic loss?
- [ ] Timelock on large operations — Can the team intervene before damage is done?
- [ ] Circuit breaker — Does anomalous activity automatically pause the protocol?
- [ ] Key rotation mechanism — Can compromised keys be revoked without redeploying?
- [ ] HSM/MPC for key storage — Are signing keys in hardware security modules?
- [ ] Monitoring and alerts — Are unusual mint patterns detected in real-time?
Key Takeaways
- Never trust a single off-chain component — treat your own infrastructure as potentially hostile
- On-chain invariant checks are non-negotiable — even with valid signatures, enforce sanity bounds
- Defense in depth isn't optional for stablecoins — one layer failing should not mean total loss
- The economic model ≠ the security model — a sound delta-neutral strategy means nothing if the minting gate is broken
- $25M was the discount outcome — the attacker minted $80M but only extracted $25M due to liquidity constraints. A more patient attacker could have done far worse.
This analysis is part of an ongoing series on DeFi security incidents. Follow for weekly breakdowns of exploits, audit techniques, and defense patterns.
Disclaimer: This article is for educational purposes. Code examples are simplified reconstructions, not the actual vulnerable code.
Top comments (0)