USD0a SwapperEngine

High-Level Overview

The SwapperEngine contract is a smart contract designed to facilitate the swapping of USDC tokens for USD0a tokens using an order matching mechanism. The contract allows users to create orders by depositing USD0a tokens, and other users can fill these orders by providing USDC tokens in return. The contract aims to provide a direct token swapping solution without the need for intermediary liquidity pools.

The main objective of the SwapperEngine contract is to enable efficient and low-slippage token swaps between users. The contract relies on oracle-based pricing to determine swap prices, which helps minimize slippage. However, liquidity within the contract depends on the availability of active orders, and users may need to wait for new orders to be created if no matching orders are available.

Key Advantage for Liquidity Providers: Users (USDC providers) can provide USDC liquidity to receive USD0a through order matching. Even though USDC is also part of the collateral set, using the SwapperEngine instead of DaoCollateral lets providers earn transaction fees (in USDC) and receive a discount, making it preferable for liquidity providers seeking fee revenue.

Contract Summary

The contract provides the following main functions:

  • depositUSD0X: Allows users to create a new order by depositing USD0a tokens.

  • cancelUSD0XOrder: Allows users to cancel an order and withdraw their deposited USD0a tokens.

  • provideUSDCReceiveUSD0X: Allows users to fill orders by providing USDC and receiving USD0a in return.

The contract also includes utility functions such as getOrder, getNextOrderId, swapperFee, and minimumUSD0XAmountProvided to retrieve order details and contract configuration. The SwapperEngine uses oracle-based pricing for both USDC and USD0a. USD0a's price is dynamic and increases over time as yield is harvested, since USD0a is a yield-bearing token. Orders can specify a minimum USD0a price to protect against unfavorable price movements.

Inherited Contracts

  • Initializable (OZ): Used to provide a safe and controlled way to initialize the contract's state variables. It ensures that the contract's initializer function can only be called once, preventing accidental or malicious reinitialization.

  • ReentrancyGuardUpgradeable (OZ): Used to protect against reentrancy attacks. It provides a modifier that can be applied to functions to prevent them from being called recursively or from being called from other functions that are also protected by the same guard.

  • PausableUpgradeable (OZ): Allows contract functionality to be paused by authorized accounts (PAUSING_CONTRACTS_ROLE to pause the contract and UNPAUSING_CONTRACTS_ROLE to unpause).

Functionality Breakdown

The SwapperEngine contract's primary purpose is to facilitate the swapping of USDC tokens for USD0a tokens using an order matching mechanism. The contract's functionality can be broken down into the following key components:

Order Creation:

Users can create new orders by calling the depositUSD0X function and specifying the amount of USD0a tokens they wish to swap, along with an optional minimum USD0a price.

  • The contract transfers the specified amount of USD0a tokens from the user to itself and creates a new order with the deposited amount, the user's address as the requester, and the minimum price requirement.

  • The order is assigned a unique order ID and stored in the contract's orders mapping.

  • Users can also use depositUSD0XWithPermit to create orders with gasless approvals.

Order Cancellation:

Users who have created an order can cancel it by calling the cancelUSD0XOrder function and specifying the order ID.

  • The contract verifies that the caller is the requester of the order and that the order is active.

  • If the conditions are met, the contract deactivates the order, sets its token amount and minimum price to zero, and transfers the deposited USD0a tokens back to the requester.

Order Matching:

Users can fill existing orders by calling provideUSDCReceiveUSD0X and specifying the recipient address, the amount of USD0a to receive, the maximum USDC amount to spend, an array of order IDs to match against, and whether partial matching is allowed.

  • The contract verifies that the caller has sufficient USDC balance and allowance to cover the required amount based on the current USDC and USD0a prices obtained from the oracles.

  • The contract iterates through the provided order IDs and attempts to match the requested USD0a amount against active orders.

  • For each order, the contract checks if the current USD0a price meets the order's minimum price requirement.

  • If partial matching is allowed and there is not enough USD0a in the orders to fulfill the entire request, the contract will partially fill orders until the requested amount is met or all orders are exhausted.

  • For each matched order, the contract transfers the corresponding USDC tokens (minus fees) from the caller to the order requester and transfers the USD0a tokens from itself to the specified recipient.

  • The transaction fee (in USDC) is deducted from the USDC amount and effectively paid to the order requester (USD0a provider), incentivizing liquidity provision.

  • If partial matching is not allowed and the requested USD0a amount cannot be fully matched, the contract reverts the transaction.

Price Calculation:

