Docs/For APs/Redeeming (Burn)

Redeeming (Burn)

How to redeem ARU for USDC at NAV. Two-step flow: request with minimum price bound, then wait for multisig approval.

Redeeming (Burn)

Redeeming = returning ARU and receiving USDC at NAV-adjacent price. You submit a request, the multisig reviews and approves at a price at or above your minimum bound, USDC lands in your wallet and your ARU is burned.

The flow

1. Approve ARU to the Subscription Manager
2. Call requestRedemption(aruAmount, minPricePerARU)
   ↓ ARU transfers from you to the manager contract (escrowed, not burned)
   ↓ Request stored with your priceBound and 48h expiry
3. Multisig reviews + approves within ≤ 4h typical, ≤ 48h max
   ↓ Price in their approval must be ≥ your minPricePerARU
   ↓ USDC moves from treasury to you; escrowed ARU is burned
4. Done. Check your USDC balance.

If the multisig doesn't approve within 48h, your request expires. You (or anyone) can call cancelExpiredRedemption(id) to get your ARU back intact — it hasn't been burned. You can also cancel any time before approval via cancelRedemption(id).

This ARU-preserving behavior is intentional and different from some other RWA tokens (e.g., Ondo USDY burns on request). For ARU, your ARU is safe until actually settled.

Step 1 — Approve ARU

Grant the Subscription Manager permission to pull ARU from your wallet.

solidityARU.approve(SUBSCRIPTION_MANAGER_ADDRESS, type(uint256).max);

Or use permit (EIP-2612) for a gasless approval combined with the redemption call in one tx.

Step 2 — Submit the request

soliditybytes32 id = subscriptionManager.requestRedemption(
    50_000 * 1e18,    // aruAmount — 50,000 ARU (18 decimals)
    1_05 * 1e16       // minPricePerARU — 1.05 × 1e18, so you require ≥ $1.05 per ARU
);

Parameters:

  • aruAmount — amount of ARU to redeem, in 18-decimal units. Must be ≥ minimumRedeemAmount() (currently 10,000 ARU).
  • minPricePerARU — the lowest price per ARU you'll accept. If the multisig approves at any price ≥ this, you get USDC at that price. Settlements below your floor revert.

What happens on-chain during Step 2

  • Your ARU transfers from your wallet to the Subscription Manager contract (escrowed — NOT burned yet)
  • A Request struct is created with your ap, amount, priceBound (your minimum), createdAt, expiresAt, and fulfilled: false
  • RedemptionRequested event emitted
  • Your per-AP open-redemption counter increments

Step 3 — Wait for approval

Multisig (typically 3-of-5 with AutoSigner) reviews. If NAV is within your priceBound floor, AutoSigner co-signs. A human countersigns, the approval fires.

On approval:

  • Admin calls approveRedemption(id, pricePerARU) where pricePerARU ≥ your priceBound
  • Your USDC = (aruAmount × pricePerARU) / 1e30 — the fixed-point conversion from 18-dec ARU to 6-dec USDC
  • USDC transfers from the treasury to your wallet
  • Your escrowed ARU is burned atomically in the same transaction
  • RedemptionApproved event emitted

Calculating what you'll receive

At price p (in 1e18 units):

usdc_received = aru_amount × p / 1e30

Worked example: redeem 50,000 ARU at price $1.10 per ARU:

usdc_received = 50_000 × 1e18 × 1.10 × 1e18 / 1e30
              = 55,000 USDC (6-dec: 55_000_000_000)

Cancelling your request

Before approval: you cancel

soliditysubscriptionManager.cancelRedemption(id);
  • Must be called by you. Others get NotYourRequest.
  • ARU returns to your wallet intact, not burned.
  • Your open-redemption slot is freed.
  • Request ID becomes non-approvable.

After expiry (48h default): anyone can cancel

soliditysubscriptionManager.cancelExpiredRedemption(id);
  • Anyone can call. ARU refund always goes to the original AP.
  • NotYetExpired reverts if called early.

Key property: your ARU is safe even during treasury stress

Consider this scenario: you submit a redemption, but the treasury doesn't have enough USDC to settle it (e.g., during a bank-run stress event when many APs are redeeming simultaneously).

  • approveRedemption will revert because the treasury safeTransferFrom fails
  • Your ARU remains in the manager contract — not burned, not lost
  • After 48h expiry, cancelExpiredRedemption returns your ARU
  • You're no worse off than before; you can try again or hold

This is the v2 safety property. The multisig cannot force your ARU to be burned without successfully paying you USDC. Worst case: delay. Never loss.

Things to know

Request doesn't affect ARU circulation until burn

While your ARU is escrowed in the contract, it's still counted in totalSupply(). It's just off-exchange. The contract holds it; it's burned only on successful approval.

This matters for analytics: escrowed redemption ARU is still live-backed ARU, not yet retired. Observable by monitoring IERC20(ARU).balanceOf(SUBSCRIPTION_MANAGER_ADDRESS).

Per-AP cap of 50 applies

Same 50-request ceiling as subscriptions, counted separately for redemptions.

Gas

  • requestRedemption: ~65k gas
  • cancelRedemption: ~50k gas
  • approveRedemption: ~100k gas (multisig pays)
  • cancelExpiredRedemption: ~50k gas

Events

  • RedemptionRequested(id, ap, aruAmount, minPrice, expiresAt)
  • RedemptionApproved(id, ap, aruAmount, usdcAmount, pricePerARU)
  • RedemptionCancelled(id, ap, aruAmount, byExpiry)

Redemption pauses vs. freezes

During market stress, MANAGER_ADMIN may call pauseRedemptions(). This:

  • Blocks new redemption requests (requestRedemption reverts)
  • Does NOT block approvals of existing pending requests
  • Does NOT block cancellation (either by you or expiry keeper)

So a pause slows the queue but doesn't strand existing flow. You can still always get your ARU back via cancel.

freeze() is irreversible and blocks new requests permanently. Existing pending requests still settle or expire normally.

Next