# Usual Tech Hub

## Welcome to the <mark style="color:purple;">**Usual**</mark>**&#x20;technical documentation**

{% hint style="info" %}
Unlike other protocols, we strive to provide **detailed insights** and create **full transparency** about our implementation, so that you can have **peace of mind** when you are using our products or want to integrate with them.
{% endhint %}

### GET STARTED RIGHT HERE

{% content-ref url="/pages/7XlZ7uW7trwmIalgdVo9" %}
[Usual Protocol Primer](/overview/usual-protocol-primer)
{% endcontent-ref %}

<table data-card-size="large" data-column-title-hidden data-view="cards" data-full-width="false"><thead><tr><th align="center"></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center"><strong>Get to know the features of the protocol</strong></td><td data-object-fit="cover"><a href="/files/yPdRs1Jku54Yh21IuoNw">/files/yPdRs1Jku54Yh21IuoNw</a></td><td><a href="/pages/n3ED3XrWOytvSuHessqf">/pages/n3ED3XrWOytvSuHessqf</a></td></tr><tr><td align="center"><strong>Understand how everything comes together</strong></td><td data-object-fit="cover"><a href="/files/ahkQgTBZGLFRPHfQtBVy">/files/ahkQgTBZGLFRPHfQtBVy</a></td><td><a href="/pages/8SudWZK13GtTANKqiFwP">/pages/8SudWZK13GtTANKqiFwP</a></td></tr><tr><td align="center"><strong>Dive into the smart contracts</strong></td><td data-object-fit="cover"><a href="/files/yufuY4kSry34ZBp2sZee">/files/yufuY4kSry34ZBp2sZee</a></td><td><a href="/pages/XodgVkq2jNI4JbBPHIkr">/pages/XodgVkq2jNI4JbBPHIkr</a></td></tr><tr><td align="center"><strong>Validate our security approach</strong></td><td data-object-fit="cover"><a href="/files/ahRpSWNsU9o7gnT41jwA">/files/ahRpSWNsU9o7gnT41jwA</a></td><td><a href="/pages/MkfnOdy9UxcHMDyNKuPL">/pages/MkfnOdy9UxcHMDyNKuPL</a></td></tr></tbody></table>


# Usual Protocol Primer

## What is the Usual protocol about? (ELI5 version)

Usual is a new kind of stablecoin protocol designed to give users more control and rewards compared to traditional stablecoins like USDC or USDT. It creates a better system where you, as a user, not only benefit from using the stablecoin but also get ownership in the protocol itself.

### **Why was Usual created?**

In the current crypto landscape, stablecoin issuers (like Tether and Circle) make a lot of money, but users don’t benefit from this wealth. Usual flips this model by redistributing profits and ownership to users. This makes it a fairer system, where users who hold or use USD0 and $USUAL actually benefit from the protocol’s success.

### **The core elements of Usual**

#### **USD0**

This is Usual’s stablecoin. It's pegged to the US dollar and backed by real world assets (RWA) like US Treasury Bills (T-Bills). Unlike other stablecoins that might have hidden risks (like depending on banks), USD0 is fully backed by super-safe assets (T-Bills), making it more secure. It’s also designed to be permissionless and easily integrated into DeFi (Decentralized Finance) ecosystems.

**Key features of USD0:**

* Fully backed by RWA T-Bills, making it stable and secure
* Completely transparent - anyone can verify the reserves backing USD0
* Works seamlessly in DeFi, allowing for easy trading, lending, or using it as collateral

#### **bUSD0**

bUSD0 (Bond USD0) represents USD0 stablecoin locked until June 11, 2028. If you want to earn more from your USD0, you can deposit it in bUSD0 for up to four years. While locked, bUSD0 still remains liquid and tradable, and it earns extra rewards in the form of yield ($USUAL and maturity yield).

**Key features of bUSD0:**

* Staked for 4 years but still tradable in DeFi
* Earns daily yield, paid in $USUAL tokens, as well as maturity yield
* Offers a minimum guaranteed yield, making it attractive for users seeking stable returns

#### ETH0

ETH0 is a synthetic ETH asset fully backed by Lido’s wstETH and issued by the Usual protocol. It allows institutional investors and crypto-native whales to maintain directional ETH exposure while capturing significantly higher yields than conventional staking or restaking.

Powered by the same architecture that underpins Usual’s stablecoin (backed by tokenized T-bills), ETH0 holders receive USUAL tokens, allowing them to outperform the underlying yield.

**Key features of USD0++:**

* Retain full ETH exposure (1:1 peg to ETH)
* Earn yield through USUAL distributions
* Redeem their position anytime for wstETH

#### **USUAL**

USUAL is Usual’s governance token, but it’s much more than just a token to vote with. It represents ownership of the protocol, meaning users benefit from the protocol’s growth and revenue. The more USD0 is used, the more valuable USUAL becomes. It also gives users a say in how the protocol is run, including decisions on collateral types and rewards distribution.

**Key features of USUAL:**

* Represents ownership in the protocol’s revenue
* The token supply grows slowly over time, ensuring it becomes more valuable as the protocol grows
* USUAL holders can stake their tokens to earn more USUAL and participate in governance


# Features

As of  the TGE (Token Generation Event) the Usual protocol contains a holistic set of features (and their smart contracts) that enable an end-to-end experience and value creation for the users.

<table data-card-size="large" data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center"><strong>Get to know USD0</strong></td><td data-object-fit="cover"><a href="/files/JQdm3yz3Fv3V3lmfyKyJ">/files/JQdm3yz3Fv3V3lmfyKyJ</a></td><td><a href="/pages/xq3FozjrmymxaHDqGZrY">/pages/xq3FozjrmymxaHDqGZrY</a></td></tr><tr><td align="center"><strong>Get to know bUSD0</strong></td><td><a href="/files/wbMv5aqkiTYoJvPxfgbC">/files/wbMv5aqkiTYoJvPxfgbC</a></td><td><a href="/pages/FFz1RXLP88QvofWykkjB">/pages/FFz1RXLP88QvofWykkjB</a></td></tr><tr><td align="center"><strong>Get to know USD0a</strong></td><td><a href="/files/aySxNw8DQRz8tnWaAjQp">/files/aySxNw8DQRz8tnWaAjQp</a></td><td><a href="/pages/ZIeBVYDcTBnknTZB5wSb">/pages/ZIeBVYDcTBnknTZB5wSb</a></td></tr><tr><td align="center"><strong>Get to know EUR0</strong></td><td><a href="/files/zo5FT2ZSqQjD69X6bLQ2">/files/zo5FT2ZSqQjD69X6bLQ2</a></td><td><a href="/pages/Zq1KKzOnPYiehFnpLQ8x">/pages/Zq1KKzOnPYiehFnpLQ8x</a></td></tr><tr><td align="center"><strong>Get to know ETH0</strong></td><td data-object-fit="cover"><a href="/files/qT6aiOwhhSRwqXMOHqyS">/files/qT6aiOwhhSRwqXMOHqyS</a></td><td><a href="/pages/swC6xwtSsbIyduQaWCgu">/pages/swC6xwtSsbIyduQaWCgu</a></td></tr><tr><td align="center"><strong>Get to know USUAL</strong></td><td data-object-fit="cover"><a href="/files/TvZ8fCwIuJZoo06rLGup">/files/TvZ8fCwIuJZoo06rLGup</a></td><td><a href="/pages/st99sweRRYSXmJ7rPngq">/pages/st99sweRRYSXmJ7rPngq</a></td></tr><tr><td align="center"><strong>Get to know USUALx</strong></td><td data-object-fit="cover"><a href="/files/qhqxMz15LLNT0t0ablMG">/files/qhqxMz15LLNT0t0ablMG</a></td><td><a href="/pages/ZzawDvfrPcL3Md49rLMh">/pages/ZzawDvfrPcL3Md49rLMh</a></td></tr><tr><td align="center"><strong>Get to know USUAL*</strong></td><td data-object-fit="cover"><a href="/files/lIknb3oH5ijPfyD7GLRF">/files/lIknb3oH5ijPfyD7GLRF</a></td><td><a href="/pages/aHp39GtVARGjCvwj9tNJ">/pages/aHp39GtVARGjCvwj9tNJ</a></td></tr><tr><td align="center"><strong>Understand our USD0 Mint &#x26; Redeem Engine</strong></td><td data-object-fit="cover"><a href="/files/2TIl4bICzuGlHkE8twRn">/files/2TIl4bICzuGlHkE8twRn</a></td><td><a href="/pages/UV46CEGOPtshzGZQP1sD">/pages/UV46CEGOPtshzGZQP1sD</a></td></tr><tr><td align="center"><strong>Understand the USUAL distribution</strong></td><td data-object-fit="cover"><a href="/files/CRLHrQo6RDHp65t15GKO">/files/CRLHrQo6RDHp65t15GKO</a></td><td><a href="/pages/Iizkk2DtLjfvRZrxx3p6">/pages/Iizkk2DtLjfvRZrxx3p6</a></td></tr></tbody></table>


# USD0

## Overview

USD0 is a USD-pegged stablecoin designed for secure and seamless use across the DeFi ecosystem. It is fully backed by US Treasury Bill tokens, offering enhanced security without reliance on traditional banks. The coin is permissionless and easily integrable, with real-time reserve transparency provided by fund administrators. USD0 consolidates liquidity from diverse sources and utilizes an innovative mint engine for efficient collateralization, ensuring peg stability and compliance with US and EU regulations, making it a reliable alternative to USDC and USDT.

<figure><img src="/files/gZhQeMTg7lG5ObGqHRT6" alt=""><figcaption><p>USD0 Overview</p></figcaption></figure>

<details>

<summary><strong>How to Mint USD0</strong></summary>

USD0 tokens can be minted through Usual's counter in two ways:

1. **Direct Mint:** By depositing an eligible RWA into the protocol to receive an equivalent amount of USD0 on a 1:1 basis.
2. **Indirect Mint**: By depositing USDC into the protocol to receive USD0 on a 1:1 basis. In this method, a third party known as the Collateral Provider (CP) supplies the necessary RWA collateral, enabling users to obtain USD0 without directly holding RWAs.&#x20;

</details>

<details>

<summary><strong>How to Redeem USD0</strong></summary>

USD0 tokens can be redeemed in two ways:

1. **Withdrawal of Underlying Assets**: Users can withdraw the Real World Asset (RWA) underlying the USD0 token directly with the Usual dApp
2. **Secondary Market Transactions**: Users can sell USD0 for USDC/T on the secondary market. As USD0 is fully redeemable within Usual's dApp, the 1:1 peg is expected to be maintained through arbitrage, similar to other fiat backed stablecoins.

</details>

## Smart Contract

{% content-ref url="/pages/kaGk2EIk5c3i9os6uhLk" %}
[USD0](/smart-contracts/token-contracts/usd0)
{% endcontent-ref %}


# bUSD0 (formerly USD0++)

## Overview

bUSD0 (Bond USD0) represents USD0 stablecoin locked until June 11, 2028. It remains transferable during this period, earning USUAL incentives and maturity yield. Users receive 1 USD0 for 1 bUSD0 at maturity. For early redemption, users need an equivalent amount of rt-USD0 - received at mint - which unlocks bUSD0 back into USD0 at a 1:1 rate anytime. Additionally, early redemption below peg can be made at a DAO set price floor.

<details>

<summary><strong>bUSD0 Issuance</strong></summary>

A holder of USD0 can deposit their USD0 into bUSD0 at any time:

1. **Depositing USD0**: The user deposits their USD0 to convert them into bUSD0.
2. **1:1 Issuance**: bUSD0 are issued on a 1:1 basis with the deposited USD0. Along side with bUSD0 users also receive redemption token (rt-bUSD0) that allows them to leave bUSD0 at any time before the maturity date.
3. **Bond Duration**: bUSD0 has a maturity date (11 June, 2028) with guaranteed 1:1 redemption — or at any time by burning the redemption token.

</details>

<details>

<summary><strong>bUSD0 Redemption</strong></summary>

Users can exit their position in the following ways:

**1) Redeem 1:1 back into USD0 using rt-bUSD0.**

Provide an equivalent amount of rt-bUSD0 (the redemption-right token received at mint) to unlock bUSD0 at full value. Any missing rt-bUSD0 can be purchased on the secondary market.

**2) Sell bUSD0 on the secondary market.**

Because bUSD0 remains fully transferable, users can exit instantly at the market price whenever you choose.

**3) Redeem at the DAO-defined floor price.**

If bUSD0 trades below its projected remaining maturity value, users can redeem at a protocol-set floor price that reflects the remaining risk-free yield of USD0, ensuring a minimum guaranteed exit.

**4) Wait until maturity.**

At maturity, bUSD0 unlocks automatically and can be redeemed 1:1 back into USD0 without requiring rt-bUSD0.

</details>

{% content-ref url="/pages/jA9gCTlpvd8kcZidif4W" %}
[bUSD0 (formerly USD0++)](/smart-contracts/token-contracts/usd0++)
{% endcontent-ref %}


# USD0a

## Overview

USD0a is a yield-bearing accrual asset designed for secure and seamless use across the DeFi ecosystem. It is fully backed by USDC, USTB and USCC tokens, offering enhanced security without reliance on traditional banks. The coin is permissionless and easily integrable, with real-time reserve transparency provided by fund administrators. USD0a consolidates liquidity from diverse sources and utilizes an innovative mint engine for efficient collateralization, with its price determined by the value of the underlying collateral and the total supply, generating yield for holders and providing a transparent, collateral-backed asset for the DeFi ecosystem.

<details>

<summary><strong>How to Mint USD0a</strong></summary>

USD0a tokens can be minted through Usual's counter in two ways:

1. **Direct Mint:** By depositing an eligible RWA into the protocol to receive an equivalent amount of USDa depending on its actual price.
2. **Indirect Mint**: By depositing USDC into the protocol to receive an equivalent amount of USDa depending on its actual price. In this method, a third party known as the Collateral Provider (CP) supplies some USDC, enabling users to obtain USD0a with a discount amount.

</details>

<details>

<summary><strong>How to Redeem USD0a</strong></summary>

USD0a tokens can be redeemed in two ways:

1. **Withdrawal of Underlying Assets**: Users can withdraw the Real World Asset (RWA) underlying the USD0a token directly with the Usual dApp

</details>

## Smart Contract

{% content-ref url="/pages/PEM5Zae6N4OwXnZqAgda" %}
[USD0a](/smart-contracts/protocol-contracts/usd0a)
{% endcontent-ref %}


# Mint & Redeem Engine

## Overview

The mint and redeem engine of the Usual protocol, combines two smart contracts: **DaoCollateral** and **Swapper Engine**. These contracts work in tandem to manage the creation and redemption of USD0 and EUR0, stablecoins backed by Real World Assets (RWAs). Together, they ensure the full collateralization, while providing users with a seamless, non-custodial trading experience. This system is enhanced by an intent-based matching system and an order-matching mechanism, offering an efficient and transparent process for minting, redeeming, and swapping USD0, EUR0 with USDC and EURC respectively. The flows below display interactions, using USD0 as an example. Other Usual issued Stablecoins work similarly.

<details>

<summary><strong>Minting USD0 via DaoCollateral</strong></summary>

* A user who holds RWAs (represented as USYC tokens) interacts with the DaoCollateral contract to mint USD0 stablecoins
* The user sends USYC tokens to the DaoCollateral contract, which calculates the equivalent amount of USD0 at the current exchange rate
* USD0 is minted and provided to the user in exchange for their USYC tokens
* This ensures that every USD0 in circulation is backed by RWAs, providing stability and security

</details>

<details>

<summary><strong>Redeeming USD0 via DaoCollateral</strong></summary>

* Users who hold USD0 stablecoins can redeem them for RWAs (USYC tokens)
* The user invokes the redeem function, providing their USD0 to the DaoCollateral contract
* The contract calculates the equivalent value of USYC tokens based on the current exchange rate and sends these tokens to the user, burning the corresponding USD0 in the process

</details>

<details>

<summary><strong>Swapping USDC and USD0 via Swapper Engine</strong></summary>

* Users can create orders specifying the amount of USDC they want to swap for USD0 by depositing USDC into the Swapper Engine
* Other users can fill these orders by providing USD0, with the contract verifying their USD0 balance and allowance
* The contract relies on an external oracle to fetch the current USDC price, ensuring that swaps happen at accurate and fair exchange rates
* Partial or full matching of orders is allowed, depending on user preferences and order availability

</details>

<details>

<summary><strong>Three-Way Intent-Based Matching System</strong></summary>

* In a three-party trade facilitated by DaoCollateral, a **USDC provider**, an **RWA provider**, and the **DaoCollateral contract** come together
  * The **USDC provider** deposits USDC into the Swapper Engine and receives USD0 in return.
  * The **RWA provider**, who holds RWAs (USYC tokens), submits an intent to exchange these tokens for USDC
  * The DaoCollateral contract mints new USD0 in exchange for the RWAs from the RWA provider and uses this newly minted USD0 to fulfill the USDC provider’s order.
  * Finally, the contract transfers the USDC from the Swapper Engine to the RWA provider, completing the trade
* This intent-based matching system ensures efficient, non-custodial trading by allowing RWA providers to retain their assets until the trade is executed.

</details>

## Smart Contracts

{% content-ref url="/pages/9VSTNV5ffFhdsBG7JCjZ" %}
[USD0 Swapper Engine](/smart-contracts/protocol-contracts/usd0/usd0-swapper-engine)
{% endcontent-ref %}

{% content-ref url="/pages/cdEnoP1Vp2m1T0Lp8xc1" %}
[USD0 DaoCollateral](/smart-contracts/protocol-contracts/usd0/usd0-daocollateral)
{% endcontent-ref %}


# EUR0

## Overview

EUR0 is a euro-pegged stablecoin designed for secure and seamless use across the DeFi ecosystem. It is fully backed by EU issued T-Bills, offering enhanced security without reliance on traditional banks. The coin is permissionless and easily integrable, with real-time reserve transparency provided by fund administrators. EUR0 consolidates liquidity from diverse sources and utilizes an innovative mint engine for efficient collateralization, ensuring peg stability and compliance with EU regulations, making it a reliable alternative to other EURO pegged stablecoins.

<details>

<summary><strong>How to Mint EUR0</strong></summary>

EUR0 tokens can be minted through Usual's counter in two ways:

* Direct Mint: By depositing an eligible RWA (e.g. Spiko euTBL) into the protocol to receive an equivalent amount of EUR0 on a 1:1 basis.
* Indirect Mint: By depositing EURC into the protocol to receive EUR0 on a 1:1 basis. In this method, a third party known as the Collateral Provider (CP) supplies the necessary RWA collateral, enabling users to obtain EUR0 without directly holding RWAs.

</details>

<details>

<summary><strong>How to Redeem EUR0</strong></summary>

* Withdrawal of Underlying Assets: Users can withdraw the Real World Asset (RWA) underlying the EUR0 token directly with Usual's dApp
* Secondary Market Transactions: Users can sell EUR0 for EURC (or any other token) on the secondary market. As EUR0 is fully redeemable within Usual's dApp the 1:1 peg is expected to be maintained through arbitrage, similar to other fiat-backed stablecoin.

</details>

## Smart Contract

{% content-ref url="/pages/LVV3gKZANqXlUlDnvBBz" %}
[EUR0](/smart-contracts/token-contracts/eur0)
{% endcontent-ref %}


# ETH0

## Overview

**ETH0** is a synthetic Ethereum-based asset issued by the Usual Protocol and **fully collateralized by Lido’s wrapped staked ETH (wstETH)**. It’s designed for institutions, whales, and sophisticated DeFi users who want to maintain ETH exposure while significantly boosting yield. Unlike traditional staked ETH (which earns \~3.5% APY), ETH0 holders don’t receive yield directly. Instead, they earn USUAL tokens, which capture protocol revenues and speculative upside, potentially pushing **effective returns to double digits** (e.g. 13% APY according to simulations).

**ETH0** allows users to:

* Retain full ETH exposure (1:1 peg to ETH)
* Earn yield through USUAL distributions
* Redeem their position anytime for wstETH
* Use ETH0 composably across DeFi platforms like Pendle or Morpho

Built on the same infrastructure as Usual’s USD0 stablecoin (backed by tokenized T-bills), ETH0 brings a **DeFi-native yield abstraction model** to ETH-based portfolios. All minting and redemption are atomic, on-chain, and secured by a rigorously audited, upgradeable contract system with oracle-based price validation.

<details>

<summary><strong>How to mint ETH0</strong></summary>

1. User holds wstETH (wrapped stETH from Lido).
2. They visit the Usual dApp and navigate to the ETH0 Vault interface.
3. The user deposits wstETH via the smart contract.
4. The protocol validates collateral via oracles and mints ETH0 tokens at a 1:1 ETH value.
5. ETH0 is sent to the user’s wallet. Minting is atomic, permissionless, and immediate.

</details>

<details>

<summary>How to redeem ETH0</summary>

1. User holds ETH0 and wants to convert back to wstETH.
2. They initiate a redemption via the Usual dApp.
3. The ETH0 tokens are burned, and the contract releases the underlying wstETH.
4. A small redemption fee (e.g., 3-5 bps) may apply.
5. The wstETH is transferred to the user’s wallet, completing the redemption.

</details>

<details>

<summary><strong>How earn yield in USUAL for holding ETH0</strong></summary>

1. By simply holding ETH0 in their wallet, users start accumulating protocol-based rewards.
2. The staking yield from the underlying wstETH is redirected to the Usual treasury.
3. That value is redistributed via USUAL token emissions, which are claimable by ETH0 holders (e.g. via a claim UI or distribution mechanism).
4. The USUAL token provides speculative upside and participation in protocol revenue—potentially boosting effective APY well beyond wstETH’s base yield.
5. Users may choose to hold, sell, or stake USUAL to amplify returns further (e.g., in USUALx programs).

</details>

## Smart Contracts

{% content-ref url="/pages/8r4eu8RTOTRGJfvRqvTf" %}
[ETH0](/smart-contracts/token-contracts/eth0)
{% endcontent-ref %}


# USUAL

## Overview

$USUAL is the governance and utility token of the protocol designed for long-term value and sustainable growth, backed by real cash flows from the Usual Protocol. It offers disinflationary issuance, with supply tied to the Total Value Locked (TVL) of staked USD0, and is aligned with future cash flows to ensure that emissions remain lower than revenue growth. USUAL holders can stake tokens to earn rewards and activate governance rights, which include managing treasury and protocol decisions. It also allows governance control over collateral types, optimizing stability.

<details>

<summary><strong>USUAL issuance</strong></summary>

USUAL is issued to USD0, USD0++, USUALx and USUAL\* users on daily basis based on the USUAL distribution math. For further details see [USUAL distribution](https://app.gitbook.com/o/qhhUYNkfevGh3Y1MDQaS/s/pUhQzPJGdJzuLTQ5sCym/overview/features#usual-distribution).

</details>

## Smart Contract

{% content-ref url="/pages/tg0GXKS5hSLFJHzLMwcs" %}
[USUAL](/smart-contracts/token-contracts/usual)
{% endcontent-ref %}


# USUAL\*

## Overview

USUAL\* is a specialized token designed for early investors, contributors, and advisors of the Usual protocol, granting them unique benefits and governance power. It inherits basic functionalities from the USUAL token. Holders of USUAL\* are entitled to 10% of all USUAL distributions, a right that is permanently integrated into the protocol and cannot be overridden. Initially, USUAL\* holders maintain majority voting control to ensure the project adheres to its roadmap during the early stages of development. Over time, the governance structure will evolve toward a more decentralized model centered on USUAL token holders, but without compromising the immutable rights of USUAL\* holders.

<details>

<summary><strong>USUAL* issuance</strong></summary>

Investor, contributors and insider will receive USUAL\* at TGE as a staked, cliffed and vested allocation that receives 10% of the daily USUAL distribution. In order to claim USUAL\* a user will have to unstake the vested allocation, thereby minting the token.&#x20;

</details>

## Smart Contract

{% content-ref url="/pages/BY7v4Ols7VxILL81pfAs" %}
[USUAL\*](/smart-contracts/token-contracts/usual-1)
{% endcontent-ref %}


# USUALx (USUAL staking)

## Overview

The UsualX staking feature is a robust, upgradeable ERC4626-compliant vault designed for secure yield generation. It offers functionalities like whitelist and blacklist management, withdrawal fees, and yield distribution over specific periods.&#x20;

<details>

<summary><strong>Receive USUAL staking yield</strong></summary>

1. **Deposit:** USUAL owner can deposit their tokens into USUALx vault and will receive a vaultshare token (call USUALx) that represents their share a will be used to calculate the amount of USUAL token rewards a user eligible for.<br>
2. **Redeem:** User can claim the yield by exchanging vaultshare tokens for the USUAL rewards within the vault against a fee that is set by the DAO. Partial redemptions are possible.

</details>

## Smart Contracts

{% content-ref url="/pages/hVEHgJJFGXbFc718EiZn" %}
[USUALx](/smart-contracts/token-contracts/usualx)
{% endcontent-ref %}

{% content-ref url="/pages/VBhNuXyI7b8ZM0aS41Hz" %}
[USUAL staking](/smart-contracts/protocol-contracts/usual/usual-staking)
{% endcontent-ref %}


# USUAL distribution

## Overview

The USUAL token distribution system is designed to ensure fair, efficient, and community-driven emission. Tokens are distributed through a daily mechanism, which adjusts based on the protocol's performance indicators, such as TVL growth and interest rates. Emissions are allocated to on-chain vaults, like UsualX and UsualS, as well as off-chain participants through a merkle proof validation process. To prevent excessive inflation, emissions are capped and decrease over time as the TVL grows. Governance controls the allocation of tokens across various categories, such as liquidity providers, stakers, and market makers, ensuring flexibility and alignment with protocol growth. For more information see [USUAL Distribution Model](/overview/architecture/usual-distribution-model).

<figure><img src="/files/ZsL80ZQWF3BF5nbrTGnM" alt=""><figcaption><p>High level flow of the USUAL distribution model</p></figcaption></figure>


# Usual bUSD0 (formerly USD0++) Investment Vault

## Overview

The **Usual bUSD0 Investment Vault** is a seamlessly integrated, yield-bearing vault designed to make DeFi investment effortless and immediate. bUSD0 holders can deposit directly into the vault and begin earning yield **synchronously** — no waiting periods, no bridging, and no off-platform interaction required. All returns are compounded through carefully curated DeFi strategies and users also receive USUAL token rewards. This synchronous model keeps user assets productive from the moment of deposit, while not needing to leave the Usual ecosystem — maximizing both convenience and capital efficiency.

<details>

<summary><strong>Depositing into the vault</strong></summary>

When a user deposits into the vault using bUSD0 (or other supported tokens), the process is immediate and fully automated. Behind the scenes, the system swaps these tokens into the vault's yield-bearing asset and deposits them — all in one synchronous transaction. Users receive vault shares instantly, which begin earning yield without delay. There's no need to manually manage assets across protocols or worry about market timing — every deposit is executed atomically, and earnings start from block one.

</details>

<details>

<summary><strong>Withdrawing from the vault</strong></summary>

Withdrawals from the vault are just as streamlined. Users redeem their shares in a single step, triggering the vault to withdraw the underlying asset, calculate and apply any fees, and swap it back to bUSD0. This entire process is handled synchronously within the same transaction, ensuring users get immediate access to their funds without waiting for batch processing or delayed harvests. It's fast, reliable, and fully integrated within the Usual infrastructure.

</details>

## Smart Contracts

{% content-ref url="/pages/XWFXRZeD1sOLrTFs4LVV" %}
[Usual bUSD0 Investment Vault](/smart-contracts/token-contracts/usual-usd0++-investment-vault)
{% endcontent-ref %}

{% content-ref url="/pages/EUSBAWJiOvY1GPFmRBY3" %}
[VaultRouter](/smart-contracts/token-contracts/usual-usd0++-investment-vault/vaultrouter)
{% endcontent-ref %}


# Architecture

{% hint style="info" %}
This architecture describes the V1 state of the USD0, ETH0 and USUAL protocol. Further updates will be commenced with new feature releases.
{% endhint %}

<figure><img src="/files/o9l1HKl5oNgY8FCvGfrG" alt=""><figcaption><p>V1 Architecture</p></figcaption></figure>

{% hint style="info" %}
This architecture describes the V1 state of the ETH0. Further updates will be commenced soon.
{% endhint %}

<figure><img src="/files/RiadAF4DjMzXwMW2jqWK" alt=""><figcaption><p>ETH0 V1 Architecture</p></figcaption></figure>

{% hint style="info" %}
This architecture describes the V1 state of the EUR0. Further updates will be commenced soon.
{% endhint %}

<figure><img src="/files/WiRMKKZ3jCHdzteBfily" alt="EUR0 V1 Architecture"><figcaption><p>EUR0 V1 Architecture</p></figcaption></figure>

The Usual protocol contracts are specifically engineered to handle complex operations such as asset swaps between Real World Assets (RWAs) and stablecoins, lifecycle management of the USD0 stablecoin, structured financial product issuance, efficient asset exchange without traditional liquidity pools, and accurate asset pricing for reliable transaction execution.

Usual's smart contracts follow the [transparent proxy pattern](https://docs.openzeppelin.com/contracts/4.x/api/proxy#TransparentUpgradeableProxy) to allow the Usual DAO to upgrade the protocol contracts, to expand its functionalities and have the possibility to remedy any unexpected issues. Our current on-chain Collateral RWA consists of [Hashnote's USYC](https://usyc.hashnote.com/).

## **Core Contracts**

### [**DaoCollateral**](/smart-contracts/protocol-contracts/usd0/usd0-daocollateral)

The `daoCollateral.sol` contract is essential in swapping real-world assets (RWAs) . It enables users to swap RWAs for the USD0 stablecoin and vice versa, and serves as a key node for converting these assets into more liquid forms like USDC.

* **Key Functionalities:**
  * **Swap and Redeem Mechanisms**: Facilitate the conversion between RWAs and Usual's stablecoin (USD0), as well as swapping into USDC for enhanced liquidity in conjunction with the SwapperEngine.

### [**USD0**](/smart-contracts/token-contracts/usd0)

The primary Stablecoin of Usual, a liquid and transferable ERC-20 token that can be staked or locked to receive rewards. It is backed by cash equivalents like tokenized money market funds.

* **Key Functionalities:**
  * **Controlled Minting and Burning**: Manages the stablecoin supply to match backing assets, essential for value stability.

### [**bUSD0 (formerly USD0++)**](#usd0-1)

The `USD0PP contract` is tailored for bond management, replicating traditional fixed end-date bonds. It allows for the issuance, management, and redemption of bUSD0 (formerly USD0++), a 4 year bond emitting off-chain yield (only during the pre-launch, on-chain afterwards)

* **Key Functionalities:**
  * **Bond Lifecycle Management**: Facilitates the minting and unwrapping of bond tokens, offering fixed-income securities in blockchain format.
  * **Emergency Withdrawal Mechanisms**: Provides options for asset withdrawal in critical situations, reinforcing trust and security for investors.
  * **Automated Parity Mechanisms**: Provides options for the Usual DAO to maintain parity of USD0<->bUSD0 (formerly USD0++) on secondary markets if deemed necessary.
  * **Floor-price redemption:** Provides an early-redemption option to redeem bUSD0 (formerly USD0++) before the bond maturity date for the floor price.

### [**SwapperEngine**](/smart-contracts/protocol-contracts/usd0/usd0-swapper-engine)

The SwapperEngine contract ensures efficient token swaps between USDC and USD0 through an order matching system, avoiding traditional liquidity pools for direct no-fee, low-slippage exchanges.

* **Key Functionalities:**
  * **Efficient Order Matching**: Allows for precise order placement and fulfillment, minimizing costs and slippage.

### [**ClassicalOracle**](/smart-contracts/utility-contracts/usd0/usd0-classicaloracle)

Essential for the ecosystem's functionality, the ClassicalOracle contract sources accurate pricing information to inform asset valuations , ensuring all financial operations are based on reliable market data.

* **Key Functionalities:**
  * **Robust Data Sources**: Aggregates and evaluate prices from pricefeeds to diminish risks related to price manipulation.
  * **Stablecoin Monitoring**: Implements checks to maintain stablecoin pegs, crucial for the ecosystem's financial stability.

### [**USUAL**](/smart-contracts/token-contracts/usualx)

The `USUAL` contract implements the governance token of the Usual Protocol, incorporating security features and role-based access control. $USUAL is a ERC-20 compliant token designed with pausability and permit functionalities, allowing for enhanced governance mechanisms and secure token operations.

* **Key Functionalities:**
  * **Role-Based Token Operations**: Implements strict access control for critical functions like minting, burning, and blacklist management through dedicated roles (USUAL\_MINT, USUAL\_BURN, BLACKLIST\_ROLE).

### [**USUAL\***](/overview/features/usual-1)

The `Usual*` contract implements the Early Contributor Token of the Usual Protocol, incorporating security features and role-based access control. $USUAL is a ERC-20 compliant token designed with pausability and permit functionalities, allowing for enhanced governance mechanisms and secure token operations. The totalSupply is capped and no further mints of `USUAL*` are possible. All Usual\* is initially locked into the [UsualSP contract](/smart-contracts/protocol-contracts/usual/usual-vested-allocation-staking) as part of the allocation/ vested mechanic.

* **Key Functionalities:**
  * **Role-Based Token Operations**:
    * Strict access control for critical functions through dedicated roles (USUALS\_BURN, BLACKLIST\_ROLE)
    * Special one-time deployment privileges for the USUALSP contract via stakeAll()

### [**Distribution Module Contract**](/smart-contracts/protocol-contracts/usual/usual-distribution)

The `DistributionModule` contract manages the daily distribution of Usual tokens across on-chain vaults (UsualX and UsualS) and off-chain user allocations. It implements a sophisticated distribution system with challenge mechanisms and merkle-proof validation to ensure fair and secure token allocation.

* **Key Functionalities:**
  * **Daily Token Distribution**:
    * Calculates and distributes new token emissions
    * Manages off-chain distribution allocations through a merkle-proof system
    * Scales distribution based on time elapsed since last distribution
  * **Security Mechanisms**:
    * Challengeable queue system for off-chain distributions
    * 7-day challenge period for distribution validation
    * Role-based access control for critical operations
  * **Distribution Features**:
    * Configurable bucket allocation percentages
    * Real-time emission calculations based on protocol parameters
    * Automated distribution tracking and validation system

### [Yield Module Contract](/smart-contracts/protocol-contracts/usual/usual-distribution/yield-module)

The `YieldModule` contract manages the collection, accumulation, and distribution of yield generated from Real World Assets (RWAs) backing the protocol's stablecoins. It serves as the central hub for yield processing and implements sophisticated mechanisms to ensure fair and efficient yield distribution across protocol participants.

* **Key Functionalities:**
  * **Yield Collection & Processing**:
    * Aggregates yield from multiple RWA sources backing USD0
    * Calculates blended interest rates from various RWA (Real World Asset) sources
    * Tracks interest rates for different assets via oracles or manual input
    * Calculates weighted average interest rates based on asset values in treasuries
    * Manages treasury addresses where assets are held
    * Provides a P90 interest rate for protocol calculations
* **Security Mechanisms:**
  * **Access Control:**
    * Role-based permissions for yield collection and calculation operations
  * **Yield Validation:**
    * Data freshness (checks if oracle data is within maxDataAge)
    * Feed interface validity (checks if Chainlink feed returns valid data)
    * Interest rate bounds (ensures rates don't exceed basis point limits)

This module works in conjunction with the Distribution Module to ensure that both newly minted tokens and accumulated yields are distributed fairly and efficiently across the protocol ecosystem.

### [ETH0](/overview/features/eth0)

`ETH0` is an Ethereum-pegged synthetic ERC-20 compliant token fully collateralized by wstETH.

* **Key Functionalities:**
  * **Controlled Minting and Burning**: Manages the ETH0 supply to match backing asset (wstETH), essential for value stability.
  * **Controlled Supply Management**:

    Mint Cap: Has a configurable mint cap to prevent excessive issuance
  * **Role-Based Token Operations**:
    * Strict access control for critical functions through dedicated roles (ETH0\_MINT, ETH0\_BURN, BLACKLIST\_ROLE)
    * Emergency stop though dedicated role (PAUSING\_CONTRACTS\_ROLE, UNPAUSING\_CONTRACTS\_ROLE)

### [ETH0 DaoCollateral](/smart-contracts/protocol-contracts/eth0/eth0-daocollateral)

`ETH0 DaoCollateral` contract is a core component of ETH0 that manages collateralization, minting, and redemption of ETH0 tokens. It ensures ETH0 is fully backed by collateral and provides secure mechanisms for token swapping and redemption with emergency safeguards.

* **Key Functionalities:**
  * **Swap and Redeem Mechanisms**: Facilitate the conversion between wstETH and Usual's ETH (ETH0).
  * **Role-Based Token Operations**: Segregated roles for admin, pausing, unpausing, and DAO operations
  * **Fee Management** Adjustable redemption fees (max 25%) for protocol sustainability and automated fee distribution to yield treasury
* **Security Mechanisms:**
  * **Counter Bank Run (CBR)**: Emergency mechanism that reduces collateral returns during market stress
  * **Pausability**: Granular pausing of swap/redeem operations and global contract pausing

### [EUR0](/smart-contracts/token-contracts/eur0)

`EUR0` is an Ethereum-pegged synthetic ERC-20 compliant token fully collateralized by EUTBL.

* **Key Functionalities:**
  * **Controlled Minting and Burning**: Manages the EUR0 supply to match backing asset (EUTBL), essential for value stability.
  * **Role-Based Token Operations**:
    * Strict access control for critical functions through dedicated roles (EUR0\_MINT, EUR0\_BURN, BLACKLIST\_ROLE)
    * Emergency stop though dedicated role (PAUSING\_CONTRACTS\_ROLE, UNPAUSING\_CONTRACTS\_ROLE)

### [EUR0 DaoCollateral](/smart-contracts/protocol-contracts/eur0/eur0-daocollateral)

`EUR0 DaoCollateral` contract is a core component of EUR0 that manages collateralization, minting, and redemption of EUR0 tokens. It ensures EUR0 is fully backed by collateral and provides secure mechanisms for token swapping and redemption with emergency safeguards.

* **Key Functionalities:**
  * **Swap and Redeem Mechanisms**: Facilitate the conversion between EUTBL and Usual's EUR (EUR0).
  * **Role-Based Token Operations**: Segregated roles for admin, pausing, unpausing, and DAO operations
  * **Fee Management** Adjustable redemption fees (max 25%) for protocol sustainability and automated fee distribution to yield treasury
* **Security Mechanisms:**
  * **Counter Bank Run (CBR)**: Emergency mechanism that reduces collateral returns during market stress
  * **Pausability**: Granular pausing of swap/redeem operations and global contract pausing

### [EUR0 SwapperEngine](/smart-contracts/protocol-contracts/eur0/eur0-swapperengine)

The SwapperEngine contract ensures efficient token swaps between EURC and EUR0 through an order matching system, avoiding traditional liquidity pools for direct no-fee, low-slippage exchanges.

* **Key Functionalities:**
  * **Efficient Order Matching**: Allows for precise order placement and fulfillment, minimizing costs and slippage.

### [USUALX Lockup](/smart-contracts/protocol-contracts/usual/usualx-lockup-contract)

The `UsualXLockup` contract allows users to lock their **UsualX** tokens for predetermined durations (1, 3, 6, or 12 months). It's designed primarily for governance participation and reward earning mechanisms, providing a secure and flexible token locking infrastructure with comprehensive position management capabilities.

* **Key Functionalities:**
  * **Locking Operations**
    * **Position Creation**: Users can create new lock positions with specified amounts and durations
    * **Intra-day Top-ups**: Enhance existing positions within the same UTC calendar day as creation
    * **Position Release**: Withdraw tokens after lock expiration
    * **Combined Operations**: Release expired positions and immediately create new ones
* **Security Mechanisms:**
  * **Role-based Permissions**: Different roles for pausing, unpausing, duration management, and forced unlocking
  * **Reentrancy Protection**: Guards against reentrancy attacks on all state-changing functions
  * **Pausable Operations:** Emergency halt capabilities for contract operations
* **Administrative Features**
  * **Lock Duration Management**: Configure which lock durations are available
  * **Batch Processing**: Efficient handling of multiple position unlock operation
  * **Balance Tracking**: Total locked amount per user


# Role Management

## Role & Permissions

### DEFAULT\_ADMIN

The DEFAULT\_ADMIN role serves as the highest administrative authority in the system, possessing complete control over role management and critical system parameters. This role can manage all other roles, control emergency functions, configure core system parameters, and execute privileged operations across all contracts. It is typically assigned to a secure multisig wallet or governance contract and cannot be renounced to prevent system lockup.\
A delay of three days must be observed before granting that role to a new address.

**Role Holders**: Usual Multisig

* Add USD0 RWA (TokenMapping)
* Unpause (AirdropDistribution, AirdropTaxCollector, DaoCollateral, DistributionModule, L2Usd0, L2Usd0PP, SwapperEngine, Usd0, USD0pp, Usual, UsualS, USUALSP, UsualX)
* Activate/Deactivate CBR (DaoCollateral)
* Set redeem fee (DaoCollateral)
* Redeem DAO (DaoCollateral)
* Unpause redeem/swap (DaoCollateral)
* Set max depeg threshold (AbstractContract)
* Initialize token oracle (ClassicalOracle, UsualOracle)
* Set role admin (RegistryAccess)
* Set contract (RegistryContract)
* Update minimum USDC amount provided (SwapperEngine)
* Emergency withdraw (USD0pp)

### PAUSING\_CONTRACTS\_ROLE

The PAUSING\_CONTRACTS\_ROLE exists as an emergency control mechanism to halt contract operations when critical issues are detected. This role has the ability to pause functionality across multiple core contracts including token transfers, DAO collateral operations, and swapper engine activities. It serves as a first line of defense against potential exploits or system anomalies.

**Role Holders**: Usual Multisig

* Pause ( DaoCollateral, DistributionModule, L2Usd0, L2Usd0PP, SwapperEngine, Usd0, USD0pp, Usual, UsualS, USUALSP, UsualX)

### UNPAUSING\_CONTRACTS\_ROLE

The UNPAUSING\_CONTRACTS\_ROLE is crucial for resuming normal operations after an emergency pause has been enacted. This role ensures that, after thorough checks and validations, the systems and contract functionalities that were halted can be safely reactivated. It is critical for maintaining operational continuity and system integrity.

**Role Holders**: Usual Multisig

* Unpause ( DaoCollateral, DistributionModule, L2Usd0, L2Usd0PP, SwapperEngine, Usd0, USD0pp, Usual, UsualS, USUALSP, UsualX)

### USUAL\_M\_PAUSE

The USUAL\_M\_PAUSE role is dedicated to managing pause functions for wrapped m. Holders of this role have the authority to initiate emergency pauses, ensuring immediate response to critical threats or issues within the system's operations. This ability is essential for maintaining system security and operational stability during unforeseen events.

**Role Holders**: Usual Pauser

* Pause (UsualM)

### USUAL\_M\_UNPAUSE

The USUAL\_M\_UNPAUSE role is critical for resuming operations that were halted due to an emergency pause. Holders of this role can safely unpause the system once the underlying issues are addressed, ensuring that the system returns to normal operations without compromising security and stability.

**Role Holders**: Usual Multisig

* Unpause (UsualM)

### USUAL\_M\_UNWRAP

The USUAL\_M\_UNWRAP role is responsible for managing the unwrapping operations within the system. This involves managing the conversion of wrapped tokens back to their original form in a secure and efficient manner, ensuring liquidity and accessibility for stakeholders.

**Role Holders**: Usual Multisig

* Unwrap (UsualM)

### USUAL\_M\_MINTCAP\_ALLOCATOR

The USUAL\_M\_MINTCAP\_ALLOCATOR is responsible for managing the allocation of the minting cap within the system. This role ensures that minting operations are within the predefined limits, maintaining stability and preventing excessive token creation which could impact the market.

**Role Holders**: Usual Mintcap Multisig

* setMintCap (UsualM)

### NONCE\_THRESHOLD\_MANAGER

The NONCE\_THRESHOLD\_MANAGER is tasked with continuous monitoring and management of the nonce thresholds within the DAO collateral system. This role requires frequent adjustments based on transaction volume and emerging security requirements, ensuring robust protection against unauthorized transaction replays.

**Role Holders**: Usual Multisig

* Monitor and adjust nonce thresholds (NonceManagement)

### NONCE\_THRESHOLD\_SETTER\_ROLE

The NONCE\_THRESHOLD\_SETTER\_ROLE exists to manage the nonce threshold parameters in the DAO collateral system. This role is responsible for setting and adjusting the nonce threshold that determines the validity of swap intents, helping prevent replay attacks and ensuring transaction ordering in the RWA to STBC swap process.

**Role Holders**: Usual Multisig

* Set nonce threshold (DaoCollateral)

### INTENT\_MATCHING\_ROLE

The INTENT\_MATCHING\_ROLE exists to facilitate secure RWA to STBC token swaps in the DAO collateral system. This role is responsible for executing swap intents by matching off-chain orders with on-chain transactions, ensuring proper order execution and token transfers between parties. The role is typically assigned to trusted swap operators or automated market makers authorized by the Usual Multisig.

**Role Holders**: Swapper Engine Keeper

* Swap RWA to STBC intent (DaoCollateral)

### DISTRIBUTION\_OPERATOR\_ROLE

The DISTRIBUTION\_OPERATOR\_ROLE exists to manage the daily distribution of USUAL tokens across various protocol buckets and off-chain distributions. This role is responsible for executing the core token distribution mechanics, including calculating new emissions, distributing tokens to on-chain vaults (Usual+ and Usual\*), and managing the off-chain distribution queue through merkle proofs. The role is typically assigned to an automated keeper managed.

**Role Holders**: Google KMS Service Account (Keeper)

* Distribute USUAL to buckets (DistributionModule)
* Queue off-chain USUAL distribution (DistributionModule)
* Reset off-chain distribution queue (DistributionModule)

### DISTRIBUTION\_ALLOCATOR\_ROLE

The DISTRIBUTION\_ALLOCATOR\_ROLE exists to manage the core economic parameters of the USUAL token distribution system. This role is responsible for configuring the distribution mechanics by setting emission rates, bucket allocations, and key distribution parameters that determine how USUAL tokens are distributed across different protocol components. The role has significant control over the tokenomics and must be carefully managed to ensure fair and efficient token distribution. It is typically assigned to a Usual Multisig under DAO oversight.

**Role Holders**: Usual DAO

* Set buckets distribution (DistributionModule)
* Set gamma (DistributionModule)
* Set rate min (DistributionModule)
* Set D (DistributionModule)
* Set M0 (DistributionModule)

### DISTRIBUTION\_CHALLENGER\_ROLE

The DISTRIBUTION\_CHALLENGER\_ROLE exists as a security mechanism to ensure the integrity of off-chain USUAL token distributions. This role has the authority to challenge and invalidate potentially incorrect or malicious distributions before they are finalized. It can challenge all distributions in the queue that are older than a specified timestamp and optionally propose new valid distributions with corrected merkle roots. The role serves as a critical safeguard against distribution errors or manipulation attempts and is typically assigned to the Usual Multisig.

**Role Holders**: Usual Multisig

* Challenge distribution (DistributionModule)

### BLACKLIST\_ROLE

The BLACKLIST\_ROLE exists as a security mechanism to protect the protocol from malicious actors, comply with regulatory requirements, and ensure rapid response to security incidents. This role has the authority to restrict specific addresses from participating in token transfers and protocol operations across multiple core contracts including L2USD0, L2USD0PP, USD0PP, USD0, USUAL, USUALS, and USUALX.

**Role Holders**: Usual Multisig

* Blacklist/Unblacklist (L2Usd0, L2Usd0PP, USD0pp, Usd0, Usual, UsualS, UsualX)

### USD0\_MINT

The USD0\_MINT role exists as a critical control mechanism for managing the supply of USD0 tokens in the system. This role has the authority to mint new USD0 tokens across multiple contracts including L2USD0, L2USD0PP, and USD0, but only when there is sufficient backing in the treasury. The role is typically assigned to the DAO Collateral contract and other protocol-controlled contracts to ensure automated and secure minting operations.

**Role Holders**: DAO Collateral Contract, SwapperEngine

* Mint (L2Usd0, L2Usd0PP, Usd0)

### USD0\_BURN

The USD0\_BURN role exists as a critical control mechanism for managing the supply of USD0 tokens in the system. This role has the authority to burn USD0 tokens across multiple contracts including L2USD0, L2USD0PP, and USD0, ensuring proper supply management and redemption functionality. The role is typically assigned to the DAO Collateral contract and SwapperEngine to enable automated burning operations during redemptions and swaps.

**Role Holders**: DAO Collateral Contract, SwapperEngine

* Burn (L2Usd0, L2Usd0PP, Usd0)
* Burn from (L2Usd0, L2Usd0PP, Usd0)

### EARLY\_BOND\_UNLOCK\_ROLE

The EARLY\_BOND\_UNLOCK\_ROLE exists to manage early bond unlocking functionality in the USD0PP (USD0 Plus Plus) contract. This role is responsible for configuring and executing early bond release mechanisms, allowing authorized entities to set up special unlock periods and allocate early unlock balances for specific bond holders.

**Role Holders**: Usual Multisig

* Allocate early unlock balance (USD0pp)
* Setup early unlock period (USD0pp)

### PEG\_MAINTAINER\_ROLE

The PEG\_MAINTAINER\_ROLE exists to maintain the USD0 peg through interactions with Curve pools and peg maintenance mechanisms. This role is responsible for triggering the Par mechanism on the USD0/USD0PP Curve pools in the case the peg is broken.

**Role Holders**: Usual Multisig

* Trigger PAR mechanism Curvepool (USD0pp)
* Unwrap peg maintainer (USD0pp)

### USUAL\_MINT

The USUAL\_MINT role exists to control the minting of new USUAL tokens. This role has the authority to mint new USUAL tokens to specified addresses, ensuring that token supply expansion follows protocol rules and economic parameters. The role is typically assigned to the Distribution Module contract to handle automated emissions and rewards distribution.

**Role Holders**: Distribution Module Contract

* Mint (Usual)

### USUAL\_BURN

The USUAL\_BURN role exists as a critical control mechanism for managing the supply of USUAL tokens in the system. This role has the authority to burn USUAL tokens from any address, ensuring proper supply management during redemptions, liquidations, or other protocol operations that require token destruction. The role is typically assigned to protocol-controlled contracts.

**Role Holders**: N/A

* Burn (Usual)
* Burn from (Usual)

### USUALS\_BURN

The USUALS\_BURN role exists as a critical control mechanism for managing the supply of USUALS tokens in the system. This role has the authority to burn USUALS tokens from any address. The role is typically assigned to protocol-controlled contracts that need to manage USUALS token supply, particularly during staking and unstaking operations.

**Role Holders**: USUALSP Contract

* Burn (UsualS)
* Burn from (UsualS)

### USUALSP\_OPERATOR\_ROLE

The USUALSP\_OPERATOR\_ROLE exists to manage the staking and allocation mechanics of the USUALS token staking program. This role is responsible for configuring initial token allocations, managing the staking process, and handling original allocation removals in the USUALSP (USUAL Staking Pool) contract. The role has significant control over the staking parameters and must be carefully managed to ensure fair distribution and proper vesting of tokens.

**Role Holders**: Usual Multisig

* Allocate (USUALSP)
* Remove original allocation (USUALSP)
* Stake UsualS (USUALSP)

### WITHDRAW\_FEE\_UPDATER\_ROLE

The WITHDRAW\_FEE\_UPDATER\_ROLE exists to manage withdrawal fee parameters in the UsualX contract. This role is responsible for adjusting the fees charged when users withdraw their tokens, allowing the protocol to maintain economic stability and prevent exploitation of the withdrawal mechanism.

**Role Holders**: Usual Multisig

* Update withdraw fee (UsualX)

### FLOOR\_PRICE\_UPDATER\_ROLE

The FLOOR\_PRICE\_UPDATER\_ROLE exists to manage the minimum price threshold for USD0PP tokens in the system. This role is responsible for adjusting the floor price parameter that helps maintain price stability and protect token holders from excessive devaluation. The role has the authority to update floor prices in the USD0PP contract, which directly impacts the minimum value guarantee of the token.

**Role Holders**: Usual Multisig

* Update floor price (USD0pp)

### USD0PP\_USUAL\_DISTRIBUTION\_ROLE

The USD0PP\_USUAL\_DISTRIBUTION\_ROLE exists to manage the USUAL token distribution rate per USD0PP token. This role is responsible for adjusting the distribution rate parameter that determines how much USUAL is distributed per USD0PP token.

**Role Holders**: Usual Multisig

* Update usualDistributionPerUsd0pp (USD0pp)

### USD0PP\_DURATION\_COST\_FACTOR\_ROLE

The USD0PP\_DURATION\_COST\_FACTOR\_ROLE exists to manage the duration cost factor that affects early redemption costs. This role is responsible for adjusting the duration cost factor parameter that helps determine the USUAL burn amount required for early redemptions.

**Role Holders**: Usual Multisig

* Update durationCostFactor (USD0pp)

### USD0PP\_TREASURY\_ALLOCATION\_RATE\_ROLE

The USD0PP\_TREASURY\_ALLOCATION\_RATE\_ROLE exists to manage the percentage of burned USUAL that goes to the treasury during early redemptions. This role is responsible for adjusting the treasury allocation rate in basis points.

**Role Holders**: Usual Multisig

* Update treasuryAllocationRate (USD0pp)

### USD0PP\_TARGET\_REDEMPTION\_RATE\_ROLE

The USD0PP\_TARGET\_REDEMPTION\_RATE\_ROLE exists to manage the daily redemption target rate for USD0PP tokens. This role is responsible for adjusting the target redemption rate (in basis points of total supply) that affects the USUAL burn calculations for early redemptions.

**Role Holders**: Usual Multisig

* Update targetRedemptionRate (USD0pp)

### USD0PP\_CAPPED\_UNWRAP\_ROLE

The `USD0PP_CAPPED_UNWRAP_ROLE` has certain responsibilities to ensure the stability and integrity of the protocol.

**Role Holders**: Usual Multisig, Joint Partner Vault Multisig, VaultRouter

* unwrapWithCa&#x70;**()**: Role holders can adjust the capped unwrap limits, which control the maximum amount of tokens that can be unwrapped in a certain period

### REDIRECTION\_ADMIN\_ROLE

The `REDIRECTION_ADMIN_ROLE` is responsible for redirecting off-chain distribution from an account to a new account

**Role Holders**: Redirection Maintainers Multisig

* redirection management of Offchain distribution: (DistributionModule)

### YIELD\_MODULE\_MAX\_DATA\_AGE\_ROLE

the `YIELD_MODULE_MAX_DATA_AGE_ROLE` is responsible for setting the maximum data age for the RWA data.

**Role Holders**: Usual Tokenomics Multisig

* can manage maximum data age for yield module. (YieldModule)

### YIELD\_MODULE\_P90\_INTEREST\_ROLE

The `YIELD_MODULE_P90_INTEREST_ROLE` is tasked with managing the P90 interest rate within the yield module.

**Role Holders**: Usual Tokenomics Multisig

* can modify P90 interest settings within the YieldModule.

### YIELD\_MODULE\_UPDATER\_ROLE

The `YIELD_MODULE_UPDATER_ROLE` is responsible for making updates within the Yield Module.

**Role Holders**: Usual Tokenomics Multisig

* Update Interest Rate to ensure accurate data.
* Update yield data feed updates to various interest and yield settings.

### YIELD\_MODULE\_TOKENOMICS\_OPERATOR\_ROLE

The `YIELD_MODULE_TOKENOMICS_OPERATOR_ROLE` is designed to manage and oversee the tokenomics aspect within the Yield Module.

**Role Holders**: Usual Tokenomics Multisig

* Add yield data feed updates to various interest and yield settings.

### YIELD\_MODULE\_SUPER\_ADMIN\_ROLE

The `YIELD_MODULE_SUPER_ADMIN_ROLE` encompasses comprehensive control over the Yield Module.

**Role Holders**: Usual Tokenomics Multisig

* Remove yield data feed.
* Manage the treasuries that are being used for the different calculations.

### VAULT\_SET\_ROUTER\_ROLE

The `VAULT_SET_ROUTER_ROLE` allows authorized entities to configure and manage router within the wrapped dollar vault system.

**Role Holders**: Usual Vault Router Multisig

* Enabling or disabling vault for wrapped dollar vaults.

### VAULT\_PAUSER\_ROLE

The `VAULT_PAUSER_ROLE` grants the authority to pause vault operations temporarily.

**Role Holders**: Usual Vault Admin Multisig

* Halting all transactions to address emergency scenarios or unforeseen issues.
* Safeguarding assets by preventing unauthorized access or fraud during a pause.
* Ensuring system integrity and stability by providing a controlled cessation of operations when necessary.

### VAULT\_UNPAUSER\_ROLE

The `VAULT_UNPAUSER_ROLE` is designated to resume vault operations after they have been paused.

**Role Holders**: Usual Vault Admin Multisig

* Reactivating transactions once it is deemed safe and all issues have been resolved.
* Restoring normal system functionality and access to vaults.
* Collaborating with relevant parties to ensure a secure and well-managed transition back to normal operations.

### FEE\_SWEEPER\_ROLE

The `FEE_SWEEPER_ROLE` can transfer the fees accumulating to the distribution module.

**Role Holders**: Yield treasury Multisig

* Collecting and distributing accrued fees from vault or bond withdrawals.

### FEE\_RATE\_SETTER\_ROLE

The `FEE_RATE_SETTER_ROLE` plays a crucial role in managing the fee rates within the system.

**Role Holders**: Yield treasury Multisig

* Alters the usualX, burn and treasury fee rate in basis points.

### UNWRAP\_CAP\_ALLOCATOR\_ROLE

the UNWRAP\_CAP\_ALLOCATOR\_ROLE can update the unwrap bUSD0 (formerly USD0++) amount of a user

**Role Holders**: Usual unwrap cap Multisig

### USUAL\_\*\*\*\_MINTCAP\_ALLOCATOR

Roles like `USUAL_USDC_MINTCAP_ALLOCATOR`, `USUAL_M_MINTCAP_ALLOCATOR` or `USUAL_USDTB_MINTCAP_ALLOCATOR` allows to set the mintcap for the corresponding tokens.

**Role Holders**: Usual mint allocator Multisig

* set the maximum amount of token that can be minted.

### WrappedDollarVault

* `VAULT_PAUSER_ROLE`
  * can call `pause`
* `VAULT_UNPAUSER_ROLE`
  * can call `unpause`
* `VAULT_SET_ROUTER_ROLE`
  * can call `setRouter`
* `VAULT_HARVESTER_ROLE`
  * can call `harvest`
* `VAULT_SET_FEE_ROLE`
  * can call `setWithdrawFeeRateBps`
  * can call `setHarvestFeeRateBps`

### YieldModule

* `YIELD_MODULE_SUPER_ADMIN_ROLE`
  * can call `removeTreasury`
  * can call `addTreasury`
  * can call `removeYieldSource`
* `YIELD_MODULE_TOKENOMICS_OPERATOR_ROLE`
  * can call `addYieldSourceWithFeed`
  * can call `addYieldSourceWithWeeklyInterest`
* `YIELD_MODULE_UPDATER_ROLE`
  * can call `updateInterestRate`
  * can call `updateFeed`
* `YIELD_MODULE_P90_INTEREST_ROLE`
  * can call `setP90InterestRate`
* `YIELD_MODULE_MAX_DATA_AGE_ROLE`
  * can call `setMaxDataAge`

### TokenMapping

* `DEFAULT_ADMIN_ROLE`
  * can call `addUsd0Rwa`

### DaoCollateral.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `activateCBR`
  * can call `deactivateCBR`
  * can call `setRedeemFee`
  * can call `redeemDao`
  * can call `unpause`
  * can call `unpauseRedeem`
  * can call `unpauseSwap`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
  * can call `pauseSwap`
  * can call `pauseRedeem`
* `NONCE_THRESHOLD_SETTER_ROLE`
  * can call `setNonceThreshold`
* `INTENT_MATCHING_ROLE`
  * can call `swapRWAtoStbcIntent`

### DistributionModule.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `unpause`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `DISTRIBUTION_OPERATOR_ROLE`
  * can call `distributeUsualToBuckets`
  * can call `queueOffChainUsualDistribution`
  * can call `resetOffChainDistributionQueue`
* `DISTRIBUTION_ALLOCATOR_ROLE`
  * can call `setBucketsDistribution`
  * can call `setGamma`
  * can call `setRateMin`
  * can call `setD`
  * can call `setM0`
* `DISTRIBUTION_CHALLENGER_ROLE`
  * can call `challengeDistribution`
* `DEFAULT_ADMIN_ROLE`
  * can call `unpause`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `BLACKLIST_ROLE`
  * can call `blacklist`
  * can call `unBlacklist`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `USD0_MINT`
  * can call `mint`
* `USD0_BURN`
  * can call `burn`
  * can call `burnFrom`
* `REDIRECTION_ADMIN_ROLE`
  * can call `acceptRedirectedOffChainDistribution`
  * can call `removeRedirectedOffChainDistribution`
  * can call `cancelInitiatedRedirectedOffChainDistribution`
  * can call `redirectOffChainDistribution`
* `FEE_RATE_SETTER_ROLE`
  * can call `setFeeRates`

### RevenueDistributionModule.sol <a href="#revenue-distribution-module---roles-documentation" id="revenue-distribution-module---roles-documentation"></a>

`OPERATOR_REVSWITCH_DISTRIBUTOR_ROLE`

* can call `distributeRevenueSwitch`

`OPERATOR_ACC_DT_DISTRIBUTOR_ROLE`

* can call `distributeAccruingDT`

`OPERATOR_REB_DT_DISTRIBUTOR_ROLE`

* can call `distributeRebasingDT`

`OPERATOR_ADMIN_ROLE`

* can call `setDailyAccruingYieldRate`
* can call `setOperatorMintCap`
* can call `setMaxRevSwitchMintCap`
* can call `setMaxAccruingMintCap`
* can call `setMaxRebasingDTMintCap`
* can call `setRewardClaimForRevenueSwitch`
* can call `setRewardClaimForAccruingDT`
* can call `setRewardClaimForRebasingDT`

`PAUSING_CONTRACTS_ROLE`

* can call `pause`
* can call `pauseRevenueSwitchDistribution`
* can call `pauseAccruingDTDistribution`
* can call `pauseRebasingDTDistribution`

`UNPAUSING_CONTRACTS_ROLE`

* can call `unpause`
* can call `unpauseRevenueSwitchDistribution`
* can call `unpauseAccruingDTDistribution`
* can call `unpauseRebasingDTDistribution`

`USD0_MINT` (on USD0 Contract)

* can call `mint` (required for the Revenue Distribution Module to mint USD0 tokens during distributions)

**Note**: The `USD0_MINT` role is granted to the RevenueDistributionModule contract on the USD0 token contract, not directly to individual operators. This allows the module to mint USD0 tokens when executing distributions.

### sUSD0.sol <a href="#susd0sol" id="susd0sol"></a>

* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `UNPAUSING_CONTRACTS_ROLE`
  * can call `unpause`
* `BLACKLIST_ROLE`
  * can call `blacklist`
  * can call `unBlacklist`
* `SUSD0_WITHDRAW_FEE_UPDATER_ROLE`
  * can call `updateWithdrawFee`
* `SUSD0_YIELD_DISTRIBUTOR_ROLE`
  * can call `startYieldDistribution`

### L2Usd0PP.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `unpause`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `USD0_MINT`
  * can call `mint`
* `USD0_BURN`
  * can call `burn`
  * can call `burnFrom`

### AbstractContract.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `setMaxDepegThreshold`

### ClassicalOracle.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `initializeTokenOracle`

### UsualOracle.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `initializeTokenOracle`

### RegistryAccess.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `setRoleAdmin`

### RegistryContract.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `setContract`

### SwapperEngine.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `unpause`
  * can call `updateMinimumUSDCAmountProvided`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `DEFAULT_ADMIN_ROLE`
  * can call `blacklist`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `USD0_BURN`
  * can call `burn`
  * can call `burnFrom`
* `USD0_MINT`
  * can call `mint`
* `BLACKLIST_ROLE`
  * can call `blacklist`
  * can call `unBlacklist`

### USD0pp.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `unpause`
  * can call `emergencyWithdraw`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `EARLY_BOND_UNLOCK_ROLE`
  * can call `allocateEarlyUnlockBalance`
  * can call `setupEarlyUnlockPeriod`
* `PEG_MAINTAINER_ROLE`
  * can call `triggerPARMechanismCurvepool`
  * can call `unwrapPegMaintainer`
* `FLOOR_PRICE_UPDATER_ROLE`
  * can call `updateFloorPrice`
* `USD0PP_USUAL_DISTRIBUTION_ROLE`
  * can call `setUsualDistributionPerUsd0pp`
* `USD0PP_DURATION_COST_FACTOR_ROLE`
  * can call `setDurationCostFactor`
* `USD0PP_TREASURY_ALLOCATION_RATE_ROLE`
  * can call `setTreasuryAllocationRate`
* `USD0PP_USUAL_BURN_TARGET_REDEMPTION_ROLE`
  * can call `setTargetRedemptionRate`
* `FEE_SWEEPER_ROLE`
  * can call `sweepFees`

### Usual.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `unpause`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `BLACKLIST_ROLE`
  * can call `blacklist`
  * can call `unBlacklist`
* `USUAL_MINT`
  * can call `mint`
* `USUAL_BURN`
  * can call `burn`
  * can call `burnFrom`

### UsualS.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `unpause`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `BLACKLIST_ROLE`
  * can call `blacklist`
  * can call `unBlacklist`
* `USUALS_BURN`
  * can call `burn`
  * can call `burnFrom`

### USUALSP.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `unpause`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `USUALSP_OPERATOR_ROLE`
  * can call `allocate`
  * can call `removeOriginalAllocation`
  * can call `stakeUsualS`

### UsualX.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `unpause`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `BLACKLIST_ROLE`
  * can call `blacklist`
  * can call `unBlacklist`
* `WHITELIST_ROLE`
  * can call `whitelist`
  * can call `unWhitelist`
* `WITHDRAW_FEE_UPDATER_ROLE`
  * can call `updateWithdrawFee`
* `FEE_SWEEPER_ROLE`
  * can call `sweepFees`

### USUALM.sol

The `USUALM` contract includes specific roles designed to manage particular functionalities and maintain the security and efficiency of the platform.

* `USUAL_M_UNPAUSE`
  * can call `unpause`
* `USUAL_M_PAUSE`
  * can call `pause`
* `BLACKLIST_ROLE`
  * can call `blacklist`
  * can call `unblacklist`
* `USUAL_M_MINTCAP_ALLOCATOR`
  * can call `setMintCap`
* `USUAL_M_UNWRAP`
  * can call `unwrap`

##

***

## ETH0 Role Management

### MINT\_CAP\_OPERATOR

The MINT\_CAP\_OPERATOR role is pivotal in controlling the minting activities for specific tokens. Holders of this role are empowered to adjust the cap on the amount of new tokens that can be minted within a certain period, ensuring that the minting process remains within defined limits to maintain token stability and prevent inflationary pressures.

**Role Holders**: Token Governance Multisig

* Update mintCap
* Monitor compliance with minting policies
* Enforce minting restrictions if caps are breached

### BLACKLIST\_ROLE

The BLACKLIST\_ROLE exists as a security mechanism to protect the protocol from malicious actors, comply with regulatory requirements, and ensure rapid response to security incidents. This role has the authority to restrict specific addresses from participating in token transfers and protocol operations across multiple core contracts including L2USD0, L2USD0PP, USD0PP, USD0, USUAL, USUALS, and USUALX.

**Role Holders**: Usual Multisig

* Blacklist/Unblacklist (ETH0)

###

### ETH0\_MINT

The ETH0\_MINT role exists as a critical control mechanism for managing the supply of ETH0 tokens in the system. This role has the authority to mint new ETH0 tokens across multiple contracts including ETH0, but only when there is sufficient backing in the treasury. The role is typically assigned to the DAO Collateral contract to ensure automated and secure minting operations.

**Role Holders**: DAO Collateral Contract

* Mint (ETH0)

### ETH0\_BURN

The ETH0\_BURN role exists as a critical control mechanism for managing the supply of ETH0 tokens in the system. This role has the authority to burn ETH0 tokens across multiple contracts including ETH0, ensuring proper supply management and redemption functionality. The role is typically assigned to the DAO Collateral contract to enable automated burning operations during redemptions and swaps.

**Role Holders**: DAO Collateral Contract

* Burn (ETH0)
* Burn from (ETH0)

### DaoCollateral.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `activateCBR`
  * can call `deactivateCBR`
  * can call `setRedeemFee`
  * can call `redeemDao`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
  * can call `pauseSwap`
  * can call `pauseRedeem`
* `UNPAUSING_CONTRACTS_ROLE`
  * can call `unpause`
  * can call `unpauseRedeem`
  * can call `unpauseSwap`
* `NONCE_THRESHOLD_SETTER_ROLE`
  * can call `setNonceThreshold`

***

## EUR0 Role Management

### BLACKLIST\_ROLE

The BLACKLIST\_ROLE exists as a security mechanism to protect the protocol from malicious actors, comply with regulatory requirements, and ensure rapid response to security incidents. This role has the authority to restrict specific addresses from participating in token transfers and protocol operations across multiple core contracts including L2USD0, L2USD0PP, USD0PP, USD0, USUAL, USUALS, and USUALX.

**Role Holders**: Usual Multisig

* Blacklist/Unblacklist (EUR0)

### EUR0\_MINT

The EUR0\_MINT role exists as a critical control mechanism for managing the supply of EUR0 tokens in the system. This role has the authority to mint new EUR0 tokens across multiple contracts including EUR0, but only when there is sufficient backing in the treasury. The role is typically assigned to the DAO Collateral contract to ensure automated and secure minting operations.

**Role Holders**: DAO Collateral Contract

* Mint (EUR0)

### EUR0\_BURN

The EUR0\_BURN role exists as a critical control mechanism for managing the supply of EUR0 tokens in the system. This role has the authority to burn EUR0 tokens across multiple contracts including EUR0, ensuring proper supply management and redemption functionality. The role is typically assigned to the DAO Collateral contract to enable automated burning operations during redemptions and swaps.

**Role Holders**: DAO Collateral Contract

* Burn (EUR0)
* Burn from (EUR0)

### DaoCollateral.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `activateCBR`
  * can call `deactivateCBR`
  * can call `setRedeemFee`
  * can call `redeemDao`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
  * can call `pauseSwap`
  * can call `pauseRedeem`
* `UNPAUSING_CONTRACTS_ROLE`
  * can call `unpause`
  * can call `unpauseRedeem`
  * can call `unpauseSwap`
* `NONCE_THRESHOLD_SETTER_ROLE`
  * can call `setNonceThreshold`

### sEUR0.sol <a href="#revenue-distribution-module---roles-documentation" id="revenue-distribution-module---roles-documentation"></a>

* **`PAUSING_CONTRACTS_ROLE`**
  * can call `pause`
* **`UNPAUSING_CONTRACTS_ROLE`**
  * can call `unpause`
* **`BLACKLIST_ROLE`**
  * can call `blacklist`
  * can call `unBlacklist`
* **`SEUR0_WITHDRAW_FEE_UPDATER_ROLE`**
  * can call `updateWithdrawFee`
* **`SEUR0_YIELD_DISTRIBUTOR_ROLE`**
  * can call `startYieldDistribution`

### SwapperEngine.sol

* `DEFAULT_ADMIN_ROLE`
  * can call `updateMinimumEURCAmountProvided`
  * can call `unpause`
* `PAUSING_CONTRACTS_ROLE`
  * can call `pause`
* `UNPAUSING_CONTRACT_ROLE`
  * can call `unpause`

### RevenueDistributionModule.sol <a href="#revenue-distribution-module---roles-documentation" id="revenue-distribution-module---roles-documentation"></a>

**`OPERATOR_REVSWITCH_DISTRIBUTOR_ROLE`**

* can call `distributeRevenueSwitch`

**`OPERATOR_ACC_DT_DISTRIBUTOR_ROLE`**

* can call `distributeAccruingDT`

**`OPERATOR_REB_DT_DISTRIBUTOR_ROLE`**

* can call `distributeRebasingDT`

**`OPERATOR_ADMIN_ROLE`**

* can call `setDailyAccruingYieldRate`
* can call `setOperatorMintCap`
* can call `setMaxRevSwitchMintCap`
* can call `setMaxAccruingMintCap`
* can call `setMaxRebasingDTMintCap`
* can call `setRewardClaimForRevenueSwitch`
* can call `setRewardClaimForAccruingDT`
* can call `setRewardClaimForRebasingDT`

**`PAUSING_CONTRACTS_ROLE`**

* can call `pause`
* can call `pauseRevenueSwitchDistribution`
* can call `pauseAccruingDTDistribution`
* can call `pauseRebasingDTDistribution`

**`UNPAUSING_CONTRACTS_ROLE`**

* can call `unpause`
* can call `unpauseRevenueSwitchDistribution`
* can call `unpauseAccruingDTDistribution`
* can call `unpauseRebasingDTDistribution`

**`EUR0_MINT` (on EUR0 Contract)**

* can call `mint` (required for the Revenue Distribution Module to mint EUR0 tokens during distributions)

**Note:** The `EUR0_MINT` role is granted to the RevenueDistributionModule contract on the EUR0 token contract, not directly to individual operators. This allows the module to mint EUR0 tokens when executing distributions.


# USUAL Distribution Model

## Introduction

The following document is a comprehensive review of the USUAL minting module. It follows that USUAL is minted based on parameters tied to TVL, the underlying interest rate for the collateral of USD0 and additional factors. It should further be noted the math for this paper is specifically focused on a single asset environment where Usual only accepts and mints USD0 (which can be locked as USD0++) for collateral deposited (based on accepted Usual collateral).

## Minting of USUAL

The minting of USUAL is completed daily and based on many different factors. The model has three layers of calculations.

### Daily Minting of USUAL - First Layer

We calculate the daily distribution as such given d the global distribution rate, Mt the minting rate, Supply++ the supply of USD0++ , and P the primary market price of USD0:

<figure><img src="/files/0z6oJ5OQWZOL0voPNHl7" alt=""><figcaption></figcaption></figure>

The distribution rate is immutable and set to 0.25 meaning we will plan to fully distribute the minting rate per the market cap of current locked assets over 4 years total. However, given the dynamic nature of TVL and Price, the real circulating supply will be dynamic and is the aggregate of the daily distribution over time.

### Minting Rate - Second Layer

The minting rate is a new concept that represents the supply of USUAL per LST to be emitted over four years (considering d = 0.25). It is inversely related to the growth of the LST supply St and directly related to changes in the interest rate Rt. This minting rate is capped so it does not exceed a set maximum rate κt allowing for some sensitivity to interest rate increases and LST supply reduction. Additionally, a growth control variable γt is included, allowing the DAO to accelerate or decelerate changes in the minting rate globally for all LST assets (set to 1 by default, but adjustable through governance).

<figure><img src="/files/XixqurMgTnXSzAtBYoLF" alt=""><figcaption></figcaption></figure>

Where M0 is the initial set minting rate. This is immutable and set to 10.

### Minting rate Factors - Third Layer

There are 4 factors calculated which are used to compute the minting rate. We use the supply, rate, scale and cap factors to complete this calculation (as first illustrated in "Minting of USUAL").

#### Supply Factor

St is a supply factor which inversely adjusts the minting rate as supply increases. It has a ceiling of 1 such that if the supply is ever below the initial supply at launch, we use this ceiling value. On the contrary, for any supply Supply++ above the initial supply Supply++, the factor will be below one. It t0 should further be noted we include price in the calculation Pt given this model can eventually be adapted to a multi asset environment (where we would still use the initial supply and current price of USD0 for the numerator rather than the initial supply and current price of the newly added asset - this is still under research).

<figure><img src="/files/0wT8U1zcz98yKXzwbO4J" alt=""><figcaption></figcaption></figure>

#### Rate Factor

Rt is a rate factor which directly adjusts the minting rate based on change in the current underlying interest rate of collateral for USD0 rt (subject to the rate floor and celing rmin and P90(πt)). We use a rate floor set by the DAO to mint and distribute a minimum amount of USUAL. Further, we use the 90th percentile of the daily rates from the last 60 days as a rate ceiling to cap the rate factor increasing significantly when large sudden changes in the underlying interest rate are realized (ideally creating a smoother transition in the number of USUAL distributed before and after large rate changes).

<figure><img src="/files/DTRTdo9akRSB254cWI0f" alt="" width="269"><figcaption></figcaption></figure>

#### Scale Factor

The scale factor γt is used to modify the minted amount of USUAL by a set base scale factor γ which is set by the DAO and by a time factor τt. The base scale factor allows the DAO to modify the daily minting of USUAL to either reduce or increase the USUAL emission rate over time; this acts as either an accelerator for inflation when set below 1 (and always above 0) and as a decelerator when set above 1. If set to 1, the scale is neutral such that the inflation is as originally intended. The time factor for this is calculated using the UNIX timestamp at which the last mint occurred and the timestamp at which the current mint occurs. This is then adjusted to calculate how many days (based on using 86400 seconds per day via DF S = 86400, the distribution frequency scalar.) have elapsed between mints to adjust the distribution (given it is supposed to be daily). Since the model is meant to operate on a daily basis but may differ in terms of times between the actual mints of USUAL This function uses the last parameter values available at the time of the call for calculations. We use this to adjust and ensure the correct amount of USUAL per time is minted from one mint to the next.

<figure><img src="/files/qoVF3C7Yx9eNWavbrxnS" alt="" width="277"><figcaption></figcaption></figure>

#### Cap Factor

Further, we set the cap factor κt based on the initial minting rate but is modified over time by the change in the underlying interest rates and the scale factor. κt is set as follows (where r0 is the initial underlying interest rate of USD0 at launch):

<figure><img src="/files/EbyRvQAtjJ52Gp4c14aK" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
The research paper on the USUAL distribution model can be downloaded below.
{% endhint %}

{% file src="/files/gxbuaqJhN0QIgMJzCkQs" %}


# Protocol Contracts

<table data-card-size="large" data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td align="center"><strong>Contracts that power USD0</strong></td><td><a href="/pages/GByHf7FKOxvvHBo1Ji9V">/pages/GByHf7FKOxvvHBo1Ji9V</a></td><td data-object-fit="cover"><a href="/files/TC2H7LlhnVw9vJ4fIAZ3">/files/TC2H7LlhnVw9vJ4fIAZ3</a></td></tr><tr><td align="center"><strong>Contracts that power USD0a</strong></td><td><a href="/pages/PEM5Zae6N4OwXnZqAgda">/pages/PEM5Zae6N4OwXnZqAgda</a></td><td><a href="/files/1Fv3955ugJkDORrZag2m">/files/1Fv3955ugJkDORrZag2m</a></td></tr><tr><td align="center"><strong>Contracts that power ETH0</strong></td><td><a href="/pages/pbn5wlGT4bqWQkfFNMAM">/pages/pbn5wlGT4bqWQkfFNMAM</a></td><td data-object-fit="cover"><a href="/files/4ytm70lRahESXi2jJLDI">/files/4ytm70lRahESXi2jJLDI</a></td></tr><tr><td align="center"><strong>Contracts that power EUR0</strong></td><td><a href="/pages/uUCCZGaMPu0mdyAzvoA6">/pages/uUCCZGaMPu0mdyAzvoA6</a></td><td><a href="/files/rwMdtZ3SCSUFbnHRE1Zg">/files/rwMdtZ3SCSUFbnHRE1Zg</a></td></tr><tr><td align="center"><strong>Contracts that power USUAL</strong></td><td><a href="/pages/LADyapgfYUhvAm94ALUd">/pages/LADyapgfYUhvAm94ALUd</a></td><td data-object-fit="cover"><a href="/files/8Vio8vvleStta0R5aMGQ">/files/8Vio8vvleStta0R5aMGQ</a></td></tr></tbody></table>


# USD0

<table data-card-size="large" data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td align="center"><strong>USD0</strong> <strong>DAO Collateral Smart Contract</strong></td><td><a href="/pages/cdEnoP1Vp2m1T0Lp8xc1">/pages/cdEnoP1Vp2m1T0Lp8xc1</a></td><td data-object-fit="cover"><a href="/files/mRoGUG3gnWewZUoAn1hm">/files/mRoGUG3gnWewZUoAn1hm</a></td></tr><tr><td align="center"><strong>Swapper Engine Smart Contract</strong></td><td><a href="/pages/9VSTNV5ffFhdsBG7JCjZ">/pages/9VSTNV5ffFhdsBG7JCjZ</a></td><td data-object-fit="cover"><a href="/files/IKcZhsVeJNj0onWut15o">/files/IKcZhsVeJNj0onWut15o</a></td></tr><tr><td align="center"><strong>USD0 Distribution Smart Contract</strong></td><td><a href="/pages/OUnleWzl74OejOHMxaRa">/pages/OUnleWzl74OejOHMxaRa</a></td><td><a href="/files/twlfjUJLxosHbWEIKDsy">/files/twlfjUJLxosHbWEIKDsy</a></td></tr></tbody></table>


# USD0 DaoCollateral

## High-Level Overview

The DaoCollateral contract is a crucial component of the USD0 stablecoin ecosystem, designed to manage the collateralization, minting, and redemption of USD0 tokens. It ensures that the circulating supply of USD0 is always fully backed by Real World Assets (RWA) collateral, providing transparency and security for USD0 holders. The contract facilitates the swapping of RWA tokens for USD0, redemption of USD0 for RWA tokens, and implements an intent-based matching system for efficient, non-custodial trading.

### Contract Summary

#### Inherited Contracts

* `Initializable` (OZ): Allows the contract to be initialized in an upgradeable pattern.
* `ReentrancyGuardUpgradeable` (OZ): Prevents reentrant attacks on sensitive functions.
* `PausableUpgradeable` (OZ): Enables pausing of contract functionality by authorized accounts.
* `NoncesUpgradeable` (OZ): Manages nonces for user operations.
* `EIP712Upgradeable` (OZ): Implements EIP-712 for structured data hashing and signing.

## Functionality Breakdown

#### Key Functionalities

1. **Minting and redeeming USD0:**

At its core, the contract accrues RWAs (USYC) by routing trades accordingly. When a user sends RWA, the daoCollateral contract mints the equivalent amount of USD0 stablecoins, and vice versa, allowing users to exchange their USD0 stablecoins for RWAs, represented as USYC tokens, at the current exchange rate.

* **Swap:** Facilitates the conversion of Real World Assets (RWAs), represented as USYC tokens, into the DAO's stablecoin (USD0). Upon initiating this function, users exchange their USYC tokens for USD0 stablecoins directly.
* **Redeem:** Allows users to redeem their USD0 stablecoins against a fee. By invoking this function, users exchange their USD0 stablecoins for RWAs, represented as USYC tokens, at the current exchange rate.

The system is also able to route Swapper Engine trades on their behalf against a different token pair (USDC/USD0), by accumulating the underlying RWAs and minting USD0 to route user's intents. This mechanism, inspired by CowSwap, allows RWA providers to retain their tokens until the trade is executed, allowing for *non-custodial, gas-less, just-in-time,* RWA liquidity providers.

2. **Intent-Based Matching System (Three-Way Trade Example):**

The Intent-Based Matching System is facilitated by the daoCollateral contract, in this example three parties are involved: a USDC provider, an RWA provider, and the daoCollateral contract itself. Here’s how it works step-by-step:

* **USDC Provider**: A user who holds USDC initiates a trade by providing USDC to the Swapper engine. In return, this user receives USD0.
* **RWA Provider**: Another user who holds Real World Assets (RWAs), such as USYC, wants to exchange these assets for USDC. This user submits their intent to trade RWAs for USDC to the daoCollateral contract.
* **daoCollateral Contract**: The daoCollateral contract plays a crucial intermediary role in this three-way trade. It accumulates the RWAs from the RWA provider. The contract mints new USD0 tokens equivalent to the value of the received RWAs. The contract then completes the trade by providing the newly minted USD0 to the Swapper engine, which matches the initial USDC provider’s trade. Finally, the daoCollateral contract gives the USDC from the USDC provider to the RWA provider.

#### 3. Role-Based Access Control

The contract implements a role-based access control system for sensitive operations:

* DEFAULT\_ADMIN\_ROLE: Has the highest level of access, including the ability to unpause the contract and perform critical administrative tasks.
* INTENT\_MATCHING\_ROLE: Required to execute intent-based swaps, ensuring that only authorized entities can match and process intents.
* NONCE\_THRESHOLD\_SETTER\_ROLE: Allows setting of nonce thresholds, which is crucial for the intent-based system's security.
* PAUSING\_CONTRACTS\_ROLE: Grants the ability to pause specific contract functionalities in case of emergencies. These roles ensure that different levels of access are properly managed and that sensitive operations are restricted to authorized entities, enhancing the overall security and governance of the contract.

### Functions Description

#### Public/External Functions

* `initialize`: Sets up the contract with initial parameters.
* `swap`: Allows users to swap RWA tokens for USD0.
* `swapWithPermit`: Similar to `swap` but uses permit for approval.
* `redeem`: Enables users to redeem USD0 for RWA tokens.
* `redeemDao`: Special redemption function for DAO operations. Only callable by DEFAULT\_ADMIN\_ROLE.
* `swapRWAtoStbc`: Facilitates swapping RWA to stablecoins through the SwapperEngine.
* `swapRWAtoStbcIntent`: Executes swaps based on signed intents. Only callable by INTENT\_MATCHING\_ROLE.
* `activateCBR`: Activates the Counter Bank Run mechanism. Only callable by DEFAULT\_ADMIN\_ROLE.
* `deactivateCBR`: Deactivates the Counter Bank Run mechanism. Only callable by DEFAULT\_ADMIN\_ROLE.
* `setRedeemFee`: Sets the fee for redemption operations. Only callable by DEFAULT\_ADMIN\_ROLE.
* `setNonceThreshold`: Set the lower bound for the intent nonce to be considered consumed. Only callable by NONCE\_THRESHOLD\_SETTER\_ROLE.
* `pauseRedeem`, `pause`, `pauseSwap`: Pausing functions for specific operations. Only callable by PAUSING\_CONTRACTS\_ROLE.
* `unpause`, `unpauseRedeem`, `unpauseSwap` : Global unpausing functions.

### Constants

* CONTRACT\_REGISTRY\_ACCESS: Address of the registry access contract.
* CONTRACT\_TOKEN\_MAPPING: Address of the token mapping contract.
* CONTRACT\_ORACLE: Address of the oracle contract.
* CONTRACT\_TREASURY: Address of the treasury contract.
* CONTRACT\_USD0: Address of the USD0 token contract.
* CONTRACT\_SWAPPER\_ENGINE: Address of the SwapperEngine contract.
* DEFAULT\_ADMIN\_ROLE: Role identifier for the default admin.
* INTENT\_MATCHING\_ROLE: Role identifier for intent matching operations.
* NONCE\_THRESHOLD\_SETTER\_ROLE: Role identifier for setting nonce thresholds.
* PAUSING\_CONTRACTS\_ROLE: Role identifier for pausing contract operations.
* MAX\_REDEEM\_FEE: Maximum allowed redemption fee.
* SCALAR\_ONE: Scalar value representing 1 in the contract's decimal system.
* SCALAR\_TEN\_KWEI: Scalar value representing 10,000 in the contract's decimal system.
* INTENT\_TYPE\_HASH: Type hash for EIP-712 structured data signing of intents.

### Key Components

* **Oracle Integration**: Uses an oracle to fetch real-time price data for RWA tokens.
* **SwapperEngine**: Interacts with the SwapperEngine contract for executing trades.
* **Token Mapping**: Manages the mapping of supported RWA tokens.
* **Access Control**: Implements role-based access control for administrative functions.

### Safeguards Implementation

* **Pausability**: Allows pausing of critical functions in emergencies.
* **Reentrancy Protection**: Uses OpenZeppelin's ReentrancyGuard to prevent reentrancy attacks.
* **Access Control**: Restricts sensitive operations to authorized roles.
* **Intent Validation**: Implements checks for intent-based swaps.


# USD0 Swapper Engine

## High-Level Overview

The **`SwapperEngine`** contract is a smart contract designed to facilitate the swapping of *USDC* tokens for *USD0* tokens using an order matching mechanism. The contract allows users to create orders specifying the amount of *USDC* they wish to swap, and other users can fill these orders by providing *USD0* 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.

It is important to note that the contract's mechanism can be utilized to facilitate a vampire attack, **RWA → USD0 → USDC → $$$ → RWA →** to churn *USDC* into USD0 by transparently staking treasury bonds to mint *USD0* swapping that *USD0* for *USDC* and cycling back into RWA ready to mint more *USD0* limited only by *USDC* order book depth.

Flow USDC Depositors:

{% @mermaid/diagram content="sequenceDiagram
autonumber
participant A as Alice
participant SW as SwapperContract
A->>SW: Deposit USDC & create order
SW->>A: Receive USD0 when order filled
" fullWidth="true" %}

Flow RWA Provider:

{% @mermaid/diagram content="sequenceDiagram
autonumber
participant A as Alice
participant R as Robert
participant SW as SwapperContract
participant DC as DaoCollateralContract
R->>UI: Sign spending approval of RWA
R->>DC: Send transactions w/ Alice offerIds
R->>DC: TransferFrom(R,DC)  RWA
DC->>DC: USD0 minting
DC->>SW: call provideUSD0ReceiveUSDC
note left of DC: transfer USD0 from DC to Alice
SW->>R: Transfer USDC
SW->>A: Transfer USD0
critical Partially filled order (not enough USDC to fulfill request)
option
SW->>DC: Return unmatched amount USD0 amount to redeem
DC->>R: Send back remaining RWA unmatched
end
" fullWidth="false" %}

### Contract Summary

The contract provides the following main functions:

* **depositUSDC**: Allows users to create a new order by depositing *USDC*.
* **withdrawUSDC**: Allows users to cancel an order and withdraw their deposited *USDC*.
* **provideUsd0ReceiveUSDC**: Allows users to fill orders by providing *USD0* and receiving *USDC* in return.

The contract also includes utility functions such as getOrder, getUsd0WadEquivalent, and getUsdcWadPrice to retrieve order details and perform price calculations. The swapperEngine has no option to define a maxUSDCPrice for buyers and seller's don't have the option to define a minimumUSDCPrice, instead the prices are provided by an USDC oracle, which also has measures against a potential USDC depeg. USD0's price is considered to be $1 == 1USD0 due to the numerous mechanisms in place to prevent a depeg, like reserves, CBR mechanism, arbitrage etc.

### 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 `DEFAULT_ADMIN_ROLE` to un-pause).

## Functionality Breakdown

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

1. **Order Creation**:
   * Users can create new orders by calling the **depositUSDC** function and specifying the amount of *USDC* they wish to swap.
   * The contract transfers the specified amount of *USDC* tokens from the user to itself and creates a new order with the deposited amount and the user's address as the requester.
   * The order is assigned a unique order ID and stored in the contract's orders mapping.
2. **Order Cancellation**:
   * Users who have created an order can cancel it by calling the **withdrawUSDC** 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 to zero, and transfers the deposited *USDC* tokens back to the requester.
3. **Order Matching**:
   * Users can fill existing orders by specifying the recipient address, the amount of *USDC* to take (or the amount of USD0 to give), an array of order IDs to match against, and whether partial matching is allowed.
   * The contract verifies that the caller has sufficient *USD0* balance and allowance to cover the required amount based on the current *USDC* Price Calculation obtained from the oracle.
   * The contract iterates through the provided order IDs and attempts to match the requested *USDC* amount against active orders.
   * If partial matching is allowed and there is not enough *USDC* in the orders to fulfil 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 *USD0* tokens from the caller to the order requester and transfers the *USDC* tokens from itself to the specified recipient.
   * If partial matching is not allowed and the requested *USDC* amount cannot be fully matched, the contract reverts the transaction.
4. **Price Calculation**:
   * The contract relies on an external oracle contract to obtain the current price of *USDC* tokens in WAD format (18 decimals).
   * The getUsdcWadPrice function is used to retrieve the current *USDC* price from the oracle.
   * The getUsd0WadEquivalent function is used to calculate the equivalent amount of *USD0* tokens for a given amount of *USDC* tokens based on the current price.

### Security Analysis

#### Method: provideUsd0ReceiveUSDC

This method allows users to provide *USD0* tokens and receive *USDC* tokens by matching against existing orders. It matches the requested *USDC* amount to the provided *USD0* tokens against the specified orders, transfers the corresponding *USDC* tokens to the recipient, and updates the order states accordingly.

```rust
1 function _provideUsd0ReceiveUSDC( ... ) internal returns (uint256 unmatchedUsdcAmount, uint256 totalUsd0Provided) {
2    if (amountUsdcToTakeInNativeDecimals == 0) { revert AmountIsZero() }
3    if (orderIdsToTake.length == 0) { revert NoOrdersIdsProvided() }
4    SwapperEngineStorageV0 storage $ = _swapperEngineStorageV0();
5    uint256 usdcWadPrice = _getUsdcWadPrice();
6    uint256 totalUsdcTaken = 0;

```

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 *USDC* to take is greater than zero.
3. Validates that at least one order ID is provided for matching.
4. Retrieves the contract's storage using the correct storage pattern.
5. Retrieves the current price of *USDC* in WAD format (18 decimals) from an oracle, ensuring that the price used for calculations is up-to-date and accurate.
6. Initializes the total amount of *USDC* taken to zero.

```rust
 8  for (uint256 i; i < orderIdsToTake.length && totalUsdcTaken < amountUsdcToTakeInNativeDecimals;) {
 9      uint256 orderId = orderIdsToTake[i];
10      UsdcOrder storage order = $.orders[orderId];
11      if (order.active) {
12          uint256 remainingAmountToTake = amountUsdcToTakeInNativeDecimals - totalUsdcTaken;
13          uint256 amountOfUsdcFromOrder = order.tokenAmount > remainingAmountToTake ? remainingAmountToTake : order.tokenAmount;
14          order.tokenAmount -= amountOfUsdcFromOrder;
15          totalUsdcTaken += amountOfUsdcFromOrder;
16          if (order.tokenAmount == 0) { order.active = false };
17          uint256 usd0Amount = _getUsd0WadEquivalent(amountOfUsdcFromOrder, usdcWadPrice);
18          totalUsd0Provided += usd0Amount;
19          $.usd0.safeTransferFrom(msg.sender, order.requester, usd0Amount);
20          $.usdcToken.safeTransfer(recipient, amountOfUsdcFromOrder);
21          emit OrderMatched(order.requester, msg.sender, orderId, amountOfUsdcFromOrder);
22      }
23      unchecked { ++i }
24  }
25  if (!partialMatchingAllowed && totalUsdcTaken != amountUsdcToTakeInNativeDecimals || totalUsdcTaken == 0) { revert AmountTooLow() }
26  return ((amountUsdcToTakeInNativeDecimals - totalUsdcTaken), totalUsd0Provided);
...
```

10. Retrieves the order details for the current order ID.
11. Checks if the order is active before processing. 12-13. If the order is active, calculates the amount of USDC to take from the current order based on the remaining amount to take and the order's available balance. 14-15. Updates the order's token amount and the total USDC taken.
12. Marks the order as inactive if its token amount reaches zero.
13. Calculates the equivalent USD0 amount for the USDC taken from the order using the \_getUsd0WadEquivalent function and the current USDC price.
14. Updates the total USD0 provided with the calculated amount.
15. Transfers the USD0 tokens from the sender to the order requester.
16. Transfers the USDC tokens from the contract to the recipient.
17. Emits an OrderMatched event with the relevant details.
18. Increments the loop counter using an unchecked block for gas optimization.
19. Reverts the transaction if partial matching is not allowed and the total USDC taken does not match the requested amount or if no USDC was taken.
20. Returns the remaining amount of USDC that was not taken and the total USD0 provided.

#### Method: getUsd0WadEquivalent

This method calculates the USD0 equivalent amount in WAD format (18 decimals) for a given USDC token amount. It converts the USDC token amount from its native decimal representation (6 decimals) to WAD format and then calculates the equivalent USD0 amount based on the provided USDC price in WAD format.

```rust
1  function _getUsd0WadEquivalent(uint256 usdcTokenAmountInNativeDecimals, uint256 usdcWadPrice) private view returns (uint256 usd0WadEquivalent) {
2      SwapperEngineStorageV0 storage $ = _swapperEngineStorageV0();
3      uint8 decimals = IERC20Metadata(address($.usdcToken)).decimals();
4      uint256 usdcWad = usdcTokenAmountInNativeDecimals.tokenAmountToWad(decimals);
5      usd0WadEquivalent = usdcWad.wadAmountByPrice(usdcWadPrice);
6  }
```

2. Retrieves the contract's storage using the correct storage pattern.
3. Retrieves the decimal places of the USDC token using the decimals() function from the IERC20Metadata interface.
4. Converts the usdcTokenAmountInNativeDecimals to WAD format (18 decimals) using the tokenAmountToWad function, which takes into account the token's native decimals.
5. Calculates the equivalent amount of USD0 tokens in WAD format by multiplying the usdcWad amount with the usdcWadPrice using the wadAmountByPrice function.

#### Method: depositUSDC

This method allows users to deposit USDC tokens and create a new order. It transfers the specified amount of USDC tokens from the caller to the contract and creates a new order with the deposited amount and the caller as the requester.

```rust
1  function depositUSDC(uint256 amountToDeposit) external nonReentrant {
2      SwapperEngineStorageV0 storage $ = _swapperEngineStorageV0();
3      if (amountToDeposit < $.minimumUSDCAmountProvided) { revert AmountTooLow();}
4      uint256 orderId = $.nextOrderId++;
5      $.orders[orderId] = UsdcOrder({requester: msg.sender, tokenAmount: amountToDeposit, active: true});
6      $.usdcToken.safeTransferFrom(msg.sender, address(this), amountToDeposit);
7      emit Deposit(msg.sender, orderId, amountToDeposit);
8  }
```

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. Retrieves the contract's storage using the correct storage pattern.
3. Validates that the amount of USDC 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.
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 UsdcOrder struct in storage using the order ID as key. The struct is set up correctly to contain: the requester's address (msg.sender), the deposited token amount (amountToDeposit), and sets the active flag to true.
6. Transfers the specified amount of USDC tokens from the caller (msg.sender) to the contract (address(this)) using the safeTransferFrom function to ensure that the transfer is successful and the contract receives the deposited tokens. If the transfer fails, the function will revert.
7. Emits a Deposit event, providing the order ID and the deposited amount for the subgraph.

#### Method: withdrawUSDC

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

```rust
 1  function withdrawUSDC(uint256 orderToCancel) external nonReentrant {
 2      SwapperEngineStorageV0 storage $ = _swapperEngineStorageV0();
 3      UsdcOrder storage order = $.orders[orderToCancel];
 4      if (!order.active) { revert OrderNotActive() }
 5      if (order.requester != msg.sender) { revert NotRequester() }
 6      uint256 amountToWithdraw = order.tokenAmount;
 7      order.active = false;
 8      order.tokenAmount = 0;
 9      $.usdcToken.safeTransfer(msg.sender, amountToWithdraw);
10      emit Withdraw(msg.sender, orderToCancel, amountToWithdraw);
11  }
```

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. Retrieves the contract's storage using the correct storage pattern.
3. Retrieves the UsdcOrder struct as storage so it will be modified.
4. 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 withdraw from invalid or canceled orders.
5. 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.
6. Retrieves the token amount associated with the order and assigns it to the amountToWithdraw variable.
7. Sets the active flag of the order to false in storage.
8. Sets the tokenAmount of the order to zero in storage.
9. Transfers the amountToWithdraw of USDC 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.
10. Emits a Withdraw event, providing the orderToCancel ID and the amountToWithdraw for the subgraph

### Method swapUsd0

This method allows users to provide *USD0* tokens and receive *USDC* tokens by matching against existing orders. It matches the specified amount of *USD0* tokens against the specified orders, transfers the corresponding *USDC* tokens to the recipient, and updates the order states accordingly.

```rust
 1  function swapUsd0(address recipient, uint256 amountUsd0ToProvideInWad, uint256[] memory orderIdsToTake, bool partialMatchingAllowed) external nonReentrant returns (uint256) {
 2      uint256 usdcWadPrice = _getUsdcWadPrice();
 3      (, uint256 totalUsd0Provided) = _provideUsd0ReceiveUSDC(
 4        recipient, _getUsdcAmountFromUsd0WadEquivalent(amountUsd0ToProvideInWad, usdcWadPrice), orderIdsToTake, partialMatchingAllowed
 5      );
 6      return amountUsd0ToProvideInWad - totalUsd0Provided;
 7  }
```

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. Retrieves the current USDC price in WAD format using the getUsdcWadPrice() function. 3-5. Calculates the equivalent amount of USDC to take in native decimals based on the provided amountUsd0ToProvideInWad and the current usdcWadPrice using the \_getUsdcAmountFromUsd0WadEquivalent function. Then calls the \_provideUsd0ReceiveUSDC function to perform the actual swap, passing the recipient, amountUsdcToTakeInNativeDecimals, orderIdsToTake, and partialMatchingAllowed parameters. The function returns the total amount of usd0 provided.
3. Returns the sum of unmatchedUsd0 in wad format including dust, representing the total amount of USD0 that was not matched or was left as dust.


# USD0 Revenue Distribution Module

## High-Level Overview <a href="#high-level-overview" id="high-level-overview"></a>

This contract manages the automated minting and distribution of USD0 tokens to three dedicated distribution buckets. The contract enables multipurpose revenue distribution with three fixed buckets: Revenue Switch, Accruing Deposit Token (Accruing DT), and Rebasing Deposit Token (Rebasing DT). Each bucket operates independently with its own frequency, mint caps, pause mechanisms, and access control.

The core features of this contract include:

**Daily Accruing Deposit Token Distribution**: The contract should be called daily to calculate and mint USD0 tokens into the accruing deposit token vault (SUSD0/UsualS). The amount to mint is automatically calculated based on the vault's total assets and a configurable daily accruing yield rate. After minting, a yield distribution period is started in the vault to distribute the minted tokens over the next 24 hours.

**Daily Rebasing Deposit Token Distribution**: The contract should be called daily to mint a specified amount of USD0 tokens into the rebasing deposit token rewards claim contract. The amount is determined off-chain and provided as a parameter, typically based on an updated Merkle root calculated off-chain.

**Weekly Revenue Switch Distribution**: The contract should be called weekly to receive and mint USD0 rewards from the DAO into the revenue switch rewards claim contract. The amount is determined by the DAO and provided as a parameter when calling the function.

**Mint Cap Management**: The contract maintains a global operator mint cap that restricts the total amount of USD0 that can be minted through Revenue Switch and Rebasing DT distributions. Accruing DT distribution does not consume from the operator mint cap. Each bucket also has its own maximum mint cap per distribution period.

**Granular Pause Mechanisms**: Each distribution bucket can be paused independently, allowing for selective disabling of specific distribution channels without affecting others.

**Access Control**: Each functionality is controlled by a role with minimal required permissions, ensuring secure and restricted access to sensitive operations.

## Contract Summary <a href="#contract-summary" id="contract-summary"></a>

#### Inherited Contracts <a href="#inherited-contracts" id="inherited-contracts"></a>

**PausableUpgradeable**: Allows contract execution to be paused or unpaused by authorized roles. Provides both global pause functionality and per-bucket pause mechanisms.

**IRevenueDistributionModule**: Interface that defines all functions that can be called by anyone (view functions) and role-restricted functions for revenue distribution operations.

#### Storage Structure <a href="#storage-structure" id="storage-structure"></a>

The contract uses ERC-7201 namespaced storage with the following key state variables:

* **operatorMintCap**: Maximum amount of USD0 that can be minted globally (applies to Revenue Switch and Rebasing DT)
* **lastRevenueSwitchDistribution**: Timestamp of last Revenue Switch distribution
* **lastAccruingDTDistribution**: Timestamp of last Accruing DT distribution
* **lastRebasingDTDistribution**: Timestamp of last Rebasing DT distribution
* **dailyAccruingYieldRate**: Daily accruing yield rate in micro basis points (1 = 0.0001%)
* **maxRevSwitchMintCap**: Maximum amount per weekly Revenue Switch distribution
* **maxAccruingMintCap**: Maximum amount per daily Accruing DT distribution
* **maxRebasingDTMintCap**: Maximum amount per daily Rebasing DT distribution
* **rewardClaimForRevenueSwitch**: Address of reward claim contract for Revenue Switch
* **rewardClaimForAccruingDT**: Address of SUSD0 vault for Accruing DT (implements ISUsd0)
* **rewardClaimForRebasingDT**: Address of reward claim contract for Rebasing DT
* **revenueSwitchDistributionPaused**: Boolean flag for Revenue Switch pause state
* **accruingDTDistributionPaused**: Boolean flag for Accruing DT pause state
* **rebasingDTDistributionPaused**: Boolean flag for Rebasing DT pause state

## Functionality Description <a href="#functionality-description" id="functionality-description"></a>

#### Public/External Functions <a href="#publicexternal-functions" id="publicexternal-functions"></a>

**Initialization**

**initialize**: Initializes the contract with the registry address, reward claim contract addresses, and initial parameter values. Sets up all three distribution buckets with their initial timestamps. Can only be called once during contract deployment.

**IRevenueDistributionModule - Distribution Functions**

**distributeRevenueSwitch**:

* Distributes USD0 tokens to the Revenue Switch bucket (weekly)
* Requires `OPERATOR_REVSWITCH_DISTRIBUTOR_ROLE`
* Validates that at least one week has passed since last distribution
* Validates amount against maxRevSwitchMintCap and operatorMintCap
* Reduces operatorMintCap by the distributed amount
* Mints USD0 directly to rewardClaimForRevenueSwitch
* Can only be called when Revenue Switch distribution is not paused

**distributeAccruingDT**:

* Distributes USD0 tokens to the Accruing DT bucket (daily)
* Requires `OPERATOR_ACC_DT_DISTRIBUTOR_ROLE`
* Automatically calculates the amount to distribute based on:
  * `rewardClaimForAccruingDT.totalAssets() * dailyAccruingYieldRate / BASIS_MILLION_POINT_BASE`
* Validates that at least one day has passed since last distribution
* Validates calculated amount against maxAccruingMintCap
* Does not consume from operatorMintCap (unlike other distributions)
* Mints USD0 directly to rewardClaimForAccruingDT vault
* Starts a yield distribution period in the vault using `startYieldDistribution`
* The yield distribution period spans from current timestamp to current timestamp + ONE\_DAY
* Can only be called when Accruing DT distribution is not paused

**distributeRebasingDT**:

* Distributes USD0 tokens to the Rebasing DT bucket (daily)
* Requires `OPERATOR_REB_DT_DISTRIBUTOR_ROLE`
* Takes amount as parameter (typically calculated off-chain from Merkle root)
* Validates that at least one day has passed since last distribution
* Validates amount against maxRebasingDTMintCap and operatorMintCap
* Reduces operatorMintCap by the distributed amount
* Mints USD0 directly to rewardClaimForRebasingDT
* Can only be called when Rebasing DT distribution is not paused

**IRevenueDistributionModule - Configuration Functions (OPERATOR\_ADMIN\_ROLE)**

**setDailyAccruingYieldRate**: Sets the daily accruing yield rate used for calculating Accruing DT distribution amounts. Rate is in micro basis points (1 = 0.0001%), must be between 0 and BASIS\_MILLION\_POINT\_BASE.

**setOperatorMintCap**: Sets the global operator mint cap that limits total USD0 minting through Revenue Switch and Rebasing DT distributions.

**setMaxRevSwitchMintCap**: Sets the maximum amount of USD0 that can be minted per weekly Revenue Switch distribution.

**setMaxAccruingMintCap**: Sets the maximum amount of USD0 that can be minted per daily Accruing DT distribution.

**setMaxRebasingDTMintCap**: Sets the maximum amount of USD0 that can be minted per daily Rebasing DT distribution.

**setRewardClaimForRevenueSwitch**: Updates the reward claim contract address for Revenue Switch.

**setRewardClaimForAccruingDT**: Updates the reward claim contract address for Accruing DT. Must implement ISUsd0 interface.

**setRewardClaimForRebasingDT**: Updates the reward claim contract address for Rebasing DT.

**IRevenueDistributionModule - View Functions**

**getOperatorMintCap**: Returns the current operator mint cap value.

**getDailyAccruingYieldRate**: Returns the current daily accruing yield rate in micro basis points.

**getRewardClaimContractForRevenueSwitch**: Returns the reward claim contract address for Revenue Switch.

**getRewardClaimContractForAccruingDT**: Returns the reward claim contract address for Accruing DT.

**getRewardClaimContractForRebasingDT**: Returns the reward claim contract address for Rebasing DT.

**getMaxRevSwitchMintCap**: Returns the maximum amount of USD0 that can be minted per weekly Revenue Switch distribution.

**getMaxAccruingMintCap**: Returns the maximum amount of USD0 that can be minted per daily Accruing DT distribution.

**getMaxRebasingDTMintCap**: Returns the maximum amount of USD0 that can be minted per daily Rebasing DT distribution.

**isRevenueSwitchDistributionPaused**: Returns whether Revenue Switch distribution is currently paused.

**isAccruingDTDistributionPaused**: Returns whether Accruing DT distribution is currently paused.

**isRebasingDTDistributionPaused**: Returns whether Rebasing DT distribution is currently paused.

**IRevenueDistributionModule - Pause Functions**

**pause**: Pauses all contract operations. Can only be called by `PAUSING_CONTRACTS_ROLE`.

**unpause**: Unpauses all contract operations. Can only be called by `UNPAUSING_CONTRACTS_ROLE`.

**pauseRevenueSwitchDistribution**: Pauses only Revenue Switch distribution. Can only be called by `PAUSING_CONTRACTS_ROLE`.

**unpauseRevenueSwitchDistribution**: Unpauses Revenue Switch distribution. Can only be called by `UNPAUSING_CONTRACTS_ROLE`.

**pauseAccruingDTDistribution**: Pauses only Accruing DT distribution. Can only be called by `PAUSING_CONTRACTS_ROLE`.

**unpauseAccruingDTDistribution**: Unpauses Accruing DT distribution. Can only be called by `UNPAUSING_CONTRACTS_ROLE`.

**pauseRebasingDTDistribution**: Pauses only Rebasing DT distribution. Can only be called by `PAUSING_CONTRACTS_ROLE`.

**unpauseRebasingDTDistribution**: Unpauses Rebasing DT distribution. Can only be called by `UNPAUSING_CONTRACTS_ROLE`.

## Functionality Breakdown <a href="#functionality-breakdown" id="functionality-breakdown"></a>

#### Setting up Calculation Parameters <a href="#setting-up-calculation-parameters" id="setting-up-calculation-parameters"></a>

`OPERATOR_ADMIN_ROLE` can change all parameter values used in distribution calculations:

* Daily accruing yield rate (used in Accruing DT amount calculation)
* Operator mint cap (global limit for Revenue Switch and Rebasing DT)
* Individual bucket maximum mint caps

There is no timelock for these changes, allowing for rapid response to market conditions or protocol needs.

#### Daily Accruing Deposit Token Distribution <a href="#daily-accruing-deposit-token-distribution" id="daily-accruing-deposit-token-distribution"></a>

`OPERATOR_ACC_DT_DISTRIBUTOR_ROLE` is required to call `distributeAccruingDT` every 24 hours to:

1. Query the total assets value from the accruing deposit token vault (SUSD0)
2. Calculate the distribution amount: `totalAssets * dailyAccruingYieldRate / BASIS_MILLION_POINT_BASE`
3. Validate the calculated amount against maxAccruingMintCap
4. Mint the calculated amount of USD0 directly to the SUSD0 vault
5. Start a yield distribution period in the vault that distributes the minted tokens over the next 24 hours

**Note**: This distribution does not consume from the operator mint cap, as it is calculated based on vault assets rather than being an arbitrary amount set by an operator.

The amount distributed scales based on the vault's total assets, ensuring that as more users deposit into the vault, more yield is distributed proportionally.

#### Daily Rebasing Deposit Token Distribution <a href="#daily-rebasing-deposit-token-distribution" id="daily-rebasing-deposit-token-distribution"></a>

`OPERATOR_REB_DT_DISTRIBUTOR_ROLE` is required to call `distributeRebasingDT` with a valid amount every 24 hours. The amount is typically calculated off-chain based on an updated Merkle root:

1. Off-chain calculation determines the total USD0 amount to mint for eligible users
2. The amount is provided as a parameter to `distributeRebasingDT`
3. The contract validates the amount against maxRebasingDTMintCap and operatorMintCap
4. If valid, the operatorMintCap is reduced by the amount
5. USD0 is minted directly to the rebasing deposit token rewards claim contract
6. Users can claim their portion using valid Merkle proofs

This distribution requires off-chain infrastructure (Watchtower) to calculate the Merkle root and determine the total distribution amount based on eligible users and their assigned allocations.

#### Weekly Revenue Switch Distribution <a href="#weekly-revenue-switch-distribution" id="weekly-revenue-switch-distribution"></a>

`OPERATOR_REVSWITCH_DISTRIBUTOR_ROLE` is required to call `distributeRevenueSwitch` with a valid amount every week. The amount is determined by the DAO:

1. DAO determines the weekly USD0 rewards amount to distribute
2. The amount is provided as a parameter to `distributeRevenueSwitch`
3. The contract validates that at least one week has passed since last distribution
4. The contract validates the amount against maxRevSwitchMintCap and operatorMintCap
5. If valid, the operatorMintCap is reduced by the amount
6. USD0 is minted directly to the revenue switch rewards claim contract

This distribution enables the DAO to directly allocate USD0 rewards on a weekly basis, separate from the automated daily distributions.

#### Mint Cap Management <a href="#mint-cap-management" id="mint-cap-management"></a>

The contract implements a two-tier mint cap system:

1. **Operator Mint Cap**: Global limit for USD0 minting through Revenue Switch and Rebasing DT distributions. This cap is consumed when either of these distributions occurs and can be increased by `OPERATOR_ADMIN_ROLE` if needed.
2. **Per-Bucket Maximum Mint Caps**: Each distribution bucket has its own maximum amount that can be minted per distribution period:
   * `maxRevSwitchMintCap`: Maximum per weekly Revenue Switch distribution
   * `maxAccruingMintCap`: Maximum per daily Accruing DT distribution
   * `maxRebasingDTMintCap`: Maximum per daily Rebasing DT distribution

Both the operator mint cap and per-bucket caps must be satisfied for a distribution to proceed (except Accruing DT, which only checks its own cap).

#### Granular Pause Mechanisms <a href="#granular-pause-mechanisms" id="granular-pause-mechanisms"></a>

The contract supports both global and per-bucket pause functionality:

* **Global Pause**: Pauses all contract operations. Can be used in emergencies to halt all distributions.
* **Per-Bucket Pause**: Each distribution bucket can be paused independently:
  * `pauseRevenueSwitchDistribution` / `unpauseRevenueSwitchDistribution`
  * `pauseAccruingDTDistribution` / `unpauseAccruingDTDistribution`
  * `pauseRebasingDTDistribution` / `unpauseRebasingDTDistribution`

This granular control allows administrators to disable specific distribution channels without affecting others, useful for addressing issues in a single bucket or temporarily suspending specific revenue streams.

#### Accruing DT Yield Distribution Period <a href="#accruing-dt-yield-distribution-period" id="accruing-dt-yield-distribution-period"></a>

When `distributeAccruingDT` is called, after minting USD0 to the SUSD0 vault, the contract calls `startYieldDistribution` on the vault with:

* `yieldAmount`: The minted USD0 amount
* `startTime`: Current block timestamp
* `endTime`: Current block timestamp + ONE\_DAY

This initiates a yield distribution period in the vault where the minted tokens are distributed over the next 24 hours to vault holders proportionally. The vault's yield-bearing mechanism ensures that shares appreciate in value as yield accrues throughout the day.

#### Rebasing DT Merkle Root Integration <a href="#rebasing-dt-merkle-root-integration" id="rebasing-dt-merkle-root-integration"></a>

The Rebasing DT distribution relies on off-chain infrastructure (Watchtower) to:

1. Calculate eligible users and their allocations
2. Generate a Merkle root from these allocations
3. Determine the total USD0 amount to mint
4. Provide the amount to `distributeRebasingDT`

The actual user claims happen through the rewards claim contract using Merkle proofs, not directly through the Revenue Distribution Module.

## Constants <a href="#constants" id="constants"></a>

**OPERATOR\_REVSWITCH\_DISTRIBUTOR\_ROLE**: Role required to distribute USD0 to Revenue Switch bucket (weekly)

**OPERATOR\_ACC\_DT\_DISTRIBUTOR\_ROLE**: Role required to distribute USD0 to Accruing DT bucket (daily)

**OPERATOR\_REB\_DT\_DISTRIBUTOR\_ROLE**: Role required to distribute USD0 to Rebasing DT bucket (daily)

**OPERATOR\_ADMIN\_ROLE**: Role required to set configuration parameters (mint caps, yield rates, reward claim addresses)

**PAUSING\_CONTRACTS\_ROLE**: Role required to pause the contract or individual distribution buckets

**UNPAUSING\_CONTRACTS\_ROLE**: Role required to unpause the contract or individual distribution buckets

**CONTRACT\_REGISTRY\_ACCESS**: Constant used to define the address of the registry access contract

**CONTRACT\_USD0**: Constant used to define the address of the USD0 contract

**INITIAL\_REVENUE\_DISTRIBUTION\_MINT\_CAP**: Initial value for operator mint cap (50,000 USD0)

**ONE\_DAY**: Duration of one day in seconds (86,400 seconds)

**ONE\_WEEK**: Duration of one week in seconds (604,800 seconds)

**BASIS\_MILLION\_POINT\_BASE**: Base value for calculating percentages in micro basis points (1,000,000, where 1 = 0.0001%)

### Safeguard Implementation <a href="#safeguard-implementation" id="safeguard-implementation"></a>

#### Access Control <a href="#access-control" id="access-control"></a>

The contract uses `CheckAccessControl` to enforce role-based access control, ensuring only authorized addresses can perform actions that require specific permissions. Each role has minimal required permissions:

* Distribution roles can only trigger their specific distribution type
* Admin role can only modify configuration parameters
* Pausing roles can only pause/unpause functionality

#### Pausability <a href="#pausability" id="pausability"></a>

The contract is pausable at both global and per-bucket levels:

* Global pause can halt all operations in emergencies
* Per-bucket pause allows selective disabling of specific distribution channels
* Separate pausing and unpausing roles prevent unauthorized changes

#### Mint Cap Restrictions <a href="#mint-cap-restrictions" id="mint-cap-restrictions"></a>

Multiple layers of mint cap validation prevent excessive minting:

1. Operator mint cap limits total USD0 minting (for Revenue Switch and Rebasing DT)
2. Per-bucket maximum caps limit individual distribution amounts
3. Both caps must be satisfied for distributions to proceed

#### Time-Based Restrictions <a href="#time-based-restrictions" id="time-based-restrictions"></a>

Distribution functions enforce time-based restrictions to prevent abuse:

* Accruing DT can only be distributed once per day
* Rebasing DT can only be distributed once per day
* Revenue Switch can only be distributed once per week

These restrictions prevent operators from rapidly minting excessive amounts and ensure distributions occur at appropriate intervals.

#### Input Validation <a href="#input-validation" id="input-validation"></a>

All functions validate inputs:

* Non-zero addresses for reward claim contracts
* Non-zero amounts where applicable
* Yield rate bounds (0 to BASIS\_MILLION\_POINT\_BASE)
* Same value checks to prevent redundant updates

#### Invariant Validation <a href="#invariant-validation" id="invariant-validation"></a>

The contract maintains system invariants:

* Operator mint cap cannot be exceeded (except for Accruing DT which doesn't consume it)
* Distribution amounts must respect per-bucket maximum caps
* Time restrictions ensure distributions occur at proper intervals
* Pause states prevent distributions when buckets are disabled

**Note**: In scenarios where overcollateralization invariants are at risk, the contract can be paused or individual buckets can be disabled as a feature flag to protect the system.

#### Restrictions on Function Call Frequency <a href="#restrictions-on-function-call-frequency" id="restrictions-on-function-call-frequency"></a>

There are strict time-based limits for distribution functions:

* `distributeAccruingDT`: Can only be called once per 24 hours
* `distributeRebasingDT`: Can only be called once per 24 hours
* `distributeRevenueSwitch`: Can only be called once per week (7 days)

These restrictions prevent unwanted emissions and ensure distributions occur at controlled, predictable intervals. The time checks use block timestamps and enforce minimum periods between distributions.


# USD0a

<table data-card-size="large" data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td align="center"><strong>USD0a</strong> <strong>DAO Collateral Smart Contract</strong></td><td><a href="/pages/u3hr7PiUpt7PbR8wlHOO">/pages/u3hr7PiUpt7PbR8wlHOO</a></td><td data-object-fit="cover"><a href="/files/mRoGUG3gnWewZUoAn1hm">/files/mRoGUG3gnWewZUoAn1hm</a></td></tr><tr><td align="center"><strong>USD0a</strong> <strong>Swapper Engine Smart Contract</strong></td><td><a href="/pages/nDdGPaG95MB7JS8RQwOc">/pages/nDdGPaG95MB7JS8RQwOc</a></td><td data-object-fit="cover"><a href="/files/IKcZhsVeJNj0onWut15o">/files/IKcZhsVeJNj0onWut15o</a></td></tr><tr><td align="center"><strong>USD0a Gateway Smart Contract</strong></td><td><a href="/pages/HsiS8Gv2D6izuPIIRF9H">/pages/HsiS8Gv2D6izuPIIRF9H</a></td><td><a href="/files/0ZWBTkML3SMA8bSo1GHQ">/files/0ZWBTkML3SMA8bSo1GHQ</a></td></tr><tr><td align="center">USD0a Reverse Gateway Smart Contract</td><td><a href="/pages/JxlZbRDTS88piNVSR7Ix">/pages/JxlZbRDTS88piNVSR7Ix</a></td><td><a href="/files/4S7c1FAJrXmwqnP13RPn">/files/4S7c1FAJrXmwqnP13RPn</a></td></tr></tbody></table>


# USD0a DaoCollateral

### High-Level Overview <a href="#high-level-overview" id="high-level-overview"></a>

The DaoCollateral contract is a crucial component of the USD0a ecosystem, designed to manage the collateralization, minting, and redemption of USD0a tokens. USD0a is a yield-bearing token that represents a proportional share of the total value of underlying collateral assets. The contract facilitates the swapping of collateral tokens (such as USCC, USTB, and USDC) for USD0a, redemption of USD0a for collateral tokens, and implements a Counter Bank Run (CBR) mechanism to protect the protocol during extreme market conditions.

### Contract Summary <a href="#contract-summary" id="contract-summary"></a>

#### Inherited Contracts <a href="#inherited-contracts" id="inherited-contracts"></a>

* **ReentrancyGuardUpgradeable (OZ)**: Prevents reentrant attacks on sensitive functions.
* **PausableUpgradeable (OZ)**: Enables pausing of contract functionality by authorized accounts.

#### Functionality Breakdown <a href="#functionality-breakdown" id="functionality-breakdown"></a>

**Key Functionalities**

**1. Minting and redeeming USD0a:**

At its core, the contract accrues collaterals by routing trades accordingly. When a user sends collateral tokens, the daoCollateral contract mints the equivalent amount of USD0a tokens, and vice versa, allowing users to exchange their USD0a tokens for collaterals at the current exchange rate.

* **Swap**: Facilitates the conversion of collateral tokens (such as USCC, USTB, and USDC) into USD0a tokens. Upon initiating this function, users exchange their collateral tokens for USD0a tokens directly. The amount of USD0a minted is calculated based on the current USD0a price in USD, which accounts for yield accumulation. Since USD0a is yield-bearing, its price increases over time depending on the collaterals price.
* **Redeem**: Allows users to redeem their USD0a tokens against a fee. By invoking this function, users exchange their USD0a tokens for collateral tokens at the current exchange rate. The redemption fee is deducted from the amount and, when CBR is not active, is minted to the yield treasury to improve the collateralization ratio.

**2. Counter Bank Run (CBR) Mechanism:**

The Counter Bank Run mechanism is a protective feature that can be activated during extreme market conditions. When activated:

* Swap functionality is automatically paused
* Redemptions continue but at a reduced rate (determined by the CBR coefficient)
* Redemption fees are burned instead of being sent to the yield treasury, helping to maintain the protocol's solvency
* The CBR coefficient (between 0 and 1) determines the discount applied to redemptions

**3. Role-Based Access Control**

The contract implements a role-based access control system for sensitive operations:

* **CBR\_OPERATOR\_ROLE**: Required to activate or deactivate the Counter Bank Run mechanism.
* **REDEEM\_FEE\_OPERATOR\_ROLE**: Allows setting of the redemption fee, which is crucial for managing protocol economics.
* **MIN\_REDEEM\_AMOUNT\_SETTER\_ROLE**: Allows setting of the minimum redeem amount in USD0a, preventing dust redemptions.
* **DAO\_REDEMPTION\_ROLE**: Grants the ability to perform fee-free redemptions for DAO operations.
* **PAUSING\_CONTRACTS\_ROLE**: Grants the ability to pause specific contract functionalities in case of emergencies.
* **UNPAUSING\_CONTRACTS\_ROLE**: Grants the ability to unpause contract functionalities.

These roles ensure that different levels of access are properly managed and that sensitive operations are restricted to authorized entities, enhancing the overall security and governance of the contract.

### Functions Description <a href="#functions-description" id="functions-description"></a>

#### Public/External Functions <a href="#publicexternal-functions" id="publicexternal-functions"></a>

* **initialize**: Sets up the contract with initial parameters including the registry contract and initial redeem fee.
* **swap**: Allows users to swap collateral tokens for USD0a. The function calculates the USD value of the collateral tokens, determines the equivalent USD0a amount based on the current USD0a price, and mints USD0a to the user.
* **swapWithPermit**: Similar to swap but uses permit for approval, enabling gasless approvals for supported tokens.
* **redeem**: Enables users to redeem USD0a for collateral tokens. A redemption fee is deducted, and the net amount is used to calculate the collateral tokens returned. The fee is minted to the yield treasury (unless CBR is active).
* **redeemDao**: Special redemption function for DAO operations that bypasses the redemption fee. Only callable by DAO\_REDEMPTION\_ROLE.
* **activateCBR**: Activates the Counter Bank Run mechanism with a specified coefficient. Automatically pauses swap functionality. Only callable by CBR\_OPERATOR\_ROLE.
* **deactivateCBR**: Deactivates the Counter Bank Run mechanism. Only callable by CBR\_OPERATOR\_ROLE.
* **setRedeemFee**: Sets the fee for redemption operations (in basis points). Only callable by REDEEM\_FEE\_OPERATOR\_ROLE.
* **setMinRedeemAmountInUSD0X**: Sets the minimum amount of USD0a that can be redeemed. Only callable by MIN\_REDEEM\_AMOUNT\_SETTER\_ROLE.
* **pauseRedeem, pauseSwap, pause**: Pausing functions for specific operations or the entire contract. Only callable by PAUSING\_CONTRACTS\_ROLE.
* **unpause, unpauseRedeem, unpauseSwap**: Global unpausing functions. Only callable by UNPAUSING\_CONTRACTS\_ROLE.

#### Getter Functions <a href="#getter-functions" id="getter-functions"></a>

* **isCBROn**: Returns whether the Counter Bank Run mechanism is currently active.
* **cbrCoef**: Returns the current CBR coefficient.
* **redeemFee**: Returns the current redemption fee in basis points.
* **minRedeemAmountInUSD0X**: Returns the minimum amount of USD0a that can be redeemed.
* **isRedeemPaused**: Returns whether redeem functionality is paused.
* **isSwapPaused**: Returns whether swap functionality is paused.

### Constants <a href="#constants" id="constants"></a>

* **CONTRACT\_REGISTRY\_ACCESS**: Address of the registry access contract.
* **CONTRACT\_TOKEN\_MAPPING**: Address of the token mapping contract.
* **CONTRACT\_ORACLE**: Address of the oracle contract.
* **CONTRACT\_TREASURY**: Address of the treasury contract holding collateral tokens.
* **CONTRACT\_YIELD\_TREASURY**: Address of the treasury contract holding fee tokens.
* **CONTRACT\_USD0X**: Address of the USD0a token contract.
* **CBR\_OPERATOR\_ROLE**: Role identifier for CBR operations.
* **REDEEM\_FEE\_OPERATOR\_ROLE**: Role identifier for setting redemption fees.
* **MIN\_REDEEM\_AMOUNT\_SETTER\_ROLE**: Role identifier for setting minimum redeem amounts.
* **DAO\_REDEMPTION\_ROLE**: Role identifier for DAO redemptions.
* **PAUSING\_CONTRACTS\_ROLE**: Role identifier for pausing contract operations.
* **UNPAUSING\_CONTRACTS\_ROLE**: Role identifier for unpausing contract operations.
* **MAX\_REDEEM\_FEE**: Maximum allowed redemption fee (2500 basis points = 25%).
* **SCALAR\_ONE**: Scalar value representing 1 in the contract's decimal system (1e18).

### Key Components <a href="#key-components" id="key-components"></a>

* **Oracle Integration**: Uses an oracle to fetch real-time price data for collateral tokens and USD0a.
* **Token Mapping**: Manages the mapping of supported collateral tokens through the TokenMapping contract.
* **Access Control**: Implements role-based access control for administrative functions through the RegistryAccess contract.
* **USD0a Price Integration**: Interacts with the USD0a token contract to get the current USD0a price in USD, which accounts for yield accumulation and determines the exchange rate for swaps and redemptions.

### Safeguards Implementation <a href="#safeguards-implementation" id="safeguards-implementation"></a>

* **Pausability**: Allows pausing of critical functions (swap, redeem, or entire contract) in emergencies.
* **Reentrancy Protection**: Uses OpenZeppelin's ReentrancyGuard to prevent reentrancy attacks.
* **Access Control**: Restricts sensitive operations to authorized roles.
* **Counter Bank Run (CBR)**: Provides a mechanism to protect the protocol during extreme market conditions by reducing redemption rates and pausing swaps.
* **Minimum Redeem Amount**: Prevents dust redemptions that could be economically inefficient.
* **Price Validation**: Ensures prices are non-zero before executing swaps or redemptions.
* **Amount Validation**: Validates that amounts are non-zero, within acceptable ranges, and meet minimum thresholds.


# USD0a SwapperEngine

### High-Level Overview <a href="#high-level-overview" id="high-level-overview"></a>

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 <a href="#contract-summary" id="contract-summary"></a>

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 <a href="#inherited-contracts" id="inherited-contracts"></a>

* **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 <a href="#functionality-breakdown" id="functionality-breakdown"></a>

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: <a href="#order-creation" id="order-creation"></a>

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: <a href="#order-cancellation" id="order-cancellation"></a>

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: <a href="#order-matching" id="order-matching"></a>

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: <a href="#price-calculation" id="price-calculation"></a>

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 <a href="#security-analysis" id="security-analysis"></a>

#### Method: provideUSDCReceiveUSD0X <a href="#method-provideusdcreceiveusd0x" id="method-provideusdcreceiveusd0x"></a>

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 <a href="#method-depositusd0x" id="method-depositusd0x"></a>

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 <a href="#method-cancelusd0xorder" id="method-cancelusd0xorder"></a>

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 <a href="#method-_getusdcamountfromusd0xwadequivalent" id="method-_getusdcamountfromusd0xwadequivalent"></a>

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 <a href="#functions-description" id="functions-description"></a>

#### Public/External Functions <a href="#publicexternal-functions" id="publicexternal-functions"></a>

* **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 <a href="#getter-functions" id="getter-functions"></a>

* **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 <a href="#constants" id="constants"></a>

* **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 <a href="#key-components" id="key-components"></a>

* **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 <a href="#safeguards-implementation" id="safeguards-implementation"></a>

* **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.


# USD0a Gateway

### High-Level Overview <a href="#high-level-overview" id="high-level-overview"></a>

The Gateway contract is a fully permissioned smart contract designed to manage intermediary treasury operations between the protocol's collateral treasury and external collateral services such as Superstate and Circle. The contract facilitates the conversion of USDC tokens (from Circle) to USCC tokens (from Superstate) through an order-based tracking system, enabling the protocol to rebalance treasury collaterals efficiently.

The main objective of the Gateway contract is to provide a secure, auditable, and controlled mechanism for interacting with external collateral services while maintaining USD0a price stability through the DebtUSDC token system. When the protocol needs to switch some USDC to USCC, the Gateway manages these operations by tracking deposits and withdrawals through orders. Critically, the Gateway mints DebtUSDC tokens when USDC is sent to Superstate to prevent USD0a price from decreasing while waiting for USCC, since USD0a price depends on the amount of collaterals in the treasury.

**Key Use Case**: The Gateway is primarily used for treasury rebalancing operations. For example, if the protocol wants to convert USDC to USCC, an authorized operator can deposit USDC through the Gateway, which transfers the USDC to the Superstate contract. The Gateway then mints DebtUSDC tokens (1:1 with the USDC amount) to maintain USD0a price stability. This is critical because USD0a price depends on the amount of collaterals in the treasury. Without minting DebtUSDC, the USD0a price would decrease when USDC is sent to Superstate (reducing treasury collateral) while waiting for USCC. By minting DebtUSDC, the protocol maintains the accounting balance, preventing USD0a price from decreasing during the conversion process. When USCC is received from Superstate, the operator can withdraw through the Gateway, which burns the corresponding DebtUSDC tokens and transfers the USCC to the collateral treasury, replacing the debt token with actual collateral.

### Contract Summary <a href="#contract-summary" id="contract-summary"></a>

The contract provides the following main functions:

* **deposit**: Allows authorized users to deposit USDC tokens, transfer them to the Superstate contract, and create a tracking order. This function also mints DebtUSDC tokens (1:1 with USDC) to the collateral treasury to maintain USD0a price stability. Without this minting, the USD0a price would decrease because it depends on the amount of collaterals in the treasury, and USDC is temporarily reduced while waiting for USCC.
* **withdraw**: Allows authorized users to withdraw USCC tokens by burning the corresponding DebtUSDC tokens for specified orders. The function accepts a `usccAmount` parameter because the exact amount received from Superstate cannot be predicted.
* **emergencyWithdraw**: Provides an emergency mechanism to recover tokens that may have been accidentally sent to the contract.
* **setSuperstateAddress**: Allows authorized users to update the Superstate contract address, enabling the protocol to adapt to contract upgrades or migrations.

The contract also includes utility functions such as `getOrder`, `getNextOrderId`, `superstate`, and `collateralTreasury` to retrieve order details and contract configuration.

The Gateway uses an order-based system to track deposits and withdrawals. Each deposit creates an order that stores the USDC amount, active status, and timestamp. Orders are deactivated during withdrawal to prevent double-spending. The DebtUSDC token system ensures that USD0a price stability is maintained during collateral conversion operations. When USDC is sent to Superstate, the treasury temporarily loses collateral, which would cause USD0a price to decrease. By minting DebtUSDC tokens (1:1 with the USDC amount), the protocol maintains the accounting balance, preventing USD0a price from decreasing while waiting for USCC. When USCC is received and DebtUSDC is burned, the actual collateral replaces the debt token.

### Inherited Contracts <a href="#inherited-contracts" id="inherited-contracts"></a>

**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 <a href="#functionality-breakdown" id="functionality-breakdown"></a>

The Gateway contract's primary purpose is to facilitate treasury rebalancing operations by managing interactions with external collateral services. The contract's functionality can be broken down into the following key components:

#### Order Creation (Deposit): <a href="#order-creation-deposit" id="order-creation-deposit"></a>

Users with the `GATEWAY_DEPOSIT_ROLE` can create new orders by calling the `deposit` function and specifying the amount of USDC tokens to deposit.

The contract transfers the specified amount of USDC tokens from the caller directly to the Superstate contract (not to the Gateway contract itself).

The contract creates a new order with a unique order ID, storing the USDC amount, active status (set to true), and the current block timestamp.

The contract mints DebtUSDC tokens (1:1 with the USDC amount) to the collateral treasury. The debt token maintains the accounting balance until USCC is received and replaces it.

The order is assigned a unique order ID (starting from 1) and stored in the contract's orders mapping.

#### Order Fulfillment (Withdraw): <a href="#order-fulfillment-withdraw" id="order-fulfillment-withdraw"></a>

Users with the `GATEWAY_WITHDRAW_ROLE` can fulfill orders by calling the `withdraw` function and specifying an array of order IDs to process and the amount of USCC tokens to withdraw.

The contract validates that all specified orders are active and exist.

For each order, the contract deactivates the order (sets `active` to false) to prevent double-spending.

The contract burns DebtUSDC tokens from the collateral treasury (1:1 with each order's USDC amount). This clears the protocol's obligation for the fulfilled orders.

The contract transfers the specified amount of USCC tokens from the Gateway contract to the collateral treasury.

**Important**: The `usccAmount` parameter is provided by the caller because the exact amount of USCC received from Superstate cannot be predicted in advance. This allows the protocol to handle variable exchange rates, fees, or other factors that may affect the final amount received from external services.

#### DebtUSDC Accounting: <a href="#debtusdc-accounting" id="debtusdc-accounting"></a>

The Gateway uses the DebtUSDC token system to maintain USD0a price stability during collateral conversion operations. When USDC is deposited and sent to Superstate, the treasury temporarily loses USDC collateral. Since USD0a price depends on the amount of collaterals in the treasury, this reduction would cause USD0a price to decrease. To prevent this, DebtUSDC tokens are minted (1:1 with the USDC amount) to maintain the accounting balance. This ensures that USD0a price remains stable while waiting for USCC from Superstate. When USCC is received and withdrawn, the corresponding DebtUSDC tokens are burned, and the actual USCC collateral replaces the debt token. This mechanism ensures that USD0a price stability is maintained throughout the entire conversion process, even when interacting with third-party services that may have processing delays.

#### External Integration: <a href="#external-integration" id="external-integration"></a>

The Gateway integrates with the Superstate contract for USDC transfers and USCC redemptions. USDC (from Circle) is transferred directly to the Superstate contract during deposits, and USCC is expected to be received from Superstate before withdrawals can be processed. The Gateway also integrates with the Registry system to access the DebtUSDC contract, collateral treasury address, and access control mechanisms.

### Security Analysis <a href="#security-analysis" id="security-analysis"></a>

#### Method: deposit <a href="#method-deposit" id="method-deposit"></a>

This method allows authorized users to deposit USDC tokens, transfer them to the Superstate contract, create a tracking order, and mint DebtUSDC tokens to the collateral treasury.

**Function Description:**

* 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.
* The function is protected by the `whenNotPaused` modifier, ensuring that deposits cannot be made when the contract is paused.
* Validates that the USDC amount is greater than zero.
* Validates that the caller has the `GATEWAY_DEPOSIT_ROLE` using role-based access control.
* 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.
* Creates a new `GatewayOrder` struct in storage using the order ID as key. The struct contains: the USDC amount, the active flag set to true, and the current block timestamp.
* Transfers the specified amount of USDC tokens from the caller directly to the Superstate contract (not to the Gateway contract) using `safeTransferFrom` to ensure that the transfer is successful. If the transfer fails, the function will revert.
* Mints DebtUSDC tokens (1:1 with the USDC amount) to the collateral treasury. This is critical for maintaining USD0a price stability. Since USD0a price depends on the amount of collaterals in the treasury, and USDC is temporarily reduced while waiting for USCC from Superstate, minting DebtUSDC prevents the USD0a price from decreasing during the conversion process. The debt token maintains the accounting balance until USCC is received and replaces it.
* Emits a `Deposit` event, providing the caller address, order ID, and USDC amount for tracking.

#### Method: withdraw <a href="#method-withdraw" id="method-withdraw"></a>

This method allows authorized users to withdraw USCC tokens by burning the corresponding DebtUSDC tokens for specified orders and transferring USCC to the collateral treasury.

**Function Description:**

* The function is protected against reentrancy attacks by using the `nonReentrant` modifier.
* The function is protected by the `whenNotPaused` modifier, ensuring that withdrawals cannot be made when the contract is paused.
* Validates that at least one order ID is provided (orderIds.length > 0).
* Validates that the USCC amount is greater than zero.
* Validates that the caller has the `GATEWAY_WITHDRAW_ROLE` using role-based access control.
* Iterates through the provided order IDs and validates that each order is active. If any order is not active or does not exist, the function will revert with an appropriate error message. This prevents any attempts to withdraw from invalid or already processed orders.
* For each order, deactivates the order by setting the `active` flag to false in storage. This prevents double-spending and ensures that orders can only be processed once.
* Burns DebtUSDC tokens from the collateral treasury (1:1 with each order's USDC amount). This clears the protocol's obligation for the fulfilled orders and ensures proper accounting.
* Accumulates the total debt tokens burned across all orders for event emission.
* Transfers the specified amount of USCC tokens from the Gateway contract to the collateral treasury using the `safeTransfer` function. This ensures that the transfer is successful. If the transfer fails, the function will revert.
* **Important**: The `usccAmount` parameter is provided by the caller because the exact amount of USCC received from Superstate cannot be predicted in advance. This allows the protocol to handle variable exchange rates, fees, or other factors that may affect the final amount received from external services.
* Emits a `Withdraw` event, providing the caller address, order IDs, total debt tokens burned, and USCC amount for tracking.

#### Method: emergencyWithdraw <a href="#method-emergencywithdraw" id="method-emergencywithdraw"></a>

This method provides an emergency mechanism to recover tokens that may have been accidentally sent to the Gateway contract.

**Function Description:**

* The function is protected against reentrancy attacks by using the `nonReentrant` modifier.
* Validates that the token address is not the zero address.
* Validates that the recipient address is not the zero address.
* Validates that the amount is greater than zero.
* Validates that the caller has the `EMERGENCY_WITHDRAW_ROLE` using role-based access control.
* Transfers the specified amount of tokens from the Gateway contract to the recipient using the `safeTransfer` function. This ensures that the transfer is successful. If the transfer fails, the function will revert.
* Emits an `EmergencyWithdraw` event, providing the token address, amount, and recipient for tracking.

#### Method: setSuperstateAddress <a href="#method-setsuperstateaddress" id="method-setsuperstateaddress"></a>

This method allows authorized users to update the Superstate contract address, enabling the protocol to adapt to contract upgrades or migrations.

**Function Description:**

* Validates that the new Superstate address is not the zero address.
* Validates that the new Superstate address is different from the current address to prevent unnecessary state changes.
* Validates that the caller has the `GATEWAY_SUPERSTATE_SETTER_ROLE` using role-based access control.
* Updates the Superstate address in storage.
* Emits a `SuperstateUpdated` event, providing the old and new Superstate addresses for tracking.

#### Getter Functions <a href="#getter-functions" id="getter-functions"></a>

**getOrder**: Returns the details of a specific order including USDC amount, active status, and timestamp.

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

**superstate**: Returns the current Superstate contract address.

**collateralTreasury**: Returns the current collateral treasury address.

### Constants <a href="#constants" id="constants"></a>

**`CONTRACT_REGISTRY_ACCESS`**: Address of the registry access contract.

**`CONTRACT_DEBT_USDC`**: Address of the DebtUSDC token contract.

**`CONTRACT_TREASURY`**: Address of the collateral treasury contract.

**`GATEWAY_DEPOSIT_ROLE`**: Role identifier for depositing USDC and creating orders.

**`GATEWAY_WITHDRAW_ROLE`**: Role identifier for withdrawing USCC and fulfilling orders.

**`EMERGENCY_WITHDRAW_ROLE`**: Role identifier for emergency token recovery.

**`GATEWAY_SUPERSTATE_SETTER_ROLE`**: Role identifier for updating the Superstate address.

**`PAUSING_CONTRACTS_ROLE`**: Role identifier for pausing contract operations.

**`UNPAUSING_CONTRACTS_ROLE`**: Role identifier for unpausing contract operations.

### Safeguards Implementation <a href="#safeguards-implementation" id="safeguards-implementation"></a>

**Pausability**: Allows pausing of contract functionality in emergencies. The contract can be paused by `PAUSING_CONTRACTS_ROLE` and unpaused by `UNPAUSING_CONTRACTS_ROLE`.

**Reentrancy Protection**: Uses OpenZeppelin's ReentrancyGuard to prevent reentrancy attacks. All state-changing functions are protected with the `nonReentrant` modifier.

**Access Control**: Restricts sensitive operations to authorized roles. Deposit operations require `GATEWAY_DEPOSIT_ROLE`, withdrawal operations require `GATEWAY_WITHDRAW_ROLE`, emergency withdrawals require `EMERGENCY_WITHDRAW_ROLE`, and Superstate address updates require `GATEWAY_SUPERSTATE_SETTER_ROLE`.

**Amount Validation**: Validates that amounts are non-zero and that order arrays are not empty before processing operations.

**Order Validation**: Validates that orders are active before processing withdrawals, preventing attempts to process invalid or already processed orders.

**Null Address Checks**: Validates that all addresses (registry, Superstate, tokens, recipient) are not the zero address before processing operations.

**Order Deactivation**: Deactivates orders during withdrawal to prevent double-spending and ensure that orders can only be processed once.

**SafeERC20**: Uses SafeERC20 for all token transfers to prevent failures from going unnoticed and to handle non-standard ERC20 implementations safely.

**Storage Safety**: Uses ERC-7201 namespaced storage pattern (`GatewayStorageV0`) to prevent storage collisions during upgrades. The contract is upgradeable via UUPS proxy pattern.

**Same Value Protection**: Prevents unnecessary state changes by validating that the new Superstate address is different from the current address before updating.


# USD0a Reverse Gateway

### High-Level Overview <a href="#high-level-overview" id="high-level-overview"></a>

The ReverseGateway contract is a fully permissioned smart contract designed to manage intermediary treasury operations between the protocol's collateral treasury and external collateral services such as Superstate. The contract facilitates the conversion of USCC tokens (from Superstate) to USDC tokens (from Circle) through an order-based tracking system, enabling the protocol to rebalance treasury collaterals efficiently.

The main objective of the ReverseGateway contract is to provide a secure and controlled mechanism for interacting with external collateral services while maintaining USD0a price stability through the DebtUSCC token system. When the protocol needs to switch some USCC to USDC, the ReverseGateway manages these operations by tracking deposits and withdrawals through orders. Critically, the ReverseGateway mints DebtUSCC tokens when USCC is sent to Superstate to prevent USD0a price from decreasing while waiting for USDC, since USD0a price depends on the amount of collaterals in the treasury.

**Key Use Case**: The ReverseGateway is primarily used for treasury rebalancing operations in the opposite direction of the Gateway. For example, if the protocol wants to convert USCC to USDC, an authorized operator can deposit USCC through the ReverseGateway, which transfers the USCC to the Superstate contract. The ReverseGateway then mints DebtUSCC tokens (1:1 with the USCC amount) to maintain USD0a price stability. This is critical because USD0a price depends on the amount of collaterals in the treasury. Without minting DebtUSCC, the USD0a price would decrease when USCC is sent to Superstate (reducing treasury collateral) while waiting for USDC. By minting DebtUSCC, the protocol maintains the accounting balance, preventing USD0a price from decreasing during the conversion process. When USDC is received from Superstate, the operator can withdraw through the ReverseGateway, which burns the corresponding DebtUSCC tokens and transfers the USDC to the collateral treasury, replacing the debt token with actual collateral.

**Important Difference from Gateway**: Unlike the Gateway contract which allows multiple concurrent deposits, the ReverseGateway enforces a single deposit at a time policy. This is implemented through an `ongoingDeposit` flag that prevents new deposits while a previous deposit is still being processed. This design ensures that only one conversion operation is active at any given time, which is critical for maintaining consistent pricing of the DebtUSCC token. By allowing only one deposit at a time, the protocol ensures that all DebtUSCC tokens are minted at a consistent price point (captured via the USCC oracle roundId), preventing price inconsistencies that could arise from multiple concurrent deposits at different price points. Additionally, this constraint simplifies the withdrawal process and reduces complexity in managing multiple concurrent orders.

### Contract Summary <a href="#contract-summary" id="contract-summary"></a>

The contract provides the following main functions:

* **deposit**: Allows authorized users to deposit USCC tokens, transfer them to the Superstate contract, and create a tracking order. This function also mints DebtUSCC tokens (1:1 with USCC) to the collateral treasury to maintain USD0a price stability. Without this minting, the USD0a price would decrease because it depends on the amount of collaterals in the treasury, and USCC is temporarily reduced while waiting for USDC. The function captures the USCC oracle roundId at the time of deposit for price tracking purposes. **Only one deposit can be active at a time** - if an ongoing deposit exists, the function will revert.
* **withdraw**: Allows authorized users to withdraw USDC tokens by burning the corresponding DebtUSCC tokens for the last (most recent) order. The function accepts a `usdcAmount` parameter because the exact amount received from Superstate cannot be predicted. After processing the withdrawal, the `ongoingDeposit` flag is reset to false, allowing new deposits.
* **emergencyWithdraw**: Provides an emergency mechanism to recover tokens that may have been accidentally sent to the contract.
* **setSuperstateAddress**: Allows authorized users to update the Superstate contract address, enabling the protocol to adapt to contract upgrades or migrations.

The contract also includes utility functions such as `getOrder`, `getNextOrderId`, `superstate`, `collateralTreasury`, `usccOracle`, `usdcToken`, `usccToken`, and `debtUSCC` to retrieve order details and contract configuration.

The ReverseGateway uses an order-based system to track deposits and withdrawals. Each deposit creates an order that stores the USCC amount, active status, timestamp, and the USCC oracle roundId at the time of deposit. Orders are deactivated during withdrawal to prevent double-spending. The DebtUSCC token system ensures that USD0a price stability is maintained during collateral conversion operations. When USCC is sent to Superstate, the treasury temporarily loses collateral, which would cause USD0a price to decrease. By minting DebtUSCC tokens (1:1 with the USCC amount), the protocol maintains the accounting balance, preventing USD0a price from decreasing while waiting for USDC. When USDC is received and DebtUSCC is burned, the actual collateral replaces the debt token.

### Inherited Contracts <a href="#inherited-contracts" id="inherited-contracts"></a>

* **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 <a href="#functionality-breakdown" id="functionality-breakdown"></a>

The ReverseGateway contract's primary purpose is to facilitate treasury rebalancing operations by managing interactions with external collateral services in the reverse direction (USCC to USDC). The contract's functionality can be broken down into the following key components:

#### Order Creation (Deposit): <a href="#order-creation-deposit" id="order-creation-deposit"></a>

* Users with the `GATEWAY_DEPOSIT_ROLE` can create new orders by calling the `deposit` function and specifying the amount of USCC tokens to deposit.
* The contract validates that no ongoing deposit exists. If an `ongoingDeposit` flag is set to true, the function will revert with an `OngoingDeposit` error, ensuring only one deposit can be processed at a time.
* The contract captures the current USCC oracle roundId by calling `latestRoundData()` on the USCC oracle. This roundId is stored in the order for price tracking and audit purposes.
* The contract transfers the specified amount of USCC tokens from the caller directly to the Superstate contract (not to the ReverseGateway contract itself).
* The contract creates a new order with a unique order ID, storing the USCC amount, active status (set to true), the current block timestamp, and the captured oracle roundId.
* The contract mints DebtUSCC tokens (1:1 with the USCC amount) to the collateral treasury. The debt token maintains the accounting balance until USDC is received and replaces it.
* The order is assigned a unique order ID (starting from 1) and stored in the contract's orders mapping.
* The `ongoingDeposit` flag is set to true to prevent concurrent deposits.

#### Order Fulfillment (Withdraw): <a href="#order-fulfillment-withdraw" id="order-fulfillment-withdraw"></a>

* Users with the `GATEWAY_WITHDRAW_ROLE` can fulfill the most recent order by calling the `withdraw` function and specifying the amount of USDC tokens to withdraw.
* The contract automatically processes the last order (identified by `nextOrderId - 1`), ensuring that orders are fulfilled in a first-in-first-out manner.
* The contract validates that the last order is active and exists. If the order is not active, the function will revert with an `OrderNotActive` error.
* The contract deactivates the order (sets `active` to false) to prevent double-spending.
* The contract burns DebtUSCC tokens from the collateral treasury (1:1 with the order's USCC amount). This clears the protocol's obligation for the fulfilled order.
* The contract transfers the specified amount of USDC tokens from the ReverseGateway contract to the collateral treasury.
* The `ongoingDeposit` flag is set to false, allowing new deposits to be processed.
* **Important**: The `usdcAmount` parameter is provided by the caller because the exact amount of USDC received from Superstate cannot be predicted in advance. This allows the protocol to handle variable exchange rates, fees, or other factors that may affect the final amount received from external services.

#### DebtUSCC Accounting: <a href="#debtuscc-accounting" id="debtuscc-accounting"></a>

The ReverseGateway uses the DebtUSCC token system to maintain USD0a price stability during collateral conversion operations. When USCC is deposited and sent to Superstate, the treasury temporarily loses USCC collateral. Since USD0a price depends on the amount of collaterals in the treasury, this reduction would cause USD0a price to decrease. To prevent this, DebtUSCC tokens are minted (1:1 with the USCC amount) to maintain the accounting balance. This ensures that USD0a price remains stable while waiting for USDC from Superstate. When USDC is received and withdrawn, the corresponding DebtUSCC tokens are burned, and the actual USDC collateral replaces the debt token. This mechanism ensures that USD0a price stability is maintained throughout the entire conversion process, even when interacting with third-party services that may have processing delays.

#### Oracle Integration: <a href="#oracle-integration" id="oracle-integration"></a>

The ReverseGateway integrates with a USCC oracle (IAggregator) to capture price information at the time of deposit. During the deposit process, the contract calls `latestRoundData()` on the USCC oracle and stores the `roundId` in the order. This allows the protocol to track the USCC price at the time of deposit, which can be useful for auditing, price verification, and ensuring fair conversions. The oracle address is set during initialization and can be queried through the `usccOracle()` getter function.

#### External Integration: <a href="#external-integration" id="external-integration"></a>

The ReverseGateway integrates with the Superstate contract for USCC transfers and USDC redemptions. USCC (from Superstate) is transferred directly to the Superstate contract during deposits, and USDC is expected to be received from Superstate before withdrawals can be processed.

### Security Analysis <a href="#security-analysis" id="security-analysis"></a>

#### Method: deposit <a href="#method-deposit" id="method-deposit"></a>

This method allows authorized users to deposit USCC tokens, transfer them to the Superstate contract, create a tracking order, and mint DebtUSCC tokens to the collateral treasury.

**Function Description:**

* 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.
* The function is protected by the `whenNotPaused` modifier, ensuring that deposits cannot be made when the contract is paused.
* Validates that the USCC amount is greater than zero.
* Validates that the caller has the `GATEWAY_DEPOSIT_ROLE` using role-based access control.
* **Validates that no ongoing deposit exists** by checking the `ongoingDeposit` flag. If an ongoing deposit is in progress, the function will revert with an `OngoingDeposit` error. This ensures only one deposit can be processed at a time.
* Sets the `ongoingDeposit` flag to true to prevent concurrent deposits.
* 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.
* Captures the current USCC oracle roundId by calling `latestRoundData()` on the USCC oracle. This roundId is stored in the order for price tracking purposes.
* Creates a new `ReverseGatewayOrder` struct in storage using the order ID as key. The struct contains: the USCC amount, the active flag set to true, the current block timestamp, and the captured oracle roundId.
* Transfers the specified amount of USCC tokens from the caller directly to the Superstate contract (not to the ReverseGateway contract) using `safeTransferFrom` to ensure that the transfer is successful. If the transfer fails, the function will revert.
* Mints DebtUSCC tokens (1:1 with the USCC amount) to the collateral treasury. This is critical for maintaining USD0a price stability. Since USD0a price depends on the amount of collaterals in the treasury, and USCC is temporarily reduced while waiting for USDC from Superstate, minting DebtUSCC prevents the USD0a price from decreasing during the conversion process. The debt token maintains the accounting balance until USDC is received and replaces it.
* Emits a `Deposit` event, providing the caller address, order ID, and USCC amount for tracking.

#### Method: withdraw <a href="#method-withdraw" id="method-withdraw"></a>

This method allows authorized users to withdraw USDC tokens by burning the corresponding DebtUSCC tokens for the last (most recent) order and transferring USDC to the collateral treasury.

**Function Description:**

* The function is protected against reentrancy attacks by using the `nonReentrant` modifier.
* The function is protected by the `whenNotPaused` modifier, ensuring that withdrawals cannot be made when the contract is paused.
* Validates that the USDC amount is greater than zero.
* Validates that the caller has the `GATEWAY_WITHDRAW_ROLE` using role-based access control.
* Automatically selects the last order (identified by `$.nextOrderId - 1`) for processing. This ensures that orders are fulfilled in a first-in-first-out manner and simplifies the withdrawal process compared to the Gateway contract which processes multiple orders.
* Validates that the last order is active. If the order is not active or does not exist, the function will revert with an `OrderNotActive` error. This prevents any attempts to withdraw from invalid or already processed orders.
* Deactivates the order by setting the `active` flag to false in storage. This prevents double-spending and ensures that orders can only be processed once.
* Burns DebtUSCC tokens from the collateral treasury (1:1 with the order's USCC amount). This clears the protocol's obligation for the fulfilled order and ensures proper accounting.
* Transfers the specified amount of USDC tokens from the ReverseGateway contract to the collateral treasury using the `safeTransfer` function. This ensures that the transfer is successful. If the transfer fails, the function will revert.
* Sets the `ongoingDeposit` flag to false, allowing new deposits to be processed.
* **Important**: The `usdcAmount` parameter is provided by the caller because the exact amount of USDC received from Superstate cannot be predicted in advance. This allows the protocol to handle variable exchange rates, fees, or other factors that may affect the final amount received from external services.
* Emits a `Withdraw` event, providing the caller address, order ID (the last order), USCC amount from the order, and USDC amount for tracking.

#### Method: emergencyWithdraw <a href="#method-emergencywithdraw" id="method-emergencywithdraw"></a>

This method provides an emergency mechanism to recover tokens that may have been accidentally sent to the ReverseGateway contract.

**Function Description:**

* The function is protected against reentrancy attacks by using the `nonReentrant` modifier.
* Validates that the token address is not the zero address.
* Validates that the recipient address is not the zero address.
* Validates that the amount is greater than zero.
* Validates that the caller has the `EMERGENCY_WITHDRAW_ROLE` using role-based access control.
* Transfers the specified amount of tokens from the ReverseGateway contract to the recipient using the `safeTransfer` function. This ensures that the transfer is successful. If the transfer fails, the function will revert.
* Emits an `EmergencyWithdraw` event, providing the token address, amount, and recipient for tracking.

#### Method: setSuperstateAddress <a href="#method-setsuperstateaddress" id="method-setsuperstateaddress"></a>

This method allows authorized users to update the Superstate contract address, enabling the protocol to adapt to contract upgrades or migrations.

**Function Description:**

* Validates that the new Superstate address is not the zero address.
* Validates that the new Superstate address is different from the current address to prevent unnecessary state changes.
* Validates that the caller has the `GATEWAY_SUPERSTATE_SETTER_ROLE` using role-based access control.
* Updates the Superstate address in storage.
* Emits a `SuperstateUpdated` event, providing the old and new Superstate addresses for tracking.

### Getter Functions <a href="#getter-functions" id="getter-functions"></a>

* **getOrder**: Returns the details of a specific order including USCC amount, active status, timestamp, and the USCC oracle roundId captured at deposit time.
* **getNextOrderId**: Returns the next order ID that will be assigned.
* **superstate**: Returns the current Superstate contract address.
* **collateralTreasury**: Returns the current collateral treasury address.
* **usccOracle**: Returns the current USCC oracle contract address.
* **usdcToken**: Returns the current USDC token contract address.
* **usccToken**: Returns the current USCC token contract address.
* **debtUSCC**: Returns the current DebtUSCC token contract address.

### Constants <a href="#constants" id="constants"></a>

* **CONTRACT\_REGISTRY\_ACCESS**: Address of the registry access contract.
* **CONTRACT\_TREASURY**: Address of the collateral treasury contract.
* **GATEWAY\_DEPOSIT\_ROLE**: Role identifier for depositing USCC and creating orders.
* **GATEWAY\_WITHDRAW\_ROLE**: Role identifier for withdrawing USDC and fulfilling orders.
* **EMERGENCY\_WITHDRAW\_ROLE**: Role identifier for emergency token recovery.
* **GATEWAY\_SUPERSTATE\_SETTER\_ROLE**: Role identifier for updating the Superstate address.
* **PAUSING\_CONTRACTS\_ROLE**: Role identifier for pausing contract operations.
* **UNPAUSING\_CONTRACTS\_ROLE**: Role identifier for unpausing contract operations.

### Safeguards Implementation <a href="#safeguards-implementation" id="safeguards-implementation"></a>

* **Pausability**: Allows pausing of contract functionality in emergencies. The contract can be paused by `PAUSING_CONTRACTS_ROLE` and unpaused by `UNPAUSING_CONTRACTS_ROLE`.
* **Reentrancy Protection**: Uses OpenZeppelin's ReentrancyGuard to prevent reentrancy attacks. All state-changing functions are protected with the `nonReentrant` modifier.
* **Access Control**: Restricts sensitive operations to authorized roles. Deposit operations require `GATEWAY_DEPOSIT_ROLE`, withdrawal operations require `GATEWAY_WITHDRAW_ROLE`, emergency withdrawals require `EMERGENCY_WITHDRAW_ROLE`, and Superstate address updates require `GATEWAY_SUPERSTATE_SETTER_ROLE`.
* **Amount Validation**: Validates that amounts are non-zero before processing operations.
* **Order Validation**: Validates that the last order is active before processing withdrawals, preventing attempts to process invalid or already processed orders.
* **Null Address Checks**: Validates that all addresses (registry, Superstate, tokens, oracle, recipient) are not the zero address before processing operations.
* **Order Deactivation**: Deactivates orders during withdrawal to prevent double-spending and ensure that orders can only be processed once.
* **Single Deposit Constraint**: Enforces that only one deposit can be active at a time through the `ongoingDeposit` flag. This prevents concurrent deposits, ensuring consistent DebtUSCC token pricing by maintaining a single price point for all outstanding debt tokens, and simplifies the withdrawal process.
* **SafeERC20**: Uses SafeERC20 for all token transfers to prevent failures from going unnoticed and to handle non-standard ERC20 implementations safely.
* **Storage Safety**: Uses ERC-7201 namespaced storage pattern (`ReverseGatewayStorageV0`) to prevent storage collisions during upgrades. The contract is upgradeable via UUPS proxy pattern.
* **Same Value Protection**: Prevents unnecessary state changes by validating that the new Superstate address is different from the current address before updating.
* **Oracle Integration**: Captures and stores the USCC oracle roundId at deposit time for price tracking and audit purposes, ensuring transparency in the conversion process.


# ETH0

<table data-card-size="large" data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td align="center"><strong>ETH0 DAO Collateral Smart Contract</strong></td><td><a href="/pages/Cz29kDyEJrPqIiHNC8n0">/pages/Cz29kDyEJrPqIiHNC8n0</a></td><td data-object-fit="cover"><a href="/files/mRoGUG3gnWewZUoAn1hm">/files/mRoGUG3gnWewZUoAn1hm</a></td></tr></tbody></table>


# ETH0 DaoCollateral

## High-Level Overview

The DaoCollateral contract is a fundamental component of the ETH0 ecosystem, designed to manage the collateralization, minting, and redemption of ETH0 tokens. It ensures that the circulating supply of ETH0 is always fully backed by collateral, providing transparency and security for ETH0 holders. The contract facilitates the swapping of collateral tokens for ETH0, redemption of ETH0 for collateral tokens, and implements a Counter Bank Run (CBR) mechanism for emergency situations.

## Contract Summary

**Inherited Contracts**<br>

* ReentrancyGuardUpgradeable (OZ): Prevents reentrant attacks on sensitive functions.
* PausableUpgradeable (OZ): Enables pausing of contract functionality by authorized accounts.
* EIP712Upgradeable (OZ): Implements EIP-712 for structured data hashing and signing.

## Functionality Breakdown

**Key Functionalities**<br>

1. M**inting and redeeming ETH0:**\
   The contract manages the collateralization of ETH0 by handling collateral tokens. When a user sends collateral, the DaoCollateral contract mints the equivalent amount of ETH0 stablecoins, and vice versa, allowing users to exchange their ETH0 stablecoins for collateral at the current exchange rate.

* Swap: Facilitates the conversion of collateral into ETH0. Upon initiating this function, users exchange their collateral tokens for ETH0 stablecoins directly.
* Redeem: Allows users to redeem their ETH0 stablecoins for collateral against a fee. By invoking this function, users exchange their ETH0 stablecoins for collateral at the current exchange rate.

2. **Counter Bank Run (CBR) Mechanism:**\
   The contract implements a Counter Bank Run mechanism that can be activated in emergency situations. When activated:

* The CBR coefficient is applied to reduce the amount of collateral returned during redemptions
* Swap functionality is automatically paused
* The system helps maintain protocol stability during market stress

3. **Role-Based Access Control**

The contract implements a role-based access control system for sensitive operations:

* **DEFAULT\_ADMIN\_ROLE**: Has the highest level of access, including the ability to manage CBR parameters and perform critical administrative tasks.
* **DAO\_REDEMPTION\_ROLE**: Required for special DAO redemption operations.
* **PAUSING\_CONTRACTS\_ROLE**: Grants the ability to pause specific contract functionalities in case of emergencies.
* **UNPAUSING\_CONTRACTS\_ROLE**: Grants the ability to unpause contract functionalities.

### Functions Description

**Public/External Functions**<br>

* `initialize`: Sets up the contract with initial parameters including registry information and redeem fee.
* `swap`: Allows users to swap collateral tokens for ETH0.
* `swapWithPermit`: Similar to swap but uses permit for approval.
* `redeem`: Enables users to redeem ETH0 for collateral tokens.
* `redeemDao`: Special redemption function for DAO operations. Only callable by DAO\_REDEMPTION\_ROLE.
* `activateCBR`: Activates the Counter Bank Run mechanism. Only callable by DEFAULT\_ADMIN\_ROLE.
* `deactivateCBR`: Deactivates the Counter Bank Run mechanism. Only callable by DEFAULT\_ADMIN\_ROLE.
* `setRedeemFee`: Sets the fee for redemption operations. Only callable by DEFAULT\_ADMIN\_ROLE.
* `pauseRedeem`, `pause`, `pauseSwap`: Pausing functions for specific operations. Only callable by PAUSING\_CONTRACTS\_ROLE.
* `unpause`, `unpauseRedeem`, `unpauseSwap`: Global unpausing functions. Only callable by UNPAUSING\_CONTRACTS\_ROLE.

### **Constants**

* `CONTRACT_REGISTRY_ACCESS`: Address of the registry access contract.
* `CONTRACT_TOKEN_MAPPING`: Address of the token mapping contract.
* `CONTRACT_ORACLE`: Address of the oracle contract.
* `CONTRACT_TREASURY`: Address of the treasury contract.
* `CONTRACT_ETH0`: Address of the ETH0 token contract.
* `CONTRACT_YIELD_TREASURY`: Address of the yield treasury contract.
* `DEFAULT_ADMIN_ROLE`: Role identifier for the default admin.
* `DAO_REDEMPTION_ROLE`: Role identifier for DAO redemption operations.
* `PAUSING_CONTRACTS_ROLE`: Role identifier for pausing contract operations.
* `UNPAUSING_CONTRACTS_ROLE`: Role identifier for unpausing contract operations.
* `MAX_REDEEM_FEE`: Maximum allowed redemption fee (25%).
* `BASIS_POINT_BASE`: Base value for basis point calculations (10000).
* `SCALAR_ONE`: Scalar value representing 1 in the contract's decimal system.

### Key Components

* **Oracle Integration**: Uses an oracle to fetch real-time price data for collateral tokens.
* **Token Mapping**: Manages the mapping of supported collateral tokens.
* **Access Control**: Implements role-based access control for administrative functions.
* **Treasury Management**: Handles the storage and distribution of collateral tokens.

### Safeguards Implementation

* **Pausability**: Allows pausing of critical functions in emergencies.
* **Reentrancy Protection**: Uses OpenZeppelin's ReentrancyGuard to prevent reentrancy attacks.
* **Access Control**: Restricts sensitive operations to authorized roles.
* **CBR Mechanism**: Implements a Counter Bank Run mechanism for emergency situations.
* **Fee Management**: Implements a configurable redemption fee system with a maximum cap of 25%.


# EUR0

<table data-card-size="large" data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td align="center"><strong>EUR0</strong> <strong>DAO Collateral Smart Contract</strong></td><td><a href="/pages/PJA3v1QnhA6HISCbpfyC">/pages/PJA3v1QnhA6HISCbpfyC</a></td><td><a href="/files/mRoGUG3gnWewZUoAn1hm">/files/mRoGUG3gnWewZUoAn1hm</a></td></tr><tr><td align="center"><strong>EUR0</strong> <strong>Swapper Engine Smart Contract</strong></td><td><a href="/pages/d1cHnmkrUTY2rxUxy2JZ">/pages/d1cHnmkrUTY2rxUxy2JZ</a></td><td><a href="/files/IKcZhsVeJNj0onWut15o">/files/IKcZhsVeJNj0onWut15o</a></td></tr><tr><td align="center"><strong>EUR0 Distribution Smart Contract</strong></td><td></td><td><a href="/files/9F8h4LLi0NCySdfIexFm">/files/9F8h4LLi0NCySdfIexFm</a></td></tr></tbody></table>


# EUR0 DaoCollateral

## DaoCollateral Contract Documentation

### High-Level Overview

The DaoCollateral contract is a fundamental component of the EUR0 ecosystem, designed to manage the collateralization, minting, and redemption of EUR0 tokens. It ensures that the circulating supply of EUR0 is always fully backed by Euro-denominated collateral, providing transparency and security for EUR0 holders. The contract facilitates the swapping of Euro collateral tokens for EUR0, redemption of EUR0 for Euro collateral tokens, and implements a Counter Bank Run (CBR) mechanism for emergency situations. Additionally, it provides advanced functionality for intent-based trading and integration with the SwapperEngine for EURC trading.

### Contract Summary

#### Inherited Contracts

* **ReentrancyGuardUpgradeable (OZ)**: Prevents reentrant attacks on sensitive functions.
* **PausableUpgradeable (OZ)**: Enables pausing of contract functionality by authorized accounts.
* **EIP712Upgradeable (OZ)**: Implements EIP-712 for structured data hashing and signing.
* **NoncesUpgradeable**: Manages nonce-based operations for intent matching and replay protection.

### Functionality Breakdown

#### Key Functionalities

**1. Basic Token Operations**

* **Minting and redeeming EUR0**: The contract manages the collateralization of EUR0 by handling Euro-denominated collateral tokens. When a user sends Euro collateral, the DaoCollateral contract mints the equivalent amount of EUR0 stablecoins, and vice versa, allowing users to exchange their EUR0 stablecoins for Euro collateral at the current exchange rate.

**2. Swap Operations**

* **swap**: Facilitates the conversion of Euro collateral into EUR0. Upon initiating this function, users exchange their Euro collateral tokens for EUR0 stablecoins directly.
* **swapWithPermit**: Similar to swap but uses ERC20Permit for gasless approval, allowing users to approve token transfers without a separate transaction.

**3. Redemption Operations**

* **redeem**: Allows users to redeem their EUR0 stablecoins for Euro collateral against a fee. By invoking this function, users exchange their EUR0 stablecoins for Euro collateral at the current exchange rate.
* **redeemDao**: Special redemption function for DAO operations that bypasses fees. Only callable by accounts with DAO\_REDEMPTION\_ROLE.

**4. Advanced Trading Features**

* **swapCollateralTokenToEurc**: Enables users to swap collateral tokens directly for EURC through the SwapperEngine. This function mints EUR0 internally and uses it to fulfill EURC orders on the SwapperEngine.
* **swapCollateralTokenToEurcIntent**: Advanced intent-based trading system that allows pre-signed orders to be executed by authorized parties. This enables gasless trading and more sophisticated trading strategies.

**5. Intent Management System**

* **Intent-based Trading**: The contract implements a sophisticated intent system where users can pre-sign trading instructions that can be executed by authorized parties (INTENT\_MATCHING\_ROLE).
* **Nonce Management**: Users can invalidate nonces to cancel pending intents or invalidate ranges of nonces for bulk cancellation.
* **Partial Matching**: Intents support partial fulfillment, allowing large orders to be filled incrementally.

**6. Counter Bank Run (CBR) Mechanism**

The contract implements a Counter Bank Run mechanism that can be activated in emergency situations. When activated:

* The CBR coefficient is applied to reduce the amount of collateral returned during redemptions
* Swap functionality is automatically paused
* The system helps maintain protocol stability during market stress

#### Role-Based Access Control

The contract implements a comprehensive role-based access control system for sensitive operations:

* **DEFAULT\_ADMIN\_ROLE**: Has the highest level of access, including the ability to manage CBR parameters and perform critical administrative tasks.
* **DAO\_REDEMPTION\_ROLE**: Required for special DAO redemption operations.
* **PAUSING\_CONTRACTS\_ROLE**: Grants the ability to pause specific contract functionalities in case of emergencies.
* **UNPAUSING\_CONTRACTS\_ROLE**: Grants the ability to unpause contract functionalities.
* **NONCE\_THRESHOLD\_SETTER\_ROLE**: Allows setting the nonce threshold for intent consumption.
* **INTENT\_MATCHING\_ROLE**: Required for executing intent-based trades on behalf of users.

### Functions Description

#### Public/External Functions

**Initialization**

* **initialize**: Sets up the contract with initial parameters including registry information and redeem fee.

**Basic Trading Functions**

* **swap**: Allows users to swap Euro collateral tokens for EUR0.
* **swapWithPermit**: Similar to swap but uses permit for approval.
* **redeem**: Enables users to redeem EUR0 for Euro collateral tokens.
* **redeemDao**: Special redemption function for DAO operations. Only callable by DAO\_REDEMPTION\_ROLE.

**Advanced Trading Functions**

* **swapCollateralTokenToEurc**: Swaps collateral tokens for EURC through the SwapperEngine with order matching.
* **swapCollateralTokenToEurcIntent**: Executes intent-based trades for collateral token to EURC swaps.

**Intent Management**

* **invalidateNonce**: Invalidates the current nonce for the message sender.
* **invalidateUpToNonce**: Invalidates all nonces up to a specified value for the message sender.

**Administrative Functions**

* **activateCBR**: Activates the Counter Bank Run mechanism. Only callable by DEFAULT\_ADMIN\_ROLE.
* **deactivateCBR**: Deactivates the Counter Bank Run mechanism. Only callable by DEFAULT\_ADMIN\_ROLE.
* **setRedeemFee**: Sets the fee for redemption operations. Only callable by DEFAULT\_ADMIN\_ROLE.
* **setNonceThreshold**: Sets the threshold for intent consumption. Only callable by NONCE\_THRESHOLD\_SETTER\_ROLE.

**Pausing Functions**

* **pauseRedeem, pause, pauseSwap**: Pausing functions for specific operations. Only callable by PAUSING\_CONTRACTS\_ROLE.
* **unpause, unpauseRedeem, unpauseSwap**: Global unpausing functions. Only callable by UNPAUSING\_CONTRACTS\_ROLE.

**View Functions**

* **redeemFee**: Returns the current redemption fee.
* **isCBROn**: Returns whether the Counter Bank Run mechanism is active.
* **cbrCoef**: Returns the current CBR coefficient.
* **isRedeemPaused**: Returns whether redeem functionality is paused.
* **isSwapPaused**: Returns whether swap functionality is paused.
* **nonceThreshold**: Returns the current nonce threshold for intent consumption.
* **orderAmountTakenCurrentNonce**: Returns the amount of tokens taken for the current nonce of an address.
* **DOMAIN\_SEPARATOR**: Returns the EIP712 domain separator for signature verification.

### Data Structures

#### Approval

```solidity
struct Approval {
    uint256 deadline;
    uint8 v; // Changes at each new signature because of ERC20 Permit nonce
    bytes32 r;
    bytes32 s;
}
```

#### Intent

```solidity
struct Intent {
    address recipient;
    address rwaToken;
    uint256 amountInTokenDecimals;
    uint256 deadline;
    bytes signature;
}
```

### Constants

#### Contract Addresses

* **`CONTRACT_REGISTRY_ACCESS`**: Address of the registry access contract.
* **`CONTRACT_TOKEN_MAPPING`**: Address of the token mapping contract.
* **`CONTRACT_ORACLE`**: Address of the oracle contract.
* **`CONTRACT_TREASURY`**: Address of the treasury contract.
* **`CONTRACT_EUR0`**: Address of the EUR0 token contract.
* **`CONTRACT_YIELD_TREASURY`**: Address of the yield treasury contract.
* **`CONTRACT_SWAPPER_ENGINE`**: Address of the swapper engine contract.

#### Role Identifiers

* **`DEFAULT_ADMIN_ROLE`**: Role identifier for the default admin.
* **`DAO_REDEMPTION_ROLE`**: Role identifier for DAO redemption operations.
* **`PAUSING_CONTRACTS_ROLE`**: Role identifier for pausing contract operations.
* **`UNPAUSING_CONTRACTS_ROLE`**: Role identifier for unpausing contract operations.
* **`NONCE_THRESHOLD_SETTER_ROLE`**: Role identifier for setting nonce thresholds.
* **`INTENT_MATCHING_ROLE`**: Role identifier for executing intent-based trades.

#### Fee and Calculation Constants

* **`MAX_REDEEM_FEE`**: Maximum allowed redemption fee (25%).
* **`BASIS_POINT_BASE`**: Base value for basis point calculations (10000).
* **`SCALAR_ONE`**: Scalar value representing 1 in the contract's decimal system.

#### Intent System Constants

* **`INTENT_TYPE_HASH`**: EIP712 type hash for intent signatures.

### Key Components

#### Oracle Integration

Uses an oracle to fetch real-time price data for Euro collateral tokens.

#### Token Mapping

Manages the mapping of supported Euro collateral tokens using `isEur0Collateral()` function.

#### Access Control

Implements comprehensive role-based access control for administrative functions and intent execution.

#### Treasury Management

Handles the storage and distribution of Euro collateral tokens across multiple treasuries.

#### SwapperEngine Integration

Provides seamless integration with the SwapperEngine for advanced trading operations and EURC trading.

#### Intent System

Implements a sophisticated intent-based trading system with:

* Pre-signed order execution
* Partial order fulfillment
* Nonce-based replay protection
* Gasless trading capabilities

### Safeguards Implementation

#### Pausability

Allows pausing of critical functions in emergencies with granular control over different functionalities.

#### Reentrancy Protection

Uses OpenZeppelin's ReentrancyGuard to prevent reentrancy attacks.

#### Access Control

Restricts sensitive operations to authorized roles with comprehensive role management.

#### CBR Mechanism

Implements a Counter Bank Run mechanism for emergency situations with configurable coefficients.

#### Fee Management

Implements a configurable redemption fee system with a maximum cap of 25%.

#### Intent Security

* Signature verification using EIP712
* Nonce-based replay protection
* Deadline enforcement
* Partial matching with threshold-based consumption

### Events

The contract emits various events for tracking operations:

* **Swap**: Emitted when tokens are swapped
* **Redeem**: Emitted when tokens are redeemed
* **IntentMatched**: Emitted when an intent is matched
* **IntentConsumed**: Emitted when an intent is fully consumed
* **NonceInvalidated**: Emitted when nonces are invalidated
* **CBRActivated/CBRDeactivated**: Emitted when CBR mechanism is activated/deactivated
* **RedeemFeeUpdated**: Emitted when redeem fee is updated
* **NonceThresholdSet**: Emitted when nonce threshold is set
* **RedeemPaused/RedeemUnPaused**: Emitted when redeem functionality is paused/unpaused
* **SwapPaused/SwapUnPaused**: Emitted when swap functionality is paused/unpaused


# EUR0 SwapperEngine

### High-Level Overview

The SwapperEngine contract is a smart contract designed to facilitate the swapping of EURC tokens for EUR0 tokens using an order matching mechanism. The contract allows users to create orders specifying the amount of EURC they wish to swap, and other users can fill these orders by providing EUR0 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.

It is important to note that the contract's mechanism can be utilized to facilitate a vampire attack, RWA → EUR0 → EURC → $$$ → RWA → to churn EURC into EUR0 by transparently staking treasury bonds to mint EUR0 swapping that EUR0 for EURC and cycling back into RWA ready to mint more EUR0 limited only by EURC order book depth.

**Flow EURC Depositors:**

* Users deposit EURC tokens to create orders
* Orders wait for matching with EUR0 providers
* When matched, users receive EUR0 tokens

**Flow RWA Provider:**

* RWA providers mint EUR0 through collateralization
* They can swap EUR0 for EURC through the SwapperEngine
* This creates a cycle: RWA → EUR0 → EURC → Cash → RWA

### Contract Summary

The contract provides the following main functions:

* **depositEURC** and **depositEURCOnBehalf**: Allows users to create a new order by depositing EURC and also to set a specific receiver with **depositEURCOnBehalf**.
* **withdrawEURC**: Allows users to cancel an order and withdraw their deposited EURC.
* **provideEur0ReceiveEURC**: Allows users to fill orders by providing EUR0 and receiving EURC in return.

The contract also includes utility functions such as `getOrder`, `getEur0WadEquivalent`, and `getEurcWadPrice` to retrieve order details and perform price calculations. The swapperEngine has no option to define a maxEURCPrice for buyers and seller's don't have the option to define a minimumEURCPrice, instead the prices are provided by an EURC oracle, which also has measures against a potential EURC depeg. EUR0's price is considered to be €1 == 1EUR0 due to the numerous mechanisms in place to prevent a depeg, like reserves, CBR mechanism, arbitrage etc.

### 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 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 DEFAULT\_ADMIN\_ROLE to un-pause).

### Functionality Breakdown

The SwapperEngine contract's primary purpose is to facilitate the swapping of EURC tokens for EUR0 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 `depositEURC` function and specifying the amount of EURC they wish to swap and the receiver of the converted amount. The contract transfers the specified amount of EURC tokens from the user to itself and creates a new order with the deposited amount, the user's address as the requester and a receiver. The order is assigned a unique order ID and stored in the contract's orders mapping.

#### Order Cancellation:

Users who have created an order can cancel it by calling the `withdrawEURC` 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 to zero, and transfers the deposited EURC tokens back to the requester.

#### Order Matching:

Users can fill existing orders by specifying the recipient address, the amount of EURC to take (or the amount of EUR0 to give), an array of order IDs to match against, and whether partial matching is allowed. The contract verifies that the caller has sufficient EUR0 balance and allowance to cover the required amount based on the current EURC Price Calculation obtained from the oracle. The contract iterates through the provided order IDs and attempts to match the requested EURC amount against active orders. If partial matching is allowed and there is not enough EURC in the orders to fulfil 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 EUR0 tokens from the caller to the order requester and transfers the EURC tokens from itself to the specified recipient. If partial matching is not allowed and the requested EURC amount cannot be fully matched, the contract reverts the transaction.

#### Price Calculation:

The contract relies on an external oracle contract to obtain the current price of EURC tokens in WAD format (18 decimals). The `_getEurcWadPrice` function is used to retrieve the current EURC price from the oracle. The `_getEur0WadEquivalent` function is used to calculate the equivalent amount of EUR0 tokens for a given amount of EURC tokens based on the current price.

### Security Analysis

#### Method: `_provideEur0ReceiveEURC`

This method allows users to provide EUR0 tokens and receive EURC tokens by matching against existing orders. It matches the requested EURC amount to the provided EUR0 tokens against the specified orders, transfers the corresponding EURC tokens to the recipient, and updates the order states accordingly.

```solidity
function _provideEur0ReceiveEURC( ... ) internal returns (uint256 unmatchedEurcAmount, uint256 totalEur0Provided) {
   if (amountEurcToTakeInNativeDecimals == 0) { revert AmountIsZero() }
   if (orderIdsToTake.length == 0) { revert NoOrdersIdsProvided() }
   SwapperEngineStorageV0 storage $ = _swapperEngineStorageV0();
   uint256 eurcWadPrice = _getEurcWadPrice();
   uint256 totalEurcTaken = 0;
```

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.

* Validates that the amount of EURC to take is greater than zero.
* Validates that at least one order ID is provided for matching.
* Retrieves the contract's storage using the correct storage pattern.
* Retrieves the current price of EURC in WAD format (18 decimals) from an oracle, ensuring that the price used for calculations is up-to-date and accurate.
* Initializes the total amount of EURC taken to zero.

```solidity
for (uint256 i; i < orderIdsToTake.length && totalEurcTaken < amountEurcToTakeInNativeDecimals;) {
    uint256 orderId = orderIdsToTake[i];
    EurcOrder storage order = $.orders[orderId];
    if (order.active) {
        uint256 remainingAmountToTake = amountEurcToTakeInNativeDecimals - totalEurcTaken;
        uint256 amountOfEurcFromOrder = order.tokenAmount > remainingAmountToTake ? remainingAmountToTake : order.tokenAmount;
        order.tokenAmount -= amountOfEurcFromOrder;
        totalEurcTaken += amountOfEurcFromOrder;
        if (order.tokenAmount == 0) { order.active = false };
        uint256 eur0Amount = _getEur0WadEquivalent(amountOfEurcFromOrder, eurcWadPrice);
        totalEur0Provided += eur0Amount;
        $.eur0.safeTransferFrom(msg.sender, order.requester, eur0Amount);
        $.eurcToken.safeTransfer(recipient, amountOfEurcFromOrder);
        emit OrderMatched(order.requester, msg.sender, orderId, amountOfEurcFromOrder);
    }
    unchecked { ++i }
}
if (!partialMatchingAllowed && totalEurcTaken != amountEurcToTakeInNativeDecimals || totalEurcTaken == 0) { revert AmountTooLow() }
return ((amountEurcToTakeInNativeDecimals - totalEurcTaken), totalEur0Provided);
```

* Retrieves the order details for the current order ID.
* Checks if the order is active before processing.
* If the order is active, calculates the amount of EURC to take from the current order based on the remaining amount to take and the order's available balance.
* Updates the order's token amount and the total EURC taken.
* Marks the order as inactive if its token amount reaches zero.
* Calculates the equivalent EUR0 amount for the EURC taken from the order using the `_getEur0WadEquivalent` function and the current EURC price.
* Updates the total EUR0 provided with the calculated amount.
* Transfers the EUR0 tokens from the sender to the order requester.
* Transfers the EURC tokens from the contract to the recipient.
* Emits an OrderMatched event with the relevant details.
* Increments the loop counter using an unchecked block for gas optimization.
* Reverts the transaction if partial matching is not allowed and the total EURC taken does not match the requested amount or if no EURC was taken.
* Returns the remaining amount of EURC that was not taken and the total EUR0 provided.

#### Method: `_getEur0WadEquivalent`

This method calculates the EUR0 equivalent amount in WAD format (18 decimals) for a given EURC token amount. It converts the EURC token amount from its native decimal representation (6 decimals) to WAD format and then calculates the equivalent EUR0 amount based on the provided EURC price in WAD format.

```solidity
function _getEur0WadEquivalent(uint256 eurcTokenAmountInNativeDecimals, uint256 eurcWadPrice) private view returns (uint256 eur0WadEquivalent) {
    SwapperEngineStorageV0 storage $ = _swapperEngineStorageV0();
    uint8 decimals = IERC20Metadata(address($.eurcToken)).decimals();
    uint256 eurcWad = eurcTokenAmountInNativeDecimals.tokenAmountToWad(decimals);
    eur0WadEquivalent = eurcWad.wadAmountByPrice(eurcWadPrice);
}
```

* Retrieves the contract's storage using the correct storage pattern.
* Retrieves the decimal places of the EURC token using the `decimals()` function from the IERC20Metadata interface.
* Converts the `eurcTokenAmountInNativeDecimals` to WAD format (18 decimals) using the `tokenAmountToWad` function, which takes into account the token's native decimals.
* Calculates the equivalent amount of EUR0 tokens in WAD format by multiplying the `eurcWad` amount with the `eurcWadPrice` using the `wadAmountByPrice` function.

#### Method: `depositEURC`

This method allows users to deposit EURC tokens and create a new order. It transfers the specified amount of EURC tokens from the caller to the contract and creates a new order with the deposited amount and the caller as the requester.

```solidity
function depositEURC(uint256 amountToDeposit) external nonReentrant whenNotPaused {
    SwapperEngineStorageV0 storage $ = _swapperEngineStorageV0();
    _depositEURC($, amountToDeposit, msg.sender, msg.sender);
}
```

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.

* Retrieves the contract's storage using the correct storage pattern.
* Validates that the amount of EURC 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.
* 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.
* Creates a new `EurcOrder` struct in storage using the order ID as key. The struct is set up correctly to contain: the requester's address (`msg.sender`), the deposited token amount (`amountToDeposit`), and sets the active flag to true.
* Transfers the specified amount of EURC tokens from the caller (`msg.sender`) to the contract (`address(this)`) using the `safeTransferFrom` function to ensure that the transfer is successful and the contract receives the deposited tokens. If the transfer fails, the function will revert.
* Emits a Deposit event, providing the order ID and the deposited amount for the subgraph.

The **`depositEURCOnBehalf`** method do the same but with a specific recipient that can be specified by the caller.

#### Method: `withdrawEURC`

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

```solidity
function withdrawEURC(uint256 orderToCancel) external nonReentrant whenNotPaused {
    SwapperEngineStorageV0 storage $ = _swapperEngineStorageV0();
    EurcOrder storage order = $.orders[orderToCancel];
    if (!order.active) { revert OrderNotActive() }
    if (order.requester != msg.sender) { revert NotRequester() }
    uint256 amountToWithdraw = order.tokenAmount;
    order.active = false;
    order.tokenAmount = 0;
    $.eurcToken.safeTransfer(msg.sender, amountToWithdraw);
    emit Withdraw(msg.sender, orderToCancel, amountToWithdraw);
}
```

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.

* Retrieves the contract's storage using the correct storage pattern.
* Retrieves the `EurcOrder` struct as storage so it will be modified.
* 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 withdraw from invalid or canceled orders.
* 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.
* Retrieves the token amount associated with the order and assigns it to the `amountToWithdraw` variable.
* Sets the active flag of the order to false in storage.
* Sets the `tokenAmount` of the order to zero in storage.
* Transfers the `amountToWithdraw` of EURC 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.
* Emits a Withdraw event, providing the `orderToCancel` ID and the `amountToWithdraw` for the subgraph.

#### Method: `swapEur0`

This method allows users to provide EUR0 tokens and receive EURC tokens by matching against existing orders. It matches the specified amount of EUR0 tokens against the specified orders, transfers the corresponding EURC tokens to the recipient, and updates the order states accordingly.

```solidity
function swapEur0(address recipient, uint256 amountEur0ToProvideInWad, uint256[] memory orderIdsToTake, bool partialMatchingAllowed) external nonReentrant whenNotPaused returns (uint256) {
    uint256 eurcWadPrice = _getEurcWadPrice();
    (, uint256 totalEur0Provided) = _provideEur0ReceiveEURC(
      recipient, _getEurcAmountFromEur0WadEquivalent(amountEur0ToProvideInWad, eurcWadPrice), orderIdsToTake, partialMatchingAllowed, eurcWadPrice
    );
    return amountEur0ToProvideInWad - totalEur0Provided;
}
```

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.

* Retrieves the current EURC price in WAD format using the `_getEurcWadPrice()` function.
* Calculates the equivalent amount of EURC to take in native decimals based on the provided `amountEur0ToProvideInWad` and the current `eurcWadPrice` using the `_getEurcAmountFromEur0WadEquivalent` function. Then calls the `_provideEur0ReceiveEURC` function to perform the actual swap, passing the recipient, `amountEurcToTakeInNativeDecimals`, `orderIdsToTake`, `partialMatchingAllowed`, and `eurcWadPrice` parameters. The function returns the total amount of EUR0 provided.
* Returns the sum of unmatched EUR0 in wad format including dust, representing the total amount of EUR0 that was not matched or was left as dust.


# EUR0 Revenue Distribution Module

### High-Level Overview <a href="#high-level-overview" id="high-level-overview"></a>

This contract manages the automated minting and distribution of EUR0 tokens to three dedicated distribution buckets. The contract enables multipurpose revenue distribution with three fixed buckets: Revenue Switch, Accruing Deposit Token (Accruing DT), and Rebasing Deposit Token (Rebasing DT). Each bucket operates independently with its own frequency, mint caps, pause mechanisms, and access control.

The core features of this contract include:

**Daily Accruing Deposit Token Distribution**: The contract should be called daily to calculate and mint EUR0 tokens into the accruing deposit token vault (SEUR0). The amount to mint is automatically calculated based on the vault's total assets and a configurable daily accruing yield rate. After minting, a yield distribution period is started in the vault to distribute the minted tokens over the next 24 hours.

**Daily Rebasing Deposit Token Distribution**: The contract should be called daily to mint a specified amount of EUR0 tokens into the rebasing deposit token rewards claim contract. The amount is determined off-chain and provided as a parameter, typically based on an updated Merkle root calculated off-chain.

**Weekly Revenue Switch Distribution**: The contract should be called weekly to receive and mint EUR0 rewards from the DAO into the revenue switch rewards claim contract. The amount is determined by the DAO and provided as a parameter when calling the function.

**Mint Cap Management**: The contract maintains a global operator mint cap that restricts the total amount of EUR0 that can be minted through Revenue Switch and Rebasing DT distributions. Accruing DT distribution does not consume from the operator mint cap. Each bucket also has its own maximum mint cap per distribution period.

**Granular Pause Mechanisms**: Each distribution bucket can be paused independently, allowing for selective disabling of specific distribution channels without affecting others.

**Access Control**: Each functionality is controlled by a role with minimal required permissions, ensuring secure and restricted access to sensitive operations.

### Contract Summary <a href="#contract-summary" id="contract-summary"></a>

#### Inherited Contracts <a href="#inherited-contracts" id="inherited-contracts"></a>

**PausableUpgradeable**: Allows contract execution to be paused or unpaused by authorized roles. Provides both global pause functionality and per-bucket pause mechanisms.

**IRevenueDistributionModule**: Interface that defines all functions that can be called by anyone (view functions) and role-restricted functions for revenue distribution operations.

#### Storage Structure <a href="#storage-structure" id="storage-structure"></a>

The contract uses ERC-7201 namespaced storage with the following key state variables:

* **operatorMintCap**: Maximum amount of EUR0 that can be minted globally (applies to Revenue Switch and Rebasing DT)
* **lastRevenueSwitchDistribution**: Timestamp of last Revenue Switch distribution
* **lastAccruingDTDistribution**: Timestamp of last Accruing DT distribution
* **lastRebasingDTDistribution**: Timestamp of last Rebasing DT distribution
* **dailyAccruingYieldRate**: Daily accruing yield rate in micro basis points (1 = 0.0001%)
* **maxRevSwitchMintCap**: Maximum amount per weekly Revenue Switch distribution
* **maxAccruingMintCap**: Maximum amount per daily Accruing DT distribution
* **maxRebasingDTMintCap**: Maximum amount per daily Rebasing DT distribution
* **rewardClaimForRevenueSwitch**: Address of reward claim contract for Revenue Switch
* **rewardClaimForAccruingDT**: Address of SEUR0 vault for Accruing DT (implements ISEur0)
* **rewardClaimForRebasingDT**: Address of reward claim contract for Rebasing DT
* **revenueSwitchDistributionPaused**: Boolean flag for Revenue Switch pause state
* **accruingDTDistributionPaused**: Boolean flag for Accruing DT pause state
* **rebasingDTDistributionPaused**: Boolean flag for Rebasing DT pause state

#### Functionality Description <a href="#functionality-description" id="functionality-description"></a>

**Public/External Functions**

**Initialization**

**initialize**: Initializes the contract with the registry address, reward claim contract addresses, and initial parameter values. Sets up all three distribution buckets with their initial timestamps. Can only be called once during contract deployment.

**IRevenueDistributionModule - Distribution Functions**

**distributeRevenueSwitch**:

* Distributes EUR0 tokens to the Revenue Switch bucket (weekly)
* Requires `OPERATOR_REVSWITCH_DISTRIBUTOR_ROLE`
* Validates that at least one week has passed since last distribution
* Validates amount against `maxRevSwitchMintCap` and `operatorMintCap`
* Reduces `operatorMintCap` by the distributed amount
* Mints EUR0 directly to `rewardClaimForRevenueSwitch`
* Can only be called when Revenue Switch distribution is not paused

**distributeAccruingDT**:

* Distributes EUR0 tokens to the Accruing DT bucket (daily)
* Requires `OPERATOR_ACC_DT_DISTRIBUTOR_ROLE`
* Automatically calculates the amount to distribute based on:
  * `rewardClaimForAccruingDT.totalAssets() * dailyAccruingYieldRate / BASIS_MILLION_POINT_BASE`
* Validates that at least one day has passed since last distribution
* Validates calculated amount against `maxAccruingMintCap`
* Does not consume from `operatorMintCap` (unlike other distributions)
* Mints EUR0 directly to `rewardClaimForAccruingDT` vault
* Starts a yield distribution period in the vault using `startYieldDistribution`
* The yield distribution period spans from current timestamp to current timestamp + `ONE_DAY`
* Can only be called when Accruing DT distribution is not paused

**distributeRebasingDT**:

* Distributes EUR0 tokens to the Rebasing DT bucket (daily)
* Requires `OPERATOR_REB_DT_DISTRIBUTOR_ROLE`
* Takes amount as parameter (typically calculated off-chain from Merkle root)
* Validates that at least one day has passed since last distribution
* Validates amount against `maxRebasingDTMintCap` and `operatorMintCap`
* Reduces `operatorMintCap` by the distributed amount
* Mints EUR0 directly to `rewardClaimForRebasingDT`
* Can only be called when Rebasing DT distribution is not paused

**IRevenueDistributionModule - Configuration Functions (OPERATOR\_ADMIN\_ROLE)**

**setDailyAccruingYieldRate**: Sets the daily accruing yield rate used for calculating Accruing DT distribution amounts. Rate is in micro basis points (1 = 0.0001%), must be between 0 and `BASIS_MILLION_POINT_BASE`.

**setOperatorMintCap**: Sets the global operator mint cap that limits total EUR0 minting through Revenue Switch and Rebasing DT distributions.

**setMaxRevSwitchMintCap**: Sets the maximum amount of EUR0 that can be minted per weekly Revenue Switch distribution.

**setMaxAccruingMintCap**: Sets the maximum amount of EUR0 that can be minted per daily Accruing DT distribution.

**setMaxRebasingDTMintCap**: Sets the maximum amount of EUR0 that can be minted per daily Rebasing DT distribution.

**setRewardClaimForRevenueSwitch**: Updates the reward claim contract address for Revenue Switch.

**setRewardClaimForAccruingDT**: Updates the reward claim contract address for Accruing DT. Must implement `ISEur0` interface.

**setRewardClaimForRebasingDT**: Updates the reward claim contract address for Rebasing DT.

**IRevenueDistributionModule - View Functions**

**getOperatorMintCap**: Returns the current operator mint cap value.

**getDailyAccruingYieldRate**: Returns the current daily accruing yield rate in micro basis points.

**getRewardClaimContractForRevenueSwitch**: Returns the reward claim contract address for Revenue Switch.

**getRewardClaimContractForAccruingDT**: Returns the reward claim contract address for Accruing DT.

**getRewardClaimContractForRebasingDT**: Returns the reward claim contract address for Rebasing DT.

**getMaxRevSwitchMintCap**: Returns the maximum amount of EUR0 that can be minted per weekly Revenue Switch distribution.

**getMaxAccruingMintCap**: Returns the maximum amount of EUR0 that can be minted per daily Accruing DT distribution.

**getMaxRebasingDTMintCap**: Returns the maximum amount of EUR0 that can be minted per daily Rebasing DT distribution.

**isRevenueSwitchDistributionPaused**: Returns whether Revenue Switch distribution is currently paused.

**isAccruingDTDistributionPaused**: Returns whether Accruing DT distribution is currently paused.

**isRebasingDTDistributionPaused**: Returns whether Rebasing DT distribution is currently paused.

**IRevenueDistributionModule - Pause Functions**

**pause**: Pauses all contract operations. Can only be called by `PAUSING_CONTRACTS_ROLE`.

**unpause**: Unpauses all contract operations. Can only be called by `UNPAUSING_CONTRACTS_ROLE`.

**pauseRevenueSwitchDistribution**: Pauses only Revenue Switch distribution. Can only be called by `PAUSING_CONTRACTS_ROLE`.

**unpauseRevenueSwitchDistribution**: Unpauses Revenue Switch distribution. Can only be called by `UNPAUSING_CONTRACTS_ROLE`.

**pauseAccruingDTDistribution**: Pauses only Accruing DT distribution. Can only be called by `PAUSING_CONTRACTS_ROLE`.

**unpauseAccruingDTDistribution**: Unpauses Accruing DT distribution. Can only be called by `UNPAUSING_CONTRACTS_ROLE`.

**pauseRebasingDTDistribution**: Pauses only Rebasing DT distribution. Can only be called by `PAUSING_CONTRACTS_ROLE`.

**unpauseRebasingDTDistribution**: Unpauses Rebasing DT distribution. Can only be called by `UNPAUSING_CONTRACTS_ROLE`.

#### Functionality Breakdown <a href="#functionality-breakdown" id="functionality-breakdown"></a>

**Setting up Calculation Parameters**

`OPERATOR_ADMIN_ROLE` can change all parameter values used in distribution calculations:

* Daily accruing yield rate (used in Accruing DT amount calculation)
* Operator mint cap (global limit for Revenue Switch and Rebasing DT)
* Individual bucket maximum mint caps

There is no timelock for these changes, allowing for rapid response to market conditions or protocol needs.

**Daily Accruing Deposit Token Distribution**

`OPERATOR_ACC_DT_DISTRIBUTOR_ROLE` is required to call `distributeAccruingDT` every 24 hours to:

* Query the total assets value from the accruing deposit token vault (SEUR0)
* Calculate the distribution amount: `totalAssets * dailyAccruingYieldRate / BASIS_MILLION_POINT_BASE`
* Validate the calculated amount against `maxAccruingMintCap`
* Mint the calculated amount of EUR0 directly to the SEUR0 vault
* Start a yield distribution period in the vault that distributes the minted tokens over the next 24 hours

**Note**: This distribution does not consume from the operator mint cap, as it is calculated based on vault assets rather than being an arbitrary amount set by an operator.

The amount distributed scales based on the vault's total assets, ensuring that as more users deposit into the vault, more yield is distributed proportionally.

**Daily Rebasing Deposit Token Distribution**

`OPERATOR_REB_DT_DISTRIBUTOR_ROLE` is required to call `distributeRebasingDT` with a valid amount every 24 hours. The amount is typically calculated off-chain based on an updated Merkle root:

* Off-chain calculation determines the total EUR0 amount to mint for eligible users
* The amount is provided as a parameter to `distributeRebasingDT`
* The contract validates the amount against `maxRebasingDTMintCap` and `operatorMintCap`
* If valid, the `operatorMintCap` is reduced by the amount
* EUR0 is minted directly to the rebasing deposit token rewards claim contract
* Users can claim their portion using valid Merkle proofs

This distribution requires off-chain infrastructure (Watchtower) to calculate the Merkle root and determine the total distribution amount based on eligible users and their assigned allocations.

**Weekly Revenue Switch Distribution**

`OPERATOR_REVSWITCH_DISTRIBUTOR_ROLE` is required to call `distributeRevenueSwitch` with a valid amount every week. The amount is determined by the DAO:

* DAO determines the weekly EUR0 rewards amount to distribute
* The amount is provided as a parameter to `distributeRevenueSwitch`
* The contract validates that at least one week has passed since last distribution
* The contract validates the amount against `maxRevSwitchMintCap` and `operatorMintCap`
* If valid, the `operatorMintCap` is reduced by the amount
* EUR0 is minted directly to the revenue switch rewards claim contract

This distribution enables the DAO to directly allocate EUR0 rewards on a weekly basis, separate from the automated daily distributions.

**Mint Cap Management**

The contract implements a two-tier mint cap system:

**Operator Mint Cap**: Global limit for EUR0 minting through Revenue Switch and Rebasing DT distributions. This cap is consumed when either of these distributions occurs and can be increased by `OPERATOR_ADMIN_ROLE` if needed.

**Per-Bucket Maximum Mint Caps**: Each distribution bucket has its own maximum amount that can be minted per distribution period:

* `maxRevSwitchMintCap`: Maximum per weekly Revenue Switch distribution
* `maxAccruingMintCap`: Maximum per daily Accruing DT distribution
* `maxRebasingDTMintCap`: Maximum per daily Rebasing DT distribution

Both the operator mint cap and per-bucket caps must be satisfied for a distribution to proceed (except Accruing DT, which only checks its own cap).

**Granular Pause Mechanisms**

The contract supports both global and per-bucket pause functionality:

**Global Pause**: Pauses all contract operations. Can be used in emergencies to halt all distributions.

**Per-Bucket Pause**: Each distribution bucket can be paused independently:

* `pauseRevenueSwitchDistribution` / `unpauseRevenueSwitchDistribution`
* `pauseAccruingDTDistribution` / `unpauseAccruingDTDistribution`
* `pauseRebasingDTDistribution` / `unpauseRebasingDTDistribution`

This granular control allows administrators to disable specific distribution channels without affecting others, useful for addressing issues in a single bucket or temporarily suspending specific revenue streams.

**Accruing DT Yield Distribution Period**

When `distributeAccruingDT` is called, after minting EUR0 to the SEUR0 vault, the contract calls `startYieldDistribution` on the vault with:

* `yieldAmount`: The minted EUR0 amount
* `startTime`: Current block timestamp
* `endTime`: Current block timestamp + `ONE_DAY`

This initiates a yield distribution period in the vault where the minted tokens are distributed over the next 24 hours to vault holders proportionally. The vault's yield-bearing mechanism ensures that shares appreciate in value as yield accrues throughout the day.

**Rebasing DT Merkle Root Integration**

The Rebasing DT distribution relies on off-chain infrastructure (Watchtower) to:

* Calculate eligible users and their allocations
* Generate a Merkle root from these allocations
* Determine the total EUR0 amount to mint
* Provide the amount to `distributeRebasingDT`

The actual user claims happen through the rewards claim contract using Merkle proofs, not directly through the Revenue Distribution Module.

#### Constants <a href="#constants" id="constants"></a>

* **OPERATOR\_REVSWITCH\_DISTRIBUTOR\_ROLE**: Role required to distribute EUR0 to Revenue Switch bucket (weekly)
* **OPERATOR\_ACC\_DT\_DISTRIBUTOR\_ROLE**: Role required to distribute EUR0 to Accruing DT bucket (daily)
* **OPERATOR\_REB\_DT\_DISTRIBUTOR\_ROLE**: Role required to distribute EUR0 to Rebasing DT bucket (daily)
* **OPERATOR\_ADMIN\_ROLE**: Role required to set configuration parameters (mint caps, yield rates, reward claim addresses)
* **PAUSING\_CONTRACTS\_ROLE**: Role required to pause the contract or individual distribution buckets
* **UNPAUSING\_CONTRACTS\_ROLE**: Role required to unpause the contract or individual distribution buckets
* **CONTRACT\_REGISTRY\_ACCESS**: Constant used to define the address of the registry access contract
* **CONTRACT\_EUR0**: Constant used to define the address of the EUR0 contract
* **INITIAL\_REVENUE\_DISTRIBUTION\_MINT\_CAP**: Initial value for operator mint cap (50,000 EUR0)
* **ONE\_DAY**: Duration of one day in seconds (86,400 seconds)
* **ONE\_WEEK**: Duration of one week in seconds (604,800 seconds)
* **BASIS\_MILLION\_POINT\_BASE**: Base value for calculating percentages in micro basis points (1,000,000, where 1 = 0.0001%)

### Safeguard Implementation <a href="#safeguard-implementation" id="safeguard-implementation"></a>

#### Access Control <a href="#access-control" id="access-control"></a>

The contract uses `CheckAccessControl` to enforce role-based access control, ensuring only authorized addresses can perform actions that require specific permissions. Each role has minimal required permissions:

* Distribution roles can only trigger their specific distribution type
* Admin role can only modify configuration parameters
* Pausing roles can only pause/unpause functionality

#### Pausability <a href="#pausability" id="pausability"></a>

The contract is pausable at both global and per-bucket levels:

* Global pause can halt all operations in emergencies
* Per-bucket pause allows selective disabling of specific distribution channels
* Separate pausing and unpausing roles prevent unauthorized changes

#### Mint Cap Restrictions <a href="#mint-cap-restrictions" id="mint-cap-restrictions"></a>

Multiple layers of mint cap validation prevent excessive minting:

* Operator mint cap limits total EUR0 minting (for Revenue Switch and Rebasing DT)
* Per-bucket maximum caps limit individual distribution amounts
* Both caps must be satisfied for distributions to proceed

#### Time-Based Restrictions <a href="#time-based-restrictions" id="time-based-restrictions"></a>

Distribution functions enforce time-based restrictions to prevent abuse:

* Accruing DT can only be distributed once per day
* Rebasing DT can only be distributed once per day
* Revenue Switch can only be distributed once per week

These restrictions prevent operators from rapidly minting excessive amounts and ensure distributions occur at appropriate intervals.

#### Input Validation <a href="#input-validation" id="input-validation"></a>

All functions validate inputs:

* Non-zero addresses for reward claim contracts
* Non-zero amounts where applicable
* Yield rate bounds (0 to `BASIS_MILLION_POINT_BASE`)
* Same value checks to prevent redundant updates

#### Invariant Validation <a href="#invariant-validation" id="invariant-validation"></a>

The contract maintains system invariants:

* Operator mint cap cannot be exceeded (except for Accruing DT which doesn't consume it)
* Distribution amounts must respect per-bucket maximum caps
* Time restrictions ensure distributions occur at proper intervals
* Pause states prevent distributions when buckets are disabled

**Note**: In scenarios where overcollateralization invariants are at risk, the contract can be paused or individual buckets can be disabled as a feature flag to protect the system.

#### Restrictions on Function Call Frequency <a href="#restrictions-on-function-call-frequency" id="restrictions-on-function-call-frequency"></a>

There are strict time-based limits for distribution functions:

* **distributeAccruingDT**: Can only be called once per 24 hours
* **distributeRebasingDT**: Can only be called once per 24 hours
* **distributeRevenueSwitch**: Can only be called once per week (7 days)

These restrictions prevent unwanted emissions and ensure distributions occur at controlled, predictable intervals. The time checks use block timestamps and enforce minimum periods between distributions.


# USUAL

<table data-card-size="large" data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td align="center"><strong>USUAL Staking Smart Contract</strong></td><td><a href="/pages/VBhNuXyI7b8ZM0aS41Hz">/pages/VBhNuXyI7b8ZM0aS41Hz</a></td><td data-object-fit="cover"><a href="/files/9ufEtuaU446PKdhzb46A">/files/9ufEtuaU446PKdhzb46A</a></td></tr><tr><td align="center"><strong>USUAL* Vested Allocation Staking Smart Contract</strong></td><td><a href="/pages/Ys4YTeX42fChfCjHdJec">/pages/Ys4YTeX42fChfCjHdJec</a></td><td data-object-fit="cover"><a href="/files/b7VkTfK4D3f4PvvRxsks">/files/b7VkTfK4D3f4PvvRxsks</a></td></tr><tr><td align="center"><strong>USUAL Distribution Smart Contracts</strong> </td><td><a href="/pages/VueIHPkjoXTXQTF7EYFu">/pages/VueIHPkjoXTXQTF7EYFu</a></td><td data-object-fit="cover"><a href="/files/CRLHrQo6RDHp65t15GKO">/files/CRLHrQo6RDHp65t15GKO</a></td></tr><tr><td align="center">USUALX Lockup Contract</td><td><a href="/pages/6EoNjjCnWpIJIXAdKJxP">/pages/6EoNjjCnWpIJIXAdKJxP</a></td><td data-object-fit="cover"><a href="/files/AdaqhUK4ntcNunMtGcV2">/files/AdaqhUK4ntcNunMtGcV2</a></td></tr></tbody></table>


# USUAL staking

## High-Level Overview

The AbstractYieldBearingVault contract is an abstract contract that extends the ERC4626Upgradeable contract and provides functionality for a vault where shares appreciate in value due to yield accrual. The contract tracks total assets deposited and accrues yield over time based on a configurable yield rate and distribution period.

Inherited by:

{% content-ref url="/pages/hVEHgJJFGXbFc718EiZn" %}
[USUALx](/smart-contracts/token-contracts/usualx)
{% endcontent-ref %}

### Contract Summary

The contract provides the following main functions:

* **totalAssets**: Calculates the total assets in the vault, including accrued yield.
* **\_deposit**: Internal function to handle 4626 deposits and mints, updates yield, and tracks total deposits explicitly to avoid vault donation attacks.
* **\_withdraw**: Internal function to handle 4626 withdrawals and mints, updates yield, and updates total deposits.
* **\_calculateEarnedYield**: Calculates the amount of yield earned since the last update.
* **\_updateYield**: Updates the yield state by calculating yield earned and adding it to total deposits.
* **\_startYieldDistribution**: Starts a new yield distribution period.

The contract uses a separate internal storage structure (YieldDataStorage) to store yield-related state variables, including total deposits, yield rate, period start and finish times, last update time, and maximum period length.

### Inherited Contracts

* [**ERC4626Upgradeable**](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/release-v5.0/contracts/token/ERC20/extensions/ERC4626Upgradeable.sol) : The contract inherits from the ERC4626Upgradeable contract, which provides the standard implementation for tokenized vaults.

## Functionality Breakdown

The contract's main functionality is to provide a foundation for implementing yield-bearing vaults that follow the ERC4626 standard. The contract handles the calculation and distribution of yield, updating the total assets in the vault based on the accrued yield.

1. **Yield Calculation and Distribution**:

* The contract tracks the total assets deposited and accrues yield over time based on a configurable yield rate and distribution period.
* The \_calculateEarnedYield function calculates the amount of yield earned since the last update, taking into account the active yield period and the yield rate.
* The \_updateYield function updates the yield state by calculating the earned yield and adding it to the total deposits. It also updates the last update timestamp and deactivates the yield period if it has finished.
* The \_startYieldDistribution function starts a new yield distribution period with a specified yield amount, start time, and end time.

2. **Deposits and Withdrawals**:

* The contract overrides the internal \_deposit and \_withdraw functions from the ERC4626Upgradeable contract to handle deposits and withdrawals while considering the yield accrual.
* The \_deposit function updates the yield, takes the deposited assets, mints shares, and updates the total deposits.
* The \_withdraw function updates the yield, burns shares, transfers the withdrawn assets, and updates the total deposits.

3. **Total Assets Calculation**:

* The totalAssets function calculates the total assets in the vault, including the accrued yield, by adding the total deposits and the earned yield.

### Security Analysis

#### Method: totalAssets

Calculates the total assets in the vault, including accrued yield since the last time totalDeposits was updated. This effectively allows yield to accrue uniformly over time.

```solidity
 1  function totalAssets() public view override returns (uint256) {
 2      YieldDataStorage storage $ = _getYieldDataStorage();
 3      uint256 currentAssets = $.totalDeposits + _calculateEarnedYield();
 4      return currentAssets;
 5  }
```

1. Function is declared as `public view`, allowing external calls without state modifications.
2. Retrieves the YieldDataStorage struct from storage.
3. Calculates current assets by adding total deposits and earned yield since the last time total deposits was updated if there is an active yield period.
4. Returns the calculated current assets as the total assets in the vault.

#### Method: \_deposit

Internal function to handle deposits, update yield, and track total deposits explicitly to only count the yield that has accrued so far. Addresses the vault donation attack. Can be overridden in the concrete implementation to allow for fees.

```solidity
 1  function _deposit(address caller, address receiver, uint256 assets, uint256 shares)
 2      internal
 3      virtual
 4      override
 5  {
 6      YieldDataStorage storage $ = _getYieldDataStorage();
 7      _updateYield();
 8      super._deposit(caller, receiver, assets, shares);
 9      $.totalDeposits += assets;
10  }
```

1-5. Function is internal, virtual, overrides the parent contract's \_deposit function.

6. Retrieves the YieldDataStorage struct from storage.
7. Updates the yield accrued by the vault before processing the deposit.
8. Calls the ERC4626Upgradeable contract's \_deposit function to take assets and mint.
9. Finally updates the totalDeposits by adding the deposited assets.

#### Method: \_withdraw

Internal function to handle withdrawals, update yield, and adjust total deposits explicitly. Can be overriden in the concrete implementation to allow for withdraw fees.

```solidity
 1  function _withdraw(
 2      address caller,
 3      address receiver,
 4      address owner,
 5      uint256 assets,
 6      uint256 shares
 7  ) internal virtual override {
 8      YieldDataStorage storage $ = _getYieldDataStorage();
 9      _updateYield();
10      super._withdraw(caller, receiver, owner, assets, shares);
11      $.totalDeposits -= assets;
12  }
```

1-7. Function is internal, virtual, overrides the parent contract's deposit function.

8. Retrieves the YieldDataStorage struct from storage.
9. Updates the yield before processing the withdrawal.
10. Calls the parent contract's \_withdraw function to burn shares then transfer assets.
11. Updates the totalDeposits by subtracting the withdrawn assets.

#### Method: \_calculateEarnedYield

Calculates the amount of yield earned since the last update without updating state.

```solidity
 1  function _calculateEarnedYield() internal view virtual returns (uint256) {
 2      YieldDataStorage storage $ = _getYieldDataStorage();
 3      if (!$.isActive) return 0;
 4      uint256 endTime = Math.min(block.timestamp, $.periodFinish);
 5      uint256 duration = endTime - $.lastUpdateTime;
 6      return Math.mulDiv(duration, $.yieldRate, YIELD_PRECISION, Math.Rounding.Floor);
 7  }
```

1. Function is declared as internal view, allowing only internal calls without state modifications.
2. Retrieves the YieldDataStorage struct from storage.
3. Returns 0 if there's no active yield period.
4. Calculates the end time as the minimum of current time and period finish time.
5. Calculates the duration since the last update capped at the current yield period finish time.
6. Calculates and returns the earned yield by multiplying by yield rate as tokens/second allowing for high decimal precision and rounding down.

### Method: \_updateYield

Updates the yield storage by calculating earned yield at the current time stamp and adding it to total deposits, then updates the last update time capped at the end of the current yield period. No-op if there is active yield period because the contract was just deployed or the previous yield period has finished.

```solidity
 1  function _updateYield() internal virtual {
 2      YieldDataStorage storage $ = _getYieldDataStorage();
 3      if (!$.isActive) return;
 4  
 5      uint256 newYield = _calculateEarnedYield();
 6      $.totalDeposits += newYield;
 7  
 8      $.lastUpdateTime = Math.min(block.timestamp, $.periodFinish);
 9  
10      if (block.timestamp >= $.periodFinish) {
11          $.isActive = false;
12      }
13  }
```

1. Function is declared as internal virtual, allowing internal calls and potential overrides.
2. Retrieves the YieldDataStorage struct from storage.
3. Returns early if there's no active yield period.
4. Calculates the new yield earned since the lastUpdateTime.
5. Adds the new yield to total deposits.
6. Updates the last update time, capped at the period finish time. 10-12. Deactivates the yield period if it has finished.

#### Method: \_startYieldDistribution

This method is left abstract and needs to be implemented in the derived contract. It's crucial for setting up the variables needed for calculating and updating yield. When implementing this method, consider the following:

* Set the `yieldRate` based on the `yieldAmount` and the duration (`endTime - startTime`) times the YIELD\_PRECISION.
* Update `periodStart`, `periodFinish`, and `lastUpdateTime`.
* Set `isActive` to true to enable yield calculations.
* Implement proper access control to prevent unauthorized yield distributions.
* Ensure that the new distribution period doesn't overlap with an existing active period.

```solidity
 1  function _startYieldDistribution(uint256 yieldAmount, uint256 startTime, uint256 endTime) internal virtual;
```


# USUAL\* Vested Allocation Staking

### High-Level Overview

The **UsualSP** contract is a smart contract designed for managing the vesting and staking of **USUALS** token allocations. It allows insiders to vest and claim their **USUALS** allocations over a pre-defined vesting period and provides users (both insiders and outsiders) the ability to stake **USUALS** tokens to receive yield in the form of liquid allocations and rewards in **USUAL** tokens. Insiders can claim their vested **USUALS** allocations after a user-specific cliff period (multiple of the **ONE\_MONTH** constant), and these tokens are distributed in monthly increments.

### Contract Summary

#### Inherited Contracts

* **RewardAccrualBase**: Base contract that handles the reward accrual mechanism for staked tokens.
* **PausableUpgradeable**: Allows contract functionality to be paused by authorized accounts (OZ implementation).
* **ReentrancyGuardUpgradeable**: Prevents reentrant attacks on sensitive functions (OZ implementation).
* **IUsualSP**: Interface defining the required methods for the **UsualSP** contract.

### Functionality Breakdown

#### SC-Flows

<figure><img src="/files/SZS9YZExgTycmIF70hKV" alt=""><figcaption></figcaption></figure>

#### Key Functionalities

* **Vesting**: Insiders receive an initial **USUALS allocation** that is vested over a defined period. This allocation is released gradually, with insiders able to claim it from their start time and after their cliff period has passed.
* **Claiming USUALS Allocations**: Insiders can claim their vested **USUALS** after the cliff period is over. The claimable amount is calculated based on the duration passed since the vesting started.
* **Staking**: Users (including insiders) can stake their **USUALS** tokens to receive liquid allocations and rewards in **USUAL** tokens. These rewards accrue over time and can be claimed.
* **Reward Accrual**: Users who stake **USUALS** tokens are eligible for rewards in **USUAL** tokens based on the staking duration and amount.
* **Pause and Unpause**: Admins with specific role have the ability to pause and unpause the contract to safeguard against attacks or during upgrades.

### Functions Description

#### Public/External Functions

* **initialize**: Initializes the contract by setting the registry contract, vesting start date, and duration.
* **claimOriginalAllocation**: Allows insiders to claim their vested **USUALS** allocations.
* **stake**: Users can stake their **USUALS** tokens to receive liquid allocations.
* **unstake**: Users can withdraw a portion of their staked **USUALS** tokens.
* **claimReward**: Users can claim their accrued rewards in **USUAL** tokens based on their allocation.
* **pause**: Pauses all token transfer operations; callable only by the PAUSING\_CONTRACTS\_ROLE.
* **unpause**: Resumes all token transfer operations; also callable only by the DEFAULT\_ADMIN\_ROLE.
* **allocate**: Function to allocate original **USUALS** allocations and set the vesting start times and cliff durations for insiders. Only callable by the USUALSP\_OPERATOR\_ROLE.
* **stakeUsualS**: Sends the total supply of **USUALS** to the staking contract. Only callable by the USUALS contract.
* **removeOriginalAllocation**: Function to remove the original allocation and claimed amounts for a list of recipients. Only callable by the USUALSP\_OPERATOR\_ROLE.
* **startRewardDistribution**: Initiates the reward distribution process. Only callable by the Distribution Module contract.

### Constants

* **CONTRACT\_REGISTRY\_ACCESS**: Registry access contract address.
* **DEFAULT\_ADMIN\_ROLE**: Default admin role. Can unpause the contract.
* **PAUSING\_CONTRACTS\_ROLE**: Role required to pause the contract.
* **USUALSP\_OPERATOR\_ROLE**: Role required for allocation management and staking operations.
* **CONTRACT\_USUALS**: The address of the **USUALS** token contract.
* **CONTRACT\_USUAL**: The address of the **USUAL** token contract.
* **CONTRACT\_DISTRIBUTION\_MODULE**: The address of the Distribution Module contract.
* **ONE\_MONTH**: Represents the duration of one month in seconds, used to calculate the vesting schedule.
* **NUMBER\_OF\_MONTHS\_IN\_THREE\_YEARS**: Used to calculate the total vesting duration over three years.
* **STARTDATE\_USUAL\_CLAIMING\_USUALSP:**  The start date of the Usual claiming.

### Safeguards Implementation

* **Pausability**: Ensures that token transfers can be halted in case of emergency.
* **Role-Based Access Control**: Restricts sensitive actions to addresses with appropriate roles.
* **ReentrancyGuard**: All external-facing functions that handle transfers or state changes are protected from reentrancy attacks.


# USUAL Distribution

## High-Level Overview

This contract manages a **Distribution** process of the Usual token. The contract should be called daily to calculate how many new tokens are created, distributed to on-chain vaults (UsualX and UsualS) and how many tokens are available to claim for the off-chain users with a valid merkle proof.

The core features of this contract include:

* **Daily Distribution**: The contract should be called daily to calculate how many new tokens are created, distributed to On Chain vaults (UsualX and UsualS) and how many tokens are available to claim for the off-chain users with a valid merkle proof. The amount distributed scales based on how much longer (after one day) it has been since the last distribution to account for calling the function at greater than 24 hour periods.
* **Merkle Proof for Off-Chain Users**: Ensures that only eligible users, validated through merkle proofs, can receive tokens from the distribution.
* **Challengeable Queue of Merkle Proofs**: The contract should have a queue of merkle proofs that can be challenged by a specific role (e.g. governance) to ensure that the off-chain distribution is fair and correct.
* **Access Control**: Each functionality should be controlled by a role with minimal required permissions.

### Contract Summary

#### Inherited Contracts

* **Initializable**: For upgradeable contract initialization.
* **PausableUpgradeable**: Allows contract execution to be paused or unpaused by an authorized role.
* **ReentrancyGuardUpgradeable**: Provides protection against reentrancy attacks.
* **IDistributionModule**: Interface that defines all functions that can be called by anyone.
* **IDistributionAllocator**: Interface that defines the functions that can be only called by the `DISTRIBUTION_ALLOCATOR_ROLE`
* **IDistributionOperator**: Interface that defines the functions that can be only called by the `DISTRIBUTION_OPERATOR_ROLE`. Those functions are used to daily distribute the Usual tokens to on-chain and off-chain buckets.
* **IOffChainDistributionChallenger**: Interface that defines the functions that can be only called by the `OFF_CHAIN_DISTRIBUTION_CHALLENGER_ROLE`. Those functions are used to challenge the off-chain distribution in the queue.

### Functionality Description

#### Public/External Functions

* **initialize**: Initializes the contract with the registry address and sets the initial `rate0` value
* **pause**: Admin function to pause the contract. Can be only called by `PAUSING_CONTRACTS_ROLE`
* **unpause**: Admin function to unpause the contract. Can be only called by `DEFAULT_ADMIN_ROLE`

#### &#x20;IDistributionModule

* **getBucketsDistribution**: Returns the current buckets distribution percentages in basis points. Off-chain buckets are LST, LYT, IYT, Bribe, Ecosystem, DAO, and Market Makers. On-Chain buckets are UsualX and UsualS.
* **calculateUsualDist**: Helper view function that calculates a simulated Usual Distribution for the provided `ratet` and `p90Rate` values. It returns `st`, `rt` and `kappa` values that were used in the calculation.
* **calculateSt**: Helper view function that returns a calculated `st` value based on provided `supplyPpt` and `pt` values.
* **calculateRt**: Helper view function that returns a calculated `rt` value based on provided `ratet` and `p90Rate` values.
* **calculateMt**: Helper view function that returns a calculated `mt` value based on provided `st`, `rt` and `kappa` values.
* **getOffChainDistributionData**: Returns the currently approved off-chain distribution `timestamp` and `merkleRoot` values. That can be used to pre-validate the merkle proof before calling the `claimOffChainDistribution` function.
* **getOffChainDistributionQueue**: Returns the current off-chain distribution queue. The queue is a list of `timestamp` and `merkleRoot` values that are used to claim the off-chain distribution.
* **getOffChainDistributionMintCap**: Returns the current off-chain distribution mint cap value. This value is the maximum amount of tokens that can be minted by through the off-chain distribution. It is reduced with every successful claim.
* **approveUnchallengedOffChainDistribution**: Approves the latest unchallenged off-chain distribution from the queue that was in the queue for more than `USUAL_DISTRIBUTION_CHALLENGE_PERIOD`. All distributions that were in the queue for more than `USUAL_DISTRIBUTION_CHALLENGE_PERIOD` are removed from the queue. Even if anyone can call this function, usually it will be called by the `DISTRIBUTION_OPERATOR_ROLE`.
* **getOffChainTokensClaimed**: Returns the amount of the tokens claimed by the given `account` address in the off-chain distribution until now.
* **claimOffChainDistribution**: Allows to claim the Usual tokens from the latest approved off-chain distribution. Caller should provide a valid merkle proof for the provided `account` and `amount`. The `amount` is the total amount of tokens that were assigned for the given `account` address since the beginning of the distribution. The Usual tokens are minted when the proof is valid and the given `account` has any tokens to claim in the approved off-chain distribution. The given `account` will only receive the tokens that were not claimed by them before based on the value returned by the `getOffChainTokensClaimed` function. The mint cap should be reduced by the claimed amount. The `getOffChainTokensClaimed` should return increased value.

#### IDistributionAllocator

* **setBucketsDistribution**: Allows to set the new buckets distribution percentages in basis points. The sum of all values should be equal to `BASIS_POINT_BASE`. The function can be only called by the `DISTRIBUTION_ALLOCATOR_ROLE`. Off-chain buckets are LST, LYT, IYT, Bribe, Ecosystem, DAO, and Market Makers. On-Chain buckets are Usual+ and Usual\*.
* **setFeeRates**: Allows to set the Treasury, UsualX and Burn fee rates.
* **getFeeRates**: Allows to get the Treasury, UsualX and Burn fee rates.
* **setD**: Set `D` parameter used it the emissions calculation formula. The function can be only called by the `DISTRIBUTION_ALLOCATOR_ROLE`.
* **getD**: Returns the current `D` parameter value.
* **setM0**: Set `m0` parameter used it the emissions calculation formula. The function can be only called by the `DISTRIBUTION_ALLOCATOR_ROLE`.
* **getM0**: Returns the current `m0` parameter value.
* **setRateMin**: Set `rateMin` parameter used it the emissions calculation formula. The function can be only called by the `DISTRIBUTION_ALLOCATOR_ROLE`.
* **getRateMin**: Returns the current `rateMin` parameter value.
* **setBaseGamma**: Set `baseGamma` parameter used it the emissions calculation formula. The function can be only called by the `DISTRIBUTION_ALLOCATOR_ROLE`.
* **getBaseGamma**: Returns the current `baseGamma` parameter value.

#### IDistributionOperator

* **distributeUsualToBuckets**: Calculates the Usual emissions based on the current state of parameters and provided `ratet` and `p90Rate` values. For on-chain buckets (Usual+ and Usual\*) the tokens are minted directly to the bucket and a vault specific distribution is started. For off-chain buckets (LST, LYT, IYT, Bribe, Ecosystem, DAO, and Market Makers) mint is delayed until the off-chain distribution is approved and tokens are claimed. The function can be only called by the `DISTRIBUTION_OPERATOR_ROLE`.
* **queueOffChainDistribution**: Queues the off-chain distribution for the given `merkleRoot`. The function can be only called by the `DISTRIBUTION_OPERATOR_ROLE`. This function cannot be called more than once per 24 hours.
* **resetOffChainDistributionQueue**: Removes all off-chain distributions from the queue. This is an emergency functionality is queue ever gets to big to be pruned during a `approveUnchallengedOffChainDistribution` call. The function can be only called by the `DISTRIBUTION_OPERATOR_ROLE`.

#### IOffChainDistributionChallenger

* **challengeOffChainDistribution**: Challenges all off-chain distributions in the queue that are older than specified timestamp. They are marked as challenged and cannot be approved. The function can be only called by the `DISTRIBUTION_CHALLENGER_ROLE`.
* **challengeAndProposeOffChainDistribution**: Challenges all off-chain distributions in the queue that are older than specified timestamp. They are marked as challenged and cannot be approved. The new off-chain distribution is proposed with the given `merkleRoot` and it still has to wait in the queue for `USUAL_DISTRIBUTION_CHALLENGE_PERIOD` before it can be approved. The function can be only called by the `DISTRIBUTION_CHALLENGER_ROLE`.

## Functionality Breakdown

### Setting up calculations parameters

* `DISTRIBUTION_ALLOCATOR_ROLE` can change all the values that are used in the emissions calculations formula. There is no timelock for those changes.
* `DISTRIBUTION_ALLOCATOR_ROLE` can change the distribution buckets shares percentages. The sum of all values should be equal to 100% (in basis points). There is no timelock for those changes.

### Daily Emissions

* `DISTRIBUTION_OPERATOR_ROLE` is required to call the `distributeUsualToBuckets` every 24 hours to calculate the new emissions and distribute them to the on-chain buckets and increase the off-chain buckets mint cap that can be claimed after successful approval of the off-chain distribution that is unchallenged and in the queue for more than `USUAL_DISTRIBUTION_CHALLENGE_PERIOD`.
* By calling `distributeUsualToBuckets`, this contract will sweep fees accumulated on `Usd0PP` and `UsualX` contracts and, if any, will redistribute those fees depending of fee rates. Those fees will be distributed to UsualX holders, Yield Treasury contract and will be burned. Fee rates can only be changed by the `FEE_RATE_SETTER_ROLE` and the sum of them should be equal to `BASIS_POINT_BASE` (10\_000).
* `DISTRIBUTION_OPERATOR_ROLE` is required to call the `queueOffChainDistribution` with a valid `merkleRoot` as soon as the off-chain distribution mint cap is increased.

### Off-Chain Distribution Queue, Approval and Challenges

* Once `DISTRIBUTOR_OPERATOR_ROLE` puts a new off-chain distribution in the queue, it has to wait for `USUAL_DISTRIBUTION_CHALLENGE_PERIOD` before it can be approved.
* Anyone can call the `approveUnchallengedOffChainDistribution` function to approve the latest unchallenged off-chain distribution from the queue that was in the queue for more than `USUAL_DISTRIBUTION_CHALLENGE_PERIOD`. This function will remove all distributions that were in the queue for more than `USUAL_DISTRIBUTION_CHALLENGE_PERIOD` which impacts the gas cost of the function. In normal circumstances, there should be only one distribution in the queue that is older than `USUAL_DISTRIBUTION_CHALLENGE_PERIOD` and has to be removed.
* `DISTRIBUTION_CHALLENGER_ROLE` can call the `challengeOffChainDistribution` function to challenge all off-chain distributions in the queue that are older than specified timestamp. They are marked as challenged and cannot be approved. In rare cases, a new off-chain distribution can be proposed and it is put in the queue.
* The queue should be treated as unordered.

### Merkle Tree Root

* The merkle tree root that is queued should be calculated off-chain and should include `account` and `amount` values for each user that is eligible for claiming the off-chain distribution. The `amount` value should be the total amount of tokens that were assigned for the given `account` address since the beginning of the distribution. The `amount` value for the given `account` should never decrease. The `account` address should be in the format `0x123...` and the `amount` should be in wei.

### Merkle Proof Validation

All claims are validated against a Merkle tree using the `MerkleProof` library, ensuring that only eligible users can receive tokens. Separate Merkle roots are set for the initial and vesting periods.

### Admin Control

Administrators have control over setting key contract parameters, such as the Merkle roots and penalty percentages, as well as pausing the contract in case of emergencies.

## Constants

* **DEFAULT\_ADMIN\_ROLE**: Role required to unpause the contract
* **PAUSING\_CONTRACTS\_ROLE**: Role required to pause the contract
* **DISTRIBUTION\_ALLOCATOR\_ROLE**: Role required to set the distribution parameters and buckets distribution percentages
* **DISTRIBUTION\_OPERATOR\_ROLE**: Role required to distribute the Usual tokens to buckets and queue the off-chain distribution
* **DISTRIBUTION\_CHALLENGER\_ROLE**: Role required to challenge the off-chain distribution in the queue
* **FEE\_RATE\_SETTER\_ROLE**: Role required to set the fee rates.
* **USUAL\_DISTRIBUTION\_CHALLENGE\_PERIOD**: The period in seconds that the off-chain distribution has to wait in the queue before it can be approved. It is 7 days by default.
* **CONTRACT\_REGISTRY\_ACCESS**: This constant is used to define the address of the registry access contract.
* **CONTRACT\_ORACLE**: This constant is used to define the address of the oracle contract.
* **CONTRACT\_USD0**: This constant is used to define the address of the USD0 contract.
* **CONTRACT\_USD0PP**: This constant is used to define the address of the USD0PP contract.
* **CONTRACT\_USUAL**: This constant is used to define the address of the Usual contract.
* **CONTRACT\_USUALSP**: This constant is used to define the address of the UsualSP contract.
* **CONTRACT\_USUALX**: This constant is used to define the address of the UsualX contract.
* **CONTRACT\_DAO\_COLLATERAL**: This constant is used to define the address of the DAO collateral contract.
* **CONTRACT\_YIELD\_TREASURY**: This constant is used to define the address of the Yield Treasury contract.
* **BASIS\_POINT\_BASE**: The base value for calculating percentages in basis points.
* **BPS\_SCALAR**: The scalar value for calculating percentages in basis points.
* **SCALAR\_ONE**: The scalar value for calculating percentages with 10^18 precision.
* **REWARD\_PERIOD\_SCALAR**: The scalar value for calculating time since last distribution above 1 day in seconds.

## Safeguard Implementation

### Reentrancy Guard

All external function handling token mints and transfer are protected with `ReentrancyGuard` to prevent reentrancy attacks.

### Access Control

The contract uses `CheckAccessControl` to enforce role-based access control, ensuring only authorized addresses can perform actions that require specific permissions. Each role has minimal required permissions.

### Pausability

The contract is pausable by `PAUSING_CONTRACTS_ROLE`, enabling the ability to pause all operations in case of an emergency. The contract can be resumed only by `DEFAULT_ADMIN_ROLE`.

### Off-chain distribution queue and challenge mechanism

The off-chain distribution can be validated for `USUAL_DISTRIBUTION_CHALLENGE_PERIOD` before it can be approved. If an invalid distribution is proposed, it can be challenged by the `DISTRIBUTION_CHALLENGER_ROLE` making it impossible to be approved.

If the queue ever gets too big, the `resetOffChainDistributionQueue` function can be called by the `DISTRIBUTION_OPERATOR_ROLE` to remove all off-chain distributions from the queue.

### Restrictions how often certain functions can be called

There is a 24 hours limit for the `calculateUsualDist` function to be called. To prevent unwanted emissions and distribution.


# Distribution Module

## High-Level Overview

This contract manages a **Distribution** process of the Usual token. The contract should be called daily to calculate how many new tokens are created, distributed to on-chain vaults (UsualX and UsualS) and how many tokens are available to claim for the off-chain users with a valid merkle proof.

The core features of this contract include:

* **Daily Distribution**: The contract should be called daily to calculate how many new tokens are created, distributed to On Chain vaults (UsualX and UsualS) and how many tokens are available to claim for the off-chain users with a valid merkle proof. The amount distributed scales based on how much longer (after one day) it has been since the last distribution to account for calling the function at greater than 24 hour periods.
* **Merkle Proof for Off-Chain Users**: Ensures that only eligible users, validated through merkle proofs, can receive tokens from the distribution.
* **Challengeable Queue of Merkle Proofs**: The contract should have a queue of merkle proofs that can be challenged by a specific role (e.g. governance) to ensure that the off-chain distribution is fair and correct.
* **Access Control**: Each functionality should be controlled by a role with minimal required permissions.

### Contract Summary

#### Inherited Contracts

* **Initializable**: For upgradeable contract initialization.
* **PausableUpgradeable**: Allows contract execution to be paused or unpaused by an authorized role.
* **ReentrancyGuardUpgradeable**: Provides protection against reentrancy attacks.
* **IDistributionModule**: Interface that defines all functions that can be called by anyone.
* **IDistributionAllocator**: Interface that defines the functions that can be only called by the `DISTRIBUTION_ALLOCATOR_ROLE`
* **IDistributionOperator**: Interface that defines the functions that can be only called by the `DISTRIBUTION_OPERATOR_ROLE`. Those functions are used to daily distribute the Usual tokens to on-chain and off-chain buckets.
* **IOffChainDistributionChallenger**: Interface that defines the functions that can be only called by the `OFF_CHAIN_DISTRIBUTION_CHALLENGER_ROLE`. Those functions are used to challenge the off-chain distribution in the queue.

### Functionality Description

#### Public/External Functions

* **initialize**: Initializes the contract with the registry address and sets the initial `rate0` value
* **pause**: Admin function to pause the contract. Can be only called by `PAUSING_CONTRACTS_ROLE`
* **unpause**: Admin function to unpause the contract. Can be only called by `DEFAULT_ADMIN_ROLE`

#### &#x20;IDistributionModule

* **getBucketsDistribution**: Returns the current buckets distribution percentages in basis points. Off-chain buckets are LST, LYT, IYT, Bribe, Ecosystem, DAO, and Market Makers. On-Chain buckets are UsualX and UsualS.
* **calculateUsualDist**: Helper view function that calculates a simulated Usual Distribution for the provided `ratet` and `p90Rate` values. It returns `st`, `rt` and `kappa` values that were used in the calculation.
* **calculateSt**: Helper view function that returns a calculated `st` value based on provided `supplyPpt` and `pt` values.
* **calculateRt**: Helper view function that returns a calculated `rt` value based on provided `ratet` and `p90Rate` values.
* **calculateMt**: Helper view function that returns a calculated `mt` value based on provided `st`, `rt` and `kappa` values.
* **getOffChainDistributionData**: Returns the currently approved off-chain distribution `timestamp` and `merkleRoot` values. That can be used to pre-validate the merkle proof before calling the `claimOffChainDistribution` function.
* **getOffChainDistributionQueue**: Returns the current off-chain distribution queue. The queue is a list of `timestamp` and `merkleRoot` values that are used to claim the off-chain distribution.
* **getOffChainDistributionMintCap**: Returns the current off-chain distribution mint cap value. This value is the maximum amount of tokens that can be minted by through the off-chain distribution. It is reduced with every successful claim.
* **approveUnchallengedOffChainDistribution**: Approves the latest unchallenged off-chain distribution from the queue that was in the queue for more than `USUAL_DISTRIBUTION_CHALLENGE_PERIOD`. All distributions that were in the queue for more than `USUAL_DISTRIBUTION_CHALLENGE_PERIOD` are removed from the queue. Even if anyone can call this function, usually it will be called by the `DISTRIBUTION_OPERATOR_ROLE`.
* **getOffChainTokensClaimed**: Returns the amount of the tokens claimed by the given `account` address in the off-chain distribution until now.
* **claimOffChainDistribution**: Allows to claim the Usual tokens from the latest approved off-chain distribution. Caller should provide a valid merkle proof for the provided `account` and `amount`. The `amount` is the total amount of tokens that were assigned for the given `account` address since the beginning of the distribution. The Usual tokens are minted when the proof is valid and the given `account` has any tokens to claim in the approved off-chain distribution. The given `account` will only receive the tokens that were not claimed by them before based on the value returned by the `getOffChainTokensClaimed` function. The mint cap should be reduced by the claimed amount. The `getOffChainTokensClaimed` should return increased value.

#### IDistributionAllocator

* **setBucketsDistribution**: Allows to set the new buckets distribution percentages in basis points. The sum of all values should be equal to `BASIS_POINT_BASE`. The function can be only called by the `DISTRIBUTION_ALLOCATOR_ROLE`. Off-chain buckets are LST, LYT, IYT, Bribe, Ecosystem, DAO, and Market Makers. On-Chain buckets are Usual+ and Usual\*.
* **setFeeRates**: Allows to set the Treasury, UsualX and Burn fee rates.
* **getFeeRates**: Allows to get the Treasury, UsualX and Burn fee rates.
* **setD**: Set `D` parameter used it the emissions calculation formula. The function can be only called by the `DISTRIBUTION_ALLOCATOR_ROLE`.
* **getD**: Returns the current `D` parameter value.
* **setM0**: Set `m0` parameter used it the emissions calculation formula. The function can be only called by the `DISTRIBUTION_ALLOCATOR_ROLE`.
* **getM0**: Returns the current `m0` parameter value.
* **setRateMin**: Set `rateMin` parameter used it the emissions calculation formula. The function can be only called by the `DISTRIBUTION_ALLOCATOR_ROLE`.
* **getRateMin**: Returns the current `rateMin` parameter value.
* **setBaseGamma**: Set `baseGamma` parameter used it the emissions calculation formula. The function can be only called by the `DISTRIBUTION_ALLOCATOR_ROLE`.
* **getBaseGamma**: Returns the current `baseGamma` parameter value.

#### IDistributionOperator

* **distributeUsualToBuckets**: Calculates the Usual emissions based on the current state of parameters and provided `ratet` and `p90Rate` values. For on-chain buckets (Usual+ and Usual\*) the tokens are minted directly to the bucket and a vault specific distribution is started. For off-chain buckets (LST, LYT, IYT, Bribe, Ecosystem, DAO, and Market Makers) mint is delayed until the off-chain distribution is approved and tokens are claimed. The function can be only called by the `DISTRIBUTION_OPERATOR_ROLE`.
* **queueOffChainDistribution**: Queues the off-chain distribution for the given `merkleRoot`. The function can be only called by the `DISTRIBUTION_OPERATOR_ROLE`. This function cannot be called more than once per 24 hours.
* **resetOffChainDistributionQueue**: Removes all off-chain distributions from the queue. This is an emergency functionality is queue ever gets to big to be pruned during a `approveUnchallengedOffChainDistribution` call. The function can be only called by the `DISTRIBUTION_OPERATOR_ROLE`.

#### IOffChainDistributionChallenger

* **challengeOffChainDistribution**: Challenges all off-chain distributions in the queue that are older than specified timestamp. They are marked as challenged and cannot be approved. The function can be only called by the `DISTRIBUTION_CHALLENGER_ROLE`.
* **challengeAndProposeOffChainDistribution**: Challenges all off-chain distributions in the queue that are older than specified timestamp. They are marked as challenged and cannot be approved. The new off-chain distribution is proposed with the given `merkleRoot` and it still has to wait in the queue for `USUAL_DISTRIBUTION_CHALLENGE_PERIOD` before it can be approved. The function can be only called by the `DISTRIBUTION_CHALLENGER_ROLE`.

## Functionality Breakdown

### Setting up calculations parameters

* `DISTRIBUTION_ALLOCATOR_ROLE` can change all the values that are used in the emissions calculations formula. There is no timelock for those changes.
* `DISTRIBUTION_ALLOCATOR_ROLE` can change the distribution buckets shares percentages. The sum of all values should be equal to 100% (in basis points). There is no timelock for those changes.

### Daily Emissions

* `DISTRIBUTION_OPERATOR_ROLE` is required to call the `distributeUsualToBuckets` every 24 hours to:
  1. Fetch the current blended weekly interest rate and P90 rate from the [Yield Module](https://app.gitbook.com/o/qhhUYNkfevGh3Y1MDQaS/s/pUhQzPJGdJzuLTQ5sCym/~/changes/119/smart-contracts/protocol-contracts/usual-distribution/yield-module)
  2. Calculate the new emissions based on these rates
  3. Distribute tokens to the on-chain buckets
  4. Increase the off-chain buckets mint cap that can be claimed after successful approval of the off-chain distribution (must be unchallenged and in queue for more than `USUAL_DISTRIBUTION_CHALLENGE_PERIOD`)
* By calling `distributeUsualToBuckets`, this contract will sweep fees accumulated on `Usd0PP` and `UsualX` contracts and, if any, will redistribute those fees depending of fee rates. Those fees will be distributed to UsualX holders, Yield Treasury contract and will be burned. Fee rates can only be changed by the `FEE_RATE_SETTER_ROLE` and the sum of them should be equal to `BASIS_POINT_BASE` (10\_000).
* `DISTRIBUTION_OPERATOR_ROLE` is required to call the `queueOffChainDistribution` with a valid `merkleRoot` as soon as the off-chain distribution mint cap is increased.

### Off-Chain Distribution Queue, Approval and Challenges

* Once `DISTRIBUTOR_OPERATOR_ROLE` puts a new off-chain distribution in the queue, it has to wait for `USUAL_DISTRIBUTION_CHALLENGE_PERIOD` before it can be approved.
* Anyone can call the `approveUnchallengedOffChainDistribution` function to approve the latest unchallenged off-chain distribution from the queue that was in the queue for more than `USUAL_DISTRIBUTION_CHALLENGE_PERIOD`. This function will remove all distributions that were in the queue for more than `USUAL_DISTRIBUTION_CHALLENGE_PERIOD` which impacts the gas cost of the function. In normal circumstances, there should be only one distribution in the queue that is older than `USUAL_DISTRIBUTION_CHALLENGE_PERIOD` and has to be removed.
* `DISTRIBUTION_CHALLENGER_ROLE` can call the `challengeOffChainDistribution` function to challenge all off-chain distributions in the queue that are older than specified timestamp. They are marked as challenged and cannot be approved. In rare cases, a new off-chain distribution can be proposed and it is put in the queue.
* The queue should be treated as unordered.

### Merkle Tree Root

* The merkle tree root that is queued should be calculated off-chain and should include `account` and `amount` values for each user that is eligible for claiming the off-chain distribution. The `amount` value should be the total amount of tokens that were assigned for the given `account` address since the beginning of the distribution. The `amount` value for the given `account` should never decrease. The `account` address should be in the format `0x123...` and the `amount` should be in wei.

### Merkle Proof Validation

All claims are validated against a Merkle tree using the `MerkleProof` library, ensuring that only eligible users can receive tokens. Separate Merkle roots are set for the initial and vesting periods.

### Admin Control

Administrators have control over setting key contract parameters, such as the Merkle roots and penalty percentages, as well as pausing the contract in case of emergencies.

## Constants

* **DEFAULT\_ADMIN\_ROLE**: Role required to unpause the contract
* **PAUSING\_CONTRACTS\_ROLE**: Role required to pause the contract
* **DISTRIBUTION\_ALLOCATOR\_ROLE**: Role required to set the distribution parameters and buckets distribution percentages
* **DISTRIBUTION\_OPERATOR\_ROLE**: Role required to distribute the Usual tokens to buckets and queue the off-chain distribution
* **DISTRIBUTION\_CHALLENGER\_ROLE**: Role required to challenge the off-chain distribution in the queue
* **FEE\_RATE\_SETTER\_ROLE**: Role required to set the fee rates.
* **USUAL\_DISTRIBUTION\_CHALLENGE\_PERIOD**: The period in seconds that the off-chain distribution has to wait in the queue before it can be approved. It is 7 days by default.
* **CONTRACT\_REGISTRY\_ACCESS**: This constant is used to define the address of the registry access contract.
* **CONTRACT\_ORACLE**: This constant is used to define the address of the oracle contract.
* **CONTRACT\_USD0**: This constant is used to define the address of the USD0 contract.
* **CONTRACT\_USD0PP**: This constant is used to define the address of the USD0PP contract.
* **CONTRACT\_USUAL**: This constant is used to define the address of the Usual contract.
* **CONTRACT\_USUALSP**: This constant is used to define the address of the UsualSP contract.
* **CONTRACT\_USUALX**: This constant is used to define the address of the UsualX contract.
* **CONTRACT\_DAO\_COLLATERAL**: This constant is used to define the address of the DAO collateral contract.
* **CONTRACT\_YIELD\_TREASURY**: This constant is used to define the address of the Yield Treasury contract.
* **BASIS\_POINT\_BASE**: The base value for calculating percentages in basis points.
* **BPS\_SCALAR**: The scalar value for calculating percentages in basis points.
* **SCALAR\_ONE**: The scalar value for calculating percentages with 10^18 precision.
* **REWARD\_PERIOD\_SCALAR**: The scalar value for calculating time since last distribution above 1 day in seconds.

## Yield Module Integration

The Distribution Module relies on the Yield Module for two critical values used in emissions calculations:

1. Blended Weekly Interest Rate: A weighted average of all RWA interest rates based on their USD value in the treasury
2. P90 Interest Rate: The 90th percentile interest rate maintained by the Yield Module

These values are fetched during the daily distribution process and used to calculate the emission rate for new USUAL tokens. This integration ensures that token emissions are directly tied to the actual yield being generated by the protocol's RWA holdings. More details on the Yield Module [here](https://app.gitbook.com/o/qhhUYNkfevGh3Y1MDQaS/s/pUhQzPJGdJzuLTQ5sCym/~/changes/119/smart-contracts/protocol-contracts/usual-distribution/yield-module).

## Safeguard Implementation

### Reentrancy Guard

All external function handling token mints and transfer are protected with `ReentrancyGuard` to prevent reentrancy attacks.

### Access Control

The contract uses `CheckAccessControl` to enforce role-based access control, ensuring only authorized addresses can perform actions that require specific permissions. Each role has minimal required permissions.

### Pausability

The contract is pausable by `PAUSING_CONTRACTS_ROLE`, enabling the ability to pause all operations in case of an emergency. The contract can be resumed only by `DEFAULT_ADMIN_ROLE`.

### Off-chain distribution queue and challenge mechanism

The off-chain distribution can be validated for `USUAL_DISTRIBUTION_CHALLENGE_PERIOD` before it can be approved. If an invalid distribution is proposed, it can be challenged by the `DISTRIBUTION_CHALLENGER_ROLE` making it impossible to be approved.

If the queue ever gets too big, the `resetOffChainDistributionQueue` function can be called by the `DISTRIBUTION_OPERATOR_ROLE` to remove all off-chain distributions from the queue.

### Restrictions how often certain functions can be called

There is a 24 hours limit for the `calculateUsualDist` function to be called. To prevent unwanted emissions and distribution.


# Yield Module

## High-Level Overview

This contract manages the blending of various Real-World Asset (RWA) interest rates and TVL vault strategies in the treasury. The contract calculates a blended weekly interest rate and maintains a `P90` (90th percentile) rate that can be used by the distribution module for token emissions calculations.

The core features of this contract include:

* **Interest Rate Management**: Manages yield sources with either Chainlink oracle feeds or manual interest rates
* **Blended Rate Calculation**: Calculates a weighted average of interest rates based on asset values in treasuries
* **P90 Rate Management**: Maintains a configurable P90 interest rate for distribution calculations
* **Treasury Management**: Tracks multiple treasury addresses for asset balance calculations
* **Access Control**: Each functionality is controlled by specific roles with minimal required permissions

## Contract Summary

### Inherited Contracts

* **PausableUpgradeable**: Allows contract execution to be paused/unpaused by authorized role
* **IYieldModule**: Interface defining all public/external functions

### Functionality Description

#### **Public/External Functions**

**Administrative Functions**:

* `initialize`: Initializes contract with registry address and sets initial max data age
* `pause`: Pauses contract operations (`PAUSING_CONTRACTS_ROLE` only)
* `unpause`: Unpauses contract operations (`DEFAULT_ADMIN_ROLE` only)

**Yield Source Management**:

* `addYieldSourceWithFeed`: Adds yield source with Chainlink oracle feed (`YIELD_MODULE_TOKENOMICS_OPERATOR_ROLE` only)
* `addYieldSourceWithWeeklyInterest`: Adds yield source with manual weekly interest rate (`YIELD_MODULE_TOKENOMICS_OPERATOR_ROLE` only)
* `removeYieldSource`: Removes a yield source (`YIELD_MODULE_SUPER_ADMIN_ROLE` only)
* `updateInterestRate`: Updates manual interest rate for a new one. This function will override the feed address if it exists (`YIELD_MODULE_UPDATER_ROLE` only)
* `updateFeed`: Updates Chainlink feed address for a new fee address (`YIELD_MODULE_UPDATER_ROLE` only)

**Treasury Management**:

* `addTreasury`: Adds a treasury address for asset balance tracking (`YIELD_MODULE_SUPER_ADMIN_ROLE` only)
* `removeTreasury`: Removes a treasury address (`YIELD_MODULE_SUPER_ADMIN_ROLE` only)

**Configuration**:

* `setMaxDataAge`: Sets maximum allowed age for oracle data (`YIELD_MODULE_MAX_DATA_AGE_ROLE` only)
* `setP90InterestRate`: Sets P90 interest rate value (`YIELD_MODULE_P90_INTEREST_ROLE` only)

**View Functions**:

* `getBlendedWeeklyInterest`: Calculates current blended weekly interest rate
* `getP90InterestRate`: Returns current P90 interest rate
* `getYieldSource`: Returns data for specific yield source
* `getYieldSourceCount`: Returns total number of yield sources
* `getAllYieldSourceData`: Returns data for all yield sources
* `getTreasuryCount`: Returns number of tracked treasuries
* `getAllTreasury`: Returns all treasury addresses

## Functionality Breakdown

### **Yield Source Management**

* Each yield source can use either a Chainlink oracle feed or manual interest rate
* Oracle feeds must provide valid, recent data within `maxDataAge`
* Manual rates are validated to be within acceptable bounds
* Interest rates are expressed in basis points (1 = 0.01%)

### **Blended Rate Calculation**

The `getBlendedWeeklyInterest()` function calculates a weighted average of all RWA interest rates based on their USD value in the treasury. Here's the detailed calculation process:

1. **Asset Value Calculation (in USD)**\
   For each RWA token:

   ```
   assetValue = price * balance / (10 ^ decimals)
   ```

   where:

   * `price` is obtained from the oracle for that RWA
   * `balance` is the sum of the RWA token balance across all registered treasuries
   * `decimals` is the token's decimal places

2. **Weighted Interest Rate**\
   For each RWA:

   ```
   weightedSum += rate * assetValue
   totalValue += assetValue
   ```

   where:

   * `rate` is either:
     * The latest valid rate from the Chainlink oracle feed if configured
     * The manually set `weeklyInterestBps` if no feed is configured
   * Oracle data must be fresher than `maxDataAge` to be considered valid

3. **Final Blended Rate**

   ```
   blendedRate = totalValue > 0 ? weightedSum / totalValue : 0
   ```

   The final rate is rounded down and must be less than `BASIS_POINT_BASE` (10000)

## Constants

* `YIELD_MODULE_TOKENOMICS_OPERATOR_ROLE`: Role for adding yield sources
* `YIELD_MODULE_SUPER_ADMIN_ROLE`: Role for removing yield sources and treasury management
* `YIELD_MODULE_P90_INTEREST_ROLE`: Role for setting P90 interest rate
* `YIELD_MODULE_MAX_DATA_AGE_ROLE`: Role for setting maximum data age
* `YIELD_MODULE_UPDATER_ROLE`: Role for updating yield sources
* `INITIAL_YIELD_MODULE_MAX_DATA_AGE`: Default maximum age for oracle data (14 days)
* `DEFAULT_YIELD_FEED_RATE`: Default rate for new oracle feeds
* `BASIS_POINT_BASE`: Base for interest rate calculations (10000 = 100%)

## Safeguard Implementation

### **Access Control**

* Role-based access control for all administrative functions
* Specific roles for different aspects of yield management
* Minimal permissions principle applied to role assignments

### **Pausability**

* Contract can be paused by `PAUSING_CONTRACTS_ROLE`
* Only `DEFAULT_ADMIN_ROLE` can unpause
* Protects against emergencies or discovered vulnerabilities

### **Data Validation**

* Oracle data freshness checks
* Interest rate bounds validation
* Duplicate treasury prevention
* Null address checks

### **Oracle Safety**

* Maximum data age enforcement
* Oracle interface validation
* Fallback to manual rates if needed


# USUALx Lockup Contract

## High-Level Overview

The UsualXLockup contract is an upgradeable vault that enables users to lock their UsualX tokens for predefined durations. It implements a flexible locking mechanism with features such as position creation, top-ups within the same UTC calendar day, and position releases after lock expiration. The contract leverages OpenZeppelin's upgradeable contracts for enhanced security and flexibility, including pausability and reentrancy protection.\
\
The primary objective of UsualXLockup is to provide a secure mechanism for users to lock their UsualX tokens, potentially for governance or reward-earning purposes, while maintaining strict control over lock durations and position management.

### Inherited Contracts

* **PausableUpgradeable**: Emergency halt capabilities
* **ReentrancyGuardUpgradeable**: Reentrancy attack prevention

### Reward Boost Mechanism

The contract enables users to lock their UsualX tokens for various durations to receive\
boosted rewards. Key points:

* Boost calculations are performed off-chain
* Contract provides only necessary on-chain data through events and state tracking

## Contract Summary

### Main Functions

* `initialize`: Contract setup with registry contract address
* `lock`: New lock position creation
* `intraDayTopUp`: Same-day position top-ups
* `release`: Token release after lock expiration
* `releaseAndLock`: Combined release and lock operations
* `unlockUserPosition`: Forced position unlock by privileged roles
* `unlockUsersPositionsBatch`: Forced batch position unlocking by privileged roles

Storage:

* Uses UsualXLockupStorageV0 structure for state variables

### Functionality Breakdown

A. Access Control and Security

* Registry contract for role-based access
* Position unlocking controls through dedicated roles

B. Position Management

* Multiple lock positions per user support
* Same-day position top-ups
* Post-expiration release functionality
* Privileged forced unlock capabilities

C. Lock Duration Management

* Predefined durations (1, 3, 6, and 12 months)
* Lock duration validation enforcement

### Method Analysis

#### Public/External Functions

#### 1. Initialize

```solidity
function initialize(address registryContract) external initializer {
    if (registryContract == address(0)) {
        revert NullAddress();
    }
    UsualXLockupStorageV0 storage $ = _usualXLockupStorageV0();
    $.registryContract = IRegistryContract(registryContract);
    $.registryAccess = IRegistryAccess($.registryContract.getContract(CONTRACT_REGISTRY_ACCESS));
    $.usualX = IERC20($.registryContract.getContract(CONTRACT_USUALX));
    $.lockDurations[ONE_MONTH] = true;
    $.lockDurations[THREE_MONTHS] = true;
    $.lockDurations[SIX_MONTHS] = true;
    $.lockDurations[ONE_YEAR] = true;
}
```

**Purpose**: Contract initialization\
**Key Features:**

* Registry contract validation
* Access control setup
* Default lock duration enablement\
  Security:
* Null address checks
* Single initialization enforcement

2. **Lock**

```solidity
function lock(address receiver, uint256 amount, uint256 lockDuration)
    external
    nonReentrant
    whenNotPaused
{
    if (receiver == address(0)) {
        revert NullAddress();
    }
    if (amount == 0) {
        revert AmountIsZero();
    }
    UsualXLockupStorageV0 storage $ = _usualXLockupStorageV0();
    _lock($, msg.sender, receiver, amount, lockDuration);
}
```

**Purpose**: New position creation\
**Key Features:**

* Amount and receiver validation
* Lock duration verification
* Position creation and event emission
* Reentrancy protection
* Pause mechanism
* Null address checks

3. **IntraDayTopUp**

```solidity
function intraDayTopUp(address receiver, uint256 amount, uint256 positionIndex)
    external
    nonReentrant
    whenNotPaused
{
    if (receiver == address(0)) {
        revert NullAddress();
    }
    if (amount == 0) {
        revert AmountIsZero();
    }
    UsualXLockupStorageV0 storage $ = _usualXLockupStorageV0();
    _topUp($, msg.sender, receiver, amount, positionIndex);
}
```

**Purpose:** Same-day position enhancement\
**Key Features:**

* Same-day validation
* Position amount update
* Event emission
* Reentrancy protection
* Position existence checks
* Active status verification

4. **Release**

```solidity
function release(address user, uint256 positionIndex) external nonReentrant whenNotPaused {
    if (user == address(0)) {
        revert NullAddress();
    }
    UsualXLockupStorageV0 storage $ = _usualXLockupStorageV0();
    _release($, user, positionIndex);
}
```

**Purpose**: Lock expiration token release\
**Key Features:**

* Lock expiration verification
* Token transfer
* Position status update
* Reentrancy protection
* Position validation
* Active status checks

#### Internal Functions

1. **\_lock**

```solidity
function _lock(
    UsualXLockupStorageV0 storage $,
    address sender,
    address receiver,
    uint256 amount,
    uint256 lockDuration
) internal {
    if ($.lockDurations[lockDuration] == false) {
        revert LockDurationIsNotEnabled();
    }

    $.usualX.safeTransferFrom(sender, address(this), amount);

    LockPosition memory lockPosition = LockPosition({
        amount: amount,
        startTime: block.timestamp,
        endTime: block.timestamp + lockDuration,
        isActive: true
    });
    $.userLockPositions[receiver].push(lockPosition);
    $.userLockedAmount[receiver] += amount;

    emit PositionCreated(
        receiver,
        $.userLockPositions[receiver].length - 1,
        lockPosition.amount,
        lockPosition.startTime,
        lockPosition.endTime
    );
}
```

**Purpose**: Core lock position creation\
**Implementation**:

* Lock duration validation
* Token transfer handling
* Position creation
* Total amount tracking
* Event emission

2. **\_topUp**

```solidity
function _topUp(
    UsualXLockupStorageV0 storage $,
    address sender,
    address receiver,
    uint256 amount,
    uint256 positionIndex
) internal {
    if (positionIndex >= $.userLockPositions[receiver].length) {
        revert PositionDoesNotExist();
    }
    LockPosition storage lockPosition = $.userLockPositions[receiver][positionIndex];
    if (!lockPosition.isActive) {
        revert PositionIsNotActive();
    }

    // Check if current time is within the same UTC calendar day as start time
    uint256 startDay = lockPosition.startTime / ONE_DAY;
    uint256 currentDay = block.timestamp / ONE_DAY;
    if (currentDay > startDay) {
        revert TopUpDelayHasPassed();
    }

    $.usualX.safeTransferFrom(sender, address(this), amount);
    lockPosition.amount += amount;
    $.userLockedAmount[receiver] += amount;
    emit PositionToppedUp(
        receiver,
        positionIndex,
        amount,
        lockPosition.amount,
        lockPosition.startTime,
        lockPosition.endTime
    );
}
```

**Purpose**: Position top-up logic\
**Implementation**:

* Position validation
* Same-day verification
* Amount updates
* Event emission

3. **\_release**

```solidity
function _release(UsualXLockupStorageV0 storage $, address user, uint256 positionIndex)
    internal
{
    if (positionIndex >= $.userLockPositions[user].length) {
        revert PositionDoesNotExist();
    }
    LockPosition storage lockPosition = $.userLockPositions[user][positionIndex];
    if (!lockPosition.isActive) {
        revert PositionIsNotActive();
    }
    if (block.timestamp < lockPosition.endTime) {
        revert PositionIsStillLocked();
    }
    uint256 positionAmount = lockPosition.amount;

    lockPosition.isActive = false;
    $.userLockedAmount[user] -= positionAmount;
    $.usualX.safeTransfer(user, positionAmount);
    emit PositionReleased(user, positionIndex, positionAmount);
}
```

**Purpose**: Token release implementation\
**Implementation**:

* Position validation
* Lock expiration check
* Token transfer
* State updates

4. **\_unlockBatchPositionsForUser**

```solidity
function _unlockBatchPositionsForUser(
    UsualXLockupStorageV0 storage $,
    address user,
    uint256 startIndex,
    uint256 endIndex
) private returns (uint256[] memory) {
    if (user == address(0)) {
        revert NullAddress();
    }
    if (startIndex > endIndex) {
        revert StartIndexGreaterThanEndIndex();
    }
    if (endIndex > $.userLockPositions[user].length) {
        revert PositionDoesNotExist();
    }
    uint256 totalAmount = 0;
    uint256[] memory unlockedIndexes = new uint256[](endIndex - startIndex + 1);
    uint256 unlockedCount = 0;
    for (uint256 j = startIndex; j <= endIndex; j++) {
        LockPosition storage lockPosition = $.userLockPositions[user][j];
        if (!lockPosition.isActive) {
            continue;
        }
        lockPosition.isActive = false;
        totalAmount += lockPosition.amount;
        unlockedIndexes[unlockedCount] = j;
        unlockedCount++;
    }
    // Optimize array length using assembly
    // solhint-disable-next-line no-inline-assembly
    assembly {
        mstore(unlockedIndexes, unlockedCount)
    }

    // Update the user's locked amount and transfer the assets
    $.userLockedAmount[user] -= totalAmount;
    $.usualX.safeTransfer(user, totalAmount);

    return unlockedIndexes;
}Purpose: Batch position unlocking
Implementation:
```

* Range validation
* Position processing
* Amount accumulation
* State updates
* Token transfers

## Flow Diagram

<figure><img src="/files/JzQiGqGdj9gify2g5z7Y" alt=""><figcaption></figcaption></figure>

## Security Considerations

**1. Access Control**

* Role-based permissions
* Registry contract integration
* Function-level access restrictions

**2. Input Validation**

* Address validation
* Amount verification
* Index range checks

**3. Protection Mechanisms**

* Reentrancy guards
* Pause functionality
* Duration controls


# Token Contracts

<table data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center"><strong>USD0 Smart Contract</strong></td><td data-object-fit="cover"><a href="/files/JQdm3yz3Fv3V3lmfyKyJ">/files/JQdm3yz3Fv3V3lmfyKyJ</a></td><td><a href="/pages/kaGk2EIk5c3i9os6uhLk">/pages/kaGk2EIk5c3i9os6uhLk</a></td></tr><tr><td align="center"><strong>bUSD0 (formerly USD0++) Smart Contract</strong></td><td data-object-fit="cover"><a href="/files/y6kilfK17GVR1h5ybJL7">/files/y6kilfK17GVR1h5ybJL7</a></td><td><a href="/pages/jA9gCTlpvd8kcZidif4W">/pages/jA9gCTlpvd8kcZidif4W</a></td></tr><tr><td align="center">USD0a Smart Contract</td><td><a href="/files/aySxNw8DQRz8tnWaAjQp">/files/aySxNw8DQRz8tnWaAjQp</a></td><td><a href="/pages/zAVgMSAut3TstcbNR85N">/pages/zAVgMSAut3TstcbNR85N</a></td></tr><tr><td align="center"><strong>ETH0 Smart Contract</strong></td><td data-object-fit="cover"><a href="/files/qT6aiOwhhSRwqXMOHqyS">/files/qT6aiOwhhSRwqXMOHqyS</a></td><td><a href="/pages/swC6xwtSsbIyduQaWCgu">/pages/swC6xwtSsbIyduQaWCgu</a></td></tr><tr><td align="center"><strong>EUR0 Smart Contract</strong></td><td><a href="/files/zo5FT2ZSqQjD69X6bLQ2">/files/zo5FT2ZSqQjD69X6bLQ2</a></td><td><a href="/pages/LVV3gKZANqXlUlDnvBBz">/pages/LVV3gKZANqXlUlDnvBBz</a></td></tr><tr><td align="center"><strong>USUAL Smart Contract</strong></td><td data-object-fit="cover"><a href="/files/TvZ8fCwIuJZoo06rLGup">/files/TvZ8fCwIuJZoo06rLGup</a></td><td><a href="/pages/tg0GXKS5hSLFJHzLMwcs">/pages/tg0GXKS5hSLFJHzLMwcs</a></td></tr><tr><td align="center"><strong>USUALx Smart Contract</strong></td><td data-object-fit="cover"><a href="/files/qhqxMz15LLNT0t0ablMG">/files/qhqxMz15LLNT0t0ablMG</a></td><td><a href="/pages/hVEHgJJFGXbFc718EiZn">/pages/hVEHgJJFGXbFc718EiZn</a></td></tr><tr><td align="center"><strong>USUAL* Smart Contract</strong></td><td data-object-fit="cover"><a href="/files/lIknb3oH5ijPfyD7GLRF">/files/lIknb3oH5ijPfyD7GLRF</a></td><td><a href="/pages/BY7v4Ols7VxILL81pfAs">/pages/BY7v4Ols7VxILL81pfAs</a></td></tr><tr><td align="center"><strong>sUSD0 Smart Contract</strong></td><td><a href="/files/RBcbWCs6KSDk5zqjyy4N">/files/RBcbWCs6KSDk5zqjyy4N</a></td><td><a href="/pages/kBxDf3Z18oxeEcwBbTp2">/pages/kBxDf3Z18oxeEcwBbTp2</a></td></tr><tr><td align="center"><strong>sEUR0 Smart Contract</strong></td><td><a href="/files/6qY8F81qyCnWGRoDuOoK">/files/6qY8F81qyCnWGRoDuOoK</a></td><td><a href="/pages/ylyMjRmRddZjAUVYLR5H">/pages/ylyMjRmRddZjAUVYLR5H</a></td></tr></tbody></table>


# USD0

## High-Level Overview

The USD0 contract is designed to manage Usuals Stablecoin, the USD0 ERC20 Token, implementing functionalities for minting, burning, and transfer operations while incorporating blacklist checks to restrict these operations to authorized addresses.&#x20;

The total USD0 supply is collateralized with at minimum 1:1 in USD Real World Assets ( read more [here](https://gitbook.usual.money/usual-mechanisms/liquid-deposit-token-ldt/usd0-rwa-stablecoin/why-usd0))

## Contract Summary

USD0 is an ERC-20 compliant token that integrates additional security and access control features to enhance its governance and usability. It inherits functionalities from ERC20PausableUpgradable and ERC20PermitUpgradeable to support permit-based approvals and pausability.

### Minting USD0

Users can swap their Real World Assets via the [USD0 DaoCollateral](/smart-contracts/protocol-contracts/usd0/usd0-daocollateral) to mint an equivalent USD amount of USD0. Alternatively, they can deposit USDC into the [USD0 Swapper Engine](/smart-contracts/protocol-contracts/usd0/usd0-swapper-engine) for a RWA Provider to exchange their RWA to USD0.&#x20;

Additionally, as part of the accumulating yield of our underlying Real World Assets, the Usual DAO can mint additional USD0 for any excess collateral above 100% + 21 days of yield.

### Redeeming USD0

Users can swap any USD0 back to the underlying Real World Assets at any time via the [USD0 DaoCollateral](/smart-contracts/protocol-contracts/usd0/usd0-daocollateral) contract, burning the USD0 in the process. In order to prevent sandwich oracle attacks on yield, the Usual DAO Treasury charges a redemption fee of`0.10%`

### Regulatory Compliance

The contract includes a blacklist feature to ensure regulatory compliance. Sanctioned addresses are prevented from interacting with the contract, and kept up to date. \
\
Usual is enforcing the OFAC Sanctions List: <https://sanctionslist.ofac.treas.gov/Home/SdnList>

As well as the FAFT: <https://www.fatf-gafi.org/en/home.html>

### Collateralization Enforcement

Minting of USD0 is only possible if the Usual DAO Treasury equals or exceeds the USD Backing Ratio of 1:1 in Real World Assets versus the USD0 totalSupply()

## Functionality Breakdown

#### Key Functionalities

* **Minting**: Tokens can be minted to an address, subject to role checks.
* **Burning**: Tokens can be burned from an address, also subject to role checks.
* **Transfers**: Only not blacklisted addresses can send or receive tokens.

### Functions Description

#### Public/External Functions

* **pause()**: Pauses all token transfer operations; callable only by the `PAUSING_CONTRACTS_ROLE`.
* **unpause()**: Resumes all token transfer operations; also callable only by the `DEFAULT_ADMIN_ROLE`.
* **transfer(address to, uint256 amount)**: Transfers tokens to a non-blacklisted address.
* **transferFrom(address sender, address to, uint256 amount)**: Transfers tokens from one non-blacklisted address to another.
* **mint(address to, uint256 amount)**: Mints tokens to a non-blacklisted address if the caller has the `USD0_MINT` role.
* **burn(uint256 amount)** and **burnFrom(address account, uint256 amount)**: Burns tokens from an address, requiring the `USD0_BURN` role.
* **blacklist(address account)** and **unBlacklist(address account)**: Those functions allows the admin to blacklist or remove from blacklist malicious users from using this token. Only callable by the BLACKLIST\_ROLE.

<br>

###


# bUSD0 (formerly USD0++)

## High-Level Overview

This smart contract manages a bond financial instrument for the UsualDAO ecosystem. It provides functionality for minting, transferring, and unstaking the liquid token. The contract complies with ERC20 standards and allows users to deposit USD0 into bUSD0 or acquire it on the secondary market.

bUSD0 (Bond USD0) represents USD0 stablecoin locked until June 11, 2028. It remains transferable during this period, earning USUAL incentives and maturity yield. Users receive 1 USD0 for 1 bUSD0 at maturity. For early redemption, users need an equivalent amount of rt-USD0 - received at mint - which unlocks bUSD0 back into USD0 at a 1:1 rate anytime. Additionally, early redemption below peg can be made at a DAO set price floor.

### **Minting bUSD0 (formerly USD0++)**

Users can stake their USD0 to convert them into bUSD0 (formerly USD0++). The issuance of bUSD0 (formerly USD0++) follows a 1:1 ratio with the staked USD0. Once staked, the assets remain immobilized for the maturity period of the bUSD0 (formerly USD0++) liquid stake, ensuring stability and predictability.

**Staking and Issuance**

* **Locking USD0**: Users stake their USD0 to mint bUSD0 (formerly USD0++).
* **1:1 Issuance**: bUSD0 (formerly USD0++) is issued on a 1:1 basis with the locked USD0.
* **Locked Duration**: Assets are locked for the maturity period of the bUSD0 (formerly USD0++) liquid staking token.
* **Locking USD0**: Users deposit their USD0 to mint bUSD0 (formerly USD0++).
* **1:1 Issuance**: Both bUSD0 (formerly USD0++) and rt-bUSD0 are issued on a 1:1 basis with the deposited USD0.
  * **Dual Token System**:
    * **bUSD0 (formerly USD0++)**: The bond asset token, transferable and composable.
    * **rt-bUSD0**: The redemption token asset, required alongside bUSD0 to reconstruct the bond back to USD0.
* **Locked Duration**: Assets are locked for the maturity period of the USD0++.

**Reconstructing Bonds**

Users can reconstruct (destroy) their bonds by burning both bUSD0 (formerly USD0++) and rt-bUSD0 tokens together to receive the underlying USD0 back. This process requires equal amounts of both tokens and can be done at any time before maturity.

* **Reconstruction Process**: Users burn equal amounts of bUSD0 (formerly USD0++) and rt-bUSD0 tokens to receive USD0 at a 1:1 ratio.
* **Token Requirements**: Both bUSD0 (formerly USD0++) and rt-bUSD0 tokens must be present in equal amounts to reconstruct the bond.

### Floor Price Mechanism

bUSD0 (formerly USD0++) includes a floor price mechanism, allowing users to unstake their bUSD0 (formerly USD0++) for USD0 at a guaranteed minimum rate.

* `updateFloorPrice(uint256 newFloorPrice)`: Allows authorized admins to update the floor price. Only callable by the `FLOOR_PRICE_UPDATER_ROLE` role.
* `unlockUsd0ppFloorPrice(uint256 usd0ppAmount)`: Allows users to unstake their bUSD0 (formerly USD0++) at the current floor price.

### USUAL Fee Mechanism

bUSD0 (formerly USD0++) includes an early redemption mechanism that allows users to unlock their bUSD0 (formerly USD0++) before maturity by transferring USUAL tokens. The amount of USUAL required for redemption is dynamically calculated based on several factors:

#### Key Functions

* `unlockUSD0ppWithUsual(uint256 usd0ppAmount, uint256 maxUsualAmount)`: Allows users to redeem bUSD0 (formerly USD0++) by transferring USUAL tokens
* `unlockUSD0ppWithUsualWithPermit(...)`: Same as above but includes permit functionality for gasless approvals
* `calculateRequiredUsual(uint256 usd0ppAmount)`: Calculates the amount of USUAL needed to redeem a given amount of bUSD0 (formerly USD0++)
* `sweepFees()` : Callable only by the `FEE_SWEEPER_ROLE` and transfers the accumulated USUAL fees to the distribution module

#### Calculation Factors

The required USUAL amount is determined by:

1. Base Distribution Rate: Amount of USUAL distributed per bUSD0 (formerly USD0++) per day
2. Duration Cost: Adjusts cost based on time window
3. Net Outflows: Considers weekly redemption volume

#### Parameters (Configurable by governance)

* `usualDistributionPerUsd0pp`: Base USUAL distribution rate (per bUSD0, formerly USD0++)
* `durationCostFactor`: Multiplier for time-based cost adjustment
* `targetRedemptionRate`: Target weekly redemption rate (in basis points of total supply)

#### Example Flow

1. User calls `calculateRequiredUsual()` to determine USUAL cost
2. User approves USUAL spend (or uses permit)
3. User calls `unlockUSD0ppWithUsual()` with desired bUSD0 (formerly USD0++) amount and maximum USUAL willing to transfer
4. Contract receive portion of USUAL, increment `accumulatedFees` variable, and returns USD0 to user

The mechanism helps maintain protocol stability by adjusting costs based on redemption volume and ensuring controlled unwinding of bUSD0 (formerly USD0++) positions.

### Peg Maintainer

* `unwrapPegMaintainer(uint256 amount)`: Allows peg maintainers to unwrap liquid staking tokens at any time. Only callable by the `PEG_MAINTAINER_ROLE` role.

### Early Unlock Period

The contract includes functionality for a temporary early unlock period, allowing users to unwrap their liquid staking tokens before the full maturity period under certain conditions. This is a temporary mechanism specifically related to the airdrop

* `setupEarlyUnlockPeriod(uint256 bondEarlyUnlockStart, uint256 bondEarlyUnlockEnd)`: Sets up the early unlock period. Only callable by the `EARLY_BOND_UNLOCK_ROLE` role.
* `temporaryOneToOneExitUnwrap(uint256 amountToUnwrap)`: Allows users to unwrap their bonds during the early unlock period. This voids any USUAL airdrop that they are entitled to
* `allocateEarlyUnlockBalance(address[] calldata addressesToAllocateTo, uint256[] calldata balancesToAllocate)`: Allocates early unlock balances to specific addresses that have accumulated potential airdrop rewards. Only callable by the `EARLY_BOND_UNLOCK_ROLE` role.

### **Regulatory Compliance**

The contract includes a blacklist feature to ensure regulatory compliance. Sanctioned addresses are prevented from interacting with the contract and are kept up to date.

### **Functionality Breakdown**

The contract flow begins with the initialization of liquid staking token parameters and related registry and token information. Liquid staking tokens can be minted, transferred, and unstaked. The contract also allows for emergency withdrawals of the underlying token.

### **Functions Description**

#### **Public/External Functions (non-view / non-pure)**

* `pause()`: Pauses all token transfer operations; callable only by the `PAUSING_CONTRACTS_ROLE`.
* `unpause()`: Resumes all token transfer operations; callable only by the `DEFAULT_ADMIN_ROLE`.
* `setupEarlyUnlockPeriod(uint256 bondEarlyUnlockStart, uint256 bondEarlyUnlockEnd)`: Sets up the early unlock period. Only callable by the `EARLY_BOND_UNLOCK_ROLE` role.
* `mint(uint256 amountUsd0)`: Mints new bonds by locking the specified amount of collateral token.
* `mint(uint256 amountUsd0, address bAssetRecipient, address rAssetRecipient)`: Mints new bonds by locking the specified amount of collateral token. bUSD0 (formerly USD0++) tokens are sent to `bAssetRecipient` and rt-bUSD0 tokens are sent to `rAssetRecipient`, both in a 1:1 ratio with the locked USD0.
* `mintWithPermit(uint256 amountUsd0, uint256 deadline, uint8 v, bytes32 r, bytes32 s)`: Mints new bonds with a permit signature.
* `unwrap()`: Unwraps the bonds and transfers the underlying collateral token to the user.
* `temporaryOneToOneExitUnwrap(uint256 amountToUnwrap)`: Allows users to unwrap their bonds during the early unlock period.
* `allocateEarlyUnlockBalance(address[] calldata addressesToAllocateTo, uint256[] calldata balancesToAllocate)`: Allocates early unlock balances to specific addresses. Only callable by the `EARLY_BOND_UNLOCK_ROLE` role.
* `unwrapPegMaintainer(uint256 amount)`: Allows peg maintainers to unwrap bonds at any time. Only callable by the `PEG_MAINTAINER_ROLE` role.
* `triggerPARMechanismCurvepool(uint256 parUsd0Amount, uint256 minimumPARMechanismGainedAmount)`: Triggers the PAR mechanism in the Curve pool.
* `emergencyWithdraw(address safeAccount)`: Allows for the emergency withdrawal of the underlying collateral token.
* `updateFloorPrice(uint256 newFloorPrice)`: Allows authorized users to update the floor price. Only callable by the `FLOOR_PRICE_UPDATER_ROLE` role.
* `unlockUsd0ppFloorPrice(uint256 usd0ppAmount)`: Allows users to unlock their bUSD0 (formerly USD0++) at the current floor price.
* `transfer(address recipient, uint256 amount)`: Transfers bonds from the sender to the recipient.
* `transferFrom(address sender, address recipient, uint256 amount)`: Transfers bonds from the sender to the recipient on behalf of the sender.

#### View Functions

* `totalBondTimes()`: Returns the total staking duration.
* `getBondEarlyUnlockDisabled(address user)`: Checks if early unlock is disabled for a user.
* `getStartTime()`: Returns the start time of the staking period.
* `getEndTime()`: Returns the end time of the staking period.
* `getFloorPrice()`: Returns the current floor price.
* `getTemporaryUnlockStartTime()`: Returns the start time of the temporary unstaking period.
* `getTemporaryUnlockEndTime()`: Returns the end time of the temporary unstaking period.
* `getAllocationEarlyUnlock(address addressToCheck)`: Returns the early unstaking allocation for an address.
* `getAccumulatedFees()`: Returns the amount of accumulated fees in USUAL of the contract.


# USD0a

### High-Level Overview <a href="#high-level-overview" id="high-level-overview"></a>

The USD0a contract is designed to manage the USD0a ERC20 Token, implementing functionalities for minting, burning, transfer operations, and value accounting while incorporating blacklist checks to restrict these operations to authorized addresses. USD0a is a yield-bearing token that represents a proportional share of the total value of underlying collateral assets. The token's price in USD depends on the prices of the underlying collateral tokens and the total supply of USD0a. USD0a value increases based on the increased value of the underlying collateral assets.

### Contract Summary <a href="#contract-summary" id="contract-summary"></a>

USD0a is an ERC-20 compliant token that integrates additional security, access control, and value accounting features to enhance its governance and usability. It inherits functionalities from `ERC20PausableUpgradeable` and `ERC20PermitUpgradeable` to support permit-based approvals and pausability.

#### Key Characteristics <a href="#key-characteristics" id="key-characteristics"></a>

* **Dynamic Pricing**: The price of USD0a in USD is calculated based on the total value of collateral backing divided by the total supply. The price depends on the prices of the underlying collateral tokens (as provided by the oracle) and the total supply of USD0a. Changes in collateral prices or supply will affect the USD0a price accordingly.
* **Collateral Backing**: USD0a tokens are backed by collateral tokens (such as USCC, USTB, and USDC) held in the collateral treasury. The price reflects the ratio of total collateral value to total supply.

### Minting USD0a <a href="#minting-usd0a" id="minting-usd0a"></a>

Users can swap their collateral tokens via the DaoCollateral contract to mint an equivalent amount of USD0a. The minting process is subject to several checks:

* The amount must not exceed the current mint cap
* The caller must have the `USD0X_MINT` role
* The recipient address must not be blacklisted

The amount of USD0a minted is calculated based on the current USD0a price in USD, which depends on the prices of the underlying collateral tokens and the total supply. The price reflects the current ratio of total collateral value to total supply.

### Redeeming USD0a <a href="#redeeming-usd0a" id="redeeming-usd0a"></a>

Users can swap any USD0a back to the underlying collateral tokens at any time via the DaoCollateral contract, burning the USD0a in the process. The redemption process includes a configurable fee to prevent oracle manipulation attacks. When redeeming, users receive collateral tokens based on the current USD0a price in USD, which reflects the current value of the underlying collateral assets.

### Regulatory Compliance <a href="#regulatory-compliance" id="regulatory-compliance"></a>

The contract includes a blacklist feature to ensure regulatory compliance. Sanctioned addresses are prevented from interacting with the contract, and the list is kept up to date. Blacklisted addresses cannot send or receive USD0a tokens.

### Price Calculation <a href="#price-calculation" id="price-calculation"></a>

The USD0a price in USD is calculated dynamically based on the total value of collateral backing divided by the total supply. The price depends on two main factors:

1. **Collateral Prices**: The prices of the underlying collateral tokens (as provided by the oracle)
2. **Total Supply**: The total number of USD0a tokens in circulation

**Price Calculation:**

* The contract retrieves all collateral tokens from the TokenMapping contract
* For each collateral token, it calculates the USD value: `balance × price` (where price comes from the oracle)
* Sums all collateral USD values to get total collateral backing
* Divides total collateral backing by total supply to get the price per USD0a token

**Price Formula:**

```
USD0a Price = Total Collateral Value / Total Supply
```

The price can increase or decrease depending on:

* Changes in collateral token prices (as reported by the oracle)
* Changes in total supply (from minting or burning)
* Changes in collateral backing (from deposits or withdrawals)

The price can be retrieved with either floor or ceiling rounding using the `getUsd0xPriceInUSD()` function.

### Functionality Breakdown <a href="#functionality-breakdown" id="functionality-breakdown"></a>

#### Key Functionalities <a href="#key-functionalities" id="key-functionalities"></a>

* **Minting**: Tokens can be minted to a non-blacklisted address, subject to role checks and mint cap requirements.
* **Burning**: Tokens can be burned from an address, subject to role checks.
* **Transfers**: Only non-blacklisted addresses can send or receive tokens.
* **Harvest Mechanism:** The harvest function calculates the amount to mint based on the configured Annual Percentage Yield (APY) and daily harvest fee, reflecting the value that has been generated by the underlying collateral assets. Harvest can only be executed once per day (enforced by `HARVEST_FREQUENCY`).
* **Mint Cap Management**: The contract implements a mint cap that can be adjusted by authorized roles.
* **Value Accounting**: The contract implements a harvest mechanism that accounts for increased collateral value by minting USD0a tokens to the yield treasury based on configured APY and daily harvest fee.
* **Dynamic Pricing**: The contract calculates the USD0a price in USD based on collateral backing and total supply.

### Functions Description <a href="#functions-description" id="functions-description"></a>

#### Public/External Functions <a href="#publicexternal-functions" id="publicexternal-functions"></a>

* **`pause()`**: Pauses all token transfer operations; callable only by the `PAUSING_CONTRACTS_ROLE`.
* **`unpause()`**: Resumes all token transfer operations; callable only by the `UNPAUSING_CONTRACTS_ROLE`.
* **`mint(address to, uint256 amount)`**: Mints tokens to a non-blacklisted address if the caller has the `USD0X_MINT` role and the mint cap is not exceeded.
* **`burn(uint256 amount)`** and **`burnFrom(address account, uint256 amount)`**: Burns tokens from an address, requiring the `USD0X_BURN` role.
* **`setMintCap(uint256 newMintCap)`**: Updates the maximum amount of USD0a that can be minted; callable only by the `MINT_CAP_OPERATOR` role. The new mint cap must be greater than or equal to the current total supply.
* **`getMintCap()`**: Returns the current mint cap for USD0a.
* **`blacklist(address account)`** and **`unblacklist(address account)`**: Allows the admin to blacklist or remove from blacklist malicious users from using this token. Only callable by the `BLACKLIST_ROLE`.
* **`isBlacklisted(address account)`**: Checks if an address is blacklisted.
* **`harvest()`**: Only callable by `USD0X_HARVEST_OPERATOR_ROLE`. Can only be called once per day (enforced by `HARVEST_FREQUENCY`).
* **`setDailyHarvestFee(uint256 newDailyHarvestFee)`**: Sets the daily harvest fee (in basis points). Only callable by `USD0X_HARVEST_FEE_OPERATOR_ROLE`. Maximum allowed is 25% (2500 basis points).
* **`setAnnualPercentageYield(uint256 newAnnualPercentageYield)`**: Sets the annual percentage yield (in basis points). Only callable by `USD0X_HARVEST_APY_OPERATOR_ROLE`. Maximum allowed is 100% (10000 basis points).
* **`getUsd0xPriceInUSD(bool roundingUp)`**: Returns the USD price of 1 USD0a token based on collateral backing. The price is calculated as total collateral value divided by total supply. Can return with floor or ceiling rounding.
* **`getDailyHarvestFee()`**: Returns the current daily harvest fee in basis points.
* **`getAnnualPercentageYield()`**: Returns the current annual percentage yield in basis points.

### Role-Based Access Control <a href="#role-based-access-control" id="role-based-access-control"></a>

The contract implements several roles for different operations:

* **USD0X\_MINT**: Required for minting new tokens
* **USD0X\_BURN**: Required for burning tokens
* **BLACKLIST\_ROLE**: Required for managing the blacklist
* **MINT\_CAP\_OPERATOR**: Required for adjusting the mint cap
* **PAUSING\_CONTRACTS\_ROLE**: Required for pausing the contract
* **UNPAUSING\_CONTRACTS\_ROLE**: Required for unpausing the contract
* **USD0X\_HARVEST\_OPERATOR\_ROLE**: Required for executing the harvest function
* **USD0X\_HARVEST\_FEE\_OPERATOR\_ROLE**: Required for setting the daily harvest fee
* **USD0X\_HARVEST\_APY\_OPERATOR\_ROLE**: Required for setting the annual percentage yield

### Safeguards Implementation <a href="#safeguards-implementation" id="safeguards-implementation"></a>

* **Pausability**: Allows pausing of all token transfers in emergencies
* **Blacklist**: Prevents sanctioned addresses from interacting with the token
* **Mint Cap**: Limits the maximum supply of USD0a
* **Role-Based Access**: Restricts sensitive operations to authorized roles
* **Harvest Frequency Limit**: Prevents harvest from being called too frequently (minimum 1 day - 60 seconds between harvests)
* **Harvest Fee Limits**: Maximum daily harvest fee is capped at 25% (2500 basis points)
* **APY Limits**: Maximum annual percentage yield is capped at 100% (10000 basis points)
* **Mint Cap Validation**: Ensures new mint cap is not smaller than current total supply

### Key Components <a href="#key-components" id="key-components"></a>

* **Oracle Integration**: Uses an oracle to fetch real-time price data for collateral tokens when calculating USD0a price.
* **Token Mapping**: Manages the list of supported collateral tokens through the TokenMapping contract.
* **Access Control**: Implements role-based access control for administrative functions through the RegistryAccess contract.
* **Yield Treasury**: Receives minted USD0a tokens from the harvest mechanism, which accounts for increased collateral value and benefits all USD0a holders proportionally.
* **Collateral Treasury**: Holds the collateral tokens that back USD0a tokens


# ETH0

## High-Level Overview

The ETH0 contract is designed to manage the ETH0 ERC20 Token, implementing functionalities for minting, burning, and transfer operations while incorporating blacklist checks to restrict these operations to authorized addresses. The total ETH0 supply is collateralized with at minimum 1:1 in collateral tokens, ensuring the stability and security of the protocol.

## Contract Summary

ETH0 is an ERC-20 compliant token that integrates additional security and access control features to enhance its governance and usability. It inherits functionalities from ERC20PausableUpgradable and ERC20PermitUpgradeable to support permit-based approvals and pausability.

### Minting ETH0

Users can swap their collateral tokens via the DaoCollateral contract to mint an equivalent amount of ETH0. The minting process is subject to several checks:

* The amount must not exceed the current mint cap
* The total supply after minting must not exceed the total collateral backing
* The caller must have the ETH0\_MINT role

### Redeeming ETH0

Users can swap any ETH0 back to the underlying collateral tokens at any time via the DaoCollateral contract, burning the ETH0 in the process. The redemption process includes a configurable fee to prevent oracle manipulation attacks.

### Regulatory Compliance

The contract includes a blacklist feature to ensure regulatory compliance. Sanctioned addresses are prevented from interacting with the contract, and the list is kept up to date.

### Collateralization Enforcement

Minting of ETH0 is only possible if the total collateral backing equals or exceeds the ETH0 totalSupply(). The contract verifies this by:

* Checking the balance of all collateral tokens in the treasury
* Converting collateral amounts to ETH using oracle prices
* Ensuring the total collateral value in ETH exceeds the new total supply

### Functionality Breakdown

Key Functionalities

* **Minting**: Tokens can be minted to an address, subject to role checks and collateralization requirements.
* **Burning**: Tokens can be burned from an address, subject to role checks.
* **Transfers**: Only non-blacklisted addresses can send or receive tokens.
* **Mint Cap Management**: The contract implements a mint cap that can be adjusted by authorized roles.

### Functions Description

Public/External Functions

* `pause()`: Pauses all token transfer operations; callable only by the PAUSING\_CONTRACTS\_ROLE.
* `unpause()`: Resumes all token transfer operations; callable only by the UNPAUSING\_CONTRACTS\_ROLE.
* `mint(address to, uint256 amount)`: Mints tokens to a non-blacklisted address if the caller has the ETH0\_MINT role and collateralization requirements are met.
* `burn(uint256 amount)` and `burnFrom(address account, uint256 amount)`: Burns tokens from an address, requiring the ETH0\_BURN role.
* `setMintCap(uint256 newMintCap)`: Updates the maximum amount of ETH0 that can be minted; callable only by the MINT\_CAP\_OPERATOR role.
* `getMintCap()`: Returns the current mint cap for ETH0.
* `blacklist(address account)` and `unBlacklist(address account)`: Allows the admin to blacklist or remove from blacklist malicious users from using this token. Only callable by the BLACKLIST\_ROLE.
* `isBlacklisted(address account)`: Checks if an address is blacklisted.

### Role-Based Access Control

The contract implements several roles for different operations:

* `ETH0_MINT`: Required for minting new tokens
* `ETH0_BURN`: Required for burning tokens
* `BLACKLIST_ROLE`: Required for managing the blacklist
* `MINT_CAP_OPERATOR`: Required for adjusting the mint cap
* `PAUSING_CONTRACTS_ROLE`: Required for pausing the contract
* `UNPAUSING_CONTRACTS_ROLE`: Required for unpausing the contract

### Safeguards Implementation

* **Pausability**: Allows pausing of all token transfers in emergencies
* **Blacklist**: Prevents sanctioned addresses from interacting with the token
* **Mint Cap**: Limits the maximum supply of ETH0
* **Collateralization Check**: Ensures ETH0 remains fully backed by collateral
* **Role-Based Access**: Restricts sensitive operations to authorized roles


# EUR0

### High-Level Overview

The EUR0 contract is designed to manage the EUR0 ERC20 Token, implementing functionalities for minting, burning, and transfer operations while incorporating blacklist checks to restrict these operations to authorized addresses. The total EUR0 supply is collateralized with at minimum 1:1 in Euro-denominated collateral tokens, ensuring the stability and security of the protocol.

### Contract Summary

EUR0 is an ERC-20 compliant token that integrates additional security and access control features to enhance its governance and usability. It inherits functionalities from `ERC20PausableUpgradeable` and `ERC20PermitUpgradeable` to support permit-based approvals and pausability.

#### Minting EUR0

Users can swap their Euro collateral tokens via the DaoCollateral contract to mint an equivalent amount of EUR0. The minting process is subject to several checks:

* The amount must not exceed the current collateral backing
* The total supply after minting must not exceed the total collateral backing
* The caller must have the `EUR0_MINT` role

#### Redeeming EUR0

Users can swap any EUR0 back to the underlying Euro collateral tokens at any time via the DaoCollateral contract, burning the EUR0 in the process. The redemption process includes a configurable fee to prevent oracle manipulation attacks.

#### Regulatory Compliance

The contract includes a blacklist feature to ensure regulatory compliance. Sanctioned addresses are prevented from interacting with the contract, and the list is kept up to date.

#### Collateralization Enforcement

Minting of EUR0 is only possible if the total collateral backing equals or exceeds the EUR0 `totalSupply()`. The contract verifies this by:

* Checking the balance of all Euro collateral tokens in the treasury
* Converting collateral amounts to EUR using oracle prices
* Ensuring the total collateral value in EUR exceeds the new total supply

### Functionality Breakdown

#### Key Functionalities

* **Minting**: Tokens can be minted to an address, subject to role checks and collateralization requirements.
* **Burning**: Tokens can be burned from an address, subject to role checks.
* **Transfers**: Only non-blacklisted addresses can send or receive tokens.
* **Blacklist Management**: The contract implements a blacklist system for regulatory compliance.

### Functions Description

#### Public/External Functions

* **`pause()`**: Pauses all token transfer operations; callable only by the `PAUSING_CONTRACTS_ROLE`.
* **`unpause()`**: Resumes all token transfer operations; callable only by the `UNPAUSING_CONTRACTS_ROLE`.
* **`mint(address to, uint256 amount)`**: Mints tokens to a non-blacklisted address if the caller has the `EUR0_MINT` role and collateralization requirements are met.
* **`burn(uint256 amount)`** and **`burnFrom(address account, uint256 amount)`**: Burns tokens from an address, requiring the `EUR0_BURN` role.
* **`blacklist(address account)`** and **`unBlacklist(address account)`**: Allows the admin to blacklist or remove from blacklist malicious users from using this token. Only callable by the `BLACKLIST_ROLE`.
* **`isBlacklisted(address account)`**: Checks if an address is blacklisted.

### Role-Based Access Control

The contract implements several roles for different operations:

* **`EUR0_MINT`**: Required for minting new tokens
* **`EUR0_BURN`**: Required for burning tokens
* **`BLACKLIST_ROLE`**: Required for managing the blacklist
* **`PAUSING_CONTRACTS_ROLE`**: Required for pausing the contract
* **`UNPAUSING_CONTRACTS_ROLE`**: Required for unpausing the contract

### Safeguards Implementation

* **Pausability**: Allows pausing of all token transfers in emergencies
* **Blacklist**: Prevents sanctioned addresses from interacting with the token
* **Collateralization Check**: Ensures EUR0 remains fully backed by Euro collateral
* **Role-Based Access**: Restricts sensitive operations to authorized roles

### Security Features

#### Blacklist Mechanism

The contract implements a comprehensive blacklist system that prevents blacklisted addresses from:

* Sending tokens (from address is blacklisted)
* Receiving tokens (to address is blacklisted)
* Any transfer operations involving blacklisted addresses

#### Collateralization Verification

The minting process includes real-time collateralization verification:

* Fetches all supported Euro collateral tokens from the token mapping
* Calculates the total value of collateral in EUR using oracle prices
* Ensures the new total supply does not exceed the collateral backing
* Prevents over-minting that would compromise the 1:1 collateralization ratio

#### Access Control

All critical functions are protected by role-based access control:

* Only authorized roles can mint, burn, pause, or manage blacklists
* Prevents unauthorized manipulation of token supply
* Ensures regulatory compliance through controlled blacklist management


# USUAL

### High-Level Overview

This section provides an overview of the USUAL smart contract. The USUAL contract is designed to manage the USUAL ERC20 Token, implementing functionalities for minting, burning, and transfer operations while incorporating blacklist checks to restrict these operations from sanctioned addresses.

### Contract Summary

USUAL is an ERC-20 compliant token that integrates additional security and access control features to enhance its governance and usability. It inherits functionalities from ERC20PausableUpgradable and ERC20PermitUpgradeable to support permit-based approvals and pausability.

#### Inherited Contracts

* **ERC20PausableUpgradeable**: Extends ERC20 to support pausability
* **ERC20PermitUpgradeable**: Extends ERC20 to support gasless transactions through signed approvals.

#### ERC20PausableUpgradeable

Standard OpenZeppelin Implementation.

#### ERC20PermitUpgradeable

Standard OpenZeppelin Implementation.

### Functions Description

#### Public/External Functions

* **pause()**: Pauses all token transfer operations; callable only by the PAUSING\_CONTRACTS\_ROLE.
* **unpause()**: Resumes all token transfer operations; also callable only by the DEFAULT\_ADMIN\_ROLE.
* **transfer(address to, uint256 amount)**: Transfers tokens to a non-sanctioned address.
* **transferFrom(address sender, address to, uint256 amount)**: Transfers tokens from one non-sanctioned address to another.
* **mint(address to, uint256 amount)**: Mints tokens to a non-sanctioned address if the caller has the USUAL\_MINT role.
* **burn(uint256 amount)** and **burnFrom(address account, uint256 amount)**: Burns tokens from an address, requiring the USUAL\_BURN role.
* **blacklist(address account)** and **unBlacklist(address account)**: Those functions allows the admin to blacklist or remove from blacklist malicious users from using this token. Only callable by the BLACKLIST\_ROLE.

### Functionality Breakdown

#### SC-Flows

<figure><img src="/files/HNvh876j62AFykd30doA" alt=""><figcaption></figcaption></figure>

#### Key Functionalities

* **Minting**: Tokens can be minted to an address, subject to role checks.
* **Burning**: Tokens can be burned from an address, also subject to role checks.
* **Transfers**: Only not sanctioned addresses can send or receive tokens.

### Constants

* **CONTRACT\_REGISTRY\_ACCESS**: This constant is used to define the address of the registry access contract
* **DEFAULT\_ADMIN\_ROLE**: This constant is used to define the default admin role for the contract.
* **PAUSING\_CONTRACTS\_ROLE**: Role required to pause the contract.
* **BLACKLIST\_ROLE**: Role required to blacklist an address.
* **USUAL\_MINT**: Role required to mint new tokens.
* **USUAL\_BURN**: Role required to burn tokens.

### Safeguards Implementation

* **Pausability**: Ensures that token transfers can be halted in case of emergency.
* **Role-Based Access Control**: Restricts sensitive actions to addresses with appropriate roles.
* **Blacklist Enforcement**: Ensures that only non-malicious addresses can participate in the token economy.


# USUAL\*

### High-Level Overview

This section provides an overview of the UsualS smart contract. The UsualS contract is designed to manage the USUALS ERC20 token, implementing essential functionalities for minting, burning, and transferring tokens, along with additional layers of control and security. The contract integrates role-based access control through a registry system, ensuring that only authorized entities can perform sensitive operations such as pausing the contract or blacklisting addresses

### Contract Summary

#### Inherited Contracts

* **ERC20PausableUpgradeable**: Extends ERC20 to support pausability
* **ERC20PermitUpgradeable**: Extends ERC20 to support gasless transactions through signed approvals.

#### ERC20PausableUpgradeable

Standard OpenZeppelin Implementation.

#### ERC20PermitUpgradeable

Standard OpenZeppelin Implementation.

### Functionality Breakdown

#### SC-Flows

<figure><img src="/files/fRIxYRS2hAvINbbDKE8u" alt=""><figcaption></figcaption></figure>

#### Key Functionalities

* **Minting**: Tokens can be minted to an address, subject to role checks.
* **Burning**: Tokens can be burned from an address, also subject to role checks.
* **Transfers**: Tokens can be sent or receive. Will revert if blacklisted.

### Functions Description

#### Public/External Functions

* **pause()**: Pauses all token transfer operations; callable only by the PAUSING\_CONTRACTS\_ROLE.
* **unpause()**: Resumes all token transfer operations; also callable only by the DEFAULT\_ADMIN\_ROLE.
* **transfer(address to, uint256 amount)**: Transfers tokens to a non-blacklisted address.
* **transferFrom(address sender, address to, uint256 amount)**: Transfers tokens from one non-blacklisted address to another.
* **burn(uint256 amount)** and **burnFrom(address account, uint256 amount)**: Burns tokens from an address, requiring the USUALS\_BURN role.
* **blacklist(address account)** and **unBlacklist(address account)**: Those functions allows the admin to blacklist or remove from blacklist malicious users from using this token. Only callable by the BLACKLIST\_ROLE.
* **stakeAll()** : Sends the total supply of **USUALS** to the staking contract. Only callable by the `USUALSP` contract.
* **isBlacklisted()**: Returns true if the account is blacklisted.

### Constants

* **CONTRACT\_REGISTRY\_ACCESS**: Registry access contract address.
* **DEFAULT\_ADMIN\_ROLE**: Default admin role.
* **PAUSING\_CONTRACTS\_ROLE**: Role required to pause the contract.
* **BLACKLIST\_ROLE**: Role required to blacklist an address.
* **USUALS\_BURN**: Role required to burn tokens.

### Safeguards Implementation

* **Pausability**: Ensures that token transfers can be halted in case of emergency.
* **Role-Based Access Control**: Restricts sensitive actions to addresses with appropriate roles.
* **Blacklist Enforcement**: Ensures that unauthorized addresses can't participate in the token economy.

###


# USUALx

### High-Level Overview

The UsualX contract is an upgradeable ERC4626-compliant yield-bearing vault. It extends the YieldBearingVaultUpgradeable contract, incorporating features such as whitelisting, blacklisting, withdrawal fees, and yield distribution linearly over a predefined yield period. The contract leverages OpenZeppelin's upgradeable contracts for enhanced security and flexibility, including pausability and reentrancy protection. It also implements EIP712 for secure off-chain signing capabilities.

The primary objective of Usualx is to provide a secure, controllable environment for yield generation and distribution, while maintaining strict control over who can interact with the contract. This design allows for potential regulatory compliance and risk management in decentralized finance applications.

### Contract Summary

The contract provides the following main functions:

* `initialize`: Sets up the contract with customizable parameters.
* `initializeV1`: Sets up the contract with new customizable parameters.
* `initializeV2`: Sets up the contract with the UsualX lockup mecanism.
* `pause` / `unpause`: Controls the operational state of the contract.
* `blacklist` / `unBlacklist`: Manages addresses prohibited from interacting with the contract.
* `whitelist` / `unWhitelist`: Controls addresses permitted to transfer tokens.
* `transfer` / `transferFrom`: Overridden to enforce whitelist restrictions.
* `startYieldDistribution`: Initiates a new yield accrual period with specified parameters.
* `deposit` / `mint`: Handles asset deposits and share minting.
* `depositAndLock`: To deposit assets and immediately locking the received shares
* `withdraw` / `redeem`: Handles asset withdrawals and share redemptions, incorporating withdrawal fees.
* `previewWithdraw` / `previewRedeem`: Simulates withdrawal and redemption operations for users. The contract uses a separate storage structure (UsualXStorageV0) to store state variables for UsualX implementation.
* `sweepFees`: Sweeps accumulated fees to the distribution module contract.

### Inherited Contracts

* YieldBearingVaultUpgradeable: Provides core yield accrual and distribution mechanisms.
* PausableUpgradeable: Enables emergency halt of contract operations.
* ReentrancyGuardUpgradeable: Prevents reentrancy attacks in critical functions.
* EIP712Upgradeable: Implements EIP712 for secure off-chain message signing.

### Functionality Breakdown

1. Access Control and Security:
   * Utilizes a registry contract for role-based access control.
   * Implements blacklist to prevent specific addresses from interacting with the contract.

* Enforces whitelist for token transfers, allowing only approved addresses to transfer tokens at launch but anyone not blacklisted to mint or interact with the vault.

2. Yield Management:

   * Allows admin-controlled yield distribution periods.
   * Accrues yield over time based on configurable parameters.
   * Integrates yield accrual with deposit and withdrawal operations.

3. Asset Management:

   * Implements ERC4626 standard for standardized vault interactions.
   * Handles deposits, withdrawals, and redemptions with consideration for accrued yield.
   * Applies withdrawal fees, potentially for protocol revenue or discouraging rapid withdrawals.
   * Implements a way to deposit some assets and lock received shares in the same transaction.

4. Upgradability and Pause Mechanism:
   * Utilizes OpenZeppelin's upgradeable contract pattern for future improvements.
   * Includes pause functionality for emergency situations.

### Security Analysis

#### Method: initialize

Initializes the vault, token, yield module, EIP712 domain, registry contract and access control, setting up the vault's initial state.

```solidity
 1  function initialize(
 2      address _registryContract,
 3      uint256 _withdrawFeeBps,
 4      string memory _name,
 5      string memory _symbol,
 6      IERC20 _underlying,
 7      uint256 _maxPeriodLength
 8  ) external initializer {
 9      __YieldBearingVault_init(_maxPeriodLength);
10      __ERC4626_init(_underlying);
11      __ERC20_init(_name, _symbol);
12      __Pausable_init_unchained();
13      __ReentrancyGuard_init();
14      __EIP712_init_unchained(_name, "1");
15  
16      if (_withdrawFeeBps > MAX_WITHDRAW_FEE) {
17          revert AmountTooBig();
18      }
19  
20      if (_registryContract == address(0)) {
21          revert NullContract();
22      }
23  
24      UsualXStorageV0 storage $ = _usualXStorageV0();
25      $.withdrawFeeBps = _withdrawFeeBps;
26      $.registryContract = IRegistryContract(_registryContract);
27      $.registryAccess = IRegistryAccess($.registryContract.getContract(CONTRACT_REGISTRY_ACCESS));
28  }
```

1-8. Set the registry contract, withdrawal fee in BPS, token name and symbol for the vault, underlying asset, and the max yield period length.

9-14. Initializes inherited contracts, with initializer parameters.

16-18. Validates withdrawal fee is below 25% preventing excessive fees that could harm users.

20-22. Ensures a valid registry contract, reverts if zero address.

24-26. Sets up contract storage with validated parameter.

27. Points at the access control registry in the registry contract.

#### Method: initializeV1 (decrepated)

Initializes the burn ration in bips and a variable linked to the USUAL token.

```solidity
1 function initializeV1() public reinitializer(2) {
2    UsualXStorageV0 storage $ = _usualXStorageV0();
3    if (INITIAL_BURN_RATIO_BPS > BASIS_POINT_BASE) {
4        revert AmountTooBig();
5    }
6    $.burnRatioBps = INITIAL_BURN_RATIO_BPS;
7    $.usualToken = IUsual($.registryContract.getContract(CONTRACT_USUAL));
8    emit BurnRatioUpdated($.burnRatioBps);
9 }
```

1\. Uses the `reintializer` modifier to set the second version of the the initialize function.

2\. Load the contract storage.

3-5. Validates `INITIAL_BURN_RATIO_BPS` constant isns't higher 100% preventing excessive burning fees.

6-7. Sets up contract storage with validated parameter.

8\. Emits an event with the new burn ration.

#### Method: initializeV2&#x20;

Initializes the UsualX Lockup contract.

```solidity
1 function initializeV2() external reinitializer(3) {
2     UsualXStorageV0 storage $ = _usualXStorageV0();
3     $.usualXLockup = IUsualXLockup($.registryContract.getContract(CONTRACT_USUALX_LOCKUP));
4 }
```

1\. Uses the `reintializer` modifier to set the third version of the the initialize function.

2\. Load the contract storage.

3\. Assign the UsualXLockup contract to a new variable.

#### Method: blacklist

Adds an address to the blacklist, preventing it from interacting with the contract.

```solidity
 1  function blacklist(address account) external {
 2      if (account == address(0)) {
 3          revert NullAddress();
 4      }
 5      UsualXStorageV0 storage $ = _usualXStorageV0();
 6      $.registryAccess.onlyMatchingRole(DEFAULT_ADMIN_ROLE);
 7      if ($.isBlacklisted[account]) {
 8          revert SameValue();
 9      }
10      $.isBlacklisted[account] = true;
11  
12      emit Blacklist(account);
13  }
```

1. Mark function as external to save gas.&#x20;

2-4. Prevents blacklisting of zero address, and reverts if trying to pass zero address.

5-6. Utilizes the registry for role-based access control, restricting to admin.

7-9. Reverts if the account is already blacklisted.

10. Adds the account to the blacklist in UsualXStorageV0.
11. Emits an event to log the blacklisting action.

#### Method: \_update

Internal hook ensuring that both sender and receiver are not blacklisted before updating the token balances.

```solidity
 1  function _update(address from, address to, uint256 amount)
 2      internal
 3      override(ERC20Upgradeable)
 4  {
 5      UsualXStorageV0 storage $ = _usualXStorageV0();
 6      if ($.isBlacklisted[from] || $.isBlacklisted[to]) {
 7          revert Blacklisted();
 8      }
 9      super._update(from, to, amount);
10  }
```

1-4. Internal function overriding the base ERC20Upgradeable implementation.

5. Retrieves storage pointer for UsualXStorageV0. 6-8. Checks both sender and receiver against blacklist, reverting if either is blacklisted.
6. Passes through to parent implementation if checks pass.

#### Method: transfer

Overrides the standard ERC20 transfer function to enforce whitelist restrictions on token transfers when the contract is deployed. This can later be removed via smart contract upgrade.

```solidity
 1  function transfer(address to, uint256 value)
 2      public
 3      override(ERC20Upgradeable, IERC20)
 4      returns (bool)
 5  {
 6      address owner = _msgSender();
 7      UsualXStorageV0 storage $ = _usualXStorageV0();
 8      if ($.isWhitelisted[owner]) {
 9          _transfer(owner, to, value);
10          return true;
11      }
12      revert NotWhitelisted();
13  }
```

1-5. Public function overriding ERC20 transfer base implementation.

6-7. Uses `_msgSender()` for potential meta-transaction support, and retrieve storage pointer.

8-11. Allows whitelisted senders to transfer tokens, otherwise reverts.

12. Reverts if sender is not whitelisted.

Security considerations:

* Correctly enforces whitelist for senders, but doesn't check recipient's whitelist status.
* Consider adding a check for the contract's paused state.
* The function doesn't emit a custom event for whitelisted transfers, which could aid in monitoring.

#### Method: startYieldDistribution

Initiates a new yield distribution period with specified parameters wrapping the internal call to add proper access control.

```solidity
 1  function startYieldDistribution(uint256 yieldAmount, uint256 startTime, uint256 endTime)
 2      external
 3  {
 4      _requireOnlyAdmin();
 5      _startYieldDistribution(yieldAmount, startTime, endTime);
 6  }
```

1-3. External function for starting a new yield period.

4. Ensures only admin set on registry access can call this function.
5. Delegates to internal function for yield distribution logic.

#### Method: depositAndLock

Combines deposit and lock operations into a single atomic transaction, allowing users to deposit assets and immediately lock the resulting shares.

```solidity
 1  function depositAndLock(uint256 assets, address receiver, uint256 lockDuration)
 2      public
 3      override
 4      whenNotPaused
 5      returns (uint256 shares)
 6  {
 7      UsualXStorageV0 storage $ = _usualXStorageV0();
 8      shares = deposit(assets, address(this));
 9      _approve(address(this), address($.usualXLockup), shares);
10      $.usualXLockup.lock(receiver, shares, lockDuration);
11      return shares;
12  }
```

1-6. Public function marked as `whenNotPaused` to prevent its usage if contract is paused

7\. Retrieves storage pointers for UsualXStorageV0

8\. Deposits assets into the vault, but instead of sending shares directly to the receiver, they are minted to the contract itself

9\. Approves the UsualXLockup contract to transfer the newly minted shares from the UsualX contract

10\. Calls the lock function on the UsualXLockup contract to lock the shares for the specified duration, with the receiver as the beneficiary.

11\. Returns the number of shares that were minted and locked

#### Method: withdraw

Overrides the ERC4626 withdraw function to include withdrawal fees and enforce withdrawal limits, calculates shares internally to avoid another storage fetch from calling previewWithdraw.

```solidity
 1  function withdraw(uint256 assets, address receiver, address owner)
 2      public
 3      override
 4      returns (uint256 shares)
 5  {
 6      UsualXStorageV0 storage $ = _usualXStorageV0();
 7      YieldDataStorage storage yieldStorage = _getYieldDataStorage();
 8  
 9      uint256 maxAssets = maxWithdraw(owner);
10      if (assets > maxAssets) {
11          revert ERC4626ExceededMaxWithdraw(owner, assets, maxAssets);
12      }
13  
14      uint256 fee = Math.mulDiv(assets, $.withdrawFeeBps, BPS_DENOMINATOR, Math.Rounding.Floor);
15      uint256 assetsWithFee = assets + fee;
16  
17      shares = convertToShares(assetsWithFee);
18  
19      yieldStorage.totalDeposits -= fee;
20  
21      super._withdraw(_msgSender(), receiver, owner, assets, shares);
22  }
```

1-5. Public function overriding the ERC4626 withdraw function.

6-7. Retrieves storage pointers for UsualXStorageV0 and YieldDataStorage.

9-12. Checks if the withdrawal amount exceeds the maximum allowed, and reverts if so.

14-15. Calculates the withdrawal fee based on the number of assets user wants to withdraw taking the precision into account.

17. Converts assets to shares, considering the fee.
18. Deducts the fee from the total deposits in the yield storage.
19. Calls parent withdrawal function with calculated values.

#### Method: sweepFees

Sweeps accumulated fees to the specified collector address, optionally burning a portion of the fees based on the burn ratio. Enforces non-reentrancy, role-based access control, and validates input.

```solidity
1 function sweepFees() external nonReentrant returns (uint256) {
2    UsualXStorageV0 storage $ = _usualXStorageV0();
3    $.registryAccess.onlyMatchingRole(FEE_SWEEPER_ROLE);
4
5    address distributionModule = $.registryContract.getContract(CONTRACT_DISTRIBUTION_MODULE);
6
7    uint256 feesToSweep = $.accumulatedFees;
8    if (feesToSweep == 0) {
9        return 0;
10    }
11
12    $.accumulatedFees = 0;
13
14    $.usualToken.safeTransfer(distributionModule, feesToSweep);
15
16    emit FeeSwept(msg.sender, distributionModule, feesToSweep);
17    return feesToSweep;
18 }
```

1\. A public external function marked as `nonReentrant` to prevent reentrancy attacks.

2-3. Retrieves storage pointer for `UsualXStorageV0` and validates that the caller has the `FEE_SWEEPER_ROLE` permission.

5\. Get the Distribution Module contract.

7-10. Get the accumulated fees. Return 0 if no fees.

12\. Reset the `accumulatedFees` variable.

14\. Transfer fees to the Distribution Module contract.

16\. Emits a `FeeSwept` event with the caller address, the distribution module address, and amount of fees swept.


# Usual bUSD0 Investment Vault

### High-Level Overview

The WrappedDollarVault contract is an upgradeable ERC4626-compliant yield-bearing vault. The contract leverages OpenZeppelin's upgradeable contracts for enhanced security and flexibility, including pausability and reentrancy protection.

The vault holds another USD-denominated ERC4626 and allows users to deposit and withdraw this token, with fees accrued in USD, and a monotonic increase in USD value per share only, rather than a monotonic increase in assets or share. The price in units of asset decreases over time due to fees accruing.

Only the registered router via the setRouter() function can call deposit, mint, withdraw, redeem . The goal of the router is to allow for swaps and permits for approvals, ensuring that arbitrary\
tokens are accepted as input and bUSD0 is accepted as output.

The primary objective of the investment vault is to have a generic contract to allow wrapping of yield bearing token from external strategies without leaving the Usual ecosystem.

### Contract Summary

The contract provides the following main functions:

* `pause`: Pause the vault's functionality.
* `unpause`: Unpause the vault's functionality.
* `setRouter`: Add or remove a router.
* `setFeeRateBps`: Set the fee rate in basis points.
* `harvest`: Harvest management fees by minting shares to the treasury.
* `feeRateBps`: Returns the fee rate in basis points.
* `getRouterState`: Returns the state of a router.
* `decimals`: Returns the number of decimals of the vault.
* `withdraw` / `redeem`: Handles asset withdrawals and share redemptions, incorporating withdrawal fees.
* `mint` / `deposit` : Handles depositing asset and mint shares of the vault
* `previewWithdraw` / `previewRedeem`: Simulates withdrawal and redemption operations for users.

### Inherited Contracts

* **PausableUpgradeable**: Enables emergency halt of contract operations.
* **ReentrancyGuardUpgradeable**: Prevents reentrancy attacks in critical functions.
* **ERC20PermitUpgradeable**: Extends ERC20 to support gasless transactions through signed
* **ERC4626Upgradable**: Provide a standard implementation for ERC4626 vault.

### Functionality Breakdown

1. Access Control and Security:
   * Utilizes a registry contract for role-based access control.
   * Implements specific role to set router *`VAULT_SET_ROUTER_ROLE`*, set fee `VAULT_SET_FEE_ROLE` and harvest `VAULT_HARVESTER_ROLE` to prevent specific addresses from interacting with the contract.
   * Enforces router registration for all the creation and destruction of vault shares, allowing only previously set router addresses to interact with the vault.
2. Fee Management:
   * Allows admin-controlled daily harvest of fee to the treasury.
   * Accrues fees over time based on configurable parameters. Fees are due when withdrawing and redeeming
   * The number of underlying assets behind a share decreases over time due to fee accruing.
3. Asset Management:
   * Implements ERC4626 standard for standardized vault interactions.
   * Handles withdrawals, and redemption with consideration for accrued fees.
   * Asset is yield bearing so its USD value will increase overtime.
4. Upgradability and Pause Mechanism:
   * Utilizes OpenZeppelin's upgradeable contract pattern for future improvements.
   * Includes pause functionality for emergency situations.

### Security Analysis

#### Method: initialize

Initializes the vault, setting up the registry contract, underlying asset, name, symbol, and initial vault state.

{% code lineNumbers="true" %}

```solidity
    function initialize(
        address registryContract_,
        address underlyingAsset_,
        string memory name_,
        string memory symbol_
    )
        public
        initializer
    {
        if (registryContract_ == address(0) || underlyingAsset_ == address(0)) {
            revert NullAddress();
        }
        __ReentrancyGuard_init();
        __ERC20_init(name_, symbol_);
        __ERC20Permit_init(name_);
        __ERC20Pausable_init();
        __ERC4626_init(IERC20(underlyingAsset_));
        WrappedDollarVaultStorageV0 storage $ = _wrappedDollarVaultStorageV0();
        $.registryContract = IRegistryContract(registryContract_);
        $.registryAccess = IRegistryAccess(
            $.registryContract.getContract(CONTRACT_REGISTRY_ACCESS)
        );
        $.treasury = $.registryContract.getContract(CONTRACT_YIELD_TREASURY);
        $.feeRateBps = DEFAULT_FEE_RATE_BPS;
        $.lastFeeRateUpdateTimestamp = block.timestamp;
        _mint(DEAD_ADDRESS, INITIAL_SHARES_SUPPLY);
    }
```

{% endcode %}

11-12. Ensures valid registry contract and underlying asset addresses, reverting if either is zero to prevent null references.

13. Initializes inherited contracts for reentrancy protection

14-15. ERC20 functionality sets the vault name, symbol and permit support.

16-17. Pausability, and ERC4626 vault standards with the underlying asset.

19-22. Sets up contract storage with the registry contract, access control from the registry.

23-26. treasury address, default fee rate, last fee update timestamp, and mints initial shares to a dead address.

***

#### Method: setRouter

Add or disable a router, updating its active state.

{% code lineNumbers="true" %}

```solidity
    function setRouter(address router, bool isActive) public whenNotPaused {
        WrappedDollarVaultStorageV0 storage $ = _wrappedDollarVaultStorageV0();
        if (!$.registryAccess.hasRole(VAULT_SET_ROUTER_ROLE, _msgSender())) {
            revert NotAuthorized();
        }
        if (router == address(0)) revert NullAddress();
        if ($.routers[router] == isActive) {
            revert SameRouterActivity(router, isActive);
        }

        $.routers[router] = isActive;
        emit RouterUpdated(router, isActive);
    }
```

{% endcode %}

1\. Sets the router address is only callable when the vault is not paused.\
3-4. Checks that the caller has the `VAULT_SET_ROUTER_ROLE` via the registry’s access control, reverting if unauthorized.\
5\. Ensures the router address is not zero, reverting if null to prevent invalid settings.\
7-8. Verifies the router’s current state differs from the requested state, reverting if unchanged to avoid redundant updates.\
9-10. Updates the router’s active state in storage and emits a `RouterUpdated` event with the router address and new status.

***

#### Method: setFeeRateBps

Set the fee rate in basis points, updating the vault’s fee structure.

{% code lineNumbers="true" %}

```solidity
    function setFeeRateBps(uint32 newFeeRateBps) external whenNotPaused {
        if (newFeeRateBps > MAX_FEE_RATE_BPS) revert InvalidFeeRate();

        WrappedDollarVaultStorageV0 storage $ = _wrappedDollarVaultStorageV0();
        if (!$.registryAccess.hasRole(VAULT_SET_FEE_ROLE, _msgSender())) {
            revert NotAuthorized();
        }
        if (newFeeRateBps == $.feeRateBps) revert SameFeeRate();
        if (block.timestamp < $.lastFeeRateUpdateTimestamp + ONE_WEEK) {
            revert FeeRateUpdateTooFrequent();
        }
        uint32 oldFeeRateBps = $.feeRateBps;
        $.feeRateBps = newFeeRateBps;
        $.lastFeeRateUpdateTimestamp = block.timestamp;
        emit FeeRateUpdated(oldFeeRateBps, newFeeRateBps);
    }
```

{% endcode %}

1-2. Sets a new fee rate in micro basis points is only callable when the vault is not paused, with a check to ensure it doesn’t exceed the maximum allowed fee rate.\
5-6. Verifies the caller has the `VAULT_SET_FEE_ROLE` via the registry’s access control, reverting if unauthorized.\
8\. Ensures the new fee rate differs from the current rate, reverting if unchanged to avoid redundant updates.\
9-10. Confirms at least one week has passed since the last fee update, reverting if too frequent to maintain stability.\
12-15. Stores the old fee rate, updates the fee rate and timestamp in storage, and emits a `FeeRateUpdated` event with the old and new rates.

***

#### Method: harvest

Harvest management fees by minting shares to the treasury based on the current fee rate

{% code lineNumbers="true" %}

```solidity
    function harvest()
        external
        whenNotPaused
        nonReentrant
        returns (uint256 sharesMinted)
    {
        WrappedDollarVaultStorageV0 storage $ = _wrappedDollarVaultStorageV0();

        if (!$.registryAccess.hasRole(VAULT_HARVESTER_ROLE, _msgSender())) {
            revert NotAuthorized();
        }

        if (block.timestamp < $.lastHarvestTimestamp + ONE_DAY) {
            revert HarvestTooFrequent();
        }

        uint256 currentSupply = totalSupply();
        sharesMinted = _feeOnTotal(currentSupply, $.feeRateBps);

        if (sharesMinted == 0) revert ZeroAmount();

        $.lastHarvestTimestamp = block.timestamp;

        _mint($.treasury, sharesMinted);

        emit Harvested(_msgSender(), sharesMinted);

        return sharesMinted;
    }
```

{% endcode %}

1-5. Initiates the harvest process to mint shares for management fees, callable only when not paused and non-reentrant, returning the number of shares minted.\
9-10. Verifies the caller has the `VAULT_HARVESTER_ROLE` via the registry’s access control, reverting if unauthorized.\
13-14. Ensures at least one day has passed since the last harvest, reverting if too frequent to prevent abuse.\
17-20. Calculates the shares to mint based on the current total supply and fee rate, reverting if the result is zero to avoid empty operations.\
22-28. Updates the last harvest timestamp, mints the calculated shares to the treasury, emits a `Harvested` event with the caller and shares minted, and returns the shares minted.

***

#### Method: previewWithdraw

{% code lineNumbers="true" %}

```solidity
    function previewWithdraw(uint256 assets)
        public
        view
        virtual
        override(ERC4626Upgradeable, IERC4626)
        returns (uint256)
    {
        WrappedDollarVaultStorageV0 storage $ = _wrappedDollarVaultStorageV0();
        // Calculate fee amount
        uint256 fee = _feeOnTotal(assets, $.feeRateBps);

        // Calculate shares needed for assets + fee
        return super.previewWithdraw(assets + fee);
    }
```

{% endcode %}

1-6. Previews the withdrawal process by calculating the shares needed to withdraw a given amount of assets, including the applicable fee, overriding the ERC4626 implementation.\
8-10. Retrieves the vault’s storage and calculates the fee based on the requested assets and the current fee rate in basis points.\
13\. Adds the fee to the requested assets and uses the parent ERC4626 `previewWithdraw` function to determine the total shares required, returning the result.

***

#### Method: previewRedeem

Previews the amount of assets that would be returned for redeeming a specified number of shares, after deducting fees

{% code lineNumbers="true" %}

```solidity
    function previewRedeem(uint256 shares)
        public
        view
        virtual
        override(ERC4626Upgradeable, IERC4626)
        returns (uint256)
    {
        // Convert shares to assets
        uint256 assets = super.previewRedeem(shares);

        WrappedDollarVaultStorageV0 storage $ = _wrappedDollarVaultStorageV0();
        // Calculate and deduct fee
        uint256 fee = _feeOnRaw(assets, $.feeRateBps);

        return assets - fee;
    }
```

{% endcode %}

1-6. Previews the redemption process by calculating the assets returned for a given number of shares, after subtracting the applicable fee, overriding the ERC4626 implementation.\
9\. Uses the parent ERC4626 `previewRedeem` function to convert the shares into assets.\
13\. Calculates the fee based on the raw asset amount and the current fee rate in basis points.\
12\. Returns the assets minus the calculated fee as the final redeemable amount

***

#### Method: \_withdraw

Internal function to handle the withdrawal of assets, including minting fee shares to the treasury.

{% code lineNumbers="true" %}

```solidity
    function _withdraw(
        address caller,
        address receiver,
        address owner,
        uint256 assets,
        uint256 shares
    )
        internal
        virtual
        override
    {
        WrappedDollarVaultStorageV0 storage $ = _wrappedDollarVaultStorageV0();

        // Calculate fee shares
        uint256 feeShares = _feeOnRaw(shares, $.feeRateBps);

        // Call parent implementation to handle the withdrawal
        super._withdraw(caller, receiver, owner, assets, shares);

        // Mint fee shares to treasury
        if (feeShares > 0) {
            _mint($.treasury, feeShares);
        }
    }
```

{% endcode %}

1-9. Executes the withdrawal process internally, taking the caller, receiver, owner, assets, and shares as inputs, overriding the parent implementation to include fee handling.\
15\. Calculates the fee in shares based on the raw shares being withdrawn and the current fee rate in basis points.\
18\. Calls the parent \_withdraw function to perform the core withdrawal logic for the specified assets and shares.\
21-22. Mints the calculated fee shares to the treasury if the fee is greater than zero, ensuring fees are collected.


# VaultRouter

### High-Level Overview

The `VaultRouter` contract serves as an intermediary for interacting with the `WrappedDollarVault`. It facilitates deposits, withdrawals, and other operations by abstracting the complexities of approvals and token swaps. The router ensures that arbitrary tokens can be used as input, while the vault operates exclusively with USD-denominated ERC4626 tokens.

The router is tightly integrated with the `WrappedDollarVault` and requires registration via the `setRouter()` function in the vault. Only registered routers can interact with the vault, ensuring controlled access and preventing unauthorized operations.

The router implementation used by the investment vault aims to swap bUSD0 to yield bearing token when depositing into the vault and swap back to bUSD0 when withdrawing from the vault.

### Contract Summary

\
The contract provides the following main functions:

* **deposit**: Swaps arbitrary tokens for the vault's underlying asset and deposits them into the vault.
* **withdraw**: Withdraws assets from the vault and swaps them for arbitrary tokens.
* **depositWithPermit**: Allows gasless approval of tokens and deposits them into the vault.
* **withdrawWithPermit**: Allows gasless approval of tokens and withdraw them from the vault.

Inherited Contracts

* **ReentrancyGuard**: Prevents reentrancy attacks in critical functions.
* **Pausable**: Enables emergency halt of contract operations.

### Functionality Breakdown

#### 1. Access Control and Security

* **Router Registration**: The router must be registered with the vault via the `setRouter()` function. This ensures only authorized routers can interact with the vault.
* **Reentrancy Protection**: All critical functions are protected against reentrancy attacks using the `nonReentrant` modifier.

#### 2. Token Swapping

* **Arbitrary Token Support**: The router integrates with external decentralized exchanges (DEXs) to swap arbitrary tokens for the vault's underlying asset. However in the current implementation we use paraswap.
* **Permit Support**: Enables gasless approvals for tokens using the `permit` function, reducing friction for users.

#### 3. Deposit and Withdrawal

* **Deposit**: Users can deposit bUSD0 or SUSDS tokens into the vault by swapping them for the vault underlying asset. The router handles the swap and deposit process seamlessly.
* **Withdraw**: Users can withdraw assets from the vault and swap them for bUSD0 tokens. The router ensures the correct amount of tokens is returned after fees.

#### 4. Upgradability and Maintenance

* **Modular Design**: The router is designed to work with any `WrappedDollarVault` vault, allowing flexibility for future upgrades.
* **VaultRouter**: The contract can be paused and a new router can be setup in the Vault. this allow for easy upgrade.

### Security Analysis

**Method: Deposit**

Swaps bUSD0 or USDS tokens for the vault's underlying asset and deposits them into the vault. This function ensures that users can interact with the vault using arbitrary tokens, abstracting the complexity of token swaps.

{% code lineNumbers="true" %}

```solidity
function deposit(
        IParaSwapAugustus augustus,
        IERC20 tokenIn,
        uint256 amountIn,
        uint256 minTokensToReceive,
        uint256 minSharesToReceive,
        address receiver,
        bytes calldata swapData
    )
        public
        payable
        whenNotPaused
        nonReentrant
        returns (uint256 sharesReceived)
    {
        if (tokenIn != USD0PP && tokenIn != SUSDS) {
            revert InvalidInputToken(address(tokenIn));
        }
        if (receiver == address(0)) {
            revert NullAddress();
        }
        uint256 tokensAmount = _convertToTokens(
            augustus, tokenIn, amountIn, minTokensToReceive, swapData
        );

        sharesReceived = VAULT.deposit(tokensAmount, receiver);
        if (sharesReceived < minSharesToReceive) {
            revert InsufficientSharesReceived();
        }
        emit Deposit(receiver, address(tokenIn), amountIn, sharesReceived);
        return sharesReceived;
    }
```

{% endcode %}

**Description**

The `deposit` function allows users to deposit an ERC20 token into the vault by first swapping it for the vault's underlying asset using ParaSwap. The swapped assets are then deposited into the vault, and the user receives vault shares in return. This function ensures that users can interact with the vault using arbitrary tokens, abstracting the complexity of token swaps. The function is protected by a `nonReentrant` modifier to prevent reentrancy attacks during the swap and deposit process. It returns the number of vault shares minted and sent to the `receiver`.

**16-21 Input Validation**:

* Ensures `augustus`, `tokenIn`, and `receiver` are valid addresses.
* Ensures `amountIn` is greater than zero to prevent invalid deposits.

**22-23 Swap Execution**:

* Interacts with ParaSwap to swap `tokenIn` for the vault's underlying asset using the provided `swapData`.
* Ensures the received tokens meet or exceed `minTokensToReceive`, reverting if the condition is not met to protect users from unfavorable swaps.

**26-29 Deposit Execution**:

* Deposits the swapped assets into the vault on behalf of the `receiver`.
* Ensures the resulting vault shares meet or exceed `minSharesToReceive`, reverting if the condition is not met to protect users from unfavorable deposits.

**30 Event Emission**:

* Emits a `Deposit` event with details of the operation, including the `receiver`, `tokenIn`, `amountIn`, and `sharesReceived`.

***

**Method: depositWithPermit**

Executes a permit before depositing it into the vault.

{% code lineNumbers="true" %}

```solidity
     function depositWithPermit(
        IParaSwapAugustus augustus,
        IERC20 tokenIn,
        uint256 amountIn,
        uint256 minTokensToReceive,
        uint256 minSharesToReceive,
        address receiver,
        bytes calldata swapData,
        PermitParams calldata permitParams
    )
        public
        whenNotPaused
        returns (uint256 sharesReceived)
    {
        try ERC20Permit(address(tokenIn)).permit(
            _msgSender(),
            address(this),
            permitParams.value,
            permitParams.deadline,
            permitParams.v,
            permitParams.r,
            permitParams.s
        ) { } catch { } // solhint-disable-line no-empty-blocks

        return deposit(
            augustus,
            tokenIn,
            amountIn,
            minTokensToReceive,
            minSharesToReceive,
            receiver,
            swapData
        );
    }

```

{% endcode %}

**15-23 Permit Execution**:

* Uses the provided `permitParams` to approve the router for spending `tokenIn` without requiring a separate transaction.

**25-32 Deposit Execution**:

* Deposits the swapped assets into the vault.
* Ensures the resulting shares meet or exceed `minSharesToReceive`.

***

#### Method: withdraw

Withdraws assets from the vault and converts them to bUSD0.

{% code lineNumbers="true" %}

```solidity
  function withdraw(
        IParaSwapAugustus augustus,
        uint256 assets,
        uint256 minUSD0ppToReceive,
        address receiver,
        bytes calldata swapData
    )
        public
        whenNotPaused
        nonReentrant
        returns (uint256 amountUSD0pp)
    {
        if (receiver == address(0)) {
            revert NullAddress();
        }

        VAULT.withdraw(assets, address(this), _msgSender());

        amountUSD0pp = _convertTokensToUSD0pp(
            augustus, assets, minUSD0ppToReceive, swapData
        );

        USD0PP.safeTransfer(receiver, amountUSD0pp);
        emit Withdraw(receiver, assets, amountUSD0pp);
        return amountUSD0pp;
    }
```

{% endcode %}

**Description**

The `withdraw` function allows users to withdraw assets from the vault and convert them to bUSD0  using ParaSwap. The withdrawn assets are swapped for bUSD0 and the resulting amount are sent to the specified receiver. It returns the amount of USD0PP received by the `receiver`.

**13-15 Input Validation**:

* Ensures `receiver` is a valid addresses.

**17 Withdrawal Execution**:

* Withdraws the specified `assets` from the vault.

**19-20 Swap Execution**:

* Interacts with ParaSwap to swap the withdrawn assets for bUSD0.
* Ensures the received bUSD0 meets or exceeds `minUSD0ppToReceive`.

**24 Event Emission**:

* Emits a `Withdraw` event with details of the operation.

***

#### Method: withdrawWithPermit

Executes a permit and withdraws assets from the vault, converting them to bUSD0.

{% code lineNumbers="true" %}

```solidity
function withdrawWithPermit(
    IParaSwapAugustus augustus,
    uint256 assets,
    uint256 minUSD0ppToReceive,
    address receiver,
    bytes calldata swapData,
    PermitParams calldata permitParams
) external returns (uint256 amountUSD0pp){
     try ERC20Permit(address(VAULT)).permit(
            _msgSender(),
            address(this),
            permitParams.value,
            permitParams.deadline,
            permitParams.v,
            permitParams.r,
            permitParams.s
        ) { } catch { } // solhint-disable-line no-empty-blocks

        return
            withdraw(augustus, assets, minUSD0ppToReceive, receiver, swapData);
    } 
```

{% endcode %}

**9-17 Permit Execution**:

* Uses the provided `permitParams` to approve the router for spending vault shares without requiring a separate transaction.

**19-20 Withdraw Execution**

* Call the vault's withdraw function


# sUSD0

### High-Level Overview <a href="#high-level-overview" id="high-level-overview"></a>

The sUSD0 contract is an upgradeable ERC4626-compliant yield-bearing vault. It extends the YieldBearingVault contract, incorporating features such as blacklisting, withdrawal fees, and yield distribution linearly over a predefined yield period. The contract leverages OpenZeppelin's upgradeable contracts for enhanced security and flexibility, including pausability and reentrancy protection. It also implements EIP712 for secure off-chain signing capabilities.

The primary objective of sUSD0 is to provide a secure, controllable environment for yield generation and distribution on USD0 deposits, while maintaining strict control over who can interact with the contract. This design allows for potential regulatory compliance and risk management in decentralized finance applications.

### Contract Summary <a href="#contract-summary" id="contract-summary"></a>

The contract provides the following main functions:

* **initialize**: Sets up the contract with customizable parameters, including initial shares minting.
* **pause / unpause**: Controls the operational state of the contract.
* **blacklist / unBlacklist**: Manages addresses prohibited from interacting with the contract.
* **startYieldDistribution**: Initiates a new yield accrual period with specified parameters.
* **deposit / mint**: Handles asset deposits and share minting.
* **depositWithPermit**: Enables gasless deposits using permit functionality.
* **withdraw / redeem**: Handles asset withdrawals and share redemptions, incorporating withdrawal fees that are immediately transferred to the treasury yield contract.
* **previewWithdraw / previewRedeem**: Simulates withdrawal and redemption operations for users.
* **updateWithdrawFee**: Updates the withdrawal fee rate with proper access control.

The contract uses a separate storage structure (SUsd0StorageV0) to store state variables for sUSD0 implementation.

### Inherited Contracts <a href="#inherited-contracts" id="inherited-contracts"></a>

* **YieldBearingVault**: Provides core yield accrual and distribution mechanisms.
* **PausableUpgradeable**: Enables emergency halt of contract operations.
* **ReentrancyGuardUpgradeable**: Prevents reentrancy attacks in critical functions.
* **EIP712Upgradeable**: Implements EIP712 for secure off-chain message signing.

### Functionality Breakdown <a href="#functionality-breakdown" id="functionality-breakdown"></a>

#### Access Control and Security: <a href="#access-control-and-security" id="access-control-and-security"></a>

* Utilizes a registry contract for role-based access control.
* Implements blacklist to prevent specific addresses from interacting with the contract.
* Enforces pause mechanism for emergency situations.
* Uses role-based permissions for administrative functions.

#### Yield Management: <a href="#yield-management" id="yield-management"></a>

* Allows admin-controlled yield distribution periods via `SUSD0_YIELD_DISTRIBUTOR_ROLE`.
* Accrues yield over time based on configurable parameters.
* Integrates yield accrual with deposit and withdrawal operations.

#### Asset Management: <a href="#asset-management" id="asset-management"></a>

* Implements ERC4626 standard for standardized vault interactions.
* Handles deposits, withdrawals, and redemptions with consideration for accrued yield.
* Applies withdrawal fees, immediately transferring them to the treasury yield contract for protocol revenue.
* Mints initial "dead" shares during initialization to support early yield distribution.

#### Upgradability and Pause Mechanism: <a href="#upgradability-and-pause-mechanism" id="upgradability-and-pause-mechanism"></a>

* Utilizes OpenZeppelin's upgradeable contract pattern for future improvements.
* Includes pause functionality for emergency situations with separate roles for pausing and unpausing.

### Security Analysis <a href="#security-analysis" id="security-analysis"></a>

#### Method: initialize <a href="#method-initialize" id="method-initialize"></a>

Initializes the vault, token, yield module, EIP712 domain, registry contract and access control, setting up the vault's initial state.

```
function initialize(address _registryContract, uint256 _withdrawFeeBps, uint256 initialShares)
    external
    initializer
{
    if (_registryContract == address(0)) {
        revert NullContract();
    }
    SUsd0StorageV0 storage $ = _susd0StorageV0();
    address _underlyingToken = IRegistryContract(_registryContract).getContract(CONTRACT_USD0);
    __YieldBearingVault_init(_underlyingToken, SUSD0Name, SUSD0Symbol);
    __Pausable_init_unchained();
    __ReentrancyGuard_init();
    __EIP712_init_unchained(SUSD0Name, "1");

    if (_withdrawFeeBps > MAX_25_PERCENT_WITHDRAW_FEE) {
        revert AmountTooBig();
    }

    if (initialShares == 0) {
        revert AmountIsZero();
    }

    $.registryAccess = IRegistryAccess(
        IRegistryContract(_registryContract).getContract(CONTRACT_REGISTRY_ACCESS)
    );
    $.withdrawFeeBps = _withdrawFeeBps;
    $.usd0Token = IUsd0(_underlyingToken);
    $.treasuryYield = IRegistryContract(_registryContract).getContract(CONTRACT_YIELD_TREASURY);

    YieldDataStorage storage y = _getYieldDataStorage();
    // mint dead shares to the vault
    y.totalDeposits = initialShares;
    _mint(address(this), initialShares);

    emit WithdrawFeeUpdated(_withdrawFeeBps);
}
```

**1-3.** Set the registry contract, withdrawal fee in BPS, and initial shares to mint.

**4-6.** Validates registry contract is not zero address, reverts if zero address.

**7.** Load the contract storage.

**8.** Retrieves the USD0 token address from the registry contract.

**9-12.** Initializes inherited contracts, with initializer parameters including vault name and symbol from constants.

**14-16.** Validates withdrawal fee is below 25% preventing excessive fees that could harm users.

**18-20.** Validates initialShares is not zero, ensuring vault starts with a valid state.

**22-24.** Sets up contract storage with registry access retrieved from the registry contract.

**25-26.** Stores withdrawal fee and USD0 token reference.

**27.** Retrieves and stores the treasury yield contract address from the registry.

**29-31.** Initializes yield storage with initial shares and mints them to the contract itself, creating "dead" shares that allow for early yield distribution before user deposits.

**33.** Emits an event with the new withdrawal fee.

#### Method: blacklist <a href="#method-blacklist" id="method-blacklist"></a>

Adds an address to the blacklist, preventing it from interacting with the contract.

```
function blacklist(address account) external {
    if (account == address(0)) {
        revert NullAddress();
    }
    SUsd0StorageV0 storage $ = _susd0StorageV0();
    $.registryAccess.onlyMatchingRole(BLACKLIST_ROLE);
    if ($.isBlacklisted[account]) {
        revert SameValue();
    }
    $.isBlacklisted[account] = true;

    emit Blacklist(account);
}
```

**1.** Mark function as external to save gas.

**2-4.** Prevents blacklisting of zero address, and reverts if trying to pass zero address.

**5-6.** Utilizes the registry for role-based access control, restricting to `BLACKLIST_ROLE`.

**7-9.** Reverts if the account is already blacklisted.

**10.** Adds the account to the blacklist in SUsd0StorageV0.

**12.** Emits an event to log the blacklisting action.

#### Method: \_update <a href="#method-_update" id="method-_update"></a>

Internal hook ensuring that both sender and receiver are not blacklisted before updating the token balances.

```
function _update(address from, address to, uint256 amount)
    internal
    override(ERC20Upgradeable)
    whenNotPaused
{
    SUsd0StorageV0 storage $ = _susd0StorageV0();
    if ($.isBlacklisted[from] || $.isBlacklisted[to]) {
        revert Blacklisted();
    }
    super._update(from, to, amount);
}
```

**1-4.** Internal function overriding the base ERC20Upgradeable implementation, includes `whenNotPaused` modifier to prevent transfers when contract is paused.

**5.** Retrieves storage pointer for SUsd0StorageV0.

**6-8.** Checks both sender and receiver against blacklist, reverting if either is blacklisted.

**9.** Passes through to parent implementation if checks pass.

#### Method: startYieldDistribution <a href="#method-startyielddistribution" id="method-startyielddistribution"></a>

Initiates a new yield distribution period with specified parameters, wrapping the internal call to add proper access control.

```
function startYieldDistribution(uint256 yieldAmount, uint256 startTime, uint256 endTime)
    external
{
    SUsd0StorageV0 storage $ = _susd0StorageV0();
    $.registryAccess.onlyMatchingRole(SUSD0_YIELD_DISTRIBUTOR_ROLE);
    _startYieldDistribution(yieldAmount, startTime, endTime);
}
```

**1-3.** External function for starting a new yield period.

**4-5.** Ensures only addresses with `SUSD0_YIELD_DISTRIBUTOR_ROLE` set on registry access can call this function.

**6.** Delegates to internal function for yield distribution logic.

#### Method: \_startYieldDistribution <a href="#method-_startyielddistribution" id="method-_startyielddistribution"></a>

Internal function to start the yield distribution with validation checks.

```
function _startYieldDistribution(uint256 yieldAmount, uint256 startTime, uint256 endTime)
    internal
    override
{
    IERC20 _asset = IERC20(asset());

    if (yieldAmount == 0) {
        revert ZeroYieldAmount();
    }
    if (startTime < block.timestamp) {
        revert StartTimeNotInFuture();
    }
    if (endTime <= startTime) {
        revert EndTimeNotAfterStartTime();
    }

    YieldDataStorage storage $ = _getYieldDataStorage();

    if (startTime < $.periodFinish) {
        revert StartTimeBeforePeriodFinish();
    }
    if (block.timestamp < $.periodFinish) {
        revert CurrentTimeBeforePeriodFinish();
    }
    _updateYield();

    uint256 periodDuration = endTime - startTime;
    uint256 newYieldRate =
        Math.mulDiv(yieldAmount, YIELD_PRECISION, periodDuration, Math.Rounding.Floor);

    if (_asset.balanceOf(address(this)) < $.totalDeposits + yieldAmount) {
        revert InsufficientAssetsForYield();
    }

    $.yieldRate = newYieldRate;
    $.periodStart = startTime;
    $.periodFinish = endTime;
    $.lastUpdateTime = startTime;
    $.isActive = true;
}
```

**1-4.** Internal function overriding the base YieldBearingVault implementation.

**5.** Gets reference to the underlying asset (USD0).

**7-9.** Validates yield amount is not zero.

**10-12.** Validates start time is in the future.

**13-15.** Validates end time is after start time.

**17.** Retrieves yield data storage.

**19-21.** Validates new period starts after the current period finishes.

**22-24.** Validates current time is after the current period finishes (prevents overlapping periods).

**25.** Updates yield state to account for any accrued yield before starting new period.

**27-28.** Calculates the yield rate per second using floor rounding to ensure conservative estimates.

**30-32.** Validates contract has sufficient assets (deposits + yield amount) to support the yield distribution.

**34-37.** Sets the new yield period parameters and activates yield distribution.

#### Method: depositWithPermit <a href="#method-depositwithpermit" id="method-depositwithpermit"></a>

Enables users to deposit assets using permit functionality, allowing gasless approvals.

```
function depositWithPermit(
    uint256 assets,
    address receiver,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) public nonReentrant whenNotPaused returns (uint256 shares) {
    try IERC20Permit(asset()).permit(msg.sender, address(this), assets, deadline, v, r, s) {} // solhint-disable-line no-empty-blocks
        catch {} // solhint-disable-line no-empty-blocks

    return deposit(assets, receiver);
}
```

**1-8.** Public function marked as `nonReentrant` and `whenNotPaused` to prevent reentrancy and ensure contract is active.

**9.** Attempts to execute permit signature to approve the contract to spend user's assets. If permit fails (e.g., token doesn't support permit), continues execution assuming approval already exists.

**11.** Calls the standard deposit function with the approved assets.

#### Method: withdraw <a href="#method-withdraw" id="method-withdraw"></a>

Overrides the ERC4626 withdraw function to include withdrawal fees and enforce withdrawal limits. Fees are immediately transferred to the treasury yield contract.

```
function withdraw(uint256 assets, address receiver, address owner)
    public
    override(ERC4626Upgradeable, ISUsd0)
    nonReentrant
    whenNotPaused
    returns (uint256 shares)
{
    SUsd0StorageV0 storage $ = _susd0StorageV0();
    YieldDataStorage storage yieldStorage = _getYieldDataStorage();
    // Check withdrawal limit
    uint256 maxAssets = maxWithdraw(owner);
    // maxAssets take into account the fee
    if (assets > maxAssets) {
        revert ERC4626ExceededMaxWithdraw(owner, assets, maxAssets);
    }

    shares = previewWithdraw(assets);
    // we need to add the fee on the assets to know exactly the shares to burn
    // assets is 100% - fee% of the total assets
    uint256 fee = Math.mulDiv(
        assets, $.withdrawFeeBps, BASIS_POINT_BASE - $.withdrawFeeBps, Math.Rounding.Ceil
    );

    // Perform withdrawal (exact assets to receiver)
    super._withdraw(_msgSender(), receiver, owner, assets, shares);
    // take the fee
    yieldStorage.totalDeposits -= fee;
    $.usd0Token.safeTransfer($.treasuryYield, fee);
}
```

**1-7.** Public function overriding the ERC4626 withdraw function, protected by `nonReentrant` and `whenNotPaused` modifiers.

**8-9.** Retrieves storage pointers for SUsd0StorageV0 and YieldDataStorage.

**10-14.** Checks if the withdrawal amount exceeds the maximum allowed (accounting for fees), and reverts if so.

**16.** Calculates shares needed using previewWithdraw which accounts for fees.

**17-20.** Calculates the withdrawal fee based on the assets being withdrawn. Uses ceiling rounding to ensure fees are not undercharged. The formula accounts for the fee being taken from assets beyond what the user receives.

**22.** Calls parent withdrawal function with calculated values, which handles share burning and asset transfer to receiver.

**23-24.** Deducts the fee from total deposits and immediately transfers the fee to the treasury yield contract.

#### Method: redeem <a href="#method-redeem" id="method-redeem"></a>

Overrides the ERC4626 redeem function to include redemption fees and enforce redemption limits. Fees are immediately transferred to the treasury yield contract.

```
function redeem(uint256 shares, address receiver, address owner)
    public
    override(ERC4626Upgradeable, ISUsd0)
    nonReentrant
    whenNotPaused
    returns (uint256 assets)
{
    SUsd0StorageV0 storage $ = _susd0StorageV0();
    YieldDataStorage storage yieldStorage = _getYieldDataStorage();

    // Check redemption limit
    uint256 maxShares = maxRedeem(owner);
    if (shares > maxShares) {
        revert ERC4626ExceededMaxRedeem(owner, shares, maxShares);
    }

    // Calculate assets after fee
    assets = previewRedeem(shares);
    uint256 assetsWithFee = convertToAssets(shares);
    uint256 fee = assetsWithFee - assets;

    // Perform redemption
    super._withdraw(_msgSender(), receiver, owner, assets, shares);

    // take the fee
    yieldStorage.totalDeposits -= fee;
    $.usd0Token.safeTransfer($.treasuryYield, fee);
}
```

**1-7.** Public function overriding the ERC4626 redeem function, protected by `nonReentrant` and `whenNotPaused` modifiers.

**8-9.** Retrieves storage pointers for SUsd0StorageV0 and YieldDataStorage.

**11-14.** Checks if the redemption amount exceeds the maximum allowed, and reverts if so.

**16-18.** Calculates assets the user will receive (after fee) and the total assets represented by the shares (before fee). The difference is the fee amount.

**20.** Calls parent withdrawal function which handles share burning and asset transfer to receiver.

**22-23.** Deducts the fee from total deposits and immediately transfers the fee to the treasury yield contract.

#### Method: previewWithdraw <a href="#method-previewwithdraw" id="method-previewwithdraw"></a>

Calculates the number of shares required to withdraw a given amount of assets, accounting for withdrawal fees.

```
function previewWithdraw(uint256 assets)
    public
    view
    override(ERC4626Upgradeable, ISUsd0)
    returns (uint256 shares)
{
    SUsd0StorageV0 storage $ = _susd0StorageV0();
    // Calculate the fee based on the equivalent assets of these shares
    uint256 fee = Math.mulDiv(
        assets, $.withdrawFeeBps, BASIS_POINT_BASE - $.withdrawFeeBps, Math.Rounding.Ceil
    );
    // Calculate total assets needed, including fee
    uint256 assetsWithFee = assets + fee;
    // Convert the total assets (including fee) to shares
    shares = _convertToShares(assetsWithFee, Math.Rounding.Ceil);
}
```

**1-5.** Public view function overriding ERC4626 previewWithdraw.

**6.** Retrieves storage pointer for SUsd0StorageV0.

**7-10.** Calculates the fee amount based on the assets being withdrawn. Uses ceiling rounding to ensure conservative estimates. The formula accounts for the fee being a percentage of the total assets needed.

**11-12.** Calculates total assets needed including the fee.

**13.** Converts the total assets (including fee) to shares using ceiling rounding.

#### Method: previewRedeem <a href="#method-previewredeem" id="method-previewredeem"></a>

Calculates the amount of assets that would be received for redeeming a given number of shares, accounting for redemption fees.

```
function previewRedeem(uint256 shares)
    public
    view
    override(ERC4626Upgradeable, ISUsd0)
    returns (uint256 assets)
{
    SUsd0StorageV0 storage $ = _susd0StorageV0();
    // Calculate the raw amount of assets for the given shares
    uint256 assetsWithFee = convertToAssets(shares);

    // Calculates the fee part of an amount `assets` that already includes fees.
    uint256 fee =
        Math.mulDiv(assetsWithFee, $.withdrawFeeBps, BASIS_POINT_BASE, Math.Rounding.Ceil);
    assets = assetsWithFee - fee;
}
```

**1-5.** Public view function overriding ERC4626 previewRedeem.

**6.** Retrieves storage pointer for SUsd0StorageV0.

**7-8.** Calculates the raw amount of assets represented by the shares (before fee deduction).

**10-11.** Calculates the fee portion using ceiling rounding to ensure conservative estimates.

**12.** Subtracts the fee from the total assets to get the net assets the user will receive.

#### Method: updateWithdrawFee <a href="#method-updatewithdrawfee" id="method-updatewithdrawfee"></a>

Updates the withdrawal fee rate with proper access control and validation.

```
function updateWithdrawFee(uint256 newWithdrawFeeBps) external {
    SUsd0StorageV0 storage $ = _susd0StorageV0();
    $.registryAccess.onlyMatchingRole(SUSD0_WITHDRAW_FEE_UPDATER_ROLE);

    if (newWithdrawFeeBps > MAX_25_PERCENT_WITHDRAW_FEE) {
        revert AmountTooBig();
    }

    if (newWithdrawFeeBps == $.withdrawFeeBps) {
        revert SameValue();
    }

    $.withdrawFeeBps = newWithdrawFeeBps;
    emit WithdrawFeeUpdated(newWithdrawFeeBps);
}
```

**1.** External function for updating withdrawal fee.

**2-3.** Retrieves storage pointer and validates caller has `SUSD0_WITHDRAW_FEE_UPDATER_ROLE`.

**5-7.** Validates new fee is below 25% maximum, preventing excessive fees.

**9-11.** Validates new fee is different from current fee, preventing unnecessary updates.

**13.** Updates the withdrawal fee in storage.

**14.** Emits an event to log the fee update.


# sEUR0

### High-Level Overview <a href="#high-level-overview" id="high-level-overview"></a>

The sEUR0 contract is an upgradeable ERC4626-compliant yield-bearing vault. It extends the YieldBearingVault contract, incorporating features such as blacklisting, withdrawal fees, and yield distribution linearly over a predefined yield period. The contract leverages OpenZeppelin's upgradeable contracts for enhanced security and flexibility, including pausability and reentrancy protection. It also implements EIP712 for secure off-chain signing capabilities.

The primary objective of sEUR0 is to provide a secure, controllable environment for yield generation and distribution on EUR0 deposits, while maintaining strict control over who can interact with the contract. This design allows for potential regulatory compliance and risk management in decentralized finance applications.

### Contract Summary <a href="#contract-summary" id="contract-summary"></a>

The contract provides the following main functions:

* **initialize**: Sets up the contract with customizable parameters, including initial shares minting.
* **pause / unpause**: Controls the operational state of the contract.
* **blacklist / unBlacklist**: Manages addresses prohibited from interacting with the contract.
* **startYieldDistribution**: Initiates a new yield accrual period with specified parameters.
* **deposit / mint**: Handles asset deposits and share minting.
* **depositWithPermit**: Enables gasless deposits using permit functionality.
* **withdraw / redeem**: Handles asset withdrawals and share redemptions, incorporating withdrawal fees that are immediately transferred to the treasury yield contract.
* **previewWithdraw / previewRedeem**: Simulates withdrawal and redemption operations for users.
* **updateWithdrawFee**: Updates the withdrawal fee rate with proper access control.

The contract uses a separate storage structure (SEur0StorageV0) to store state variables for sEUR0 implementation.

### Inherited Contracts <a href="#inherited-contracts" id="inherited-contracts"></a>

* **YieldBearingVault**: Provides core yield accrual and distribution mechanisms.
* **PausableUpgradeable**: Enables emergency halt of contract operations.
* **ReentrancyGuardUpgradeable**: Prevents reentrancy attacks in critical functions.
* **EIP712Upgradeable**: Implements EIP712 for secure off-chain message signing.

### Functionality Breakdown <a href="#functionality-breakdown" id="functionality-breakdown"></a>

**Access Control and Security:**

* Utilizes a registry contract for role-based access control.
* Implements blacklist to prevent specific addresses from interacting with the contract.
* Enforces pause mechanism for emergency situations.
* Uses role-based permissions for administrative functions.

**Yield Management:**

* Allows admin-controlled yield distribution periods via SEUR0\_YIELD\_DISTRIBUTOR\_ROLE.
* Accrues yield over time based on configurable parameters.
* Integrates yield accrual with deposit and withdrawal operations.

**Asset Management:**

* Implements ERC4626 standard for standardized vault interactions.
* Handles deposits, withdrawals, and redemptions with consideration for accrued yield.
* Applies withdrawal fees, immediately transferring them to the treasury yield contract for protocol revenue.
* Mints initial "dead" shares during initialization to support early yield distribution.

**Upgradability and Pause Mechanism:**

* Utilizes OpenZeppelin's upgradeable contract pattern for future improvements.
* Includes pause functionality for emergency situations with separate roles for pausing and unpausing.

### Security Analysis <a href="#security-analysis" id="security-analysis"></a>

#### Method: initialize <a href="#method-initialize" id="method-initialize"></a>

Initializes the vault, token, yield module, EIP712 domain, registry contract and access control, setting up the vault's initial state.

```
function initialize(address _registryContract, uint256 _withdrawFeeBps, uint256 initialShares)
    external
    initializer
{
    if (_registryContract == address(0)) {
        revert NullContract();
    }
    SEur0StorageV0 storage $ = _seur0StorageV0();
    address _underlyingToken = IRegistryContract(_registryContract).getContract(CONTRACT_EUR0);
    __YieldBearingVault_init(_underlyingToken, SEUR0Name, SEUR0Symbol);
    __Pausable_init_unchained();
    __ReentrancyGuard_init();
    __EIP712_init_unchained(SEUR0Name, "1");
    if (_withdrawFeeBps > MAX_25_PERCENT_WITHDRAW_FEE) {
        revert AmountTooBig();
    }
    if (initialShares == 0) {
        revert AmountIsZero();
    }
    $.registryAccess = IRegistryAccess(
        IRegistryContract(_registryContract).getContract(CONTRACT_REGISTRY_ACCESS)
    );
    $.withdrawFeeBps = _withdrawFeeBps;
    $.eur0Token = IEur0(_underlyingToken);
    $.treasuryYield = IRegistryContract(_registryContract).getContract(CONTRACT_YIELD_TREASURY);
    YieldDataStorage storage y = _getYieldDataStorage();
    // mint dead shares to the vault
    y.totalDeposits = initialShares;
    _mint(address(this), initialShares);
    emit WithdrawFeeUpdated(_withdrawFeeBps);
}
```

1-3. Set the registry contract, withdrawal fee in BPS, and initial shares to mint.\
4-6. Validates registry contract is not zero address, reverts if zero address.\
7\. Load the contract storage.\
8\. Retrieves the EUR0 token address from the registry contract.\
9-12. Initializes inherited contracts, with initializer parameters including vault name and symbol from constants.\
14-16. Validates withdrawal fee is below 25% preventing excessive fees that could harm users.\
18-20. Validates initialShares is not zero, ensuring vault starts with a valid state.\
22-24. Sets up contract storage with registry access retrieved from the registry contract.\
25-26. Stores withdrawal fee and EUR0 token reference.\
27\. Retrieves and stores the treasury yield contract address from the registry.\
29-31. Initializes yield storage with initial shares and mints them to the contract itself, creating "dead" shares that allow for early yield distribution before user deposits.\
33\. Emits an event with the new withdrawal fee.

#### Method: pause <a href="#method-pause" id="method-pause"></a>

Pauses the contract operations, preventing most function calls until unpaused.

```
function pause() external {
    SEur0StorageV0 storage $ = _seur0StorageV0();
    $.registryAccess.onlyMatchingRole(PAUSING_CONTRACTS_ROLE);
    _pause();
}
```

1. External function to pause the contract.
2. Retrieves storage pointer for SEur0StorageV0.
3. Ensures only addresses with PAUSING\_CONTRACTS\_ROLE set on registry access can call this function.
4. Calls the internal pause function from PausableUpgradeable.

#### Method: unpause <a href="#method-unpause" id="method-unpause"></a>

Unpauses the contract operations, allowing normal function calls to resume.

```
function unpause() external {
    SEur0StorageV0 storage $ = _seur0StorageV0();
    $.registryAccess.onlyMatchingRole(UNPAUSING_CONTRACTS_ROLE);
    _unpause();
}
```

1. External function to unpause the contract.
2. Retrieves storage pointer for SEur0StorageV0.
3. Ensures only addresses with UNPAUSING\_CONTRACTS\_ROLE set on registry access can call this function.
4. Calls the internal unpause function from PausableUpgradeable.

#### Method: blacklist <a href="#method-blacklist" id="method-blacklist"></a>

Adds an address to the blacklist, preventing it from interacting with the contract.

```
function blacklist(address account) external {
    if (account == address(0)) {
        revert NullAddress();
    }
    SEur0StorageV0 storage $ = _seur0StorageV0();
    $.registryAccess.onlyMatchingRole(BLACKLIST_ROLE);
    if ($.isBlacklisted[account]) {
        revert SameValue();
    }
    $.isBlacklisted[account] = true;
    emit Blacklist(account);
}
```

1. Mark function as external to save gas.\
   2-4. Prevents blacklisting of zero address, and reverts if trying to pass zero address.\
   5-6. Utilizes the registry for role-based access control, restricting to BLACKLIST\_ROLE.\
   7-9. Reverts if the account is already blacklisted.
2. Adds the account to the blacklist in SEur0StorageV0.
3. Emits an event to log the blacklisting action.

#### Method: unBlacklist <a href="#method-unblacklist" id="method-unblacklist"></a>

Removes an address from the blacklist, allowing it to interact with the contract again.

```
function unBlacklist(address account) external {
    SEur0StorageV0 storage $ = _seur0StorageV0();
    $.registryAccess.onlyMatchingRole(BLACKLIST_ROLE);
    if (!$.isBlacklisted[account]) {
        revert SameValue();
    }
    $.isBlacklisted[account] = false;
    emit UnBlacklist(account);
}
```

1. External function to remove an address from the blacklist.
2. Retrieves storage pointer for SEur0StorageV0.
3. Ensures only addresses with BLACKLIST\_ROLE set on registry access can call this function.\
   4-6. Reverts if the account is not currently blacklisted.
4. Removes the account from the blacklist.
5. Emits an event to log the unblacklisting action.

#### Method: \_update <a href="#method-_update" id="method-_update"></a>

Internal hook ensuring that both sender and receiver are not blacklisted before updating the token balances.

```
function _update(address from, address to, uint256 amount)
    internal
    override(ERC20Upgradeable)
    whenNotPaused
{
    SEur0StorageV0 storage $ = _seur0StorageV0();
    if ($.isBlacklisted[from] || $.isBlacklisted[to]) {
        revert Blacklisted();
    }
    super._update(from, to, amount);
}
```

1-4. Internal function overriding the base ERC20Upgradeable implementation, includes whenNotPaused modifier to prevent transfers when contract is paused.\
5\. Retrieves storage pointer for SEur0StorageV0.\
6-8. Checks both sender and receiver against blacklist, reverting if either is blacklisted.\
9\. Passes through to parent implementation if checks pass.

#### Method: startYieldDistribution <a href="#method-startyielddistribution" id="method-startyielddistribution"></a>

Initiates a new yield distribution period with specified parameters, wrapping the internal call to add proper access control.

```
function startYieldDistribution(uint256 yieldAmount, uint256 startTime, uint256 endTime)
    external
{
    SEur0StorageV0 storage $ = _seur0StorageV0();
    $.registryAccess.onlyMatchingRole(SEUR0_YIELD_DISTRIBUTOR_ROLE);
    _startYieldDistribution(yieldAmount, startTime, endTime);
}
```

1-3. External function for starting a new yield period.\
4-5. Ensures only addresses with SEUR0\_YIELD\_DISTRIBUTOR\_ROLE set on registry access can call this function.\
6\. Delegates to internal function for yield distribution logic.

#### Method: \_startYieldDistribution <a href="#method-_startyielddistribution" id="method-_startyielddistribution"></a>

Internal function to start the yield distribution with validation checks.

```
function _startYieldDistribution(uint256 yieldAmount, uint256 startTime, uint256 endTime)
    internal
    override
{
    IERC20 _asset = IERC20(asset());
    if (yieldAmount == 0) {
        revert ZeroYieldAmount();
    }
    if (startTime < block.timestamp) {
        revert StartTimeNotInFuture();
    }
    if (endTime <= startTime) {
        revert EndTimeNotAfterStartTime();
    }
    YieldDataStorage storage $ = _getYieldDataStorage();
    if (startTime < $.periodFinish) {
        revert StartTimeBeforePeriodFinish();
    }
    if (block.timestamp < $.periodFinish) {
        revert CurrentTimeBeforePeriodFinish();
    }
    _updateYield();
    uint256 periodDuration = endTime - startTime;
    uint256 newYieldRate =
        Math.mulDiv(yieldAmount, YIELD_PRECISION, periodDuration, Math.Rounding.Floor);
    if (_asset.balanceOf(address(this)) < $.totalDeposits + yieldAmount) {
        revert InsufficientAssetsForYield();
    }
    $.yieldRate = newYieldRate;
    $.periodStart = startTime;
    $.periodFinish = endTime;
    $.lastUpdateTime = startTime;
    $.isActive = true;
}
```

1-4. Internal function overriding the base YieldBearingVault implementation.\
5\. Gets reference to the underlying asset (EUR0).\
7-9. Validates yield amount is not zero.\
10-12. Validates start time is in the future.\
13-15. Validates end time is after start time.\
17\. Retrieves yield data storage.\
19-21. Validates new period starts after the current period finishes.\
22-24. Validates current time is after the current period finishes (prevents overlapping periods).\
25\. Updates yield state to account for any accrued yield before starting new period.\
27-28. Calculates the yield rate per second using floor rounding to ensure conservative estimates.\
30-32. Validates contract has sufficient assets (deposits + yield amount) to support the yield distribution.\
34-37. Sets the new yield period parameters and activates yield distribution.

#### Method: deposit <a href="#method-deposit" id="method-deposit"></a>

Allows users to deposit assets and receive shares in return.

```
function deposit(uint256 assets, address receiver)
    public
    override(ERC4626Upgradeable, ISEur0)
    whenNotPaused
    returns (uint256 shares)
{
    return super.deposit(assets, receiver);
}
```

1-6. Public function overriding the ERC4626 deposit function, protected by whenNotPaused modifier.\
7\. Delegates to parent implementation which handles share calculation and minting.

#### Method: mint <a href="#method-mint" id="method-mint"></a>

Allows users to mint shares by depositing the equivalent amount of assets.

```
function mint(uint256 shares, address receiver)
    public
    override(ERC4626Upgradeable, ISEur0)
    whenNotPaused
    returns (uint256)
{
    return super.mint(shares, receiver);
}
```

1-6. Public function overriding the ERC4626 mint function, protected by whenNotPaused modifier.\
7\. Delegates to parent implementation which handles asset deposit and share minting.

#### Method: depositWithPermit <a href="#method-depositwithpermit" id="method-depositwithpermit"></a>

Enables users to deposit assets using permit functionality, allowing gasless approvals.

```
function depositWithPermit(
    uint256 assets,
    address receiver,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) public nonReentrant whenNotPaused returns (uint256 shares) {
    try IERC20Permit(asset()).permit(msg.sender, address(this), assets, deadline, v, r, s) {} // solhint-disable-line no-empty-blocks
        catch {} // solhint-disable-line no-empty-blocks
    return deposit(assets, receiver);
}
```

1-8. Public function marked as nonReentrant and whenNotPaused to prevent reentrancy and ensure contract is active.\
9\. Attempts to execute permit signature to approve the contract to spend user's assets. If permit fails (e.g., token doesn't support permit), continues execution assuming approval already exists.\
11\. Calls the standard deposit function with the approved assets.

#### Method: withdraw <a href="#method-withdraw" id="method-withdraw"></a>

Overrides the ERC4626 withdraw function to include withdrawal fees and enforce withdrawal limits. Fees are immediately transferred to the treasury yield contract.

```
function withdraw(uint256 assets, address receiver, address owner)
    public
    override(ERC4626Upgradeable, ISEur0)
    nonReentrant
    whenNotPaused
    returns (uint256 shares)
{
    SEur0StorageV0 storage $ = _seur0StorageV0();
    YieldDataStorage storage yieldStorage = _getYieldDataStorage();
    // Check withdrawal limit
    uint256 maxAssets = maxWithdraw(owner);
    // maxAssets take into account the fee
    if (assets > maxAssets) {
        revert ERC4626ExceededMaxWithdraw(owner, assets, maxAssets);
    }
    shares = previewWithdraw(assets);
    // we need to add the fee on the assets to know exactly the shares to burn
    // assets is 100% - fee% of the total assets
    uint256 fee = Math.mulDiv(
        assets, $.withdrawFeeBps, BASIS_POINT_BASE - $.withdrawFeeBps, Math.Rounding.Ceil
    );
    // Perform withdrawal (exact assets to receiver)
    super._withdraw(_msgSender(), receiver, owner, assets, shares);
    // take the fee
    yieldStorage.totalDeposits -= fee;
    $.eur0Token.safeTransfer($.treasuryYield, fee);
}
```

1-7. Public function overriding the ERC4626 withdraw function, protected by nonReentrant and whenNotPaused modifiers.\
8-9. Retrieves storage pointers for SEur0StorageV0 and YieldDataStorage.\
10-14. Checks if the withdrawal amount exceeds the maximum allowed (accounting for fees), and reverts if so.\
16\. Calculates shares needed using previewWithdraw which accounts for fees.\
17-20. Calculates the withdrawal fee based on the assets being withdrawn. Uses ceiling rounding to ensure fees are not undercharged. The formula accounts for the fee being taken from assets beyond what the user receives.\
22\. Calls parent withdrawal function with calculated values, which handles share burning and asset transfer to receiver.\
23-24. Deducts the fee from total deposits and immediately transfers the fee to the treasury yield contract.

#### Method: redeem <a href="#method-redeem" id="method-redeem"></a>

Overrides the ERC4626 redeem function to include redemption fees and enforce redemption limits. Fees are immediately transferred to the treasury yield contract.

```
function redeem(uint256 shares, address receiver, address owner)
    public
    override(ERC4626Upgradeable, ISEur0)
    nonReentrant
    whenNotPaused
    returns (uint256 assets)
{
    SEur0StorageV0 storage $ = _seur0StorageV0();
    YieldDataStorage storage yieldStorage = _getYieldDataStorage();
    // Check redemption limit
    uint256 maxShares = maxRedeem(owner);
    if (shares > maxShares) {
        revert ERC4626ExceededMaxRedeem(owner, shares, maxShares);
    }
    // Calculate assets after fee
    assets = previewRedeem(shares);
    uint256 assetsWithFee = convertToAssets(shares);
    uint256 fee = assetsWithFee - assets;
    // Perform redemption
    super._withdraw(_msgSender(), receiver, owner, assets, shares);
    // take the fee
    yieldStorage.totalDeposits -= fee;
    $.eur0Token.safeTransfer($.treasuryYield, fee);
}
```

1-7. Public function overriding the ERC4626 redeem function, protected by nonReentrant and whenNotPaused modifiers.\
8-9. Retrieves storage pointers for SEur0StorageV0 and YieldDataStorage.\
11-14. Checks if the redemption amount exceeds the maximum allowed, and reverts if so.\
16-18. Calculates assets the user will receive (after fee) and the total assets represented by the shares (before fee). The difference is the fee amount.\
20\. Calls parent withdrawal function which handles share burning and asset transfer to receiver.\
22-23. Deducts the fee from total deposits and immediately transfers the fee to the treasury yield contract.

#### Method: previewWithdraw <a href="#method-previewwithdraw" id="method-previewwithdraw"></a>

Calculates the number of shares required to withdraw a given amount of assets, accounting for withdrawal fees.

```
function previewWithdraw(uint256 assets)
    public
    view
    override(ERC4626Upgradeable, ISEur0)
    returns (uint256 shares)
{
    SEur0StorageV0 storage $ = _seur0StorageV0();
    // Calculate the fee based on the equivalent assets of these shares
    uint256 fee = Math.mulDiv(
        assets, $.withdrawFeeBps, BASIS_POINT_BASE - $.withdrawFeeBps, Math.Rounding.Ceil
    );
    // Calculate total assets needed, including fee
    uint256 assetsWithFee = assets + fee;
    // Convert the total assets (including fee) to shares
    shares = _convertToShares(assetsWithFee, Math.Rounding.Ceil);
}
```

1-5. Public view function overriding ERC4626 previewWithdraw.\
6\. Retrieves storage pointer for SEur0StorageV0.\
7-10. Calculates the fee amount based on the assets being withdrawn. Uses ceiling rounding to ensure conservative estimates. The formula accounts for the fee being a percentage of the total assets needed.\
11-12. Calculates total assets needed including the fee.\
13\. Converts the total assets (including fee) to shares using ceiling rounding.

#### Method: maxWithdraw <a href="#method-maxwithdraw" id="method-maxwithdraw"></a>

Returns the maximum amount of assets that can be withdrawn by a given owner, accounting for fees.

```
function maxWithdraw(address owner)
    public
    view
    override(ERC4626Upgradeable, ISEur0)
    returns (uint256)
{
    return previewRedeem(balanceOf(owner));
}
```

1-5. Public view function overriding ERC4626 maxWithdraw.\
6\. Calculates the maximum withdrawable assets by previewing the redemption of all shares owned by the owner, which automatically accounts for fees.

#### Method: previewRedeem <a href="#method-previewredeem" id="method-previewredeem"></a>

Calculates the amount of assets that would be received for redeeming a given number of shares, accounting for redemption fees.

```
function previewRedeem(uint256 shares)
    public
    view
    override(ERC4626Upgradeable, ISEur0)
    returns (uint256 assets)
{
    SEur0StorageV0 storage $ = _seur0StorageV0();
    // Calculate the raw amount of assets for the given shares
    uint256 assetsWithFee = convertToAssets(shares);
    // Calculates the fee part of an amount `assets` that already includes fees.
    uint256 fee =
        Math.mulDiv(assetsWithFee, $.withdrawFeeBps, BASIS_POINT_BASE, Math.Rounding.Ceil);
    assets = assetsWithFee - fee;
}
```

1-5. Public view function overriding ERC4626 previewRedeem.\
6\. Retrieves storage pointer for SEur0StorageV0.\
7-8. Calculates the raw amount of assets represented by the shares (before fee deduction).\
10-11. Calculates the fee portion using ceiling rounding to ensure conservative estimates.\
12\. Subtracts the fee from the total assets to get the net assets the user will receive.

#### Method: updateWithdrawFee <a href="#method-updatewithdrawfee" id="method-updatewithdrawfee"></a>

Updates the withdrawal fee rate with proper access control and validation.

```
function updateWithdrawFee(uint256 newWithdrawFeeBps) external {
    SEur0StorageV0 storage $ = _seur0StorageV0();
    $.registryAccess.onlyMatchingRole(SEUR0_WITHDRAW_FEE_UPDATER_ROLE);
    if (newWithdrawFeeBps > MAX_25_PERCENT_WITHDRAW_FEE) {
        revert AmountTooBig();
    }
    if (newWithdrawFeeBps == $.withdrawFeeBps) {
        revert SameValue();
    }
    $.withdrawFeeBps = newWithdrawFeeBps;
    emit WithdrawFeeUpdated(newWithdrawFeeBps);
}
```

1. External function for updating withdrawal fee.\
   2-3. Retrieves storage pointer and validates caller has SEUR0\_WITHDRAW\_FEE\_UPDATER\_ROLE.\
   5-7. Validates new fee is below 25% maximum, preventing excessive fees.\
   9-11. Validates new fee is different from current fee, preventing unnecessary updates.
2. Updates the withdrawal fee in storage.
3. Emits an event to log the fee update.

#### Method: isBlacklisted <a href="#method-isblacklisted" id="method-isblacklisted"></a>

Checks if an address is currently blacklisted.

```
function isBlacklisted(address account) external view returns (bool) {
    SEur0StorageV0 storage $ = _seur0StorageV0();
    return $.isBlacklisted[account];
}
```

1. External view function to check blacklist status.
2. Retrieves storage pointer for SEur0StorageV0.
3. Returns the blacklist status for the given account.

#### Method: withdrawFeeBps <a href="#method-withdrawfeebps" id="method-withdrawfeebps"></a>

Returns the current withdrawal fee in basis points.

```
function withdrawFeeBps() public view returns (uint256) {
    SEur0StorageV0 storage $ = _seur0StorageV0();
    return $.withdrawFeeBps;
}
```

1. Public view function to retrieve withdrawal fee.
2. Retrieves storage pointer for SEur0StorageV0.
3. Returns the current withdrawal fee in basis points.

#### Method: getYieldRate <a href="#method-getyieldrate" id="method-getyieldrate"></a>

Returns the current yield rate used for yield distribution.

```
function getYieldRate() external view returns (uint256) {
    YieldDataStorage storage $ = _getYieldDataStorage();
    return $.yieldRate;
}
```

1. External view function to retrieve yield rate.
2. Retrieves yield data storage.
3. Returns the current yield rate value.


# Utility Contracts

<table data-card-size="large" data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center"><strong>Get infos on USD0(++) related oracles</strong></td><td data-object-fit="cover"><a href="/files/M7LOxu5bNwKAXpjktjOn">/files/M7LOxu5bNwKAXpjktjOn</a></td><td><a href="/pages/PYSsgZnHwVS85WrfLt8o">/pages/PYSsgZnHwVS85WrfLt8o</a></td></tr><tr><td align="center"><strong>Get infos on USD0a related oracles</strong></td><td><a href="/files/871eUjEeSeh2aY329gn6">/files/871eUjEeSeh2aY329gn6</a></td><td><a href="/pages/nXRyvT0EShCLiCsaLUGF">/pages/nXRyvT0EShCLiCsaLUGF</a></td></tr><tr><td align="center"><strong>Get infos on ETH0 related oracles</strong></td><td data-object-fit="cover"><a href="/files/W4jrYr88smmCbyrfBtSv">/files/W4jrYr88smmCbyrfBtSv</a></td><td><a href="/pages/q87wQW2hZaQIzqolSGBo">/pages/q87wQW2hZaQIzqolSGBo</a></td></tr><tr><td align="center"><strong>Get infos on EUR0 related oracles</strong></td><td><a href="/files/tsXVsyLZiTrv6dpyCkJl">/files/tsXVsyLZiTrv6dpyCkJl</a></td><td><a href="/pages/i8iXmvuzcclVTOkyCnaR">/pages/i8iXmvuzcclVTOkyCnaR</a></td></tr><tr><td align="center"><strong>Get infos on USUAL related oracles</strong></td><td data-object-fit="cover"><a href="/files/h8jo2gD7bWmuAruT9E3c">/files/h8jo2gD7bWmuAruT9E3c</a></td><td><a href="/pages/X194XmhBLFufluwPKXS4">/pages/X194XmhBLFufluwPKXS4</a></td></tr></tbody></table>


# USD0

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>What is the ClassicalOracle?</strong></td><td data-object-fit="cover"><a href="/files/ayHj7MHSh5BzFJ4j11pI">/files/ayHj7MHSh5BzFJ4j11pI</a></td><td><a href="/pages/VavVzfKhyYQmrBH1GWDO">/pages/VavVzfKhyYQmrBH1GWDO</a></td></tr><tr><td><strong>What is the Abstract Oracle?</strong></td><td data-object-fit="cover"><a href="/files/AIkjlyLrpNbjp7aQiAbF">/files/AIkjlyLrpNbjp7aQiAbF</a></td><td><a href="/pages/kZOhxdGxlLLFmcpPaNQY">/pages/kZOhxdGxlLLFmcpPaNQY</a></td></tr><tr><td><strong>What Oracles does Pyth provide?</strong></td><td data-object-fit="cover"><a href="/files/8cw1PnWhHGGV21yCcrXl">/files/8cw1PnWhHGGV21yCcrXl</a></td><td><a href="/pages/zTWFyyJjRgGUSahimZ2o">/pages/zTWFyyJjRgGUSahimZ2o</a></td></tr><tr><td><strong>What Oracles does Chainlink provide?</strong></td><td data-object-fit="cover"><a href="/files/kKagHZyi84MxG6zP26pm">/files/kKagHZyi84MxG6zP26pm</a></td><td></td></tr></tbody></table>


# USD0 ClassicalOracle

{% hint style="info" %}
Pricefeeds:

Chainlink USDC ETH: 0x8fffffd4afb6115b954bd326cbe7b4ba576818f6

Hashnote Oracle USYC ETH: 0x4c48bcb2160f8e0adbf9d4f3b034f1e36d1f8b3e
{% endhint %}

## High-Level Overview

The ClassicalOracle contract is used by DaoCollateral and the swapperEngine  to fetch the price of external tokens, i.e. RWAs and stablecoins.

The price of tokens is used for minting and redeeming the right amount of USD0.

It is an upgradable contract.

### Contract Summary

Most of the contract’s logic is inherited from AbstractOracle. Two responsibilities remain in ClassicalOracle itself:

* Initializing `tokenToOracleInfo` for each supported token with a ChainlinkV3Aggregator-compatible price feed
* Interacting with the aggregator to fetch the latest price and its number of decimals

### Inherited Contracts

* **IOracle**: Common interface used by other contracts and external service (e.g. the dApp) to interact with UsualOracle and ClassicalOracle. Ensures function signatures are the ones expected by these external actors.
* **AbstractOracle**: Encapsulates most of the logic and the implementation of public/external functions from IOracle.

## Functionality Breakdown

After deploying the contract, the administrator should initialize the price feed for all supported RWAs and stablecoins (i.e. USYC, USDC, and USDT).

When another contract or external service calls `getPrice` or `getQuote`, the inherited AbstractOracle contract calls the virtual function `_latestRoundData` passing the desired token as parameter. This function is implemented in ClassicalOracle and retrieves the associated price aggregator for this token, then calls `decimals` and `latestRoundData` which are returned to AbstractOracle.

#### Flow Diagram

<figure><img src="/files/SyIYgphomAarrDz9XQgQ" alt=""><figcaption></figcaption></figure>

### Functions Description

#### Public/External Functions

* **initializeTokenOracle(address token, address dataSource, uint64 timeout, bool isStablecoin)**: Registers a new supported token or updates the data source (price aggregator) for an existing token. The new price feed must have been last updated within the last `timeout` seconds. This check is only performed once. If `isStablecoin` is true, the depeg check will be enabled and `getPrice`/`getQuote` will revert if the price is not around $1.

Also see AbstractOracle for the other public/external functions.


# USD0 Abstract Oracle

## High-Level Overview

The AbstractOracle contract is inherited by the ClassicalOracle. It is not meant to be deployed on its own and is designed to safely be inherited by upgradable contracts, and upgradable contracts only.

### Contract Summary

The shared logic contained in AbstractOracle includes:

* Converting the price of the oracle of arbitrary decimals into wad (18 decimals)
* Computing a quote (USD value) for a given token and amount of tokens
* Making sure stablecoins haven’t depegged
* Allowing the admin to set the maximum allowed price variation for stablecoins

The inheriting contracts are responsible for initializing the `tokenToOracleInfo` mapping as well as implementing `_latestRoundData` to handle the specific interaction for the corresponding oracle.

#### Inherited Contracts

* **IOracle**: Common interface used by other contracts and external service (e.g. the dApp) to interact with UsualOracle and ClassicalOracle. Ensures function signatures are the ones expected by these external actors.
* **Initializable**: Allows to handle contract setup and upgrades.

## Functionality Breakdown

The main functionality of this contract is to get the price a given token by its address with `getPrice`. The AbstractOracle contract calls the virtual function `_latestRoundData`. It then converts the returned amount to 18 decimals. Finally, it runs the anti-depeg check for stablecoins.

The `getQuote` function calls `getPrice` internally, and then applies a cross-product to the amount given as parameter, yielding the final quote.

### Functions Description

#### Public/External Functions

* **getMaxDepegThreshold()**: Returns the current maximum allowed price variation for stablecoins in basis points (e.g. with a value of 500, `getPrice` and `getQuote` will revert if the price of a stablecoin is outside the range $0.95-$1.05). View function.
* **setMaxDepegThreshold(uint256 maxAuthorizedDepegPrice)**: Updates the maximum allowed price variation and emits a `SetMaxDepegThreshold` event. Nonpayable function. Reserved for admin use only.
* **getPrice(address token)**: Returns the price of the given token scaled to 18 decimals (e.g. a return value of 3e18 means the token price is $3). Reverts if the token is a stablecoin and it’s outside of the allowed price variation range. View function.
* **getQuote(address token)**: Returns the USD value equivalent to the given amount of the given token (e.g. if the token price is $3, calling with 1e6 will return 3e6, no matter the number of decimals of the token). Reverts if the token is a stablecoin and it’s outside of the allowed price variation range. View function.

### Remediation Strategies

* **Off-chain data sources:** We do not rely on on-chain oracles, such as Uniswap or Curve. These protocols could more easily be vulnerable to sandwich and/or flashloan attacks, enabling price manipulation.
* **Dual-oracle cross-verification**: *Not live yet, will require a future upgrade.* Drawing inspiration from [Liquity’s PriceFeed](https://github.com/liquity/dev/blob/main/packages/contracts/contracts/PriceFeed.sol), we could add a secondary oracle and compare prices between the two. This would reduce the impact of one of the two oracles getting hacked or freezing. We had implemented such a system, but didn’t find any other reliable price feed for USDC, USDT, nor USYC.


# Chainlink Oracles

[Chainlink](https://chain.link/), the standard for onchain finance, has provided us with USD0 and bUSD0 (formerly USD0++) price feeds that are available on Ethereum.

## USD0

{% embed url="<https://data.chain.link/feeds/ethereum/mainnet/usd0-usd>" %}
USD0/USD Pricefeed
{% endembed %}

Etherscan: [0x7e891DEbD8FA0A4Cf6BE58Ddff5a8ca174FebDCB](https://etherscan.io/address/0x7e891DEbD8FA0A4Cf6BE58Ddff5a8ca174FebDCB)

## bUSD0 (formerly USD0++)

Etherscan: [0xFC9e30Cf89f8A00dba3D34edf8b65BCDAdeCC1cB](https://etherscan.io/address/0xfc9e30cf89f8a00dba3d34edf8b65bcdadecc1cb)


# Pyth Oracles

[Pyth](https://www.pyth.network/), a leader in on-chain data provisioning, has provided us with USD0 and bUSD0 (formerly USD0++) price feeds which are available on more than 75 blockchains.

## USD0

{% embed url="<https://www.pyth.network/price-feeds/crypto-usd0-usd>" %}
USD0/USD Pricefeed
{% endembed %}

## bUSD0 (formerly USD0++)

{% embed url="<https://www.pyth.network/price-feeds/crypto-usd0%2B%2B-usd?cluster=pythnet&range=1D>" %}
bUSD0 (formerly USD0++)/USD Pricefeed
{% endembed %}


# USD0a

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>What is the ClassicalOracle?</strong></td><td data-object-fit="cover"><a href="/files/ayHj7MHSh5BzFJ4j11pI">/files/ayHj7MHSh5BzFJ4j11pI</a></td><td><a href="/pages/XHapxbExQuboh8yBWQDh">/pages/XHapxbExQuboh8yBWQDh</a></td></tr><tr><td>What is the DebtUSDC Oracle?</td><td><a href="/files/YNb8YIV3HxRQc2N76q71">/files/YNb8YIV3HxRQc2N76q71</a></td><td><a href="/pages/N12ydOaZGaMCfjXZuXPH">/pages/N12ydOaZGaMCfjXZuXPH</a></td></tr><tr><td>What is the DebtUSCC Oracle?</td><td><a href="/files/HXUG8hGJFFU2G0mnzpTq">/files/HXUG8hGJFFU2G0mnzpTq</a></td><td><a href="/pages/qzI70ygOODjZriYgEW7S">/pages/qzI70ygOODjZriYgEW7S</a></td></tr></tbody></table>


# USD0a Classical Oracle

## High-Level Overview

The ClassicalOracle contract is used by DaoCollateral to fetch the price of collaterals. This is also used for minting and redeeming the right amount of USD0a. It is an upgradable contract.

### Contract Summary

The logic contained in ClassicalOracle includes:

* Initializing `tokenToOracleInfo` for each supported token with a ChainlinkV3Aggregator-compatible price feed
* Converting the price of the oracle of arbitrary decimals into wad (18 decimals)
* Computing a quote (USD value) for a given token and amount of tokens
* Making sure stablecoins haven’t depegged
* Allowing the admin to set the maximum allowed price variation for stablecoins
* Interacting with the aggregator to fetch the latest price and its number of decimals

### Inherited Contracts

* **IOracle**: Common interface used by other contracts and external service (e.g. the dApp) to interact with the ClassicalOracle. Ensures function signatures are the ones expected by these external actors.
* **Initializable**: Allows to handle contract setup and upgrades.

## Functionality Breakdown

After deploying the contract, the administrator should initialize the price feed for all supported collateral thanks to the `initializeTokenOracle` function.

When another contract or external service calls `getPrice` or `getQuote`, the contract calls the virtual function `_latestRoundData` passing the desired token as parameter. This function is implemented in ClassicalOracle and retrieves the associated price aggregator for this token, then calls `decimals` and `latestRoundData.`

### Functions Description

#### Public/External Functions

* **initializeTokenOracle(address token, address dataSource, uint64 timeout, bool isStablecoin)**: Registers a new supported token or updates the data source (price aggregator) for an existing token. The new price feed must have been last updated within the last `timeout` seconds. This check is only performed once. If `isStablecoin` is true, the depeg check will be enabled and `getPrice`/`getQuote` will revert if the price is not around $1.
* **getMaxDepegThreshold()**: Returns the current maximum allowed price variation for stablecoins in basis points (e.g. with a value of 500, `getPrice` and `getQuote` will revert if the price of a stablecoin is outside the range $0.95-$1.05). View function.
* **setMaxDepegThreshold(uint256 maxAuthorizedDepegPrice)**: Updates the maximum allowed price variation and emits a `SetMaxDepegThreshold` event. Nonpayable function. Reserved for admin use only.
* **getPrice(address token)**: Returns the price of the given token scaled to 18 decimals (e.g. a return value of 3e18 means the token price is $3). Reverts if the token is a stablecoin and it’s outside of the allowed price variation range. View function.
* **getQuote(address token, uint256 amount)**: Returns the USD value equivalent to the given amount of the given token (e.g. if the token price is $3, calling with 1e6 will return 3e6, no matter the number of decimals of the token). Reverts if the token is a stablecoin and it’s outside of the allowed price variation range. View function.


# DebtUSDC Oracle

### High-Level Overview <a href="#high-level-overview" id="high-level-overview"></a>

The DebtUSDCOracle contract is a simple wrapper around the USDC/USD Chainlink price feed that implements a price cap mechanism. The contract ensures that the DebtUSDC token price never exceeds $1 USD, maintaining price stability and preventing oracle manipulation from affecting the protocol's debt token pricing.

### Contract Summary <a href="#contract-summary" id="contract-summary"></a>

The contract provides a Chainlink-compatible aggregator interface that:

* Wraps the underlying USDC/USD price feed
* Caps the maximum price at $1 USD (1e8 with 8 decimals)
* Returns price data in the standard Chainlink AggregatorV3Interface format

### Key Functionality <a href="#key-functionality" id="key-functionality"></a>

#### latestRoundData <a href="#latestrounddata" id="latestrounddata"></a>

Returns the latest price data from the USDC/USD feed with a price cap applied:

* If the USDC/USD feed price is at or below $1, returns the actual price
* If the USDC/USD feed price exceeds 1,returns1,returns1 as the maximum price

This ensures that DebtUSDC tokens maintain a stable price ceiling, preventing oracle anomalies or manipulation from causing the debt token price to exceed its intended value.

#### getRoundData <a href="#getrounddata" id="getrounddata"></a>

Not supported - reverts with `NotSupported` error. Only `latestRoundData` is available.

### Constants <a href="#constants" id="constants"></a>

* **PRICE\_FEED\_DECIMALS**: 8 (standard Chainlink decimals)
* **MAX\_USDC\_ORACLE\_PRICE**: 1e8 (represents $1.00 with 8 decimals)

### Immutable Variables <a href="#immutable-variables" id="immutable-variables"></a>

* **USDC\_USD\_FEED**: The underlying USDC/USD Chainlink price feed aggregator

### Use Case <a href="#use-case" id="use-case"></a>

The DebtUSDCOracle is used by the protocol to price DebtUSDC tokens. By capping the price at $1, the protocol ensures that debt tokens maintain their intended value relationship with USDC, preventing any oracle manipulation or price anomalies from affecting the protocol's accounting.


# DebtUSCC Oracle

### High-Level Overview <a href="#high-level-overview" id="high-level-overview"></a>

The DebtUSCCOracle contract is a proxy oracle that provides Chainlink-compatible price data for DebtUSCC tokens. Unlike a standard oracle wrapper, this contract returns the USCC/USD price from the time of the last deposit in the ReverseGateway contract, ensuring price consistency for all outstanding DebtUSCC tokens.

### Contract Summary <a href="#contract-summary" id="contract-summary"></a>

The contract provides a Chainlink-compatible aggregator interface that:

* Integrates with the ReverseGateway to track deposit timing
* Returns the USCC/USD price from the oracle round captured during the last deposit
* Maintains price consistency for all outstanding DebtUSCC tokens

### Key Functionality <a href="#key-functionality" id="key-functionality"></a>

#### latestRoundData <a href="#latestrounddata" id="latestrounddata"></a>

Returns the USCC/USD price data based on the last ReverseGateway deposit:

* **If no deposits exist** (nextOrderId == 1): Returns the latest price from the USCC/USD feed
* **If deposits exist**: Returns the price from the USCC/USD feed at the roundId captured during the last deposit

This design ensures that all outstanding DebtUSCC tokens are priced consistently at the same price point (the price when they were minted), maintaining accounting integrity and preventing price inconsistencies.

#### getRoundData <a href="#getrounddata" id="getrounddata"></a>

Not supported - reverts with `NotSupported` error. Only `latestRoundData` is available.

### Integration with ReverseGateway <a href="#integration-with-reversegateway" id="integration-with-reversegateway"></a>

The contract queries the ReverseGateway contract to:

1. Get the next order ID to determine if any deposits have occurred
2. Retrieve the roundId from the last order (if deposits exist)
3. Use that roundId to fetch the historical USCC/USD price from the oracle

This integration ensures that the DebtUSCC oracle price reflects the price at which the debt tokens were minted, maintaining consistency with the single deposit constraint in ReverseGateway.

### Constants <a href="#constants" id="constants"></a>

* **PRICE\_FEED\_DECIMALS**: 8 (standard Chainlink decimals)

### Immutable Variables <a href="#immutable-variables" id="immutable-variables"></a>

* **USCC\_USD\_FEED**: The underlying USCC/USD Chainlink price feed aggregator
* **REVERSE\_GATEWAY**: The ReverseGateway contract address

### Use Case <a href="#use-case" id="use-case"></a>

The DebtUSCCOracle is used by the protocol to price DebtUSCC tokens. By returning the price from the time of the last deposit, the oracle ensures that all outstanding DebtUSCC tokens maintain a consistent price point, which is critical for:

* Maintaining accounting accuracy
* Ensuring USD0a price stability
* Aligning with the single deposit constraint in ReverseGateway


# ETH0

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>What is the ETH0 ClassicalOracle?</strong></td><td data-object-fit="cover"><a href="/files/fTlLGXAs4ncZkkEY5I5b">/files/fTlLGXAs4ncZkkEY5I5b</a></td><td><a href="/pages/dlj87FoBDXPoiL6Gd1hw">/pages/dlj87FoBDXPoiL6Gd1hw</a></td></tr><tr><td><strong>What is the ETH0 Abstract Oracle?</strong></td><td data-object-fit="cover"><a href="/files/mnHmDKfeANvVZNcd6H3a">/files/mnHmDKfeANvVZNcd6H3a</a></td><td><a href="/pages/nsmD5FA1BRoDtSRjRfjJ">/pages/nsmD5FA1BRoDtSRjRfjJ</a></td></tr><tr><td><strong>What is the Lido wstETH Oracle about?</strong></td><td data-object-fit="cover"><a href="/files/VQNbBaclQ3SUzXmD91Aq">/files/VQNbBaclQ3SUzXmD91Aq</a></td><td><a href="/pages/xMqhTR3IwkZjSfoS0RM3">/pages/xMqhTR3IwkZjSfoS0RM3</a></td></tr></tbody></table>


# ETH0 Classical Oracle

## High-Level Overview

The ClassicalOracle contract is used by DaoCollateral to fetch the price of external tokens. The price of tokens is used for minting and redeeming the right amount of ETH0. It is an upgradable contract.

### Contract Summary

Most of the contract’s logic is inherited from AbstractOracle. Two responsibilities remain in ClassicalOracle itself:

* Initializing `tokenToOracleInfo` for each supported token with a ChainlinkV3Aggregator-compatible price feed
* Interacting with the aggregator to fetch the latest price and its number of decimals

### Inherited Contracts

* **IOracle**: Common interface used by other contracts and external service (e.g. the dApp) to interact with the ClassicalOracle. Ensures function signatures are the ones expected by these external actors.
* **AbstractOracle**: Encapsulates most of the logic and the implementation of public/external functions from IOracle.

## Functionality Breakdown

After deploying the contract, the administrator should initialize the price feed for all supported collateral.

When another contract or external service calls `getPrice` or `getQuote`, the inherited AbstractOracle contract calls the virtual function `_latestRoundData` passing the desired token as parameter. This function is implemented in ClassicalOracle and retrieves the associated price aggregator for this token, then calls `decimals` and `latestRoundData` which are returned to AbstractOracle.

#### Flow Diagram

<figure><img src="/files/SyIYgphomAarrDz9XQgQ" alt=""><figcaption></figcaption></figure>

### Functions Description

#### Public/External Functions

* **initializeTokenOracle(address token, address dataSource, uint64 timeout, bool isStablecoin)**: Registers a new supported token or updates the data source (price aggregator) for an existing token. The new price feed must have been last updated within the last `timeout` seconds. This check is only performed once. If `isStablecoin` is true, the depeg check will be enabled and `getPrice`/`getQuote` will revert if the price is not around $1.

Also see AbstractOracle for the other public/external functions.


# ETH0 Abstract Oracle

## High-Level Overview

The AbstractOracle contract is inherited by the ClassicalOracle. It is not meant to be deployed on its own and is designed to safely be inherited by upgradable contracts, and upgradable contracts only.

### Contract Summary

The shared logic contained in AbstractOracle includes:

* Converting the price of the oracle of arbitrary decimals into wad (18 decimals)
* Computing a quote (USD value) for a given token and amount of tokens
* Making sure stablecoins haven’t depegged
* Allowing the admin to set the maximum allowed price variation for stablecoins

The inheriting contracts are responsible for initializing the `tokenToOracleInfo` mapping as well as implementing `_latestRoundData` to handle the specific interaction for the corresponding oracle.

#### Inherited Contracts

* **IOracle**: Common interface used by other contracts and external service (e.g. the dApp) to interact with the ClassicalOracle. Ensures function signatures are the ones expected by these external actors.
* **Initializable**: Allows to handle contract setup and upgrades.

## Functionality Breakdown

The main functionality of this contract is to get the price a given token by its address with `getPrice`. The AbstractOracle contract calls the virtual function `_latestRoundData`. It then converts the returned amount to 18 decimals. Finally, it runs the anti-depeg check for stablecoins.

The `getQuote` function calls `getPrice` internally, and then applies a cross-product to the amount given as parameter, yielding the final quote.

### Functions Description

#### Public/External Functions

* **getMaxDepegThreshold()**: Returns the current maximum allowed price variation for stablecoins in basis points (e.g. with a value of 500, `getPrice` and `getQuote` will revert if the price of a stablecoin is outside the range $0.95-$1.05). View function.
* **setMaxDepegThreshold(uint256 maxAuthorizedDepegPrice)**: Updates the maximum allowed price variation and emits a `SetMaxDepegThreshold` event. Nonpayable function. Reserved for admin use only.
* **getPrice(address token)**: Returns the price of the given token scaled to 18 decimals (e.g. a return value of 3e18 means the token price is $3). Reverts if the token is a stablecoin and it’s outside of the allowed price variation range. View function.
* **getQuote(address token)**: Returns the USD value equivalent to the given amount of the given token (e.g. if the token price is $3, calling with 1e6 will return 3e6, no matter the number of decimals of the token). Reverts if the token is a stablecoin and it’s outside of the allowed price variation range. View function.

### Remediation Strategies

* **Off-chain data sources:** We do not rely on on-chain oracles, such as Uniswap or Curve. These protocols could more easily be vulnerable to sandwich and/or flashloan attacks, enabling price manipulation.
* **Dual-oracle cross-verification**: *Not live yet, will require a future upgrade.* Drawing inspiration from [Liquity’s PriceFeed](https://github.com/liquity/dev/blob/main/packages/contracts/contracts/PriceFeed.sol), we could add a secondary oracle and compare prices between the two. This would reduce the impact of one of the two oracles getting hacked or freezing.


# Lido wstETH Oracle

{% hint style="info" %}
The contract operates under the assumption that stETH maintains a 1:1 peg with ETH, as stETH represents staked ETH in the Lido protocol.
{% endhint %}

## High-Level Overview

The `LidoProxyWstETHPriceFeed` contract is a specialized oracle implementation that serves as a proxy for the Lido wstETH/ETH price feed. It implements the Chainlink AggregatorV3Interface to provide standardized price feed data for wstETH in terms of ETH, making it compatible with the broader Chainlink oracle ecosystem.

## Contract Summary

This contract acts as a wrapper around the Lido wstETH contract, converting the stETH per token ratio into a standardized price feed format. It maintains compatibility with the Chainlink AggregatorV3Interface while providing real-time wstETH/ETH price data.

### Key Features

1. **Chainlink Compatibility**

* Implements the AggregatorV3Interface
* Provides standardized price feed data structure
* Maintains consistent decimal precision (18 decimals)

2. **Real-time Price Data**

* Fetches live wstETH/ETH conversion rates from the Lido contract
* Updates price data on every query
* Provides both round-specific and latest price data

3. **Standardized Interface**

* Returns price data in a format compatible with Chainlink consumers
* Includes round information, timestamps, and price values
* Maintains consistent decimal precision across all operations

### Functions Description

#### Public/External Functions

* `decimals()`: Returns the number of decimals used in the price feed (18)
* `description()`: Returns the description of the price feed ("wstETH / ETH")
* `version()`: Returns the version of the price feed implementation (1)
* `getRoundData(uint80 roundId_)`: Returns historical price data for a specific round
* `latestRoundData()`: Returns the most recent price data

Returns:

* `roundId`: The latest round ID (always 1)
* `answer`: The current wstETH/ETH price
* `startedAt`: Current block timestamp
* `updatedAt`: Current block timestamp
* `answeredInRound`: The round ID (always 1)

#### State Variables

* `WST_ETH_CONTRACT`: Immutable address of the Lido wstETH contract
* `PRICE_FEED_DECIMALS`: Constant value of 18, representing the number of decimals used in price feed output

#### Error Handling

`InvalidDecimalsNumber()`: Thrown when the wstETH contract's decimals don't match the expected PRICE\_FEED\_DECIMALS (18)

### Security Considerations

1. I**mmutable Contract Address**

* The wstETH contract address is set during construction and cannot be changed
* Prevents potential manipulation of the price source

2. **Decimal Validation**

* Validates the wstETH contract's decimals during construction
* Ensures consistent decimal precision across the system

3. **Real-time Price Updates**

* Price data is fetched directly from the Lido contract on each query
* No stale price data is stored or returned

Integration Notes

1. **Chainlink Compatibility**

* Can be used as a drop-in replacement for Chainlink price feeds
* Compatible with any system expecting AggregatorV3Interface implementation

2. **Price Data Usage**

* The answer returned represents the wstETH/stETH exchange rate based on the `stEthPerToken()` function
* All price data is returned with 18 decimal precision
* Timestamps are based on block.timestamp for real-time accuracy

3. **Round Data**

* While the contract implements the round-based interface, it doesn't maintain historical round data
* All round queries return current price data with appropriate round identifiers


# EUR0

<table data-card-size="large" data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td align="center"><strong>What is the EUR0 ClassicalOracle?</strong></td><td><a href="/pages/WzQNw9TedlFddueGgEBq">/pages/WzQNw9TedlFddueGgEBq</a></td><td></td></tr><tr><td align="center"><strong>What is the CircleEURCOracle?</strong></td><td><a href="/pages/Q3fbzaDn4WoQ4p23c30z">/pages/Q3fbzaDn4WoQ4p23c30z</a></td><td></td></tr><tr><td align="center"><strong>What is the Monerium Swapper Helper?</strong></td><td></td><td><a href="/files/upj7w5guvCj1Zn4tS9YH">/files/upj7w5guvCj1Zn4tS9YH</a></td></tr></tbody></table>


# EUR0 Classical Oracle

{% hint style="info" %}
Unlike other Usual protocols, the ClassicalOracle contract has been merged with the AbstractOracle one
{% endhint %}

## High-Level Overview

The ClassicalOracle contract is used by DaoCollateral to fetch the price of external tokens. The price of tokens is used for minting and redeeming the right amount of EUR0. It is an upgradable contract.

### Contract Summary

The logic contained in ClassicalOracle includes:

* Initializing `tokenToOracleInfo` for each supported token with a ChainlinkV3Aggregator-compatible price feed
* Converting the price of the oracle of arbitrary decimals into wad (18 decimals)
* Computing a quote (USD value) for a given token and amount of tokens
* Making sure stablecoins haven’t depegged
* Allowing the admin to set the maximum allowed price variation for stablecoins
* Interacting with the aggregator to fetch the latest price and its number of decimals

### Inherited Contracts

* **IOracle**: Common interface used by other contracts and external service (e.g. the dApp) to interact with the ClassicalOracle. Ensures function signatures are the ones expected by these external actors.
* **Initializable**: Allows to handle contract setup and upgrades.

## Functionality Breakdown

After deploying the contract, the administrator should initialize the price feed for all supported collateral thanks to the `initializeTokenOracle` function.

When another contract or external service calls `getPrice` or `getQuote`, the contract calls the virtual function `_latestRoundData` passing the desired token as parameter. This function is implemented in ClassicalOracle and retrieves the associated price aggregator for this token, then calls `decimals` and `latestRoundData.`

### Functions Description

#### Public/External Functions

* **initializeTokenOracle(address token, address dataSource, uint64 timeout, bool isStablecoin)**: Registers a new supported token or updates the data source (price aggregator) for an existing token. The new price feed must have been last updated within the last `timeout` seconds. This check is only performed once. If `isStablecoin` is true, the depeg check will be enabled and `getPrice`/`getQuote` will revert if the price is not around $1.
* **getMaxDepegThreshold()**: Returns the current maximum allowed price variation for stablecoins in basis points (e.g. with a value of 500, `getPrice` and `getQuote` will revert if the price of a stablecoin is outside the range $0.95-$1.05). View function.
* **setMaxDepegThreshold(uint256 maxAuthorizedDepegPrice)**: Updates the maximum allowed price variation and emits a `SetMaxDepegThreshold` event. Nonpayable function. Reserved for admin use only.
* **getPrice(address token)**: Returns the price of the given token scaled to 18 decimals (e.g. a return value of 3e18 means the token price is $3). Reverts if the token is a stablecoin and it’s outside of the allowed price variation range. View function.
* **getQuote(address token)**: Returns the USD value equivalent to the given amount of the given token (e.g. if the token price is $3, calling with 1e6 will return 3e6, no matter the number of decimals of the token). Reverts if the token is a stablecoin and it’s outside of the allowed price variation range. View function.


# Circle EURC/EUR Oracle

### High-Level Overview

The CircleEurcOracle contract is a specialized oracle implementation that serves as a proxy for Circle EURC price feeds. It implements the Chainlink AggregatorV3Interface to provide standardized price feed data for EURC in terms of EUR (not USD), making it compatible with the broader Chainlink oracle ecosystem. **The aim of this oracle is to return a price of EURC in EUR and not in USD.**

### Contract Summary

This contract acts as a wrapper around two separate Chainlink price feeds (EURC/USD and EUR/USD), converting the USD-denominated prices into a standardized EURC/EUR price feed format. It maintains compatibility with the Chainlink AggregatorV3Interface while providing real-time EURC/EUR price data through cross-rate calculation.

### Key Features

#### Chainlink Compatibility

* Implements the AggregatorV3Interface
* Provides standardized price feed data structure
* Maintains consistent decimal precision (8 decimals)

#### Cross-Rate Price Calculation

* Fetches live EURC/USD and EUR/USD conversion rates from Chainlink feeds
* Calculates EURC/EUR price through cross-rate conversion: `EURC/EUR = (EURC/USD) / (EUR/USD)`
* Updates price data on every query using the most recent available data

#### Standardized Interface

* Returns price data in a format compatible with Chainlink consumers
* Includes round information, timestamps, and price values
* Maintains consistent decimal precision across all operations

### Functions Description

#### Public/External Functions

* **`decimals()`**: Returns the number of decimals used in the price feed (8)
* **`description()`**: Returns the description of the price feed ("EURC / EUR")
* **`version()`**: Returns the version of the price feed implementation (1)
* **`getRoundData(uint80 roundId_)`**: Returns historical price data for a specific round
* **`latestRoundData()`**: Returns the most recent price data

**Returns:**

* **roundId**: The round ID from the EURC/USD feed
* **answer**: The calculated EURC/EUR price
* **startedAt**: Timestamp from the EURC/USD feed
* **updatedAt**: Minimum timestamp between EURC/USD and EUR/USD feeds
* **answeredInRound**: The round ID from the EURC/USD feed

### State Variables

* **`EURC_USD_FEED`**: Immutable address of the EURC/USD Chainlink price feed
* **`EUR_USD_FEED`**: Immutable address of the EUR/USD Chainlink price feed
* **`PRICE_FEED_DECIMALS`**: Constant value of 8, representing the number of decimals used in price feed output

### Error Handling

* **InvalidDecimalsNumber()**: Thrown when either price feed's decimals don't match the expected PRICE\_FEED\_DECIMALS (8)

### Security Considerations

#### Immutable Contract Addresses

* Both price feed addresses are set during construction and cannot be changed
* Prevents potential manipulation of the price sources

#### Decimal Validation

* Validates both price feeds' decimals during construction
* Ensures consistent decimal precision across the system

#### Cross-Rate Calculation

* Price data is calculated in real-time using the latest available data from both feeds
* Uses the minimum timestamp between both feeds to ensure data freshness
* No stale price data is stored or returned

#### Price Feed Independence

* Relies on two independent Chainlink price feeds
* Reduces single points of failure in price discovery
* Provides more robust price data through cross-validation

### Integration Notes

#### Chainlink Compatibility

* Can be used as a drop-in replacement for Chainlink price feeds
* Compatible with any system expecting AggregatorV3Interface implementation

#### Price Data Usage

* The answer returned represents the EURC/EUR exchange rate calculated as: `(EURC/USD price) / (EUR/USD price)`
* All price data is returned with 8 decimal precision
* Timestamps are synchronized between both feeds for accuracy

#### Round Data

* Historical round data is based on the EURC/USD feed's round structure
* EUR/USD data is always fetched from the latest round for cross-rate calculation
* Round queries return calculated prices with appropriate round identifiers


# Monerium Swapper Helper

### **High-Level Overview**

The `SwapperHelper` contract is a helper utility that performs 1:1 swaps between a collateral token and a stablecoin on behalf of a user. It coordinates a three-way token movement where:

* The **caller** supplies stablecoin (EUR0) and receives collateral (EURe).
* The **recipient** supplies collateral (EURe) and receives stablecoin (EUR0).

The contract supports both standard ERC20 approvals and ERC20 Permit-based approvals (EIP-2612) for the collateral token, enabling gasless approval flows for EOAs. An optional `operator` role can be configured to restrict who is allowed to initiate swaps.

### **Contract Summary**

`SwapperHelper` sits between a collateral token (EURe) and a stablecoin (EUR0) and enforces a 1:1 exchange rate between them, assuming they share the same number of decimals. The contract.

### **Key Features**

**1:1 Swap Mechanism**

* Swaps collateral and stablecoin at a 1:1 rate, enforced by equal decimals on both tokens.
* The caller ends up with collateral; the recipient ends up with stablecoin.

**Permit-Based Approval Flow**

* `swapOnBehalfWithPermit` uses `IERC20Permit` to approve collateral spending via signature.
* Allows recipients to authorize swaps without an on-chain approval transaction (EOA only).

### **Functions Description**

#### **Public / External Functions**

* **`swapOnBehalfWithPermit(address recipient, uint256 maxAmount, uint256 deadline, uint8 v, bytes32 r, bytes32 s)`** \
  Performs a 1:1 swap using an ERC20 Permit signature for collateral.
  * **Parameters**:
    * `recipient`: Address providing collateral and receiving stablecoin.
    * `maxAmount`: Maximum collateral amount to swap (and stablecoin to transfer).
    * `deadline`: Permit deadline; reverts if `block.timestamp > deadline`.
    * `v`, `r`, `s`: ECDSA signature components for the permit.
  * **Requirements**:
    * `COLLATERAL_TOKEN` supports `permit`.
    * Signature must authorize `recipient` → `this` for `maxAmount` until `deadline`.
    * Caller must have approved sufficient stablecoin allowance to `this`.
    * `deadline` must not be expired; otherwise reverts with `DeadlineExpired()`.
    * Operator check must pass (see `_swapOnBehalf`).
* **`swapOnBehalf(address recipient, uint256 maxAmount)`** \
  Performs a 1:1 swap based on pre-existing ERC20 approvals (no permit).
  * **Parameters**:
    * `recipient`: Address providing collateral and receiving stablecoin.
    * `maxAmount`: Maximum collateral amount to swap (and stablecoin to transfer).
  * **Requirements**:
    * `recipient` must have approved this contract to spend collateral.
    * Caller must have approved this contract to spend stablecoin.
    * Operator check must pass.
* **`changeOperator(address newOperator)`** \
  Updates the `operator` address.
  * **Parameters**:
    * `newOperator`: New operator address (can be zero to make swaps permissionless).

### **State Variables**

* **`COLLATERAL_TOKEN`**\
  Collateral token is **EURe** and used in swaps (must implement `permit` for `swapOnBehalfWithPermit`).
* **`STABLECOIN`**\
  Stablecoin token is **EUR0** and used in swaps.
* **`operator`**\
  Optional operator address restricting who can initiate swaps. `address(0)` means permissionless.

### **Error Handling**

* **`NullAddress()`**: Thrown when a required address parameter is zero.
* **`DeadlineExpired()`**: Thrown when a provided permit deadline has already passed.
* **`ZeroAmount()`**: Thrown when a swap or recovery amount resolves to zero.
* **`NotAuthorized()`**: Thrown when a non-operator initiates a swap while an operator is configured.
* **`InsufficientBalance()`**: Thrown if stablecoin balance check after transfer fails, indicating an unexpected token behavior.
* **`InvalidDecimals()`**: Thrown in the constructor when collateral and stablecoin decimals differ.
* **`NotAllowed()`**: Thrown when attempting to renounce ownership.
* **`SameValue()`**: Thrown when collateral and stablecoin addresses are the same.

### **Security Considerations**

#### **Immutable Token References**

* `COLLATERAL_TOKEN` and `STABLECOIN` are `immutable` and set once in the constructor.
* Prevents arbitrary token reconfiguration.

#### **Decimal Consistency**

* Validates equal decimals for collateral and stablecoin at deployment.
* Ensures 1:1 swaps are value-consistent in token units.

#### **Operator Access Control**

* Optional operator limit reduces who can execute swaps in controlled environments.
* Owner can update the operator or set it to zero for permissionless use.

#### **Balance Verification**

* After transferring stablecoin from caller to contract, the contract checks that its balance increased as expected.
* Protects against non-standard ERC20 implementations that do not behave as expected.

#### **Reentrancy and Token Safety**

* Uses `SafeERC20` for all token transfers.
* The stablecoin and collateral transfers are ordered to minimize risk; the final transfer (`safeTransferFrom` of collateral) is from the recipient to the caller.
* Comments acknowledge arbitrary ERC20 sends, justified because the recipient is the intended beneficiary of stablecoin.

#### **Ownership Retention**

* Ownership cannot be renounced, ensuring a responsible address for operator and recovery actions.

#### **Token Recovery**

* Owner-only `recoverERC20` prevents tokens from being permanently stuck in the contract.

### **Integration Notes**

* **Token Requirements**
  * `COLLATERAL_TOKEN`:
    * Must be ERC20-compliant.
    * Must implement `IERC20Permit` for the permit-based swap function.
  * `STABLECOIN`:
    * Standard ERC20.
  * Both tokens must:
    * Have identical `decimals()`.
    * Be distinct addresses.
* **Using `swapOnBehalfWithPermit`**
  1. Recipient signs an ERC20 Permit approving this contract to spend up to `maxAmount` collateral.
  2. Caller provides the signature parameters and `maxAmount`.
  3. Contract attempts the permit (non-fatal if it fails) and then swaps up to the minimum of:
     * Recipient’s collateral allowance to the contract.
     * Recipient’s collateral balance.
     * Provided `maxAmount`.
* **Using `swapOnBehalf`**
  1. Recipient approves this contract to spend collateral.
  2. Caller approves this contract to spend stablecoin.
  3. Caller calls `swapOnBehalf(recipient, maxAmount)`.
  4. Swap executes for the capped amount as above.
* **Operator Configuration**
  * For open, permissionless swaps, deploy with `_operator = address(0)` or later call `changeOperator(address(0))`.
  * For controlled environments (e.g., only a specific router or backend), set `_operator` to that address.
* **Event Usage**
  * Listen to `SwapOnBehalf(caller, recipient, amount)` (defined in `ISwapperHelper`) to index executed swaps.
  * Listen to `OperatorChanged(newOperator)` to track operator role changes.


# USUAL

<table data-card-size="large" data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center"><strong>What Oracle does Redstone provide?</strong></td><td data-object-fit="cover"><a href="/files/u50PQRyN7fhxFs8t0PSR">/files/u50PQRyN7fhxFs8t0PSR</a></td><td><a href="/pages/mKPmbkMbBZ2jYQstOzu0">/pages/mKPmbkMbBZ2jYQstOzu0</a></td></tr></tbody></table>


# RedStone Oracle

[RedStone](https://www.redstone.finance/) is a leading oracle provider fulfilling the growing need for decentralized applications (dApps) to access data feeds that are frequently updated, reliable, and secure.

## USUAL

{% embed url="<https://app.redstone.finance/app/feeds/ethereum-mainnet/usual/>" %}
USUAL/USD Pricefeed
{% endembed %}

Etherscan: [0x2240AE461B34CC56D654ba5FA5830A243Ca54840](https://etherscan.io/address/0x2240AE461B34CC56D654ba5FA5830A243Ca54840)


# USD0 Collateral

<table data-card-size="large" data-column-title-hidden data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center"><strong>Get to know USYC</strong></td><td data-object-fit="cover"><a href="/files/dP4VdPjPoGdOZtPYxGPH">/files/dP4VdPjPoGdOZtPYxGPH</a></td><td><a href="/pages/ccQw6B8njaxteqnCyyKP">/pages/ccQw6B8njaxteqnCyyKP</a></td></tr><tr><td align="center"><strong>Get to know M</strong></td><td data-object-fit="cover"><a href="/files/ZFj1tFsHCZVCc5bG20mH">/files/ZFj1tFsHCZVCc5bG20mH</a></td><td><a href="/pages/0JoCqnNJtNkj2GolQJuj">/pages/0JoCqnNJtNkj2GolQJuj</a></td></tr><tr><td align="center"><strong>Get to know USDtb</strong></td><td data-object-fit="cover"><a href="/files/pBa6QSJ3awv4pgr6EdOJ">/files/pBa6QSJ3awv4pgr6EdOJ</a></td><td></td></tr><tr><td align="center">Get to know USDC</td><td data-object-fit="cover"><a href="/files/paim4M6My3rjBxu0FNat">/files/paim4M6My3rjBxu0FNat</a></td><td><a href="/pages/OganhkB0PfVF8ummionJ">/pages/OganhkB0PfVF8ummionJ</a></td></tr></tbody></table>


# USYC by Hashnote

## Who is Hashnote?

Hashnote is a regulated asset manager providing both US and International investors with customizable digital asset exposure.

More on [Hashnote](https://www.hashnote.com/).

## What is USYC?

USYC is the on-chain representation of the Hashnote International Short Duration Yield Fund Ltd. ("SDYF"). SDYF invests primarily in reverse repo and U.S. Government backed securities.

More on [USYC](https://usyc.hashnote.com/).<br>


# M by M0

## Who is M0?

M^0 is an on-chain protocol, as well as a set of off-chain standards and APIs, that allows multiple Minters to issue a fully fungible stablecoin called $M. Minters connect to the protocol to manage the supply of $M, while Validators support the process independently by providing near-constant information on the presence of off-chain collateral held in best-in-class storage structures. This coordination is underpinned by a novel governance mechanism called the Two Token Governor.

Website of [M0](https://www.m0.org).

## What is M?

$M is a fungible token that can be generated by a Minter by locking Eligible Collateral, currently short term T-bills, in a secure off-chain facility. Once generated, a Minter can then sell these tokens into the market. With selling and buying back these tokens at the price of $1, $M serves as a stablecoin, offering a stable, digital representation of the US dollar. $M can also be used as raw material to create other stablecoin products.

More on [M](https://www.m0.org/faqs).


# UsualM

## High-Level Overview

The **UsualM** smart contract manages the **UsualM ERC20 Token** and acts as a wrapped version of the **WrappedM** token (wrapped version of the M token). It allows users to wrap **WrappedM** tokens into **UsualM**, adding enhanced functionality such as pausability, blacklist enforcement, and mint cap restrictions. It also supports permits and implements role-based access control to ensure secure operations.

This contract is specifically designed to interact with the **WrappedM** token while enforcing access control through a **Registry Access Contract**. Key features include wrapping, unwrapping, minting, and pausing operations.

### Contract Summary

**UsualM** is an ERC-20 token with additional features that provide security and operational flexibility. It integrates with OpenZeppelin upgradeable modules for pausability and permit-based approvals. Moreover, it enforces blacklist restrictions to prevent interactions with malicious or sanctioned addresses and limits the maximum supply via a configurable mint cap.

#### **Inherited Contracts**

* **ERC20PausableUpgradeable**: Enables pausability of token transfers, ensuring operations can be halted in emergencies.
* **ERC20PermitUpgradeable**: Supports gasless approvals through EIP-2612 signatures, enabling off-chain approval of token transfers.
* **ERC20Upgradeable**: Provides the core ERC-20 token implementation.

### Functions Description

#### Public/External Functions

* **wrap(address recipient, uint256 amount):** Wraps the specified amount of **WrappedM** tokens into **UsualM** tokens for the `recipient`.
* **wrapWithPermit(address recipient, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s):** Wraps **WrappedM** tokens using a permit signature for approval, enabling gasless wrapping.
* **unwrap(address recipient, uint256 amount):** Unwraps **UsualM** tokens into **WrappedM** tokens, subject to role checks on the caller.
* **setMintCap(uint256 newMintCap):** Updates the mint cap for the token. Callable only by accounts with the `USUAL_M_MINTCAP_ALLOCATOR` role.
* **pause():** Pauses all token transfers. Callable only by accounts with the `USUAL_M_PAUSE` role.
* **unpause():** Resumes all token transfers. Callable only by accounts with the `USUAL_M_UNPAUSE` role.
* **blacklist(address account):** Blacklists an address, preventing it from interacting with the token. Callable only by accounts with the `BLACKLIST_ROLE`.
* **unBlacklist(address account):** Removes an address from the blacklist. Callable only by accounts with the `BLACKLIST_ROLE`.

## Functionality Breakdown

### SC-Flows

#### Key Functionalities

* **Wrapping:** Users can wrap **WrappedM** tokens into **UsualM**, making use of enhanced token features.
* **Unwrapping:** Users can unwrap **UsualM** tokens back into **WrappedM**, subject to role checks.
* **Mint Cap Enforcement:** Ensures that the total supply of **UsualM** tokens does not exceed the configured mint cap.
* **Blacklist Enforcement:** Prevents blacklisted addresses from participating in token transfers.
* **Pausability:** Allows administrators to halt all token transfers during emergencies.

### Constants

* **USUAL\_M\_UNWRAP:** Role required to unwrap tokens.
* **USUAL\_M\_PAUSE:** Role required to pause the contract.
* **USUAL\_M\_UNPAUSE:** Role required to unpause the contract.
* **USUAL\_M\_MINTCAP\_ALLOCATOR:** Role required to update the mint cap.
* **BLACKLIST\_ROLE:** Role required to blacklist/unblacklist accounts.

### Safeguards Implementation

* **Pausability:** The contract integrates pausability to ensure all token transfers can be halted in emergencies. Only accounts with the appropriate roles can pause/unpause the contract.
* **Role-Based Access Control:** Sensitive operations such as pausing, unwrapping, blacklisting, and updating the mint cap are restricted to accounts with specific roles. This ensures that only authorized entities can perform these operations.
* **Mint Cap Enforcement:** The total supply of **UsualM** tokens is capped by a configurable limit, ensuring supply control.
* **Blacklist Enforcement:** The contract prevents interactions with blacklisted addresses, safeguarding the token economy from malicious actors.


# USDtb by Ethena

## Who is Ethena?

Ethena is a pioneering synthetic dollar protocol built on the Ethereum blockchain, offering a crypto-native alternative to traditional financial systems. Its flagship product, USDe, is a synthetic dollar designed to provide stability and scalability without relying on conventional banking infrastructure.

Find out more about [Ethena](https://ethena.fi/).

## What is USDtb?

In December 2024, Ethena introduced USDtb, a stablecoin backed primarily by BlackRock's USD Institutional Digital Liquidity Fund (BUIDL). This fund invests in short-term U.S. government debt, cash, and repos, providing a stable and secure foundation for USDtb. The stablecoin's reserves are composed of approximately 90% BUIDL and 10% stablecoins like USDC to facilitate liquidity and redemptions. USDtb offers a distinct risk profile compared to Ethena's earlier synthetic dollar token, USDe, which utilizes a derivative-based trading strategy. By being fully backed by reserve assets, USDtb provides users with a more stable and reliable digital asset option.

More on [USDtb](https://usdtb.money/).


# UsualUSDtb

## High-Level Overview

The **UsualUSDTB** smart contract manages the **UsualUSDTB** ERC20 Token and acts as a wrapped version of the **USDTB** token. It allows users to wrap **USDTB** tokens into **UsualUSDTB**, adding enhanced functionality such as pausability, blacklist enforcement, and mint cap restrictions. It also supports permits and implements role-based access control to ensure secure operations.\
This contract is specifically designed to interact with the **USDTB** token while enforcing access control through a Registry Access Contract. Key features include wrapping, unwrapping, minting, and pausing operations.

### Contract Summary

**UsualUSDTB** is an ERC-20 token with additional features that provide security and operational flexibility. It integrates with OpenZeppelin upgradeable modules for pausability and permit-based approvals. Moreover, it enforces blacklist restrictions to prevent interactions with malicious or sanctioned addresses and limits the maximum supply via a configurable mint cap.

#### **Inherited Contracts**

* **ERC20PausableUpgradeable**: Enables pausability of token transfers, ensuring operations can be halted in emergencies.
* **ERC20PermitUpgradeable**: Supports gasless approvals through EIP-2612 signatures, enabling off-chain approval of token transfers.
* **ERC20Upgradeable**: Provides the core ERC-20 token implementation.

### Functions Description

#### Public/External Functions

* **wrap(address recipient, uint256 amount)**: Wraps the specified amount of **USDTB** tokens into **UsualUSDTB** tokens for the recipient.
* **wrapWithPermit(address recipient, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s)**: Wraps **USDTB** tokens using a permit signature for approval, enabling gasless wrapping.
* **unwrap(address recipient, uint256 amount)**: Unwraps **UsualUSDTB** tokens into **USDTB** tokens, subject to role checks on the caller.
* **setMintCap(uint256 newMintCap)**: Updates the mint cap for the token. Callable only by accounts with the **USUAL\_USDTB\_MINTCAP\_ALLOCATOR** role.
* **pause()**: Pauses all token transfers. Callable only by accounts with the **USUAL\_USDTB\_PAUSE** role.
* **unpause()**: Resumes all token transfers. Callable only by accounts with the **USUAL\_USDTB\_UNPAUSE** role.
* **blacklist(address account)**: Blacklists an address, preventing it from interacting with the token. Callable only by accounts with the **BLACKLIST\_ROLE**.
* **unBlacklist(address account)**: Removes an address from the blacklist. Callable only by accounts with the **BLACKLIST\_ROLE**.

## Functionality Breakdown

### SC-Flows

<figure><img src="/files/GKGoW1iPHqsW8uP9mcRG" alt=""><figcaption></figcaption></figure>

#### Key Functionalities

* **Wrapping**: Users can wrap **USDTB** tokens into **UsualUSDTB**, making use of enhanced token features.
* **Unwrapping**: Users can unwrap **UsualUSDTB** tokens back into **USDTB**, subject to role checks.
* **Mint Cap Enforcement**: Ensures that the total supply of **UsualUSDTB** tokens does not exceed the configured mint cap.
* **Blacklist Enforcement**: Prevents blacklisted addresses from participating in token transfers.
* **Pausability**: Allows administrators to halt all token transfers during emergencies.

### Constants

* **USUAL\_USDTB\_UNWRAP**: Role required to unwrap tokens.
* **USUAL\_USDTB\_PAUSE**: Role required to pause the contract.
* **USUAL\_USDTB\_UNPAUSE**: Role required to unpause the contract.
* **USUAL\_USDTB\_MINTCAP\_ALLOCATOR**: Role required to update the mint cap.
* **BLACKLIST\_ROLE**: Role required to blacklist/unblacklist accounts.
* **USUAL\_USDTB\_DECIMALS**: Set to 18 decimals for the token.

### Safeguards Implementation

* **Pausability**: The contract integrates pausability to ensure all token transfers can be halted in emergencies. Only accounts with the appropriate roles can pause/unpause the contract.
* **Role-Based Access Control**: Sensitive operations such as pausing, unwrapping, blacklisting, and updating the mint cap are restricted to accounts with specific roles. This ensures that only authorized entities can perform these operations.
* **Mint Cap Enforcement**: The total supply of **UsualUSDTB** tokens is capped by a configurable limit, ensuring supply control.
* **Blacklist Enforcement**: The contract prevents interactions with blacklisted addresses, safeguarding the token economy from malicious actors.
* **Safe Type Conversion**: The contract includes \_safe96() function to safely convert uint256 to uint96 for mint cap storage, preventing overflow issues.


# USDC by Circle

## Who is Circle?

Circle is a financial technology company that develops infrastructure for digital currencies and payments. It is the principal issuer of USDC and a founding member of the Centre Consortium, which governs the standards and policies around USDC issuance and usage.

Find out more about [Circle](https://www.circle.com/fr/about-circle).

## What is USDC?

USDC (USD Coin) is a fiat-backed stablecoin issued by Circle. Each USDC token is intended to be redeemable 1:1 for U.S. dollars, with reserves held in cash and short-duration U.S. government obligations. These reserves are held with regulated financial institutions, and Circle publishes regular attestations from third-party accounting firms to verify the backing of USDC in circulation.\
USDC is available on multiple blockchains and is used in a variety of applications, including payments, trading, decentralized finance (DeFi), and remittances.

More on [USDC](https://www.circle.com/fr/usdc).


# UsualUSDC

## High-Level Overview

The **UsualUSDC** smart contract manages the **UsualUSDC** ERC20 Token and acts as a wrapped version of the USDC token. It allows users to wrap USDC tokens into **UsualUSDC**, adding enhanced functionality such as pausability, blacklist enforcement, mint cap restrictions, redemption fees, and allowlist-based redemption controls. It also supports permits and implements role-based access control to ensure secure operations.\
This contract is specifically designed to interact with the USDC token while enforcing access control through a Registry Access Contract. Key features include wrapping, unwrapping with fee collection, minting, pausing operations, and redemption allowlist management.

### Contract Summary

**UsualUSDC** is an ERC-20 token with additional features that provide security, operational flexibility, and revenue generation capabilities. It integrates with OpenZeppelin upgradeable modules for pausability and permit-based approvals. Moreover, it enforces blacklist restrictions to prevent interactions with malicious or sanctioned addresses, limits the maximum supply via a configurable mint cap, implements redemption fees for revenue generation, and restricts unwrapping to allowlisted addresses only.

#### **Inherited Contracts**

* **ERC20PausableUpgradeable**: Enables pausability of token transfers, ensuring operations can be halted in emergencies.
* **ERC20PermitUpgradeable**: Supports gasless approvals through EIP-2612 signatures, enabling off-chain approval of token transfers.
* **ERC20Upgradeable**: Provides the core ERC-20 token implementation.

### Functions Description

#### Public/External Functions

Wrapping Functions:

* **wrap(address recipient, uint256 amount):** Wraps the specified amount of USDC tokens into **UsualUSDC** tokens for the recipient.
* **wrapWithPermit(address recipient, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s):** Wraps USDC tokens using a permit signature for approval, enabling gasless wrapping.

Unwrapping Functions:

* **unwrap(address recipient, uint256 amount):** Unwraps **UsualUSDC** tokens into USDC tokens, subject to allowlist checks and redemption fee collection.

Admin Functions:

* **setMintCap(uint256 newMintCap)**: Updates the mint cap for the token. Callable only by accounts with the **USUAL\_USDC\_MINTCAP\_ALLOCATOR** role.
* **pause()**: Pauses all token transfers. Callable only by accounts with the **USUAL\_USDC\_PAUSE** role.
* **unpause()**: Resumes all token transfers. Callable only by accounts with the **USUAL\_USDC\_UNPAUSE** role.
* **blacklist(address account)**: Blacklists an address, preventing it from interacting with the token. Callable only by accounts with the **BLACKLIST\_ROLE**.
* **unBlacklist(address account)**: Removes an address from the blacklist. Callable only by accounts with the **BLACKLIST\_ROLE**.

Redemption Management Functions:

* **addToRedemptionAllowList(address account)**: Adds an account to the redemption allowlist. Callable only by accounts with the **USUAL\_USDC\_REDEMPTION\_ROLE**.
* **removeFromRedemptionAllowList(address account)**: Removes an account from the redemption allowlist. Callable only by accounts with the **USUAL\_USDC\_REDEMPTION\_ROLE**.
* **setRedemptionFee(uint256 newRedemptionFeeBps)**: Sets the redemption fee in basis points. Callable only by accounts with the **USUAL\_USDC\_REDEMPTION\_ROLE**.
* **setFeeRecipient(address newFeeRecipient)**: Sets the fee recipient address. Callable only by accounts with the **USUAL\_USDC\_FEE\_RECIPIENT\_ROLE**.

## Functionality Breakdown

### SC-Flows

<figure><img src="/files/Cp1tUpYE7fEtvtMJprQn" alt=""><figcaption></figcaption></figure>

#### Key Functionalities

* **Wrapping**: Users can wrap USDC tokens into **UsualUSDC**, making use of enhanced token features.
* **Unwrapping** **with Fees**: Users can unwrap **UsualUSDC** tokens back into USDC, subject to allowlist checks and redemption fee collection.
* **Mint Cap Enforcement**: Ensures that the total supply of **UsualUSDC** tokens does not exceed the configured mint cap.
* **Blacklist Enforcement**: Prevents blacklisted addresses from participating in token transfers.
* **Pausability**: Allows administrators to halt all token transfers during emergencies.
* **Redemption Allowlist**: Restricts unwrapping functionality to allowlisted addresses only.
* **Fee Collection**: Implements configurable redemption fees for revenue generation.

### Constants

* **USUAL\_USDC\_PAUSE**: Role required to pause the contract.
* **USUAL\_USDC\_UNPAUSE**: Role required to unpause the contract.
* **USUAL\_USDC\_MINTCAP\_ALLOCATOR**: Role required to update the mint cap.
* **BLACKLIST\_ROLE**: Role required to blacklist/unblacklist accounts.
* **USUAL\_USDC\_REDEMPTION\_ROLE**: Role required to manage redemption allowlist and fees.
* **USUAL\_USDC\_FEE\_RECIPIENT\_ROLE**: Role required to update fee recipient.
* **USUAL\_USDC\_DECIMALS**: Token decimals (6, matching USDC).
* **BPS\_SCALAR**: Basis points scalar (10,000 for 100%).

### Safeguards Implementation

* **Pausability**: The contract integrates pausability to ensure all token transfers can be halted in emergencies. Only accounts with the appropriate roles can pause/unpause the contract.
* **Role-Based Access Control**: Sensitive operations such as pausing, blacklisting, updating the mint cap, managing redemption allowlist, and setting fees are restricted to accounts with specific roles. This ensures that only authorized entities can perform these operations.
* **Mint Cap Enforcement**: The total supply of **UsualUSDC** tokens is capped by a configurable limit, ensuring supply control.
* **Blacklist Enforcement**: The contract prevents interactions with blacklisted addresses, safeguarding the token economy from malicious actors.
* **Redemption Allowlist**: Unwrapping is restricted to allowlisted addresses only, providing additional control over who can redeem tokens.
* **Fee Collection**: Configurable redemption fees provide revenue generation while discouraging excessive unwrapping.
* **Input Validation**: Comprehensive checks for zero addresses, invalid amounts, and same-value operations prevent common errors and ensure data integrity.


# USD0a Collateral

<table data-card-size="large" data-column-title-hidden data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center"><strong>Get to know USTB</strong></td><td><a href="/files/l1uUsHSlrilK4FllCGos">/files/l1uUsHSlrilK4FllCGos</a></td><td><a href="/pages/qyIgBjpuk3ry3EeAAPnK">/pages/qyIgBjpuk3ry3EeAAPnK</a></td></tr><tr><td align="center"><strong>Get to know USCC</strong></td><td><a href="/files/PAKQBxTYjQa2LiD7FRO4">/files/PAKQBxTYjQa2LiD7FRO4</a></td><td><a href="/pages/UcG2JwFsMvcOUMCM354w">/pages/UcG2JwFsMvcOUMCM354w</a></td></tr><tr><td align="center">Get to know USDC</td><td data-object-fit="cover"><a href="/files/paim4M6My3rjBxu0FNat">/files/paim4M6My3rjBxu0FNat</a></td><td><a href="/pages/p1Ckq1EdprvLSqVP4yx0">/pages/p1Ckq1EdprvLSqVP4yx0</a></td></tr></tbody></table>


# USTB by Superstate

## Who is Superstate?

Superstate is an asset-management firm building regulated, tokenized investment products on blockchain. Its mission is to bridge traditional financial markets with crypto-native infrastructure, allowing investors to hold real-world assets directly on-chain.

Find out more about [Superstate](https://superstate.com/).

## What is USTB?

USTB is a tokenized fund backed primarily by short-duration U.S. Treasury bills. The fund holds high-quality government debt and cash, providing a conservative yield-bearing option for on-chain investors. Unlike synthetic or derivative-based products, USTB represents shares in a fully backed, regulated investment fund. By offering on-chain access to T-bills, USTB gives users a transparent and lower-risk way to hold dollar-based assets while earning short-term Treasury yields.

More on [USTB](https://superstate.com/assets/ustb).


# USCC by Superstate

## Who is Superstate?

Superstate is an asset-management firm building regulated, tokenized investment products on blockchain. Its mission is to bridge traditional financial markets with crypto-native infrastructure, allowing investors to hold real-world assets directly on-chain.

Find out more about [Superstate](https://superstate.com/).

## What is USCC?

USCC is the **Superstate Crypto Carry Fund**, tokenized as an ERC-20 (and in book-entry form), that executes a “cash-and-carry” strategy: it buys spot Bitcoin and Ether, and sells futures on those assets.\
It targets yield by exploiting the price differential between spot and futures markets, while remaining market-neutral (i.e., limited directional exposure). The fund is available to **qualified purchasers**

More on [USCC](https://superstate.com/assets/uscc).


# USDC by Circle

## Who is Circle?

Circle is a financial technology company that develops infrastructure for digital currencies and payments. It is the principal issuer of USDC and a founding member of the Centre Consortium, which governs the standards and policies around USDC issuance and usage.

Find out more about [Circle](https://www.circle.com/fr/about-circle).

## What is USDC?

USDC (USD Coin) is a fiat-backed stablecoin issued by Circle. Each USDC token is intended to be redeemable 1:1 for U.S. dollars, with reserves held in cash and short-duration U.S. government obligations. These reserves are held with regulated financial institutions, and Circle publishes regular attestations from third-party accounting firms to verify the backing of USDC in circulation.\
USDC is available on multiple blockchains and is used in a variety of applications, including payments, trading, decentralized finance (DeFi), and remittances.

More on [USDC](https://www.circle.com/fr/usdc).


# ETH0 Collateral

<table data-card-size="large" data-column-title-hidden data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center"><strong>Get to know wstETH by Lido</strong></td><td data-object-fit="cover"><a href="/files/lMOULbYeecyrLQ4cBXyY">/files/lMOULbYeecyrLQ4cBXyY</a></td><td><a href="/pages/tPNOAVmpuyJpGy81GcfL">/pages/tPNOAVmpuyJpGy81GcfL</a></td></tr></tbody></table>


# wstETH by Lido

## Who is Lido?

Lido is a leading liquid staking protocol built on the Ethereum blockchain, offering a secure and accessible way for users to stake their ETH while maintaining liquidity. As one of the largest staking providers in the Ethereum ecosystem, Lido enables users to earn staking rewards without the technical complexity or minimum requirements of running their own validator.

Find out more about [Lido](https://help.lido.fi/en/articles/5230607-what-is-lido).

## What is wstETH?

`wstETH` (Wrapped Staked ETH) is Lido's wrapped version of `stETH` (Staked ETH), designed to provide enhanced composability and integration capabilities within the DeFi ecosystem. When users stake their ETH through Lido, they receive `stETH`, which represents their staked ETH position. `wstETH` is then created by wrapping `stETH`, making it compatible with ERC-20 standards and easier to integrate with various DeFi protocols. This makes `wstETH` an ideal collateral asset for protocols like `ETH0`, as it combines the security of staked ETH with the flexibility of a wrapped token.

More on [wstETH](https://help.lido.fi/en/articles/5231836-what-is-lido-s-wsteth).


# EUR0 Collateral

<table data-card-size="large" data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center"><strong>Get to know EURTBL by Spiko</strong></td><td><a href="/files/AgRM3xBu72eIchnPC0hh">/files/AgRM3xBu72eIchnPC0hh</a></td><td><a href="/pages/bq0Pm9hmRyAIk9NhOfvK">/pages/bq0Pm9hmRyAIk9NhOfvK</a></td></tr></tbody></table>


# EUTBL by Spiko

### Who is Spiko?

Spiko is a financial technology company that specializes in tokenizing traditional financial instruments, particularly European Treasury Bills. They provide access to institutional-grade money market funds through blockchain technology, enabling users to participate in traditional financial markets while maintaining the benefits of decentralized finance.

Find out more about [Spiko](https://docs.spiko.io/documentation/intro/welcome/).

### What is EUTBL?

EUTBL (Spiko EU T-Bills) is Spiko's wrapped version of their EU T-Bills Money Market Fund, designed to provide enhanced composability and integration capabilities within the DeFi ecosystem. When users invest in Spiko's EU T-Bills Money Market Fund, they receive EUTBL tokens, which represent their position in the underlying European Treasury Bills. EUTBL is then created by wrapping the fund shares, making it compatible with ERC-20 standards and easier to integrate with various DeFi protocols. This makes EUTBL an ideal collateral asset for protocols like EUR0, as it combines the stability of European Treasury Bills with the flexibility of a wrapped token.

More on [EUTBL](https://www.spiko.io/spiko-euro).


# Contract Deployments

On this page we have collected all our smart contract deployments, so that you can easily verify their authenticity.

All our contracts are verified & their code is inspectable. They utilize transparent proxies, therefore you can see the implementation code/ABI, if you choose `Read/Write as Proxy` on Etherscan.

## Ethereum Mainnet

### USUAL

<table><thead><tr><th width="234">Contract Name</th><th>Address &#x26; Etherscan Link</th></tr></thead><tbody><tr><td>USUAL</td><td><a href="https://etherscan.io/address/0xC4441c2BE5d8fA8126822B9929CA0b81Ea0DE38E">0xC4441c2BE5d8fA8126822B9929CA0b81Ea0DE38E</a></td></tr><tr><td>USUALx</td><td><a href="https://etherscan.io/address/0x06B964d96f5dCF7Eae9d7C559B09EDCe244d4B8E">0x06B964d96f5dCF7Eae9d7C559B09EDCe244d4B8E</a></td></tr><tr><td>USUALS</td><td><a href="https://etherscan.io/address/0x094b360ae512a65584d4f5be33d68b2e08677b89">0x094B360AE512A65584d4f5Be33D68B2E08677b89</a></td></tr><tr><td>USUALSP</td><td><a href="https://etherscan.io/address/0xa55AF35E5F4bb6A82E0A290570BcE38Ce2757d37">0xa55AF35E5F4bb6A82E0A290570BcE38Ce2757d37</a></td></tr><tr><td>USUAL distribution</td><td><a href="https://etherscan.io/address/0x75cC0C0DDD2Ccafe6EC415bE686267588011E36A">0x75cC0C0DDD2Ccafe6EC415bE686267588011E36A</a></td></tr><tr><td>AirdropDistribution</td><td><a href="https://etherscan.io/address/0x89e813661628a277714C76d80c7fcB192a0896Ed">0x89e813661628a277714C76d80c7fcB192a0896Ed</a></td></tr><tr><td>AirdropTaxCollector</td><td><a href="https://etherscan.io/address/0xA6cd248943F3d3415458b264e2C890FF422A4c01">0xA6cd248943F3d3415458b264e2C890FF422A4c01</a></td></tr><tr><td>YieldModule</td><td><a href="https://etherscan.io/address/0x647F8987C288bf6D2fDb332918E1E14424839EDA">0x647F8987C288bf6D2fDb332918E1E14424839EDA</a></td></tr><tr><td>UsualX Lockup</td><td><a href="https://etherscan.io/address/0x85B6F9BDdb10c6B320d07416a250F984f0F0E9ED#code">0x85b6f9bddb10c6b320d07416a250f984f0f0e9ed</a></td></tr></tbody></table>

### USD0

<table><thead><tr><th width="234">Contract Name</th><th>Address &#x26; Etherscan Link</th></tr></thead><tbody><tr><td>USD0</td><td><a href="https://etherscan.io/address/0x73A15FeD60Bf67631dC6cd7Bc5B6e8da8190aCF5">0x73A15FeD60Bf67631dC6cd7Bc5B6e8da8190aCF5</a></td></tr><tr><td>bUSD0 (formerly USD0++)</td><td><a href="https://etherscan.io/token/0x35D8949372D46B7a3D5A56006AE77B215fc69bC0">0x35D8949372D46B7a3D5A56006AE77B215fc69bC0</a></td></tr><tr><td>rt-bUSD0</td><td><a href="https://etherscan.io/token/0x82DCA22b48B14DE38ccf83B03330120c4b8acFe9">0x82DCA22b48B14DE38ccf83B03330120c4b8acFe9</a></td></tr><tr><td>sUSD0</td><td><a href="https://etherscan.io/address/0xd861bE82dEe3223CFBEd160791f6550b0704D406">0xd861bE82dEe3223CFBEd160791f6550b0704D406</a></td></tr><tr><td>DaoCollateral</td><td><a href="https://etherscan.io/address/0xde6e1F680C4816446C8D515989E2358636A38b04">0xde6e1F680C4816446C8D515989E2358636A38b04</a></td></tr><tr><td>SwapperEngine</td><td><a href="https://etherscan.io/address/0xB969B0d14F7682bAF37ba7c364b351B830a812B2">0xB969B0d14F7682bAF37ba7c364b351B830a812B2</a></td></tr><tr><td>TokenMapping</td><td><a href="https://etherscan.io/address/0x43882C864a406D55411b8C166bCA604709fDF624">0x43882C864a406D55411b8C166bCA604709fDF624</a></td></tr><tr><td>RegistryAccess</td><td><a href="https://etherscan.io/address/0x0D374775E962c3608B8F0A4b8B10567DF739bb56">0x0D374775E962c3608B8F0A4b8B10567DF739bb56</a></td></tr><tr><td>RegistryContract</td><td><a href="https://etherscan.io/address/0x0594cb5ca47eFE1Ff25C7B8B43E221683B4Db34c">0x0594cb5ca47eFE1Ff25C7B8B43E221683B4Db34c</a></td></tr><tr><td>ClassicalOracle</td><td><a href="https://etherscan.io/address/0xb97e163cE6A8296F36112b042891CFe1E23C35BF">0xb97e163cE6A8296F36112b042891CFe1E23C35BF</a></td></tr><tr><td>Chainlink USD0 Oracle</td><td><a href="https://etherscan.io/address/0x7e891DEbD8FA0A4Cf6BE58Ddff5a8ca174FebDCB">0x7e891DEbD8FA0A4Cf6BE58Ddff5a8ca174FebDCB</a></td></tr><tr><td>Chainlink bUSD0 (formerly USD0++) Oracle</td><td><a href="https://etherscan.io/address/0xfc9e30cf89f8a00dba3d34edf8b65bcdadecc1cb">0xFC9e30Cf89f8A00dba3D34edf8b65BCDAdeCC1cB</a></td></tr><tr><td>USD0RewardsClaim</td><td><a href="https://etherscan.io/address/0xB3911C121909736A9C1a76e5Cf078D19a3E7d233">0xB3911C121909736A9C1a76e5Cf078D19a3E7d233</a></td></tr><tr><td>Revenue Distribution Module</td><td><a href="https://etherscan.io/address/0x6ec631c19372d5a9345Ec4aeED93BA9eb0A45F77">0x6ec631c19372d5a9345Ec4aeED93BA9eb0A45F77</a></td></tr></tbody></table>

### USD0a

<table><thead><tr><th width="234">Contract Name</th><th>Address &#x26; Etherscan Link</th></tr></thead><tbody><tr><td>USD0a</td><td><a href="https://etherscan.io/address/0x2e7fC02bE94BC7f0cD69DcAB572F64bcC173cd81">0x2e7fC02bE94BC7f0cD69DcAB572F64bcC173cd81</a></td></tr><tr><td>DaoCollateral</td><td><a href="https://etherscan.io/address/0xecD854A1a0ddd5f35F2F24eC3605D8BAebF77039">0xecD854A1a0ddd5f35F2F24eC3605D8BAebF77039</a></td></tr><tr><td>SwapperEngine</td><td><a href="https://etherscan.io/address/0x51B18b90A81a7Ff90FA5e7968358aAb18D479f4e">0x51B18b90A81a7Ff90FA5e7968358aAb18D479f4e</a></td></tr><tr><td>TokenMapping</td><td><a href="https://etherscan.io/address/0x9D99EA108550f7777348bfA49e79589DB2a7d6e5">0x9D99EA108550f7777348bfA49e79589DB2a7d6e5</a></td></tr><tr><td>RegistryAccess</td><td><a href="https://etherscan.io/address/0xe4B1a03087D5BcB56d4fD6aF8267278246C0b982">0xe4B1a03087D5BcB56d4fD6aF8267278246C0b982</a></td></tr><tr><td>RegistryContract</td><td><a href="https://etherscan.io/address/0xd1014B9517E5A8D1f61812484a8553eEe8845309">0xd1014B9517E5A8D1f61812484a8553eEe8845309</a></td></tr><tr><td>ClassicalOracle</td><td><a href="https://etherscan.io/address/0xaA3E78B52E5003a7f82a7ef1C01447028e669fAE">0xaA3E78B52E5003a7f82a7ef1C01447028e669fAE</a></td></tr><tr><td>Gateway</td><td><a href="https://etherscan.io/address/0xaAF8c2ae29190D6F886115b92b6b1Fcd513931Ab">0xaAF8c2ae29190D6F886115b92b6b1Fcd513931Ab</a></td></tr><tr><td>DebtUSDC Token</td><td><a href="https://etherscan.io/address/0xcbA56BB5FECc6A3d35393F8dffdd28Af02EF1748">0xcbA56BB5FECc6A3d35393F8dffdd28Af02EF1748</a></td></tr><tr><td>DebtUSDC Oracle</td><td><a href="https://etherscan.io/address/0x28b5735de1990d5c3c5dfb4ad7d2496579e1f5ea">0x28b5735dE1990d5C3c5Dfb4Ad7D2496579e1f5Ea</a></td></tr><tr><td>CircleUSDC Oracle</td><td><a href="https://etherscan.io/address/0x2ad0Eb228cCF87FcBeC4F85a779Aa61CD6784bEC">0x2ad0Eb228cCF87FcBeC4F85a779Aa61CD6784bEC</a></td></tr></tbody></table>

### EUR0

<table><thead><tr><th width="234">Contract Name</th><th>Address &#x26; Etherscan Link</th></tr></thead><tbody><tr><td>EUR0</td><td><a href="https://etherscan.io/address/0x3c89Cd1884E7beF73ca3ef08d2eF6EC338fD8E49">0x3c89Cd1884E7beF73ca3ef08d2eF6EC338fD8E49</a></td></tr><tr><td>sEUR0</td><td><a href="https://etherscan.io/address/0x35f43C6604B0DE814ABAa2D94C878BD1F5165478">0x35f43C6604B0DE814ABAa2D94C878BD1F5165478</a></td></tr><tr><td>DaoCollateral</td><td><a href="https://etherscan.io/address/0xB9677b45BffBE3d586D2AE2cbCD1775577B166D1">0xB9677b45BffBE3d586D2AE2cbCD1775577B166D1</a></td></tr><tr><td>SwapperEngine</td><td><a href="https://etherscan.io/address/0x46c023cbBdFffed1A3A3ef0C915610DEEb14847A">0x46c023cbBdFffed1A3A3ef0C915610DEEb14847A</a></td></tr><tr><td>TokenMapping</td><td><a href="https://etherscan.io/address/0xf20Ba8F5195fCC094d94a937F0d2719f6Da14A4a">0xf20Ba8F5195fCC094d94a937F0d2719f6Da14A4a</a></td></tr><tr><td>RegistryAccess</td><td><a href="https://etherscan.io/address/0x65771978FF9238162a41c77384c9F55C1eC9e9Ab">0x65771978FF9238162a41c77384c9F55C1eC9e9Ab</a></td></tr><tr><td>RegistryContract</td><td><a href="https://etherscan.io/address/0x2b98Bbb548eE8F442F63A92a06a1CDb5f5bd52AF">0x2b98Bbb548eE8F442F63A92a06a1CDb5f5bd52AF</a></td></tr><tr><td>ClassicalOracle</td><td><a href="https://etherscan.io/address/0x3b4b5CB9865A354d6c3faaDDD8753a2e55D60546">0x3b4b5CB9865A354d6c3faaDDD8753a2e55D60546</a></td></tr><tr><td>Circle EURC/EUR Oracle</td><td><a href="https://etherscan.io/address/0x2A02fDaB11F05D5b16B16E01e140a8AF12A5F69B">0x2A02fDaB11F05D5b16B16E01e140a8AF12A5F69B</a></td></tr><tr><td>YieldModule</td><td><a href="https://etherscan.io/address/0x042d3c300C547aE60d6a5B3bc62D6FbDA7DBf59D">0x042d3c300C547aE60d6a5B3bc62D6FbDA7DBf59D</a></td></tr><tr><td>Revenue Distribution Module</td><td><a href="https://etherscan.io/address/0x78331cC94BbF86293bDa80cA10463812b1E73179">0x78331cC94BbF86293bDa80cA10463812b1E73179</a></td></tr><tr><td>Monerium Swapper Helper</td><td><a href="https://etherscan.io/address/0x7a03038711d8905c8a7f56b857777dea1447a2f0">0x7a03038711d8905c8a7f56b857777dea1447a2f0</a></td></tr></tbody></table>

### ETH0

<table><thead><tr><th width="234">Contract Name</th><th>Address &#x26; Etherscan Link</th></tr></thead><tbody><tr><td>ETH0</td><td><a href="https://etherscan.io/address/0x734eec7930bc84ec5732022b9eb949a81fb89abe">0x734eec7930bc84ec5732022b9eb949a81fb89abe</a></td></tr><tr><td>DaoCollateral</td><td><a href="https://etherscan.io/address/0xAAD0a80fB8F0DA4799E457b5Ae8EA70Fa61a45fc">0xAAD0a80fB8F0DA4799E457b5Ae8EA70Fa61a45fc</a></td></tr><tr><td>TokenMapping</td><td><a href="https://etherscan.io/address/0x934F166Aec37a02AA213D93394243b231fc5b4B9">0x934F166Aec37a02AA213D93394243b231fc5b4B9</a></td></tr><tr><td>RegistryAccess</td><td><a href="https://etherscan.io/address/0x6d2A468450ACf416791B12109f15797B1944152F">0x6d2A468450ACf416791B12109f15797B1944152F</a></td></tr><tr><td>RegistryContract</td><td><a href="https://etherscan.io/address/0xfE35066Ce9b91026E0C0056d6F4520e409B793cA">0xfE35066Ce9b91026E0C0056d6F4520e409B793cA</a></td></tr><tr><td>ClassicalOracle</td><td><a href="https://etherscan.io/address/0x8a03c57069A25C7E6e62e9C0d03a2CC10A74b1a7">0x8a03c57069A25C7E6e62e9C0d03a2CC10A74b1a7</a></td></tr><tr><td>Lido wstETH Oracle</td><td><a href="https://etherscan.io/address/0xEB9B65345B1eeD32153Ef85D97874c1aD98e5DC4">0xEB9B65345B1eeD32153Ef85D97874c1aD98e5DC4</a></td></tr></tbody></table>

### Treasuries

<table><thead><tr><th width="234">Contract Name</th><th>Address &#x26; Etherscan Link</th></tr></thead><tbody><tr><td>Collateral treasury</td><td><a href="https://etherscan.io/address/0xdd82875f0840AAD58a455A70B88eEd9F59ceC7c7">0xdd82875f0840AAD58a455A70B88eEd9F59ceC7c7</a></td></tr><tr><td>Yield Treasury</td><td><a href="https://etherscan.io/address/0x81ad394C0Fa87e99Ca46E1aca093BEe020f203f4">0x81ad394C0Fa87e99Ca46E1aca093BEe020f203f4</a></td></tr><tr><td>Longterm Treasury</td><td><a href="https://etherscan.io/address/0xF3D913De4B23ddB9CfdFAF955BAC5634CbAE95F4">0xF3D913De4B23ddB9CfdFAF955BAC5634CbAE95F4</a></td></tr><tr><td>USD0a Collateral Treasury</td><td><a href="https://etherscan.io/address/0xbfBE929807cADbc3fd5191800DFB10454ff5c792">0xbfBE929807cADbc3fd5191800DFB10454ff5c792</a></td></tr><tr><td>USD0a Yield Treasury</td><td><a href="https://etherscan.io/address/0x81ad394C0Fa87e99Ca46E1aca093BEe020f203f4">0x81ad394C0Fa87e99Ca46E1aca093BEe020f203f4</a></td></tr><tr><td>EUR0 Collateral Treasury</td><td><a href="https://etherscan.io/address/0x11D75bC93aE69350231D8fF0F5832A697678183E">0x11D75bC93aE69350231D8fF0F5832A697678183E</a></td></tr><tr><td>EUR0 Yield Treasury</td><td><a href="https://etherscan.io/address/0x81ad394C0Fa87e99Ca46E1aca093BEe020f203f4">0x81ad394C0Fa87e99Ca46E1aca093BEe020f203f4</a></td></tr></tbody></table>

## Arbitrum One

<table><thead><tr><th width="233">Contract Name</th><th>Address &#x26; ArbiScan Link</th></tr></thead><tbody><tr><td>RegistryAccess</td><td><a href="https://arbiscan.io/address/0x168BA269fc6CDe6115F3b03C94F55831165D374F">0x168BA269fc6CDe6115F3b03C94F55831165D374F</a></td></tr><tr><td>RegistryContract</td><td><a href="https://arbiscan.io/address/0x3F44A0D493Ef5ae030fCf36a2b5d4365fb22BC4A">0x3F44A0D493Ef5ae030fCf36a2b5d4365fb22BC4A</a></td></tr><tr><td>USD0</td><td><a href="https://arbiscan.io/address/0x35f1C5cB7Fb977E669fD244C567Da99d8a3a6850#code">0x35f1C5cB7Fb977E669fD244C567Da99d8a3a6850</a></td></tr><tr><td>bUSD0 (formerly USD0++)</td><td><a href="https://arbiscan.io/address/0x2B65F9d2e4B84a2dF6ff0525741b75d1276a9C2F">0x2B65F9d2e4B84a2dF6ff0525741b75d1276a9C2F</a></td></tr><tr><td>USUAL</td><td><a href="https://arbiscan.io/address/0x6A5D904519A2b605Da2D5DA7137ED5F4184F6513">0x6A5D904519A2b605Da2D5DA7137ED5F4184F6513</a></td></tr></tbody></table>

## BASE

<table><thead><tr><th width="233">Contract Name</th><th>Address &#x26; BaseScan Link</th></tr></thead><tbody><tr><td>RegistryAccess</td><td><a href="https://basescan.org/address/0x2EF13d2626bb115A46eBD72475C0be7f56Cdf013">0x2EF13d2626bb115A46eBD72475C0be7f56Cdf013</a></td></tr><tr><td>RegistryContract</td><td><a href="https://basescan.org/address/0xB4c3f4cA17FAF31C0A5186A2ddA19Dbc26cE04e0">0xB4c3f4cA17FAF31C0A5186A2ddA19Dbc26cE04e0</a></td></tr><tr><td>USD0</td><td><a href="https://basescan.org/address/0x758a3e0b1F842C9306B783f8A4078C6C8C03a270">0x758a3e0b1F842C9306B783f8A4078C6C8C03a270</a></td></tr><tr><td>USUAL</td><td><a href="https://basescan.org/address/0x4ACD4D03af6F9cc0fB7C5f0868B7b6287D7969c5">0x4ACD4D03af6F9cc0fB7C5f0868B7b6287D7969c5</a></td></tr></tbody></table>

## BNB Chain

<table><thead><tr><th width="233">Contract Name</th><th>Address &#x26; BscScan Link</th></tr></thead><tbody><tr><td>RegistryAccess</td><td><a href="https://bscscan.com/address/0x2EF13d2626bb115A46eBD72475C0be7f56Cdf013">0x2EF13d2626bb115A46eBD72475C0be7f56Cdf013</a></td></tr><tr><td>RegistryContract</td><td><a href="https://bscscan.com/address/0xB4c3f4cA17FAF31C0A5186A2ddA19Dbc26cE04e0">0xB4c3f4cA17FAF31C0A5186A2ddA19Dbc26cE04e0</a></td></tr><tr><td>USD0</td><td><a href="https://bscscan.com/address/0x758a3e0b1f842c9306b783f8a4078c6c8c03a270#code">0x758a3e0b1f842c9306b783f8a4078c6c8c03a270</a></td></tr><tr><td>USUAL</td><td><a href="https://bscscan.com/address/0x4ACD4D03af6F9cc0fB7C5f0868B7b6287D7969c5">0x4ACD4D03af6F9cc0fB7C5f0868B7b6287D7969c5</a></td></tr></tbody></table>

## TAC

<table><thead><tr><th width="233">Contract Name</th><th>Address &#x26; BscScan Link</th></tr></thead><tbody><tr><td>RegistryAccess</td><td><a href="https://explorer.tac.build/address/0xB4c3f4cA17FAF31C0A5186A2ddA19Dbc26cE04e0">0xB4c3f4cA17FAF31C0A5186A2ddA19Dbc26cE04e0</a></td></tr><tr><td>RegistryContract</td><td><a href="https://explorer.tac.build/address/0x9D9b970be71AD9d0b8Fa7A018B7Ab53dbf17D1C6">0x9D9b970be71AD9d0b8Fa7A018B7Ab53dbf17D1C6</a></td></tr><tr><td>USD0</td><td><a href="https://explorer.tac.build/address/0x9bB6983Ca454320BD8691409690B4FCCD489EE96">0x9bB6983Ca454320BD8691409690B4FCCD489EE96</a></td></tr><tr><td>bUSD0 (formerly USD0++)</td><td><a href="https://explorer.tac.build/address/0x1791BAff6a5e2F2A1340e8B7C1EA2B0c1E2DD1ea">0x1791BAff6a5e2F2A1340e8B7C1EA2B0c1E2DD1ea</a></td></tr></tbody></table>

## Real World Assets

<table><thead><tr><th width="239">Contract Name</th><th width="355">Address &#x26; Explorer Link</th><th width="263">Chain</th></tr></thead><tbody><tr><td>USYC</td><td><a href="https://etherscan.io/address/0x136471a34f6ef19fE571EFFC1CA711fdb8E49f2b">0x136471a34f6ef19fE571EFFC1CA711fdb8E49f2b</a></td><td>Ethereum</td></tr><tr><td>M by M0</td><td><a href="https://etherscan.io/token/0x866a2bf4e572cbcf37d5071a7a58503bfb36be1b">0x866A2BF4E572CbcF37D5071A7a58503Bfb36be1b</a></td><td>Ethereum</td></tr><tr><td>UsualM (Wrapped M)</td><td><a href="https://etherscan.io/token/0x4Cbc25559DbBD1272EC5B64c7b5F48a2405e6470">0x4Cbc25559DbBD1272EC5B64c7b5F48a2405e6470</a></td><td>Ethereum</td></tr><tr><td>USDtb</td><td><a href="https://etherscan.io/token/0xC139190F447e929f090Edeb554D95AbB8b18aC1C?a=0x58073531a2809744d1bf311d30fd76b27d662abb">0xC139190F447e929f090Edeb554D95AbB8b18aC1C</a></td><td>Ethereum</td></tr><tr><td>UsualUSDtb</td><td><a href="https://etherscan.io/address/0x58073531a2809744d1bf311d30fd76b27d662abb">0x58073531a2809744D1bF311D30FD76B27D662abB</a></td><td>Ethereum</td></tr><tr><td>USDC</td><td><a href="https://etherscan.io/token/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48">0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48</a></td><td>Ethereum</td></tr><tr><td>UsualUSDC</td><td><a href="https://etherscan.io/address/0xb672b3976baa3952bfb2ece8eefb784f8dab1424#readProxyContract">0xb672B3976bAa3952bFb2eCE8eeFB784f8daB1424</a></td><td>Ethereum</td></tr><tr><td>euTBL</td><td><a href="https://etherscan.io/token/0xa0769f7a8fc65e47de93797b4e21c073c117fc80">0xa0769f7a8fc65e47de93797b4e21c073c117fc80</a></td><td>Ethereum</td></tr></tbody></table>

## bUSD0 (formerly USD0++) Investment Vaults

deployed and curated by Usual (more info [here](https://tech.usual.money/smart-contracts/token-contracts/usual-usd0++-investment-vault))

<table><thead><tr><th width="239">Contract Name</th><th width="355">Address &#x26; Explorer Link</th><th width="263">Chain</th></tr></thead><tbody><tr><td>usUSDS++</td><td><a href="https://etherscan.io/address/0x67ec31a47a4126A66C7bb2fE017308cf5832A4Db">0x67ec31a47a4126A66C7bb2fE017308cf5832A4Db</a></td><td>Ethereum</td></tr><tr><td>usUSDS++ vault router</td><td><a href="https://etherscan.io/address/0x4f6e3115d607A10A68c9Ab35102016cC92b178FD#code">0x4F6E3115d607A10A68C9ab35102016cC92b178fD</a></td><td>Ethereum</td></tr></tbody></table>

## CCIP Bridging

<table><thead><tr><th width="245">Contract Name</th><th width="355">Address &#x26; Explorer Link</th><th width="263">Chain</th></tr></thead><tbody><tr><td>LockReleaseTokenPool USD0</td><td><a href="https://etherscan.io/address/0xc3d39b77032114c8884276dae0f02cdf75162782">0xC3d39B77032114c8884276Dae0F02cdF75162782</a></td><td>Ethereum</td></tr><tr><td>BurnMintTokenPool USD0</td><td><a href="https://basescan.org/address/0x8d20f295518b12e63f65ab7cf930ad88e8d17cba">0x8d20F295518B12E63F65aB7cf930AD88e8d17cbA</a></td><td>Base</td></tr><tr><td>BurnMintTokenPool USD0</td><td><a href="https://bscscan.com/address/0x8d20f295518b12e63f65ab7cf930ad88e8d17cba">0x8d20F295518B12E63F65aB7cf930AD88e8d17cbA</a></td><td>BNB</td></tr><tr><td>LockReleaseTokenPool USUAL</td><td><a href="https://etherscan.io/address/0x72a0203b731edece2ddaa506a048c0378c44366a">0x72a0203b731EdECE2DdAa506a048c0378C44366a</a></td><td>Ethereum</td></tr><tr><td>BurnMintTokenPool USUAL</td><td><a href="https://basescan.org/address/0x30ea2d525ef7c234f8aa6e3a8909b88f71244cb0">0x30Ea2d525eF7C234F8AA6E3a8909B88f71244cB0</a></td><td>Base</td></tr><tr><td>BurnMintTokenPool USUAL</td><td><a href="https://bscscan.com/address/0x30ea2d525ef7c234f8aa6e3a8909b88f71244cb0">0x30Ea2d525eF7C234F8AA6E3a8909B88f71244cB0</a></td><td>BNB</td></tr></tbody></table>

## Layer0 Bridging

<table><thead><tr><th width="245">Contract Name</th><th width="355">Address &#x26; Explorer Link</th><th width="263">Chain</th></tr></thead><tbody><tr><td>USD0 L1OFTAdapter</td><td><a href="https://etherscan.io/address/0xE14C486b93C3B62F76F88cf8FE4B36fb672f3B26">0xE14C486b93C3B62F76F88cf8FE4B36fb672f3B26</a></td><td>Ethereum</td></tr><tr><td>bUSD0 (formerly USD0++) L1OFTAdapter</td><td><a href="https://etherscan.io/address/0xd155d91009cbE9B0204B06CE1b62bf1D793d3111">0xd155d91009cbE9B0204B06CE1b62bf1D793d3111</a></td><td>Ethereum</td></tr><tr><td>bUSD0 (formerly USD0++) L1OFTAdapter (for TAC)</td><td><a href="https://etherscan.io/address/0x8Cc230FC8d736BF3Fbe911A17c6c59d522F85ff4#readContract">0x8Cc230FC8d736BF3Fbe911A17c6c59d522F85ff4</a></td><td>Ethereum</td></tr><tr><td>USUAL L1OFTAdapter</td><td><a href="https://etherscan.io/address/0xd277CBCFe8cB37CA90129a33EC7eE590ee392b59">0xd277CBCFe8cB37CA90129a33EC7eE590ee392b59</a></td><td>Ethereum</td></tr><tr><td>USD0 OFTMintAndBurnAdapter</td><td><a href="https://arbiscan.io/address/0xE14C486b93C3B62F76F88cf8FE4B36fb672f3B26">0xE14C486b93C3B62F76F88cf8FE4B36fb672f3B26</a></td><td>Arbitrum One</td></tr><tr><td>bUSD0 (formerly USD0++) OFTMintAndBurnAdapter</td><td><a href="https://arbiscan.io/address/0xd155d91009cbE9B0204B06CE1b62bf1D793d3111">0xd155d91009cbE9B0204B06CE1b62bf1D793d3111</a></td><td>Arbitrum One</td></tr><tr><td>USUAL OFTMintAndBurnAdapter</td><td><a href="https://arbiscan.io/address/0xd277CBCFe8cB37CA90129a33EC7eE590ee392b59">0xd277CBCFe8cB37CA90129a33EC7eE590ee392b59</a></td><td>Arbitrum One</td></tr><tr><td>USD0 OFTMintAndBurnAdapter</td><td><a href="https://explorer.tac.build/address/0xE14C486b93C3B62F76F88cf8FE4B36fb672f3B26?tab=read_write_contract">0xE14C486b93C3B62F76F88cf8FE4B36fb672f3B26</a></td><td>TAC</td></tr><tr><td>USD0PP OFTMintAndBurnAdapter</td><td><a href="https://explorer.tac.build/address/0xd155d91009cbE9B0204B06CE1b62bf1D793d3111?tab=contract">0xd155d91009cbE9B0204B06CE1b62bf1D793d3111</a></td><td>TAC</td></tr></tbody></table>


# Security Practices

## Security Approach

### Multi-layered Security Strategy

1. **Secure Development Practices**: We follow industry-standard secure coding practices and regularly review our codebase for potential vulnerabilities.
2. **Tokenomics Design and Simulation**: Mechanisms implemented in our smart contracts undergo thorough analysis by a team of economists to optimize and simulate their behavior to validate the designs.
3. **Access Control**: We implement robust access control mechanisms to ensure only authorized parties can interact with sensitive functions.
4. **Upgrade Mechanisms**: Our contracts include secure upgrade patterns to allow for improvements without compromising security or user funds.
5. **Smart Contract Security Audits**: Our contracts are periodically reviewed by multiple security auditors and bug bounty campaigns to find any vulnerabilities.
6. **Continuous Monitoring**: We employ advanced monitoring tools to detect any unusual activity or potential threats in real-time, allowing for swift response to any security incidents.


# Testing Framework

## Testing Framework

Our comprehensive testing framework ensures the reliability and security of our protocol:

1. **Unit Testing**: Extensive unit tests cover individual functions and components.
2. **Integration Testing**: We perform thorough integration tests to ensure different parts of the system work together seamlessly.
3. **Fuzz Testing**: Automated fuzz testing helps identify edge cases and unexpected inputs that could lead to vulnerabilities.
4. **Stress Testing**: We simulate extreme scenarios to ensure our protocol remains stable under pressure and shifts in interest rates.
5. **Scenario Testing**: Complex real-world scenarios are modeled and tested to validate the protocol's behavior in various market conditions.


# Monitoring Framework

Our security operations provides 24/7/365 monitoring of the Usual protocol. This ensures that any potential issues or anomalies are detected and addressed promptly.

### Passive Monitoring

This foundational level focuses on monitoring the critical components that form the backbone of our protocol's security:

* **Critical Role Monitoring**: Continuous tracking of all accounts with elevated privileges within the system.
* **Multisig Activity**: Real-time monitoring of all multisignature wallet activities to ensure proper authorization of significant actions.
* **Key Event Tracking**: Vigilant observation of crucial events such as:
  * Changes in role assignments
  * Updates to proxy implementations
  * Administrative changes

Any activity at this level triggers immediate notifications to our security team for verification and response.

### Active Monitoring

This level involves monitoring the operational aspects of our protocol to detect any deviations from expected behavior:

* **Contract State Changes**: Tracking significant state changes across all protocol contracts.
* **Mechanism Monitoring**: Continuous oversight of key protocol mechanisms, including:
  * Collateral Backing Ratio (CBR) activations and deactivations
  * Pausing and unpausing of contract functionalities
  * Activities within the DaoCollateral and SwapperEngine contracts
* **Threshold Alerts**: Notifications triggered by unusual transaction volumes, large token movements, or unexpected price fluctuations.

Anomalies detected at this level prompt immediate investigation by our security and development teams.

#### Automated defense mechanisms

Our highest level of security involves automated circuit breakers that immediately pause contract operations in response to critical security events:

* **Asset Protection**: Automatic pause triggers in response to suspicious movement of protocol funds
* **Protocol Integrity**: Immediate response to unexpected changes in core protocol metrics, balances, and under collateralization.
* **Access Security**: Detection and response to potential security access anomalies
* **Smart Contract Safety**: Automated protection against suspicious contract interactions that could impact protocol security

These automated defense mechanisms serve as the protocol's last line of defense, automatically pausing relevant contract operations when critical security thresholds are breached. This "circuit breaker" approach ensures the protocol can enter a safe state while our security team investigates and responds to potential threats.


# Audits

Smart Contract safety and security is paramount to us. Therefore we we ensure that every  public release has been vetted thoroughly by reputable Smart Contract auditors.

## **Security is Our Top Priority**

Smart contract risk is highly prevalent among DeFi protocols. One of Usual’s top priorities is to mitigate and reduce the potential risk from the underlying Usual smart contracts by conducting in-depth audits aimed at identifying potential vulnerabilities, logical errors, or inefficiencies and further by conducting continuous security monitoring of the smart contracts. The audits are conducted by leading industry experts and will be used to enhance trust through proper risk and security management on the smart contracts. Please find below the chronological overview of our completed audits.

## **May 2024**

### **Auditor**

[Cantina](https://cantina.xyz/welcome)

* Lead Security Researcher: <mark style="color:purple;">xmxanuel</mark>
* Security Researcher: <mark style="color:purple;">deadroses</mark>
* Associate Security Researcher: <mark style="color:purple;">jonatas</mark>

### **Scope**

* Codebase Simplification: Replacing the "mint engine" with the "swap engine"
* Cantina Managed Audit Phase 1: Permissioned launch smart contracts audit
* Cantina Managed Audit Phase 2: Permissionless launch smart contracts audit

{% file src="/files/f6K4KmesPNScjAMjXdqS" %}
Spearbit Cantina Report for Permissionless launch
{% endfile %}

{% file src="/files/4llA3JLM7kXPksvB4e6R" %}
Spearbit Cantina Report for Permissionless launch
{% endfile %}

## **June 2024**

### **Auditor**

[Cantina](https://cantina.xyz/welcome)

### **Scope**

* Public security competition managed by Cantina on the same scope that audited in May 2024
* Link: [Public Competition & Bug Bounty Program](https://cantina.xyz/competitions/31a752e3-8ece-49b3-a9ee-d7294c659340)

{% file src="/files/Itb2GY6ZlPLY9qSyySS0" %}
Pegasus Audit Competition run by Cantina
{% endfile %}

## October 2024

### Auditor

[Paladin](https://paladinsec.co/)

### Scope

* L2 Token contracts
* OFT MintAndBurnAdapter
* L1 OFT Adapter
* Link: [L2 Tokens & Adapter Audit](https://paladinsec.co/projects/usual/)

{% file src="/files/OK1R1tZ1pjC2ieNWNKfw" %}
L2 Token Audit conducted by Paladin
{% endfile %}

## November 2024

### Auditors

[Cantina](https://cantina.xyz/welcome)

* Lead Security Researcher: <mark style="color:purple;">deadroses</mark>
* Lead Security Researcher: <mark style="color:purple;">xmxanuel</mark>
* Security Researcher: <mark style="color:purple;">Phaze</mark>
* Associate Security Researcher: <mark style="color:purple;">Chinmay Farkya</mark>

[Halborn](https://www.halborn.com/)

[Sherlock](https://www.sherlock.xyz/) (public audit competition)

### Scope

V1 contract upgrades & additions covering:

* bUSD0 (formerly USD0++)
* DAO Collateral
* SwapperEngine
* USUAL
* USUALS
* USUALSP
* USUAL distribution
* USUAL Airdrop
* USUALx

{% file src="/files/JkQBQvpHK3QTdwrWIx9B" %}
Spearbit Cantina Report for Usual Pegasus Phase 1
{% endfile %}

{% file src="/files/OM5uDC4E3AaDOdAHwhC7" %}

{% file src="/files/byDN3MW0XWZn1mYUIBEG" %}
Halborn Usual V1
{% endfile %}

{% file src="/files/D1U9xVpmqq1j4jBQfHzn" %}
Sherlock - Usual V1 Audit Competition Report.pdf
{% endfile %}

## December 2024

### Auditors

Blackthorne

[Cantina](https://cantina.xyz/welcome)

### Scope

* WrappedM aka UsualM
* bUSD0 (formerly USD0++) unwrap with Cap for vault strategies
* USUALx

{% file src="/files/gQ6yN3EKb6jXFG7iq2ll" %}
Blackthorn Audit Report - WrappedM
{% endfile %}

{% file src="/files/3rjFIqpGJmowGWEpXzYp" %}
Spearbit Cantina Report for UsualM extension
{% endfile %}

{% file src="/files/tgUvWX8LSSXsnHgZXK3c" %}
Spearbit Cantina Report for USD0pp adjustments
{% endfile %}

## January 2025

### Auditors<br>

[Spearbit](https://cantina.xyz/portfolio/51ba92e3-1c77-4e55-be3f-b43b529fd38b)

### Scope

* Claim Redirect
* Fee sweep via DistributionModule
* USUALx adjustment for fee sweep
* bUSD0 (formerly USD0++) adjustment for fee sweep

{% file src="/files/8FCQxw0OMVere5QXEKAD" %}
Spearbit - Audit Report on Redirect & Fee Sweep
{% endfile %}

## February 2025

### Auditors

[Sherlock](https://www.sherlock.xyz/)\
\
[Spearbit](https://spearbit.com/)

### Scope

* Euler USL vault and oracle
* Usual USL Economic Risk Assessment
* UsualUSDtb
* Yield Module

{% file src="/files/hC3cqfjEiE9lf5EIhLXQ" %}
Sherlock - Audit Report on USL on Euler
{% endfile %}

{% file src="/files/C9bbb7HUMiTeUvGoVSkz" %}
Spearbit - Audit Report on USL on Euler
{% endfile %}

{% file src="/files/uDrsIpEkRvbU2skGyCM5" %}
OAK Security - Usual USL Economic Risk Assessment
{% endfile %}

{% file src="/files/a9j1XOUxulxH1CCzP9mF" %}
Sherlock - Audit Report on UsualUSDtb
{% endfile %}

{% file src="/files/Js9ZuNuz9yBPwjDVjqRz" %}
Spearbit - Audit Report on Yield Module
{% endfile %}

For more detailed information on our security measures or to report a potential vulnerability, please contact our security team at <security@usual.company>.

## March 2025

### Auditors

[Sherlock](https://www.sherlock.xyz/)\
\
[Spearbit](https://spearbit.com/)

### Scope

* Usual bUSD0 (formerly USD0++) Investment Vault
* Coherent Audit competition on overall protocol

{% file src="/files/EGdNGX5bydxBEspPaVqL" %}
Spearbit - Usual bUSD0 (formerly USD0++) Investment Vault
{% endfile %}

{% file src="/files/U76LhoOoxozfPXNw6zuw" %}
Sherlock - Usual Labs Public Audit Contest
{% endfile %}

{% file src="/files/FRxD1XOHRNRKoGc0UBN1" %}
Halborn - bUSD0 (formerly USD0++) Investment vault
{% endfile %}

## May 2025

### Auditors

[Hexens](https://hexens.io/)

[Halborn](https://www.halborn.com/audits)

[Sherlock](https://www.sherlock.xyz/)\
\
[Spearbit](https://spearbit.com/)

### Scope

* ETH0 Protocol
* ETH0 Zapper Contract
* USUALX Lockup Contract

{% file src="/files/JKpfoeOpNUJwZPX7tbTE" %}

{% file src="/files/Nu9odywhXcTpA2FSKeMN" %}
Sherlock - Audit report on ETH0 Zapper contract
{% endfile %}

{% file src="/files/Kmd1mY7r8B7htgfBpEke" %}
Hexens - Audit report on UsualX Lockup Contract
{% endfile %}

{% file src="/files/dcNTKduJtObNObEHt2xg" %}
Halborn - Audit report on UsualX Lockup Contract
{% endfile %}

## July 2025

### Auditors

[Sherlock](https://www.sherlock.xyz/)

[Spearbit](https://spearbit.com/)

### Scope

* bUSD0 (formerly USD0++) Upgrade (Updating Burn Redemption Mechanism)
* Sync Vault remediation
* Usual USDC

{% file src="/files/ivujlwXsFkHhryBOEJw3" %}

Sherlock - Audit report on bUSD0 (formerly USD0++) upgrade (Burn Redemption Mechanism)

{% file src="/files/he7yJUOHYsPkRnoYthBK" %}

{% file src="/files/4GuMSI87aNhDAIA3mONr" %}

## October 2025

### Auditors

[Sherlock](https://www.sherlock.xyz/)

### Scope

* EUR0

{% file src="/files/c4b7kAhhZ67TK4hiGMff" %}

## November 2025

### Auditors

[Hexens](https://hexens.io/)

[Halborn](https://www.halborn.com/audits)

[Sherlock](https://www.sherlock.xyz/)

### Scope

* sUSD0
* sEUR0
* RDM (Revenue Distribution Module)
* USD0a Protocol
* bUSD0 (formerly USD0++) Upgrade

{% file src="/files/zWDH8pKfBLMbMja1FLfd" %}

{% file src="/files/rI1pmyEg5PHxVED8SbF9" %}

{% file src="/files/l4EM79SuSei9g579zkdD" %}

{% file src="/files/6xYz3DWmHOjDGUIwQKBU" %}

{% file src="/files/XJ6pChauFj2sBtHlRui1" %}

{% file src="/files/iCSn19J7AIoDtkqHAXcU" %}


# Bug Bounty

In addition to regular audits, and always because security is a major concern for our protocol, we have a bug bounty program for the Usual Protocol smart contracts on Ethereum.

## **Why Bug Bounty?**

This program aims to strengthen the security of our protocol by encouraging ethical hackers to report potential security flaws of varying degrees of impact. By leveraging the expertise of security researchers, we can proactively identify and address vulnerabilities before they can be exploited. The safety of our users and the integrity of the Usual Protocol are our top priorities, and we know that an incentivized security program is crucial to maintaining a robust and resilient ecosystem.

## **Bug Bounty Program Description**

The program follows a **severity matrix** to classify findings and determine rewards based on potential impact. Critical vulnerabilities affecting our **Total Value Locked (TVL)** are the highest priority, while lower-severity issues are assessed accordingly.

#### **Scope of the Bug Bounty**

The **Core Stablecoin Protocol** is the primary focus of this bug bounty, as it directly affects the security of our TVL. The following contracts (and their imports) are in scope:

* **Chains in scope**

Ethereum Mainnet only. (Smart contracts on any other networks or testnets are out-of-scope.)

* **Core Stablecoin Protocol**
  * [USD0](https://etherscan.io/token/0x73a15fed60bf67631dc6cd7bc5b6e8da8190acf5)
  * [USD0PP](https://etherscan.io/token/0x35D8949372D46B7a3D5A56006AE77B215fc69bC0)
  * [DaoCollateral](https://etherscan.io/token/0xde6e1F680C4816446C8D515989E2358636A38b04)
  * [RegistryAccess](https://etherscan.io/address/0x0D374775E962c3608B8F0A4b8B10567DF739bb56)
  * [RegistryContract](https://etherscan.io/address/0x0594cb5ca47eFE1Ff25C7B8B43E221683B4Db34c)
  * [ClassicalOracle](https://etherscan.io/address/0xb97e163cE6A8296F36112b042891CFe1E23C35BF)
  * [SwapperEngine](https://etherscan.io/address/0xB969B0d14F7682bAF37ba7c364b351B830a812B2)
  * [TokenMapping](https://etherscan.io/address/0x43882C864a406D55411b8C166bCA604709fDF624)

These contracts handle stablecoin issuance, structured financial product management, swaps between **Real-World Assets (RWAs)** and stablecoins, and asset pricing. Their security is mission-critical.

Additional areas covered by the bug bounty include:

* **RWA Token Wrapper Contracts and Euler**
  * [UsualM](https://etherscan.io/token/0x4Cbc25559DbBD1272EC5B64c7b5F48a2405e6470)
  * [UsualUSDtb](https://etherscan.io/address/0x58073531a2809744d1bf311d30fd76b27d662abb)
  * [EulerOracle](https://etherscan.io/address/0xe1DeE60c516a8350704Ec24a6E856c9F533d1c1b)

These ERC-20 wrapper contracts enhance security for RWAs like wrappedM by M0 or USDtB by Ethena. Exploits here could impact a limited portion of TVL based on mint caps.

For any USL Euler-Vault-related code, we refer to the [Cantina Bug Bounty.](https://cantina.xyz/bounties/4d285eee-602e-440a-845e-25e155cec26a)

* **Usual Token & Distribution Module**
  * [Usual](https://etherscan.io/address/0xC4441c2BE5d8fA8126822B9929CA0b81Ea0DE38E)
  * [Usual\*](https://etherscan.io/address/0x094B360AE512A65584d4f5Be33D68B2E08677b89)
  * [UsualX](https://etherscan.io/address/0x06B964d96f5dCF7Eae9d7C559B09EDCe244d4B8E)
  * [DistributionModule](https://etherscan.io/address/0x75cC0C0DDD2Ccafe6EC415bE686267588011E36A)
  * [YieldModule](https://etherscan.io/address/0x647F8987C288bf6D2fDb332918E1E14424839EDA#readProxyContract)

The Usual Protocol’s token distribution system, tied to RWA yield, is also included, though it is a lower priority than the stablecoin core.

#### **Out of Scope**

The following vulnerabilities and attack vectors are **out of scope** and will not be rewarded:

* &#x20;Any code or contracts **not deployed on Ethereum mainnet** (e.g. development branches, testnet or staging deployments)
* &#x20;Any **known issues** already identified in prior audits or otherwise documented by Usual Labs
* &#x20;Front-end websites or web applications (UI/UX) – (Issues here may be eligible for **discretionary** rewards at the team's discretion, but are not part of the core smart contract bounty scope)
* &#x20;Integrations with external protocols (e.g. Curve pools or any third-party platform integrations)
* &#x20;Oracle contracts or RWA token contracts **maintained by third parties** (bugs in external dependency contracts are out-of-scope)
* &#x20;Risks related to RWA Tokenizer contracts (including external oracles).
* &#x20;Issues that require **privileged access** (admin/governance only actions or intended permissioned functions)
* &#x20;Pure gas optimization improvements with no security impact
* Theoretical attacks requiring impractical **brute-force** methods or only resulting in minor rounding/precision errors
* Economic or market-manipulation attacks that are not symmetric or require extreme market turmoil conditions.
* Incorrect data or pricing information supplied by third-party oracles.
* &#x20;Vulnerabilities related to malicious bridge implementations (e.g., LayerZero or Chainlink CCIP).
* Issues related to the SwapperEngine when the underlying asset isn't USDC or when Circle itself is compromised.
* Issues solely related to missing or incorrect NatSpec comments, outdated documentation, or comment hygiene

#### **Judging**

Sherlock’s security team will triage all submissions and determine severity based on impact. **Usual Labs will not be judging** submissions in this program. Sherlock will decide whether a reported issue is valid and what severity/reward applies, in accordance with the criteria below.

#### Severity Definitions

| **Severity** | **Scope**           | **Potential Impact**                                                    |
| ------------ | ------------------- | ----------------------------------------------------------------------- |
| **Critical** | Core contracts only | Theft or **irreversible loss** of **5%–100%** of TVL                    |
| **High**     | Entire protocol     | Significant loss of funds (**1%–5%** of TVL) or equivalent impact       |
| **Medium**   | Individual users    | Loss or permanent lock of funds for **individual users** (not systemic) |

## **Bug Bounty Links**

To take part in the program and find out more, visit the Sherlock website by following this [LINK](https://audits.sherlock.xyz/bug-bounties).


# Integrate bUSD0

{% hint style="info" %}
TL:DR - Integrate bUSD0 in your offering and easily expose your community to USUAL rewards, capitalising at minimum on the underlying RWA yield and potentially much more.

Current options to integrate bUSD0 rewards in USUAL are:

* [Reward-Redistribution by integration partner](/integrations/integrate-busd0/reward-redistribution-by-integration-partner)
* [Claim Address Redirect](/integrations/integrate-busd0/claim-address-redirect) (if integration partner can't claim the rewards that accumulate on their smart contracts).
  {% endhint %}

## Recap - What is bUSD0 (formerly USD0++) about?

bUSD0 (Bond USD0) represents USD0 stablecoin locked until June 11, 2028. It remains transferable during this period, earning USUAL incentives and maturity yield. Users receive 1 USD0 for 1 bUSD0 at maturity. For early redemption, users need an equivalent amount of rt-USD0 - received at mint - which unlocks bUSD0 back into USD0 at a 1:1 rate anytime. Additionally, early redemption below peg can be made at a DAO set price floor.

**Supply: ∞** - each USD0 can be deposited into bUSD0

**Contract standard:** ERC-20

**Reward distribution approach:** <mark style="color:$info;">**Claim bearing**</mark>

**For more insights check out:**

[bUSD0 (formerly USD0++) Deep dive](https://docs.usual.money/usual-products/usd0-liquid-staking-token)

[bUSD0 (formerly USD0++) Smart Contract](/smart-contracts/token-contracts/usd0++)

[USUAL Deep Dive](https://docs.usual.money/usual-products/usual-governance-token)

[USUAL Smart Contract](/smart-contracts/token-contracts/usual)

## Why should you enhance your product offering with bUSD0?

The Usual Protocol is one of the first stablecoin issuer to redistribute generated value in the form of a governance token via bUSD0, directly incentivizing protocol liquidity, ***while remaining fully transferable and composable.*** 100% of the generated revenues are pooled into the protocol's treasury. Consequently, USUAL a genuine governance token, backed by real RWA yield and revenue, granting ownership rights over the protocol's actual revenues, future revenues, and infrastructure.

These USUAL rewards guarantee at least rewards as high as the underlying RWA yield, in reality is likely to be higher due the protocol's unique [tokenomics of USUAL](https://docs.usual.money/usual-products/usual-governance-token/usual-tokenomics). USUAL distribution is designed to be disinflationary, meaning its value theoretically increases as the Total Value Locked (TVL) in bUSD0 grows. In that sense early participation is highly advantageous. This sets it apart from many other governance tokens, which often lack intrinsic value.

## How can bUSD0 be integrated?

### Reward logic = Claim bearing

bUSD0 introduces a new logic for rewards distribution. Unlike other tokens, bUSD0 is a "**Claim bearing**" token, not yield bearing or rebasing. Holders of bUSD0 are eligible for "Claiming" daily $USUAL rewards. By default the Usual reward system assigns the holder's address as the recipient of these rewards.

The Usual protocol enhances composability by integrating logic that tracks and maps user deposits and activity across other protocols. For instance, Usual monitors deposits of bUSD0 into Morpho, enabling it to reward users who use their bUSD0 deposits as collateral on Morpho.

When integrated, the user experience is straightforward. Users can utilize the integrated protocols such as Morpho and Pendle, and directly claiming rewards for their bUSD0 ownership and activity in the "[Earn](https://app.usual.money/earn)" section of the Usual interface on a daily basis.

This setup provides clarity on token values while allowing users to manage and utilize their bUSD0  assets seamlessly, without losing their "**Claim**" on the underlying USUAL rewards. For optimal performance, protocols are highly encouraged to completely integrate with the Usual reward system, so that USUAL rewards are automatically assigned to their users via the daily [USUAL distribution](/overview/features/usual-distribution), ready to be "claimed".

### Integration Tiers

For an integration to be considered completely integrated, empowering a straightforward claim experience for bUSD0 holder/users please refer to tier list below:

| Integration Tier     | Reward UX                                                       | Examples                   |
| -------------------- | --------------------------------------------------------------- | -------------------------- |
| Fully integrated     | USUAL is claimed via [Earn page](https://app.usual.money/earn)  | Curve, Pendle, Morpho      |
| Partially integrated | USUAL is claimed and redistributed by integration partner       | Euler, Superform, Contango |
| Not integrated       | USUAL can't be claimed from smart contract, USUAL remains stale | Maybe your smart contract? |

If you are in the lowest tier, don't fret - we are here to help! Checkout the integration options below.

## What integration options are currently supported?

<table data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center"><strong>Reward redistribution by integration partner</strong></td><td><a href="/files/xkFrkFgVzv1AmEiwOuca">/files/xkFrkFgVzv1AmEiwOuca</a></td><td><a href="/pages/sG0zAezuzskuS2wJNZLi">/pages/sG0zAezuzskuS2wJNZLi</a></td></tr><tr><td align="center"><strong>Claim Address Redirect</strong></td><td><a href="/files/agiRM0bJVA3bWHa1D6LK">/files/agiRM0bJVA3bWHa1D6LK</a></td><td><a href="/pages/8oisHE0lmpLoeZB7Vt59">/pages/8oisHE0lmpLoeZB7Vt59</a></td></tr></tbody></table>


# Reward redistribution by integration partner

## Overview

In this case, the integration partners need to have a function in their smart contract to claim and mint the USUAL. Subsequently, it is the responsibility of the integration partners to redistribute the USUAL to their users according to the conditions described in their product offering.

As mentioned previously, by default, the Usual reward system assigns the holder's address as the recipient of these rewards. This means that for integration partners who integrate bUSD0 in their LP or vault offering, which is not "fully integrated" into the reward system, the USUAL accumulates daily on the contract address of the respective LP or vault.

{% hint style="info" %}
This approach is only considered as "Partially integrated", i.e. overall rewards are claimed by integrator and subsequently distributed to endusers. No native claim experience via Usual's [Earn page](https://app.usual.money/earn).
{% endhint %}

{% hint style="warning" %}
If the USUAL rewards are redistributed by integration partners, it is the SOLE RESPONSIBILITY of the respective bUSD0 integrator to reward its user.

That means as an enduser, please reach out to the respective integrator in case of any reward disputes or challenges.
{% endhint %}


# Claim Address Redirect

## Overview

If a bUSD0 integration partner can't by themselves mint and claim the USUAL rewards that accumulate on their smart contract, then this "Claim Address Redirect" integration feature enables them to access the USUAL and redistribute it to their Users as lined out [here](/integrations/integrate-busd0/reward-redistribution-by-integration-partner).

### Detailed Flow

{% hint style="info" %}
In order to be eligible for a claim address redirect the USUAL accumulating on the address needs to fulfil the following prerequisites:

* $100 worth of USUAL/month
* $1000 worth of USUAL in total
  {% endhint %}

1. Contact the USUAL DAO via the established communication channel.
   1. If no channel is available yet, set one up (if you work in Crypto you know how 😏)
2. Communicate the contract address on which the USUAL accumulates as well as the address that should "Claim" it.
   1. For the best "Claim" experience after the successful redirect we recommend that address is set up in a (MultiSig) wallet (such as [Safe](https://safe.global/)), which can interact with our dApp or Etherscan.
3. In order to add your claim address we require "sufficient" proof that you are the deployer or the project team behind the contract address that should be redirected.
   1. Sufficient proof could be:
      1. Social proof
      2. Governance proof (e.g. DAO vote)
      3. Signed message from original deployer
      4. Proof of redistribution
   2. Once the proof has been established, the Claim Redirect will be added to the [DistributionModule](/smart-contracts/protocol-contracts/usual/usual-distribution).
4. After the "Claim Redirect Address" has been added, a pre-defined challenge period (**5 days**) will start, in which the USUAL DAO admin or the original claim address owner can cancel the addition of the claim address.
5. As soon as the challenge period has concluded the added "Claim address" can claim the USUAL via the Usual dApp's [Earn page](https://app.usual.money/earn) (or [Etherscan](https://etherscan.io/address/0x75cC0C0DDD2Ccafe6EC415bE686267588011E36A#writeProxyContract#F3)).

{% hint style="warning" %}
As long as an integration is not fully integrated with the reward system (i.e. enduser can claim USUAL via [Earn page](https://app.usual.money/earn)) it is up to the bUSD0 integrator to reward its endusers.

As USUAL DAO we strive to diligently enact the "Claim Address Redirect" process. However, it's up to the integrators to provide correct addresses, sufficient proof and reward their users properly. As an enduser please take up any reward disputes and challenges with the respective integrator.
{% endhint %}


# Community & Support

Join our lively communities or get support when you need it.

## Socials

<table data-view="cards"><thead><tr><th align="center"></th></tr></thead><tbody><tr><td align="center"><a href="https://telegram.usual.money"><strong>Telegram</strong></a></td></tr><tr><td align="center"><a href="https://linkedin.usual.money"><strong>LinkedIn</strong></a></td></tr><tr><td align="center"><a href="https://discord.usual.money"><strong>Discord</strong></a></td></tr><tr><td align="center"><a href="https://x.usual.money"><strong>X</strong></a></td></tr><tr><td align="center"><a href="https://linktr.ee/usualmoney"><strong>Linktree</strong></a></td></tr><tr><td align="center"><a href="https://www.youtube.com/channel/UCxshfCtZTlahG_Bwchclb8A"><strong>Youtube</strong></a></td></tr></tbody></table>

## Contact

Please contact us via this [**form**](https://usual.money/form/contact-us).


# References

Learn more about Usual by diving into resources provided below.

## Curated by Usual

<table data-view="cards"><thead><tr><th align="center"></th></tr></thead><tbody><tr><td align="center"><a href="https://app.usual.money/"><strong>dApp</strong></a></td></tr><tr><td align="center"><a href="https://usual.money/"><strong>Usual Website</strong></a></td></tr><tr><td align="center"><a href="https://docs.usual.money"><strong>Usual Docs</strong></a></td></tr><tr><td align="center"><a href="https://blog.usual.money/"><strong>Usual Blog</strong></a></td></tr><tr><td align="center"><a href="https://breezy.usual.money"><strong>Jobs at Usual</strong></a></td></tr></tbody></table>

## Curated by 3rd Parties

<table data-view="cards"><thead><tr><th align="center"></th></tr></thead><tbody><tr><td align="center"><a href="https://CGusd0.usual.money"><strong>Coingecko</strong></a></td></tr><tr><td align="center"><a href="https://CMCusd0.usual.money"><strong>Coinmarketcap</strong></a></td></tr><tr><td align="center"><a href="https://DLusd0.usual.money"><strong>Defillama</strong></a></td></tr><tr><td align="center"><a href="https://dune.com/usual_team/usual"><strong>Dune</strong> </a></td></tr><tr><td align="center"><a href="https://rwa.usual.money"><strong>RWA.xyz</strong></a></td></tr><tr><td align="center"><a href="https://tokenterminal.com/explorer/projects/usual"><strong>Token Terminal</strong></a></td></tr></tbody></table>




---

[Next Page](/llms-full.txt/1)