The contract relies on external oracle contracts to obtain the current prices of both USDC and USD0a tokens in WAD format (18 decimals).

  • The _getPrices function retrieves both USDC and USD0a prices from their respective oracles.

  • USD0a's price is dynamic and reflects the yield-bearing nature of the token, increasing over time as yield is harvested.

  • The _getUsdcAmountFromUSD0XWadEquivalent function calculates the equivalent amount of USDC tokens needed for a given amount of USD0a tokens based on the current prices.

Security Analysis

Method: provideUSDCReceiveUSD0X

This method allows users to provide USDC tokens and receive USD0a tokens by matching against existing orders. It matches the requested USD0a amount to the provided USDC tokens against the specified orders, transfers the corresponding USDC tokens (minus fees) to order requesters, and updates the order states accordingly.

Function Description:

  1. The function is protected against reentrancy attacks by using the nonReentrant modifier, ensuring that the function cannot be called recursively or from other functions that are also protected by the same guard.

  2. Validates that the amount of USD0a to receive is greater than zero.

  3. Validates that at least one order ID is provided for matching.

  4. Retrieves and validates prices from oracles, ensuring that USD0a price is non-zero.

  5. Checks that the caller has sufficient USDC balance to cover the required amount (including fees).

  6. For each order, validates that the current USD0a price meets the order's minimum price requirement (if specified).

  7. Processes orders sequentially, updating order states atomically.

  8. Validates that the total USDC spent does not exceed the maximum allowed amount specified by the caller.

  9. Reverts if partial matching is not allowed and the requested USD0a amount cannot be fully matched.

  10. Transfers are performed using SafeERC20 to prevent failures from going unnoticed.

Method: depositUSD0X

This method allows users to deposit USD0a tokens and create a new order. It transfers the specified amount of USD0a tokens from the caller to the contract and creates a new order with the deposited amount, the caller as the requester, and an optional minimum USD0a price.

Function Description:

  1. The function is protected against reentrancy attacks by using the nonReentrant modifier.

  2. Validates that the amount of USD0a to deposit is greater than or equal to the minimum required amount specified in the contract's storage. This prevents any attempts to deposit amounts below the minimum threshold.

  3. Checks that the caller is not blacklisted in the USD0a token contract.

  4. Sets the value of orderId to the current value of $.nextOrderId then increments by 1. Since it is initialized as 1, the first orderId will be one and so on.

  5. Creates a new SwapperOrder struct in storage using the order ID as key. The struct contains: the requester's address (msg.sender), the deposited token amount, the active flag set to true, and the minimum USD0a price.

  6. Transfers the specified amount of USD0a tokens from the caller to the contract using safeTransferFrom to ensure that the transfer is successful. If the transfer fails, the function will revert.

  7. Emits a Deposit event, providing the order ID and the deposited amount for tracking.

Method: cancelUSD0XOrder

This method allows the requester of an order to cancel their deposited USD0a tokens and get the deposited amount back. It deactivates the specified order, sets its token amount and minimum price to zero, and transfers the deposited USD0a tokens back to the requester.

Function Description:

  1. The function is protected against reentrancy attacks by using the nonReentrant modifier.

  2. Retrieves the SwapperOrder struct as storage so it will be modified.

  3. Checks if the order is active using the active flag. If the order is not active or does not exist, the function will revert with an appropriate error message. This prevents any attempts to cancel invalid or already canceled orders.

  4. Verifies that the caller (msg.sender) is the requester of the order. This ensures that only the original requester can cancel their own order and withdraw the deposited tokens.

  5. Retrieves the token amount associated with the order and assigns it to the amountToWithdraw variable.

  6. Sets the active flag of the order to false in storage.

  7. Sets the tokenAmount and minimumUsd0xPrice of the order to zero in storage.

  8. Transfers the amountToWithdraw of USD0a tokens from the contract back to the requester (msg.sender) using the safeTransfer function. This ensures that the transfer is successful and the requester receives their tokens. If the transfer fails, the function will revert.

  9. Emits an OrderCancelled event, providing the order ID and the amount withdrawn for tracking.

Method: _getUsdcAmountFromUSD0XWadEquivalent

This method calculates the USDC token amount in native decimals for a given USD0a amount in WAD format. It converts the USD0a amount to its USD value, then calculates the equivalent USDC amount based on the provided USDC price.

Function Description:

  1. Retrieves the contract's storage using the correct storage pattern.

  2. Retrieves the decimal places of the USDC token using the decimals() function from the IERC20Metadata interface.

  3. Calculates the USD value of the USD0a amount by multiplying the USD0a amount (in WAD) with the USD0a price (in WAD) and dividing by SCALAR_ONE.

  4. Converts the USD value to USDC tokens in native decimals by multiplying with 10^decimals and dividing by the USDC price in WAD format.

