> For a complete index of Agora Finance documentation, fetch https://docs.agora.finance/llms.txt

# Pair Contract

> Pair contract API reference — swap execution, reserve management, pricing, and fee configuration

Deployment Address: `AgoraStableSwap` is deployed with CREATE3 using a salt derived from token0 + token1, which guarantees the address can be predicted off-chain before the contract exists. The contract is a [proxy‐based upgradeable contract](../core-concepts/#deterministic-deployment), so the address remains constant while logic can be upgraded.

## Access‑Control Roles

| Role constant                 | Capabilities                                                                                                                                                         |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ACCESS_CONTROL_MANAGER_ROLE` | Grants/revokes any other role                                                                                                                                        |
| `WHITELISTER_ROLE`            | Adds or removes [`APPROVED_SWAPPER`](#accesscontrol-roles)                                                                                                           |
| `APPROVED_SWAPPER`            | Allowed to execute swaps through [`swap`](#swap-1), [`swapTokensForExactTokens`](#swaptokensforexacttokens), [`swapExactTokensForTokens`](#swapexacttokensfortokens) |
| `FEE_SETTER_ROLE`             | Adjusts per‑asset [purchase fees](../core-concepts/#purchasefees)                                                                                                    |
| `TOKEN_REMOVER_ROLE`          | Removes excess tokens & collected fees                                                                                                                               |
| `PAUSER_ROLE`                 | Pauses / unpauses swaps                                                                                                                                              |
| `PRICE_SETTER_ROLE`           | Pushes oracle price updates                                                                                                                                          |

---

## Events

### `Swap`

```solidity
event Swap(
    address indexed sender,
    uint256 amount0In,
    uint256 amount1In,
    uint256 amount0Out,
    uint256 amount1Out,
    address indexed to
);
```

Emitted at the end of every successful [`swap`](#swap-1) call. Tracks exact in/out amounts (including fees).

* Only a caller with the [`APPROVED_SWAPPER`](#accesscontrol-roles) role can trigger this event.

### `Sync`

```solidity
event Sync(uint256 reserve0, uint256 reserve1);
```

Emitted whenever on‑chain reserves are brought in‑sync with the contract's internal state.

* Fired from [`swap`](#swap-1), `sync`, [`removeTokens`](#removetokens-1), and [`collectFees`](#collectfees).
* No roles required for `sync()`

### `SwapFees`

```solidity
event SwapFees(uint256 token0FeesAccumulated, uint256 token1FeesAccumulated);
```

Logs the incremental fee amounts captured during a [`swap`](#swap-1).

### `ConfigureOraclePrice`

```solidity
event ConfigureOraclePrice(uint256 basePrice, int256 annualizedInterestRate);
```

Fired by [`configureOraclePrice`](#state-changing-functions) whenever the on‑chain oracle price curve is updated.

* Callable only by [`PRICE_SETTER_ROLE`](#accesscontrol-roles).

### `SetOraclePriceBounds`

```solidity
event SetOraclePriceBounds(
    uint256 minBasePrice,
    uint256 maxBasePrice,
    int256 minAnnualizedInterestRate,
    int256 maxAnnualizedInterestRate
);
```

Signals an update to the guardrails enforced on future oracle‑price changes.

* Emitted by [`setOraclePriceBounds`](#state-changing-functions); caller must hold [`ACCESS_CONTROL_MANAGER_ROLE`](#accesscontrol-roles).

### `SetTokenPurchaseFees`

```solidity
event SetTokenPurchaseFees(uint256 token0PurchaseFee, uint256 token1PurchaseFee);
```

Emitted when live purchase fees are changed via [`setTokenPurchaseFees`](#state-changing-functions).

* Requires [`FEE_SETTER_ROLE`](#accesscontrol-roles).

### `SetFeeBounds`

```solidity
event SetFeeBounds(
    uint256 minToken0PurchaseFee,
    uint256 maxToken0PurchaseFee,
    uint256 minToken1PurchaseFee,
    uint256 maxToken1PurchaseFee
);
```

Defines the outer limits within which future purchase‑fee updates must fall.

* Emitted by [`setFeeBounds`](#state-changing-functions)
* caller must hold [`ACCESS_CONTROL_MANAGER_ROLE`](#accesscontrol-roles).

### `SetApprovedSwapper`

```solidity
event SetApprovedSwapper(address indexed approvedSwapper, bool isApproved);
```

Logged when an address is granted or revoked permission to call the low‑level [`swap`](#swap-1).

* Emitted by [`setApprovedSwappers`](#state-changing-functions)
* Caller must hold [`WHITELISTER_ROLE`](#accesscontrol-roles).

### `SetTokenReceiver`

```solidity
event SetTokenReceiver(address indexed tokenReceiver)
```

Fired by [`setTokenReceiver`](#state-changing-functions) when the treasury destination for *non‑fee* token withdrawals is updated.

* Requires [`ACCESS_CONTROL_MANAGER_ROLE`](#accesscontrol-roles).

### `SetFeeReceiver`

```solidity
event SetFeeReceiver(address indexed feeReceiver);
```

Fired by [`setFeeReceiver`](#state-changing-functions) when the destination for *fee* withdrawals is updated.

* Requires [`ACCESS_CONTROL_MANAGER_ROLE`](#accesscontrol-roles).

### `RemoveTokens`

```solidity
event RemoveTokens(address indexed tokenAddress, uint256 amount)
```

Emitted by both [`removeTokens`](#removetokens) and [`collectFees`](#collectfees).

* [`removeTokens`](#removetokens) moves "excess" liquidity to `tokenReceiverAddress`.
* [`collectFees`](#collectfees) transfers accumulated fees to `feeReceiverAddress`.
* Both functions require [`TOKEN_REMOVER_ROLE`](#accesscontrol-roles).

### `SetPaused`

```solidity
event SetPaused(bool isPaused);
```

Global circuit‑breaker toggle, emitted by [`setPaused`](#state-changing-functions).

* Callable only by [`PAUSER_ROLE`](#accesscontrol-roles).

---

## Read-Only Functions

| Function                                                      | Returns                                                | Notes                                       |
| ------------------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------- |
| `name()`                                                      | Pair name string (`"TOKEN0/TOKEN1‑x.y.z"`)             | Versioned human label                       |
| `isPaused()`                                                  | `bool`                                                 | Swap availability                           |
| `token0()` / `token1()`                                       | `address`                                              | Immutable after init                        |
| `reserve0()` / `reserve1()`                                   | `uint256`                                              | Excludes un‑claimed fees                    |
| `token0PurchaseFee()` / `token1PurchaseFee()`                 | `uint256` (18 dec)                                     | Current purchase fee                        |
| `priceLastUpdated()`                                          | `uint256` (timestamp)                                  |                                             |
| `perSecondInterestRate()`                                     | `int256` (18 dec)                                      | Signed APR ÷ 365 days                       |
| `basePrice()`                                                 | `uint256` (18 dec)                                     | Spot price at `priceLastUpdated`            |
| `token0FeesAccumulated()` / `token1FeesAccumulated()`         | `uint256`                                              | Un‑collected fees                           |
| `minToken*PurchaseFee()` / `maxToken*PurchaseFee()`           | bounds                                                 | Config limits                               |
| `tokenReceiverAddress()` / `feeReceiverAddress()`             | `address`                                              | Treasury destinations                       |
| `minBasePrice()` / `maxBasePrice()`                           | `uint256`                                              | Oracle price guardrails                     |
| `minAnnualizedInterestRate()` / `maxAnnualizedInterestRate()` | `int256`                                               | Oracle APR guardrails                       |
| `token0Decimals()` / `token1Decimals()`                       | `uint8`                                                | Cached for gas                              |
| `getPrice()`                                                  | Current price (18 dec)                                 | Overloaded version also accepts `timestamp` |
| `getPriceNormalized()`                                        | Price scaled so both tokens appear at 18 dec precision |                                             |
| `version()`                                                   | `{major,minor,patch}`                                  | Contract logic version                      |

### `getAmountsOut`

```solidity
function getAmountsOut(
    uint256 amountIn,
    address[] calldata path
) external view returns (uint256[] memory amounts);
```

Determines how many output tokens a *router‑style* swap would return for a given `amountIn`.

* **Path rules** – Must be length 2 and equal to `[token0, token1]` or `[token1, token0]`; otherwise reverts [`InvalidPath`](#errors) / [`InvalidPathLength`](#errors).
* **Pricing** – Uses the live oracle price [`getPrice()`](#read-only-functions) and the **current purchase‑fee parameters** for the *outgoing* token.
* **Liquidity check** – Reverts [`InsufficientLiquidity()`](#errors) if reserves can't satisfy the quote.
* **Return value** – `amounts[0] == amountIn`, `amounts[1] == deterministic quote` (fees already deducted).

This is a pure view helper—calling it does **not** move funds or mutate state. This function is used by [`swapExactTokensForTokens`](#swapexacttokensfortokens)

### `getAmountsIn`

```solidity
function getAmountsIn(
    uint256 amountOut,
    address[] calldata path
) external view returns (uint256[] memory amounts);
```

Inverse of [`getAmountsOut`](#getamountsout): calculates the minimum tokens *required* to receive a specified `amountOut`.

* **Path rules** – Same as above; reverts on invalid path length or composition.
* **Pricing** – Considers current oracle price plus purchase fee for the *incoming* token.
* **Reserve guard** – Reverts [`InsufficientLiquidity()`](#errors) if `amountOut` exceeds current reserves of the outgoing asset.
* **Return value** – `amounts[0] == required amountIn`, `amounts[1] == amountOut`. This function is used by [`swapTokensForExactTokens`](#swaptokensforexacttokens)

---

## State-Changing Functions

### Admin / Config

| Signature                                                                                                      | Role                                                  | Effect                                                          |
| -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------------------- |
| [`setTokenReceiver(address)`](#settokenreceiver)                                                               | [`ACCESS_CONTROL_MANAGER_ROLE`](#accesscontrol-roles) | Redirects excess token withdrawals                              |
| [`setFeeReceiver(address)`](#setfeereceiver)                                                                   | [`ACCESS_CONTROL_MANAGER_ROLE`](#accesscontrol-roles) | Redirects fee outflows                                          |
| [`setApprovedSwappers(address[] addrs, bool flag)`](#setapprovedswapper)                                       | [`WHITELISTER_ROLE`](#accesscontrol-roles)            | Batch grant / revoke [`APPROVED_SWAPPER`](#accesscontrol-roles) |
| [`setFeeBounds(uint256 min0,uint256 max0,uint256 min1,uint256 max1)`](#setfeebounds)                           | [`ACCESS_CONTROL_MANAGER_ROLE`](#accesscontrol-roles) | Hard caps for future fee changes                                |
| [`setTokenPurchaseFees(uint256 fee0,uint256 fee1)`](#settokenpurchasefees)                                     | [`FEE_SETTER_ROLE`](#accesscontrol-roles)             | Updates live purchase fees                                      |
| [`setPaused(bool)`](#setpaused)                                                                                | [`PAUSER_ROLE`](#accesscontrol-roles)                 | Global circuit‑breaker                                          |
| [`setOraclePriceBounds(uint256 minPrice,uint256 maxPrice,int256 minAPR,int256 maxAPR)`](#setoraclepricebounds) | [`ACCESS_CONTROL_MANAGER_ROLE`](#accesscontrol-roles) | Guardrails for oracle updates                                   |
| [`configureOraclePrice(uint256 basePrice,int256 annualizedInterestRate)`](#configureoracleprice)               | [`PRICE_SETTER_ROLE`](#accesscontrol-roles)           | Pushes new price and annualized interest rate                   |

## Treasury

### `removeTokens`

```solidity
function removeTokens(address token, uint256 amount) external;
```

* **Who / Role** – [`TOKEN_REMOVER_ROLE`](#accesscontrol-roles)
* **Purpose** – Withdraws *surplus* tokens (not counted as fees) to `tokenReceiverAddress`.
* **Events** – [`RemoveTokens`](#removetokens)(token, amount) then [`Sync`](#sync)(reserve0,reserve1)
* **Reverts** –
  * [`InsufficientTokens()`](#errors) – trying to pull more than surplus balance
  * [`InvalidTokenAddress()`](#errors) – token not part of the pair

### `collectFees`

```solidity
function collectFees(address token, uint256 amount) external;
```

* **Who / Role** – [`TOKEN_REMOVER_ROLE`](#accesscontrol-roles)
* **Purpose** – Transfers **accrued fees** to `feeReceiverAddress`.
* **Events** – [`RemoveTokens`](#removetokens)(token, amount) then [`Sync`](#sync)(...)
* **Reverts** – Same conditions as [`removeTokens`](#removetokens), but checked against `_FeesAccumulated`.

## Swapping APIs

### `swapExactTokensForTokens`

```solidity
function swapExactTokensForTokens(
    uint256 amountIn,
    uint256 amountOutMin,
    address[] calldata path,
    address to,
    uint256 deadline
) external returns (uint256[] memory amounts);
```

High‑level "exact‑in" swap helper (router style).

* **Flow**
  1. Quotes output via internal math.
  2. Requires `amountOut ≥ amountOutMin`; else [`InsufficientOutputAmount()`](#errors).
  3. Pulls `amountIn` from caller via `safeTransferFrom`.
  4. Delegates to the low‑level [`swap`](#swap-1).
* **Events** – Propagates [`Swap`](#swap), [`SwapFees`](#swapfees), [`Sync`](#sync).
* **Reverts** – [`Expired()`](#errors), [`InvalidPath*`](#errors), liquidity or price‑related errors.

### `swapTokensForExactTokens`

```solidity
function swapTokensForExactTokens(
    uint256 amountOut,
    uint256 amountInMax,
    address[] calldata path,
    address to,
    uint256 deadline
) external returns (uint256[] memory amounts);
```

High‑level "exact‑out" variant.

* **Checks** – Requires `amountIn ≤ amountInMax` or reverts [`ExcessiveInputAmount()`](#errors).
* Mirrors [`swapExactTokensForTokens`](#swapexacttokensfortokens) otherwise.

### `swap`

```solidity
function swap(
    uint256 amount0Out,
    uint256 amount1Out,
    address to,
    bytes calldata data
) external;
```

Low‑level primitive that can perform **flash‑swaps** if `data` is non‑empty.

* **Who / Role** – [`APPROVED_SWAPPER`](#accesscontrol-roles)
* **Rules** – Exactly one of `amount0Out`, `amount1Out` must be non‑zero; else [`InvalidSwapAmounts()`](#errors).
* **Callback** – If `data` is supplied, `to` must implement [UniswapV2CallbackInterface](https://docs.uniswap.org/contracts/v2/guides/smart-contract-integration/using-flash-swaps).
* **Invariant** – Ensures required tokens *plus fees* are returned, else reverts [`InsufficientInputAmount()`](#errors).
* **Events** – [`SwapFees`](#swapfees) → [`Sync`](#sync) → [`Swap`](#swap) (in that order).

---

## Errors

| Error                                                                                                 | Trigger                                                                             |
| ----------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| [`InvalidTokenAddress()`](#errors)                                                                    | Token not in pair for [`collectFees`](#collectfees)/[`removeTokens`](#removetokens) |
| [`InvalidPath()`](#errors) / [`InvalidPathLength()`](#errors)                                         | Path must be `[token0,token1]` or reverse                                           |
| [`InvalidSwapAmounts()`](#errors)                                                                     | Both `amount0Out` and `amount1Out` non‑zero or zero                                 |
| [`Expired()`](#errors)                                                                                | Deadline passed in router helpers                                                   |
| [`InsufficientLiquidity()`](#errors)                                                                  | Reserves too low                                                                    |
| [`InvalidToken0PurchaseFee()`](#errors) / [`InvalidToken1PurchaseFee()`](#errors)                     | Fee outside configured bounds                                                       |
| [`ExcessiveInputAmount()`](#errors)                                                                   | `amountIn` exceeds caller‑supplied max                                              |
| [`InsufficientOutputAmount()`](#errors)                                                               | Quoted out \< `amountOutMin`                                                        |
| [`InsufficientInputAmount()`](#errors)                                                                | Fewer tokens in than required by pricing                                            |
| [`PairIsPaused()`](#errors)                                                                           | Swaps disabled                                                                      |
| [`BasePriceOutOfBounds()`](#errors) / [`AnnualizedInterestRateOutOfBounds()`](#errors)                | Oracle update outside guardrails                                                    |
| [`MinBasePriceGreaterThanMaxBasePrice()`](#errors)                                                    | Invalid bounds                                                                      |
| [`MinAnnualizedInterestRateGreaterThanMax()`](#errors)                                                | —                                                                                   |
| [`MinToken0PurchaseFeeGreaterThanMax()`](#errors) / [`MinToken1PurchaseFeeGreaterThanMax()`](#errors) | Fee bounds inverted                                                                 |
| [`InsufficientTokens()`](#errors)                                                                     | Treasury withdrawal exceeds balance                                                 |
| [`IncorrectDecimals()`](#errors)                                                                      | Init decimals mismatch with token contracts                                         |

---

## Interface

```solidity
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.4;

library AgoraStableSwapPair {
    struct Version {
        uint256 major;
        uint256 minor;
        uint256 patch;
    }
}

interface IAgoraStableSwapPair {
    struct InitializeParams {
        address token0;
        uint8 token0Decimals;
        address token1;
        uint8 token1Decimals;
        uint256 minToken0PurchaseFee;
        uint256 maxToken0PurchaseFee;
        uint256 minToken1PurchaseFee;
        uint256 maxToken1PurchaseFee;
        uint256 token0PurchaseFee;
        uint256 token1PurchaseFee;
        address initialAdminAddress;
        address initialWhitelister;
        address initialFeeSetter;
        address initialTokenRemover;
        address initialPauser;
        address initialPriceSetter;
        address initialTokenReceiver;
        address initialFeeReceiver;
        uint256 minBasePrice;
        uint256 maxBasePrice;
        int256 minAnnualizedInterestRate;
        int256 maxAnnualizedInterestRate;
        uint256 basePrice;
        int256 annualizedInterestRate;
    }

    error AddressIsNotRole(string role);
    error AnnualizedInterestRateOutOfBounds();
    error BasePriceOutOfBounds();
    error CannotRemoveLastManager();
    error ExcessiveInputAmount();
    error Expired();
    error IncorrectDecimals();
    error InsufficientInputAmount();
    error InsufficientLiquidity();
    error InsufficientOutputAmount();
    error InsufficientTokens();
    error InvalidInitialization();
    error InvalidPath();
    error InvalidPathLength();
    error InvalidSwapAmounts();
    error InvalidToken0PurchaseFee();
    error InvalidToken1PurchaseFee();
    error InvalidTokenAddress();
    error MinAnnualizedInterestRateGreaterThanMax();
    error MinBasePriceGreaterThanMaxBasePrice();
    error MinToken0PurchaseFeeGreaterThanMax();
    error MinToken1PurchaseFeeGreaterThanMax();
    error NotInitializing();
    error PairIsPaused();
    error ReentrancyGuardReentrantCall();
    error RoleNameTooLong();
    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
    error SafeERC20FailedOperation(address token);

    event ConfigureOraclePrice(uint256 basePrice, int256 annualizedInterestRate);
    event Initialized(uint64 version);
    event RemoveTokens(address indexed tokenAddress, uint256 amount);
    event RoleAssigned(string indexed role, address indexed address_);
    event RoleRevoked(string indexed role, address indexed address_);
    event SetApprovedSwapper(address indexed approvedSwapper, bool isApproved);
    event SetFeeBounds(
        uint256 minToken0PurchaseFee,
        uint256 maxToken0PurchaseFee,
        uint256 minToken1PurchaseFee,
        uint256 maxToken1PurchaseFee
    );
    event SetFeeReceiver(address indexed feeReceiver);
    event SetOraclePriceBounds(
        uint256 minBasePrice,
        uint256 maxBasePrice,
        int256 minAnnualizedInterestRate,
        int256 maxAnnualizedInterestRate
    );
    event SetPaused(bool isPaused);
    event SetTokenPurchaseFees(uint256 token0PurchaseFee, uint256 token1PurchaseFee);
    event SetTokenReceiver(address indexed tokenReceiver);
    event Swap(
        address indexed sender,
        uint256 amount0In,
        uint256 amount1In,
        uint256 amount0Out,
        uint256 amount1Out,
        address indexed to
    );
    event SwapFees(uint256 token0FeesAccumulated, uint256 token1FeesAccumulated);
    event Sync(uint256 reserve0, uint256 reserve1);

    function ACCESS_CONTROL_MANAGER_ROLE() external view returns (string memory);

    function AGORA_ACCESS_CONTROL_STORAGE_SLOT() external view returns (bytes32);

    function AGORA_STABLE_SWAP_STORAGE_SLOT() external view returns (bytes32);

    function APPROVED_SWAPPER() external view returns (string memory);

    function FEE_PRECISION() external view returns (uint256);

    function FEE_SETTER_ROLE() external view returns (string memory);

    function PAUSER_ROLE() external view returns (string memory);

    function PRICE_PRECISION() external view returns (uint256);

    function PRICE_SETTER_ROLE() external view returns (string memory);

    function TOKEN_REMOVER_ROLE() external view returns (string memory);

    function WHITELISTER_ROLE() external view returns (string memory);

    function assignRole(string memory _role, address _newAddress, bool _addRole) external;

    function basePrice() external view returns (uint256);

    function calculatePrice(
        uint256 _priceLastUpdated,
        uint256 _timestamp,
        int256 _perSecondInterestRate,
        uint256 _basePrice
    ) external pure returns (uint256 _price);

    function collectFees(address _tokenAddress, uint256 _amount) external;

    function configureOraclePrice(uint256 _basePrice, int256 _annualizedInterestRate) external;

    function feeReceiverAddress() external view returns (address);

    function getAllRoles() external view returns (string[] memory _roles);

    function getAmount0In(
        uint256 _amount1Out,
        uint256 _token0OverToken1Price,
        uint256 _token1PurchaseFee
    ) external pure returns (uint256 _amount0In, uint256 _token1PurchaseFeeAmount);

    function getAmount0Out(
        uint256 _amount1In,
        uint256 _token0OverToken1Price,
        uint256 _token0PurchaseFee
    ) external pure returns (uint256 _amount0Out, uint256 _token0PurchaseFeeAmount);

    function getAmount1In(
        uint256 _amount0Out,
        uint256 _token0OverToken1Price,
        uint256 _token0PurchaseFee
    ) external pure returns (uint256 _amount1In, uint256 _token0FeeAmount);

    function getAmount1Out(
        uint256 _amount0In,
        uint256 _token0OverToken1Price,
        uint256 _token1PurchaseFee
    ) external pure returns (uint256 _amount1Out, uint256 _token1PurchaseFeeAmount);

    function getAmountsIn(uint256 _amountOut, address[] memory _path) external view returns (uint256[] memory _amounts);

    function getAmountsOut(uint256 _amountIn, address[] memory _path) external view returns (uint256[] memory _amounts);

    function getPrice() external view returns (uint256 _currentPrice);

    function getPrice(uint256 _timestamp) external view returns (uint256 _price);

    function getPriceNormalized() external view returns (uint256 _normalizedPrice);

    function getRoleMembers(string memory _role) external view returns (address[] memory _members);

    function hasRole(string memory _role, address _address) external view returns (bool);

    function implementationAddress() external view returns (address);

    function initialize(InitializeParams memory _params) external;

    function isPaused() external view returns (bool);

    function maxAnnualizedInterestRate() external view returns (int256);

    function maxBasePrice() external view returns (uint256);

    function maxToken0PurchaseFee() external view returns (uint256);

    function maxToken1PurchaseFee() external view returns (uint256);

    function minAnnualizedInterestRate() external view returns (int256);

    function minBasePrice() external view returns (uint256);

    function minToken0PurchaseFee() external view returns (uint256);

    function minToken1PurchaseFee() external view returns (uint256);

    function name() external view returns (string memory);

    function perSecondInterestRate() external view returns (int256);

    function priceLastUpdated() external view returns (uint256);

    function proxyAdminAddress() external view returns (address);

    function removeTokens(address _tokenAddress, uint256 _amount) external;

    function requireValidPath(address[] memory _path, address _token0, address _token1) external pure;

    function reserve0() external view returns (uint256);

    function reserve1() external view returns (uint256);

    function setApprovedSwappers(address[] memory _approvedSwappers, bool _setApproved) external;

    function setFeeBounds(
        uint256 _minToken0PurchaseFee,
        uint256 _maxToken0PurchaseFee,
        uint256 _minToken1PurchaseFee,
        uint256 _maxToken1PurchaseFee
    ) external;

    function setFeeReceiver(address _feeReceiver) external;

    function setOraclePriceBounds(
        uint256 _minBasePrice,
        uint256 _maxBasePrice,
        int256 _minAnnualizedInterestRate,
        int256 _maxAnnualizedInterestRate
    ) external;

    function setPaused(bool _setPaused) external;

    function setTokenPurchaseFees(uint256 _token0PurchaseFee, uint256 _token1PurchaseFee) external;

    function setTokenReceiver(address _tokenReceiver) external;

    function swap(uint256 _amount0Out, uint256 _amount1Out, address _to, bytes memory _data) external;

    function swapExactTokensForTokens(
        uint256 _amountIn,
        uint256 _amountOutMin,
        address[] memory _path,
        address _to,
        uint256 _deadline
    ) external returns (uint256[] memory _amounts);

    function swapTokensForExactTokens(
        uint256 _amountOut,
        uint256 _amountInMax,
        address[] memory _path,
        address _to,
        uint256 _deadline
    ) external returns (uint256[] memory _amounts);

    function sync() external;

    function token0() external view returns (address);

    function token0Decimals() external view returns (uint8);

    function token0FeesAccumulated() external view returns (uint256);

    function token0PurchaseFee() external view returns (uint256);

    function token1() external view returns (address);

    function token1Decimals() external view returns (uint8);

    function token1FeesAccumulated() external view returns (uint256);

    function token1PurchaseFee() external view returns (uint256);

    function tokenReceiverAddress() external view returns (address);

    function version() external pure returns (AgoraStableSwapPair.Version memory _version);
}
```

---

## ABI

The ABI of the `AgorastableSwapPair` is available [here](https://testnet.snowscan.xyz/address/0x2B2572cCD3794ba2f7DF7423cfCD4a441f3E8a10#code)