Decay

Decay is an instruction in SwapVM, the swap engine behind 1inch Aqua. It is one of the opcodes exposed by the deployed Aqua swap router (AquaSwapVMRouter).

Decay applies a Mooniswap-style virtual balance adjustment: after a swap it temporarily inflates balanceIn and deflates balanceOut, then gradually restores them over a decay period. This creates a spread that discourages sandwich attacks.

Decay is one of the SwapVM opcodes registered on the Aqua router (AquaOpcodes): Controls, XYCSwap, XYCConcentrate, Decay, Fee, PeggedSwap, and Extruction.

Source: src/instructions/Decay.sol


Args encoding

Field Offset Size Description
period 0 2 bytes (uint16) Decay period in seconds

Build with DecayArgsBuilder.build(uint16 decayPeriod).


Instructions

_decayXD

Solidity
1
function _decayXD(Context memory ctx, bytes calldata args) internal

Applies time-decaying offsets to virtual balances before running the nested swap formula.

Behavior

  1. Reads period from args
  2. Reads decaying offsets from storage:
  • _offsets[orderHash][tokenIn][true] → added to balanceIn (making input look more expensive)
  • _offsets[orderHash][tokenOut][false] → subtracted from balanceOut (making output look smaller)
  1. Calls ctx.runLoop() to execute the nested swap formula with adjusted balances
  2. In swap mode, records new offsets for the amounts transacted:
  • Adds swapAmountIn to _offsets[orderHash][tokenIn][false]
  • Adds swapAmountOut to _offsets[orderHash][tokenOut][true]

Offset decay formula (per stored DecayingOffset { offset, timestamp }):

timeLeft = (timestamp + period) - block.timestamp    // 0 if expired
currentOffset = offset * timeLeft / period

Offsets decay linearly to zero over period seconds. Expired offsets return zero.

Constraint: Must be placed before swap amounts are computed (amountIn == 0 || amountOut == 0).

Quote/swap divergence: In quote mode, offsets are read but not updated. A quote reflects the current spread; the swap applies and records new offsets. Do not use backward jumps to this instruction.

Errors: DecayShouldBeCalledBeforeSwapAmountsComputation(amountIn, amountOut).


Storage layout

Solidity
1
2
3
4
5
6
7
8
mapping(bytes32 orderHash =>
    mapping(address token =>
        mapping(bool buyOrSell => DecayingOffset))) internal _offsets;

struct DecayingOffset {
    uint216 offset;
    uint40 timestamp;
}

Packed into a single storage slot (216 + 40 = 256 bits). Uses assembly for single-slot SLOAD/SSTORE.


  • Balances: sets the initial reserves; _decayXD adjusts them further.
  • XYCSwap: the typical swap formula nested after decay.

Did you find what you need?