DEV Community

ohmygod
ohmygod

Posted on

The Resolv USR Stablecoin Exploit: How a Compromised Off-Chain Signer Let an Attacker Mint 80M Unbacked Tokens and Steal $25M

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:

  1. Collateral Deposit: Users deposit USDC/USDT into the protocol
  2. Off-Chain Oracle + Signer: An off-chain service calculates the appropriate USR mint amount based on hedging positions and collateral value
  3. Mint Authorization: The off-chain signer produces a signature authorizing the smart contract to mint USR
  4. 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);
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Phase 4: The Dump

The attacker immediately began swapping USR across multiple DEXes:

  1. Curve Finance: Large USR → USDC swaps
  2. Uniswap V3: USR → USDT conversions
  3. 1inch Aggregator: Optimized routing for remaining tokens
  4. 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);
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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");
    }
}
Enter fullscreen mode Exit fullscreen mode

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

  1. Never trust a single off-chain component — treat your own infrastructure as potentially hostile
  2. On-chain invariant checks are non-negotiable — even with valid signatures, enforce sanity bounds
  3. Defense in depth isn't optional for stablecoins — one layer failing should not mean total loss
  4. The economic model ≠ the security model — a sound delta-neutral strategy means nothing if the minting gate is broken
  5. $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)