Functions Description

Public/External Functions

  • initialize: Sets up the contract with initial parameters including the registry contract, initializing the minimum USD0a amount and swapper fee.

  • depositUSD0X: Allows users to deposit USD0a tokens and create a new order with an optional minimum USD0a price. The function calculates the order ID, creates the order, and transfers USD0a tokens to the contract.

  • depositUSD0XWithPermit: Similar to depositUSD0X but uses permit for approval, enabling gasless approvals for USD0a tokens.

  • cancelUSD0XOrder: Enables users to cancel their order and withdraw their deposited USD0a tokens. Only the order requester can cancel their own order.

  • provideUSDCReceiveUSD0X: Allows users to provide USDC tokens and receive USD0a tokens by matching against existing orders. The function processes orders, applies fees, and handles transfers.

  • pause: Pauses the contract. Only callable by PAUSING_CONTRACTS_ROLE.

  • unpause: Unpauses the contract. Only callable by UNPAUSING_CONTRACTS_ROLE.

  • updateSwapperFee: Sets the swapper fee (in basis points). Only callable by SWAPPER_FEE_OPERATOR_ROLE.

  • updateMinimumUSD0XAmountProvided: Sets the minimum amount of USD0a that must be deposited to create an order. Only callable by MINIMUM_USD0X_PROVIDED_OPERATOR_ROLE.

Getter Functions

  • getOrder: Returns the details of a specific order including active status, token amount, and minimum USD0a price.

  • getNextOrderId: Returns the next order ID that will be assigned.

  • swapperFee: Returns the current swapper fee in basis points.

  • minimumUSD0XAmountProvided: Returns the minimum amount of USD0a required to create an order.

Constants

  • CONTRACT_REGISTRY_ACCESS: Address of the registry access contract.

  • CONTRACT_ORACLE: Address of the oracle contract.

  • CONTRACT_USD0X: Address of the USD0a token contract.

  • USDC: Address of the USDC token contract.

  • SWAPPER_FEE_OPERATOR_ROLE: Role identifier for updating the swapper fee.

  • MINIMUM_USD0X_PROVIDED_OPERATOR_ROLE: Role identifier for updating the minimum USD0a amount.

  • PAUSING_CONTRACTS_ROLE: Role identifier for pausing contract operations.

  • UNPAUSING_CONTRACTS_ROLE: Role identifier for unpausing contract operations.

  • MAX_SWAPPER_FEE: Maximum allowed swapper fee (1000 basis points = 10%).

  • INITIAL_SWAPPER_FEE: Initial swapper fee (5 basis points = 0.05%).

  • MINIMUM_USD0X_PROVIDED: Minimum amount of USD0a required to create an order (100 USD0a).

  • SCALAR_ONE: Scalar value representing 1 in the contract's decimal system (1e18).

  • BASIS_POINT_BASE: Base for basis point calculations (10,000).

Key Components

  • Oracle Integration: Uses oracles to fetch real-time price data for both USDC and USD0a tokens. USD0a's price is dynamic and reflects yield accumulation.

  • Order Management: Maintains a mapping of orders with unique IDs, allowing users to create, cancel, and match orders efficiently.

  • Fee Mechanism: Implements a fee system where USDC providers pay fees (in USDC) to USD0a providers, incentivizing liquidity provision through the SwapperEngine.

  • Price Protection: Orders can specify a minimum USD0a price to protect against unfavorable price movements during order execution.

  • Access Control: Implements role-based access control for administrative functions through the RegistryAccess contract.

Safeguards Implementation

  • Pausability: Allows pausing of contract functionality in emergencies.

  • Reentrancy Protection: Uses OpenZeppelin's ReentrancyGuard to prevent reentrancy attacks.

  • Access Control: Restricts sensitive operations to authorized roles.

  • Price Validation: Ensures prices are non-zero and validates minimum price requirements before executing swaps.

  • Amount Validation: Validates that amounts are non-zero, within acceptable ranges, and meet minimum thresholds.

  • Blacklist Check: Prevents blacklisted addresses from creating orders.

  • Maximum Spend Protection: Allows users to specify a maximum USDC amount to spend, protecting against unexpected price movements.

  • Partial Matching Control: Allows users to specify whether partial order matching is acceptable, providing flexibility while protecting against incomplete fills.

Last updated

Was this helpful?