Source: https://ipor.io/docs.md # IPOR Fusion Docs > Documentation for IPOR Fusion, onchain vault infrastructure: guides for depositors, builders and institutions, governance and resources. ## Fusion Docs Welcome to the IPOR Fusion Protocol's documentation. - **Fusion for Depositors**: Access professionally curated, auto-optimized yield strategies with a click. — [What is a Fusion Vault?](https://ipor.io/docs/fusion-for-depositors/what-is-a-fusion-vault.md) - **Fusion for Curators and Builders**: Discover Fusion infrastructure and build your first automated onchain vault. — [Build on Fusion](https://ipor.io/docs/build-on-fusion.md) - **Fusion for Institutions**: Sovereign vault infrastructure for institutional-grade, onchain asset management. — [Fusion for Institutions](https://ipor.io/docs/fusion-for-institutions.md) - **IPOR Benchmarks and Derivatives**: Learn about IPOR Protocol's onchain, plain vanilla interest and stake rate swaps and benchmarks. — [IPOR Derivatives](https://ipor.io/docs/ipor-derivatives.md) - **Governance and Tokenomics**: Join the DAO and participate in community-decision making. — [DAO Governance](https://ipor.io/docs/dao-governance/dao-governance/fusion-dao-governance.md) - **Resources**: Access IPOR Protocol's Glossary, research and whitepapers, and brand assets. — [Resources](https://ipor.io/docs/resources.md) --- Source: https://ipor.io/docs/fusion-for-depositors.md # Introduction to Fusion ## Professional DeFi Asset Management Simplified IPOR Fusion is a professional-grade asset management layer that provides **one-click access to sophisticated DeFi strategies**. It acts as an intelligent gateway to the broader DeFi ecosystem, offering a non-custodial and transparent way to grow your capital using institutional-grade infrastructure. By depositing into a Fusion vault, you delegate the complexity of yield optimization to strategists ("[Atomists](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-atomist.md)") who actively manage your assets across protocols in the ecosystem. ## How It Works Fusion is designed to make participating in advanced DeFi strategies as simple as using a standard "Earn" button: 1. **Select a Strategy:** Choose a vault based on your risk profile and desired underlying asset (e.g., USDC or ETH). 2. **Provide Liquidity:** Deposit assets to receive vault shares. These shares represent your ownership of the pool and the yield it generates. 3. **Passive Management:** Professional strategists ("[Alphas](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-alpha.md)") manage the portfolio behind the scenes, e.g. automatically rebalancing funds across different DeFi protocols to capture optimal returns. 4. **Withdraw When You Need To:** Monitor your growth in real time. Withdraw instantly when the vault holds enough liquid assets, or through a scheduled withdrawal (see [Withdrawing](https://ipor.io/docs/fusion-for-depositors/user-guide/withdrawing.md)). ## Core Features - **Expert Management:** Benefit from active management by professional strategists. - **Universal Access:** Tap into liquidity across all major DeFi protocols from a single entry point. - **Cost-Efficient Management:** Strategy execution and rebalancing are handled by the vault, meaning depositors don't pay direct gas costs for complex portfolio operations. - **Total Transparency:** Every strategy move and performance metric is verifiable on-chain 24/7. > **Want to understand the specific advantages?** Check out the [TL;DR: Why Fusion?](https://ipor.io/docs/fusion-for-depositors/why-fusion.md) page. > > **Ready to dive in?** Explore the [available vaults](https://app.ipor.io/fusion). --- Source: https://ipor.io/docs/fusion-for-depositors/what-is-a-fusion-vault.md # What is a Fusion Vault? Fusion vaults are the central part of the Fusion asset management infrastructure. They enable sophisticated asset management automation in the background, accessible via a standard front-end deposit. All the sophisticated data collection, processing, and execution is handled in the back end by the [Alpha](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-alpha.md) role. Users enjoy full transparency on the front end. They can check which markets are connected to any Fusion vault, view the vault's performance, and learn the current and historical allocation of funds. ![Image](https://ipor.io/docs/assets/fusion-for-depositors/image-2-50107e.png) __ ![Image](https://ipor.io/docs/assets/fusion-for-depositors/image-3-1367af.png) __ [Here](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fusion-vault.md) you can find a more technical documentation. --- Source: https://ipor.io/docs/fusion-for-depositors/why-fusion.md # TL;DR: Why Fusion? ## **Smart Automation** Fusion provides intelligence-driven execution for various DeFi operations, including lending optimization, leveraged looping, carry trades, arbitrage, leveraged farming, and more, curated by professional curators ("[Atomists](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-atomist.md)"). ## **One-Click Yield Optimization** Fusion provides a single access point to multiple yield venues, reducing operational burden and enhancing capital deployment efficiency. Liquidity providers can deposit in a vault with a single click, and their funds are automatically distributed across the vault's connected markets to optimize yield. ## **Modularity and Adaptability** DeFi moves fast. IPOR Fusion enables seamless, swift, and secure integration of new DeFi protocols, empowering curators and liquidity providers to seize the latest opportunities as they arise. A new market is to be added to the vault strategy? No need to move funds to a new vault; Fusion strategies can be upgraded on the fly thanks to [Fuses](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fuse.md). ## **Automated Risk Management** Fusion incorporates an intelligent layer that is capable of automating rebalancing, optimization, and risk management, enabling swift and effective responses to evolving market conditions. Under normal circumstances, Fusion vaults actively perform yield-optimization operations. In periods of market stress, however, Fusion can automatically withdraw liquidity to minimize or entirely eliminate exposure to DeFi markets. To learn more, [read this piece](https://x.com/compose/articles/edit/1988586935124705280) on Fusion's performance during the xUSD market stress. ## **Institutional-grade Security** Built by seasoned developers, IPOR Fusion Protocol infrastructure prioritizes security and robust smart contract design. For more security-related information, please refer to the [Security Features](https://ipor.io/docs/fusion-for-depositors/why-fusion/security-features.md) section. ## **Network Effect Without Risk “Spill-over”** IPOR Fusion adoption offers a growing “palette” of protocol integrations and business logic, paired with “siloed” risk exposure, protecting users from spillover effects. Siloed risk exposure between Fusion vaults ensures potential losses are not socialized. --- Source: https://ipor.io/docs/fusion-for-depositors/why-fusion/security-features.md # Security Features > IPOR Fusion infrastructure is developed to deliver peace of mind for Atomists and liquidity providers. ## Siloed Risk Management IPOR Fusion's modular architecture isolates risks within individual vaults, ensuring that potential losses in one vault do not affect others. Risks are siloed to the particular markets and assets a vault is connected with via Fuses and substrates. This design bolsters security by preventing risk spillover across the ecosystem, empowering investors to choose strategies that match their risk appetite. ## Balance Fuses Fusion's accounting uses [Balance Fuses](https://ipor.io/docs/build-on-fusion/developer-guide/balance-fuses.md). That means the vaults account for them self. While other vaults require "trust me bro" accounting fed from offchain by the curator, Fusion vaults known their own balance. ## Audits Fusion is [audited](https://ipor.io/docs/build-on-fusion/developer-guide/security-and-audits.md). ## Active Risk Monitoring To ensure ongoing security, the IPOR Fusion infrastructure supports Guardian roles that can be assigned to specialized security firms such as smart contract exploit detectors. These entities actively monitor onchain risks and can take immediate protective actions, such as pausing strategies if anomalies are detected. An [Atomist](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-atomist.md) could also delegate a special Alpha role to recall funds from external protocols to the vault in case of threats. Other risk modules can be built and customized, such as monitoring for things like asset depegs, economic risks, and more. This proactive approach reduces the likelihood of loss, reinforcing the integrity of vault assets. --- Source: https://ipor.io/docs/fusion-for-depositors/user-guide/depositing.md # Depositing Depositing into Fusion vaults is identical to depositing into other DeFi vaults, even if the underlying strategy is sophisticated in nature. 1. Determine the amount you want to deposit (make sure you have the correct wallet connected). 2. Click "Approve." ![Image](https://ipor.io/docs/assets/fusion-for-depositors/image-57-a0ea73.png) __ 3. Once the transaction is approved, click "Deposit" and confirm the transaction in your wallet. ![Image](https://ipor.io/docs/assets/fusion-for-depositors/image-60-ce6089.png) __ 4. Upon successful deposit, you will receive ERC-4626 vault shares, which are fully ERC-20 compliant. Depending on your wallet type, you may need to manually add the vault share's address for your deposits to appear in your wallet. --- Source: https://ipor.io/docs/fusion-for-depositors/user-guide/depositing/how-to-choose-a-vault.md # How to Choose a Vault IPOR Fusion is a neutral infrastructure layer that provides the technology - the Fusion Vault - to enable professional DeFi management. Fusion is the vault protocol, while each vault is curated and managed by its own third-party [**Atomist**](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-atomist.md) (the Curator). When selecting a vault, your primary focus should be the specific strategy provided by the Atomist. Here are some tips to evaluate your options: ### 1. Read the Strategy Description The most important step is to read the vault's description provided by the Atomist. This text explains the vault’s "mission profile"- for example, whether it focuses on stable yield from lending protocols like Aave and Compound, or seeks higher returns through leveraged looping. The description should align with your own risk tolerance and investment goals. ### 2. KYC- Know Your Curator (Atomist) In the IPOR Fusion ecosystem, the Atomist is the architect. They are responsible for: - **Whitelisting:** Choosing which protocols and assets the vault is allowed to interact with. - **Risk Management:** Setting limits on how much capital can be placed in a single protocol. - **Execution:** Directing the [**Alpha**](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-alpha.md) (strategy execution) on how to deploy capital. As a user, you are essentially selecting a manager you trust to navigate the DeFi landscape on your behalf. ### 3. Check the Underlying Asset Every Fusion Vault is built around a single underlying token (e.g., USDC, USDT, or ETH). Your investment relates to that asset. When you deposit, you receive vault shares. Yield generated by the strategy is reflected in the rising price of these shares relative to the underlying token. ### 4. Understand Fees To support the management of the vault, Atomists may implement two types of [fees](https://ipor.io/docs/fusion-for-depositors/user-guide/vault-fees.md). These are automatically handled by the protocol and are reflected in the share price: - **Management Fee:** An annualized percentage for the ongoing operation of the vault. - **Performance Fee:** A percentage of the profits earned. ### 5. Liquidity and Withdrawals Check if the vault is optimized for your time horizon. IPOR Fusion offers flexibility in how you [exit](https://ipor.io/docs/fusion-for-depositors/user-guide/withdrawing.md): - **Instant Withdrawals:** Many vaults keep a portion of "idle" liquidity or use automated tools to pull funds back from lending markets instantly. - **Scheduled Withdrawals:** Some advanced strategies (like leveraged looping) may require a "Request and Release" process. If a vault uses this, it will be noted in the interface, and you may need to wait a short period (the **Redemption Delay**) after requesting your funds to complete the withdrawal. ### 6. Notifications Atomists have the option to display announcements directly on the vault details page. Additionally, each Atomist has a dedicated channel in the [IPOR Labs Discord server](https://discord.gg/zGUZUY43FE). It's recommended that you join the channels for all Fusion vaults where you have funds to stay up to date on announcements. ### 7. Summary: The Neutral Layer Always remember that IPOR Fusion is the vault protocol. While the protocol includes hardcoded safety features, such as price validation and market limits, the actual performance and risk-taking decisions are the sole responsibility of the **Atomist**. Choose a vault where the strategy and the Atomist's reputation meet your expectations. --- Source: https://ipor.io/docs/fusion-for-depositors/user-guide/withdrawing.md # Withdrawing Withdrawing from Fusion vaults depends on the type of vault. Please refer to the next subsections to learn more. ## Instant Withdrawal ![Image](https://ipor.io/docs/assets/fusion-for-depositors/image-65-10f326.png) __ Vaults that support the instant withdrawal method allow users to withdraw their assets immediately without any waiting period. This is particularly true for vaults with liquid strategies, such as a lending optimizer vault. ## Scheduled Withdrawal Withdrawing from some types of Fusion vaults (like leveraged looping) requires unwinding a complex \[leveraged] position. As a result, withdrawals must be scheduled in advance to give the Atomist sufficient time to prepare the necessary liquidity. Scheduling a withdrawal is a two-step process: 1. **Request Withdrawal**: First, submit a withdrawal request. ![Image](https://ipor.io/docs/assets/fusion-for-depositors/image-66-7d7ebd.png) __ 2. The vault manager has a specific time, individually specified for each vault, to process and fulfill it. 3. Monitor the withdrawal page to check the status. 4. **Finalize Withdrawal**: Once ready, the funds will become available for withdrawal. > NOTE: Missing the withdrawal window will restart the two-step process and incur an additional [Offboarding Contribution](https://ipor.io/docs/fusion-for-depositors/user-guide/vault-fees/onboarding-and-offboarding-contributions.md), if this is levied in the respective vault. ## Hybrid Withdrawal Vaults support both scheduled and instant withdrawals (hybrid withdrawals) unless the Atomist has turned scheduled withdrawals off. If a scheduled withdrawal vault has a buffer of liquid assets, it may permit instant withdrawals when the requested amount is equal to or less than the available (unused) liquidity. --- Source: https://ipor.io/docs/fusion-for-depositors/user-guide/tracking-your-position.md # Tracking Your Position Once you deposit funds in a Fusion vault, your total position will be displayed at the top of the Fusion dashboard in the My Assets box. ![Image](https://ipor.io/docs/assets/fusion-for-depositors/image-81-4a78a6.png) __ You will also be able to review your deposits per vault in the "My Positions" tab. ![Image](https://ipor.io/docs/assets/fusion-for-depositors/image-82-50b507.png) __ --- Source: https://ipor.io/docs/fusion-for-depositors/user-guide/tracking-your-position/tracking-your-fusion-points.md # Tracking Your Fusion Points You can track your Fusion Points per vault in the Points page. ![Image](https://ipor.io/docs/assets/fusion-for-depositors/image-11-db3984.png) __ To earn a 10% points boost for yourself and other users, generate a referral code and share it with your community/friends. The bonus will only be activated if the user is not already a Fusion user or has not been one in the past. ![Image](https://ipor.io/docs/assets/fusion-for-depositors/image-15-3e099e.png) __ ![Image](https://ipor.io/docs/assets/fusion-for-depositors/image-16-a52971.png) __ --- Source: https://ipor.io/docs/fusion-for-depositors/user-guide/vault-fees.md # Vault Fees Detailed information about each vault's fee structure can be found on the "Vault Info" page (next to "Overview") for each Fusion vault. ![Image](https://ipor.io/docs/assets/fusion-for-depositors/image-22e796.png) __ Fusion vaults aim to set a standard for transparency in DeFi. The "Vault Info" page includes essential information in that respect, including the wallets of vault-related roles and contracts, as well as, all fees, contributions, and other essential information. ![Image](https://ipor.io/docs/assets/fusion-for-depositors/image-64-db7798.png) __ It's recommended that users check the "Vault Info" page before depositing in a vault, so they are informed about fees and the deposit/withdrawal policy. ## Fee Accounting Schedule Fees are not charged on a fixed calendar schedule (such as monthly or annually). Instead: - **Automated Deductions**: The fee is calculated and deducted automatically whenever the vault's share price updates—such as during user deposits, withdrawals, or strategy rebalances. - **Real-Time Share Pricing**: Because fees are processed in parallel with share price updates, the price displayed on your dashboard is always fully up-to-date and net of fees, ensuring no hidden charges at withdrawal. ## Where Do the Fees Go? When performance fees are collected, they are held in a secure contract and split between: 1. **The IPOR DAO**: A portion goes to the protocol to support the network. 2. **The Vault Curator**: A portion goes directly to the strategists and partners who build and manage the vault. --- Source: https://ipor.io/docs/fusion-for-depositors/user-guide/vault-fees/management-fee.md # Management Fee ## Management Fee The Management Fee is a time-based fee charged on the total assets under management (AUM) in a vault. ### How It Works - **Continuous Accrual**: The fee does not wait for a monthly or yearly bill. Instead, it accrues continuously, second-by-second, based on how long your assets remain in the vault. - **Always Net of Fees**: The fee is calculated and updated automatically whenever any user deposits, withdraws, or when the strategy rebalances. This ensures the vault balance and share price shown on your dashboard are always up-to-date and net of fees. ### A Simple Example - You deposit 1,000 USDC into a vault. - The vault has a 0.2% annual management fee. - **After One Year**: If you leave your funds in the vault for a full year, the total accrued fee is 2 USDC (0.2% of 1,000 USDC). - **After Six Months**: If you decide to withdraw your funds after exactly six months, the fee calculated up to that second is 1 USDC (half of the annual fee). - **The Result**: The fee recipient receives 1 USDC worth of minted vault shares. Your remaining shares are worth 999 USDC (plus any yield the strategy generated during those six months) --- Source: https://ipor.io/docs/fusion-for-depositors/user-guide/vault-fees/performance-fee.md # Performance Fee The Performance Fee is a profit-based fee charged only on the gains earned by a vault's strategy. The total amount is displayed on the "Vault Info" page of each vault. ## How It Works - **Only on Profit**: You only pay a fee when your investment grows. If the vault doesn't make a profit, you do not pay a performance fee. - **The "Peak" Rule (High Water Mark)**: We track the highest value (the "peak") the vault has ever reached. If the market dips and then recovers, you are never charged a fee twice for the same growth. You only pay a fee when the vault sets a brand-new profit peak. ## A Simple Example - You deposit 1,000 USDC into a vault with a 10% performance fee. - The strategy successfully earns interest, and your share of the vault grows to 1,100 USDC. - **The Gain**: You made a profit of 100 USDC. - **The Fee (10%)**: The fee is 10 USDC (10% of 100 USDC). - **The Result**: The strategist receives 10 USDC worth of vault shares. You keep 90 USDC (90% of the profit) and your vault balance is now worth 1,090 USDC. --- Source: https://ipor.io/docs/fusion-for-depositors/user-guide/vault-fees/onboarding-and-offboarding-contributions.md # Onboarding and Offboarding Contributions In many DeFi vaults, the arrival or departure of large amounts of liquidity can create hidden costs for existing participants. IPOR Fusion provides the infrastructure for **Onboarding and Offboarding Contributions**—mechanisms designed to protect long-term depositors and ensure the vault's health. Unlike traditional protocol fees, these contributions are not kept by a central authority or DAO. Instead, they are distributed directly back to the vault's internal liquidity, effectively benefiting all remaining share holders. ### Why are these contributions necessary? When a user joins or leaves a vault, the vault's composition changes. This may require the Alpha to rebalance assets across various protocols, which involves: - **Slippage and Swap Fees:** The price impact of moving large volumes of assets through decentralized exchanges, as well as the fundamental trading fees charged by those protocols. - **Yield Dilution:** If a user enters a vault right before a significant yield realization, they would "dilute" the profit meant for those who held through the risk period. Onboarding and Offboarding contributions ensure that the person causing these actions covers the associated costs, rather than the existing liquidity providers. ### Onboarding Contributions When you deposit assets into an IPOR Fusion vault, an **Onboarding Contribution** may be applied. #### How it works: 1. You deposit an amount of underlying assets (e.g., USDC). 2. A small percentage (defined by the vault's configuration) is calculated as a contribution. 3. The remaining assets are used to mint your vault shares. 4. The "contribution" amount remains within the vault, instantly increasing the **Total Assets** value for every existing share. **Result:** The Joiner pays a small entry premium, and the Stayers see a slight increase in their share price. ### Offboarding Contributions Similarly, when you withdraw assets from a vault, an **Offboarding Contribution** may be applied to the transaction. #### How it works: 1. You request a withdrawal or redemption of your shares. 2. The vault calculates the asset value of those shares. 3. A small percentage is deducted from the outgoing amount. 4. These assets stay in the vault or the shares are burned, which increases the proportional ownership of the remaining participants. **Result:** The Leaver covers the potential liquidity extraction costs, and the Stayers are compensated for the cost of rebalancing. ### Individual Vault Management As a neutral infrastructure, IPOR Fusion allows individual vaults to determine their own contribution policies. These are managed by **Atomists**, who decide the specific amounts for onboarding or offboarding contributions based on the vault's specific strategy and goals. By implementing these contributions, a vault can achieve: - **Value Accrual:** Every time a user joins or leaves, the internal value of the vault's assets is redistributed, resulting in a marginal accrual for existing holders. - **Fairness:** Users who move in and out of the vault frequently contribute more to the vault's pool than those who remain deposited for long periods. - **Sustainability:** The vault can cover the operational costs of rebalancing liquidity without eating into the organic yield generated by the underlying strategies. > Tip: > > You can always check the current contribution rates in the **Vault Info** section of the IPOR Fusion interface before committing your transaction. Watch the short video below to learn more. --- Source: https://ipor.io/docs/fusion-for-depositors/user-guide/risks.md # Risks While no protocol is entirely risk-free, the Fusion infrastructure has implemented [extensive measures](https://ipor.io/docs/fusion-for-depositors/why-fusion/security-features.md) to minimize potential issues. The protocol's code is publicly available, has undergone multiple smart contract [audits](https://ipor.io/docs/fusion-for-depositors/why-fusion/security-features.md), and is subject to an ongoing bug bounty campaign and specialized technical reviews. Key risk categories and their corresponding mitigation strategies are detailed below. For more in-depth information, refer to the security and audits sections. | Risk Category | Description | Mitigation Strategy | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Smart Contract Risk | Potential for bugs or vulnerabilities in the Fusion Protocol code or underlying reserve tokens. | Audits and Governance: Code is public, audited by multiple firms, and any changes require thorough vetting and community approval via onchain governance. An ongoing bug bounty program is also in place. | | Oracle Risk | Reliance on third-party data providers (oracles) for price feeds and other external data (e.g., liquid staking token redemption ratios). A compromised or failed oracle could lead to incorrect asset valuations. | Decentralized Oracles: Uses robust, tamper-resistant decentralized oracle solutions, such as Chainlink, for reliable data feeds. | | Strategy Risk | Inherent in DeFi vaults, involving potential losses from the failure of underlying investment strategies defined by Atomists. This includes poorly performing strategies, improper asset management, and external risks from interacting with other protocols (e.g., impermanent loss, liquidation, exploits). | Transparency and Oversight: All Atomist-defined investment strategies are publicly visible, allowing for continuous scrutiny by the community, security experts, and contributors. | | Network Risk | Issues related to the underlying blockchain networks on which Fusion operates, such as congestion, censorship, or security vulnerabilities. | Robust Onboarding Framework: Fusion Governance employs a rigorous network onboarding framework to vet new networks before integration, with all integration decisions overseen by community-based onchain governance. | --- Source: https://ipor.io/docs/fusion-for-depositors/user-guide/faq-vault-pauses.md # FAQ: Vault Pauses In decentralized finance, security is paramount. The IPOR Fusion protocol uses a modular architecture equipped with emergency safeguards—called "circuit breakers"—to protect your assets during extreme events. This short guide explains how and why a vault might be paused, and what it means for you and your funds. ### What does it mean when a vault is paused? When an IPOR Fusion vault is paused, it enters an emergency "frozen" state. This instantly locks down the vault's core operations, meaning the vault cannot execute new strategies, move assets to external protocols, or process deposits and withdrawals. This is a temporary defensive measure designed to secure the vault's assets while a potential threat is assessed. ### Why would a vault be paused? A vault is typically paused only during critical, emergency situations where the safety of user funds might be compromised. Common reasons include: - **Suspected Exploits:** If irregular activity or a potential hack is detected within the vault or an external protocol it interacts with. - **Severe Oracle Failures:** If the price feeds (oracles) that the vault relies on to value its assets fail or report highly manipulated data. - **Extreme Market Volatility:** If market conditions become so erratic that normal vault operations (like swapping or supplying assets) would result in unacceptable losses. ### Who can pause a vault? Only designated security accounts (the [Guardian](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/access-management.md) role) have the authority to trigger a pause. This role is strictly for defensive actions and can execute a pause instantly to ensure immediate protection. The specific entity holding this power can vary from vault to vault, but it is often the vault owner or an external security service provider. ### Can I deposit or withdraw my assets during a pause? **No.** While a vault is paused, both deposits and withdrawals are temporarily halted. - **Deposits:** You cannot add new funds or mint new shares. - **Withdrawals:** You cannot execute instant withdrawals or redeem scheduled withdrawal requests. This lockdown ensures that if an exploit or oracle manipulation is occurring, malicious actors cannot drain assets from the vault. ### What happens to my scheduled withdrawal request? If you have initiated a scheduled withdrawal, your request remains safely in the queue. However, you will not be able to finalize the redemption (exchange your shares for assets) until the vault is unpaused and normal operations resume. ### Does a pause affect the whole IPOR Fusion protocol? **No.** Because IPOR Fusion uses an isolated architecture, a pause is localized to a specific vault or supporting contract. If Vault A is paused due to a suspected issue, Vault B continues to operate normally, assuming it is unaffected by the threat. ### How is a pause lifted? Once the vault's operating team has assessed the situation and confirmed that the threat has been resolved or mitigated (for example, by removing a compromised external protocol from the vault's strategy), the appropriate authority will unpause the vault. As soon as the vault is unpaused, all normal operations, including your ability to deposit and withdraw, will resume. --- Source: https://ipor.io/docs/build-on-fusion.md # Fusion Introduction > What IPOR Fusion is, who this documentation is for, and how onchain and offchain responsibilities split between vaults and Alphas. ## What is Fusion? IPOR Fusion is an [institutional-grade](https://ipor.io/docs/fusion-for-institutions.md) asset management infrastructure for automated execution. It is an unopinionated and customizable framework that asset managers can use to deploy assets onchain while implementing custom algorithms offchain. Functioning as a universal integration layer, the protocol utilizes a modular [vault architecture](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fusion-vault.md) to connect with the entire DeFi ecosystem. Complex cross-protocol interactions are routed through isolated, standardized adapter contracts known as "Fuses." This composable design allows builders to bundle multiple operations into a single, atomic execution, abstracting the technical overhead of managing diverse protocol interfaces. It can be considered the _Prime Brokerage Protocol of DeFi_. From a TradFi asset manager's perspective, Fusion is a single entry point for the integration, coordination, monitoring, execution, and accounting of sophisticated DeFi strategies. The protocol clearly separates concerns between onchain state and offchain computation: - **Onchain components:** Smart contracts enforce transparent asset allocation, strict risk limits, and verifiable accounting. - **Offchain execution:** External agents (called "[Alphas](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-alpha.md)") execute strategy operations based on parameters and logic configured by vault managers (called "[Atomists](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-atomist.md)"). ## Who is this documentation for? This section provides technical specifications and integration guides for anyone building on or interacting with the Fusion ecosystem. The primary audience includes: - **Vault Managers (Atomists) & Risk Managers** configuring market substrates, exposure limits, and role-based access controls. - **Backend Developers** building offchain execution agents (Alphas). - **Smart Contract Engineers** integrating new protocols via the Fuse architecture. - **Integrators** connecting external applications to Fusion's ERC4626 vault interfaces. If you require technical support or have specific integration questions, please open a ticket on the IPOR Labs Discord server. > **Note:** To stay up to date on frontend, MCP and SDK feature updates, join the [**announcement channel on Telegram**](https://t.me/fusionsdk) --- Source: https://ipor.io/docs/build-on-fusion/fusion-for-agents.md # Fusion for agents > Router page for AI agents: which Fusion interface (MCP, SDK, API) to use for which task, plus the minimal vault-creation example. ### Fusion for agents #### Fusion for Agents — Start Here Use this page to choose the correct machine interface for working with IPOR Fusion. Start here if you are using Codex, Claude or another AI agent to inspect Fusion vaults, prepare transactions or build integrations. This page is a router to the canonical Fusion interfaces. It does not replace the detailed technical documentation. **Choose the right interface** **Fusion MCP** Use Fusion MCP to inspect deployed Fusion state and research existing vaults, including available vault configuration, Fuses, Balance Fuses, substrates, roles, oracle configuration, registered contracts and other information exposed by the server. **Hosted MCP connection** Transport: `Streamable HTTP` Server URL: `https://mcp.ipor.io/mcp` The server URL is an MCP transport endpoint. Add it through the MCP settings of the relevant AI client. Do not open it as a normal webpage. Full tool list, resources, prompts, client setup commands and a worked example: MCP For a locally installed alternative, use the MCP server included in the Python SDK: [Install the SDK-bundled Fusion MCP server](https://github.com/IPOR-Labs/ipor-fusion.py#mcp-server) **Python SDK** Use the official Python SDK to create Fusion vaults, construct contract calls, encode calldata and submit transactions through a configured signer. - [Python SDK repository](https://github.com/IPOR-Labs/ipor-fusion.py) - [FusionFactory implementation](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/src/ipor_fusion/core/fusion_factory.py) - [SDK installation and quickstart](https://github.com/IPOR-Labs/ipor-fusion.py#quickstart) The executed, transaction-by-transaction SDK walk is on Deploy your first Fusion vault. Factory addresses per chain are on Addresses; revert selectors and the role table are on Common Errors. **Fusion Vault Launchpad** Use the Fusion Vault Launchpad when the task is a complete vault deployment: create, configure, verify and rehearse a Plasma Vault from one JSON strategy file, with a human in the loop. The pipeline runs 17 idempotent steps on top of the Python SDK and verifies the result from the vault's own contracts. A dry-run needs no key; a fork rehearsal on a local anvil fork deposits, executes every declared fuse, checks accounting and withdraws; a live broadcast needs the human's own funded key and an explicit sign-off. - [Fusion Vault Launchpad repository](https://github.com/IPOR-Labs/fusion-vault-launchpad) - [AGENTS.md — operating guide for agents, read first](https://github.com/IPOR-Labs/fusion-vault-launchpad/blob/main/AGENTS.md) - [Using the repository with your agent](https://github.com/IPOR-Labs/fusion-vault-launchpad/blob/main/docs/09-using-with-your-agent.md) Supported chains: Ethereum and Base. Two worked examples ship: a USDC vault on Aave V3 and a leveraged wstETH/USDC loop on Morpho Blue, both on Base. **Fusion API** Use the Fusion API for public vault, product and historical data exposed through HTTP endpoints. [Fusion API documentation](https://ipor.io/docs/build-on-fusion/developer-guide/api.md) **Machine-readable documentation** Use the machine-readable documentation indexes to discover and retrieve Fusion documentation: - [llms.txt](https://ipor.io/docs/llms.txt) - [llms-full.txt](https://ipor.io/docs/llms-full.txt) - [Fusion documentation homepage](https://ipor.io/docs.md) - [ipor.io/llms.txt](https://ipor.io/llms.txt): protocol-wide index across the app, the docs, the SDK and the Fusion Vault Launchpad Pages in this guide written for agents carry the `agents` tag: MCP, Deploy your first Fusion vault, Addresses, Common Errors and SDK. GitBook also exposes individual documentation pages as Markdown. If a raw Markdown URL cannot be retrieved, do not assume the page is unavailable. Retry through the normal HTML page, `llms.txt`, `llms-full.txt` or the linked GitHub source. **Deployments and ABIs** Use the canonical IPOR ABI and deployment repository to resolve supported contract names, chain-specific deployment addresses and ABIs. [IPOR deployments and ABIs](https://github.com/IPOR-Labs/ipor-abi) An address or ABI does not, by itself, prove that a Fuse or other component is compatible with a particular vault, market or strategy. **Creating a Fusion vault** Vault creation is available through `FusionFactory.clone()` in the Python SDK. ```python from web3 import Web3 from ipor_fusion import Web3Context from ipor_fusion.core import FusionFactory ctx = Web3Context.from_url( url=RPC_URL, private_key=PRIVATE_KEY, ) factory = FusionFactory( ctx, Web3.to_checksum_address(FUSION_FACTORY_ADDRESS), ) clone_call = factory.clone( asset_name="Example Fusion Vault", asset_symbol="exampleFV", underlying_token=Web3.to_checksum_address(ASSET_ADDRESS), redemption_delay_seconds=0, owner=Web3.to_checksum_address(OWNER_ADDRESS), dao_fee_package_index=0, ) preview = clone_call.call() calldata = clone_call.calldata receipt = clone_call.send() ``` The returned call supports three workflows: - `clone_call.call()` performs a read-only `eth_call` preview and returns the predicted Fusion deployment. - `clone_call.calldata` returns unsigned calldata for an external signer or multisig workflow. - `clone_call.send()` submits the transaction using the signer configured in `Web3Context`. Resolve the chain-specific `IporFusionFactoryProxy` address through the canonical deployment registry: [IPOR deployments and ABIs](https://github.com/IPOR-Labs/ipor-abi) Preview creation again immediately before submission because the predicted deployment depends on the factory's current state. **Creation is not configuration** Creating a vault deploys the Fusion vault infrastructure. It does not make the vault strategy-ready. Depending on the intended strategy, post-deployment configuration can include: - access roles and execution permissions; - Functional Fuses and Balance Fuses; - substrates and dependencies; - price feeds and oracle configuration; - limits and withdrawal configuration. Use the existing configuration documentation for the detailed process: - [Vault configuration step-by-step](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step.md) - [Access Management](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/access-management.md) - [Substrates](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/substrates.md) - [Price Oracle Middleware](https://ipor.io/docs/build-on-fusion/developer-guide/price-oracle-middleware.md) - [What is a Fuse?](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fuse.md) **Rules for agents** - Use Fusion MCP for deployed-state inspection and research. - Use the Python SDK for vault creation and call construction. - For a complete vault deployment, use the Fusion Vault Launchpad instead of assembling the steps by hand. Never broadcast to a live chain without a clean fork rehearsal and the human's explicit "yes" for that exact strategy file. - Resolve production addresses through the canonical deployment registry. - Do not infer production configuration from tests or an arbitrary existing vault. - If an authoritative integration or configuration requirement cannot be found, return `UNKNOWN` rather than guessing. - Preview and prepare transactions by default. Signing or broadcasting requires explicit authorization. --- Source: https://ipor.io/docs/build-on-fusion/architecture-overview/general.md # General > High-level map of the Fusion architecture: how vaults, fuses, Atomists and Alphas fit together. > IPOR Fusion's architecture is modular, built with flexibility and composability in mind. It consists of three core elements: - [**Vaults**](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fusion-vault.md) (ERC4626 compliant) accept deposits and put capital to work by deploying it in a series of strategies that will be dynamically managed by Alpha Keepers (Alphas for short); - [**Fuses**](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fuse.md) are small contracts that connect vaults with specific actions within DeFi protocols; - [**Atomists**](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-atomist.md) are curators that design the strategy of the vault; - [**Alphas**](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-alpha.md) are the off-chain agents or bots responsible for maintaining the strategy operations of a specific vault. They run off-chain automated software to optimize asset allocation by calling functions on Fuses within the limits set by the Atomist. ![Diagram of operational vaults with fuses and alpha connected](https://ipor.io/docs/assets/build-on-fusion/chart-3-22fc2a.jpg) _Diagram of operational vaults with fuses and alpha connected_ ## Asset Ownership All deposited assets are held by the vault and can not be shared in any way between multiple vaults. That makes things like taking loans against deposited assets possible so that the strategies like leveraged looping are possible on Fusion. ![Image](https://ipor.io/docs/assets/build-on-fusion/screenshot-2024-09-12-at-9-27-00-am-cbbaa5.png) __ ## Upgradability and Configuration Vaults and fuses are not upgradable. Their functionality, however, can be extended by connecting new fuses, or removing unused fuses. Vaults allow for a certain degree of configuration (see more here: [Configuration](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step.md)) ## Supported Blockchains Fusion is currently available on the following blockchains. - Ethereum - Base - Arbitrum - Unichain - Ink - Avalanche - Plasma - TAC Depending on demand, Fusion will also be deployed to other blockchains. --- Source: https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fusion-vault.md # What is a Fusion vault? > The Plasma Vault's implemented standards (ERC-4626, ERC-20, OZ Votes, Access Manager), redemption delay, rewards, fees and configuration surface. ## Architecture Vaults in IPOR Fusion are called Plasma Vaults and are the central part of the Fusion system. Plasma Vaults implement a Diamond Proxy pattern and delegate calls to fuses and attached contracts to manage this such as fees and rewards collection. ![A Plasma Vault's relation to other elements of the system](https://ipor.io/docs/assets/build-on-fusion/chart-2-10db03.jpg) _A Plasma Vault's relation to other elements of the system_ ### Implemented Standards Plasma Vaults implement multiple standards that enable an array of desired functionalities. ### ERC4626 All Plasma Vaults implement the ERC4626 standard. ### ERC20 All Plasma Vaults implement the ERC20 standard. Standard functionality can be restricted at the time of the vault creation, namely: - **Minting and redemption** can be restricted by the vault creator so that only the whitelisted addresses have access to those methods. This setting can only be lifted, not added later. That means if the vault is created as closed/whitelisted it can later become an open vault, however if it is already unrestricted then it cannot be moved to a restricted mode - Transferability can be restricted upon vault creation. This setting can only be lifted making transferability possible but not the other way around ### Open Zeppelin Votes Plasma Vaults implement OpenZeppelin Votes.sol to enable integration with DAOs and DAO Protocols such as [Aragon](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/vault-governance-and-depositor-led-security-best-practices.md). This implementation allows for counting shares for any given block and allows voting on proposals without the need for locking or wrapping the share tokens. OpenZeppelin Votes add to gas cost when dealing with shares, and Vault Creators can opt-out of this integration at the time of vault creation. ### Open Zeppelin Access Manager Plasma Vaults rely on [OpenZeppelin Access Manager](https://docs.openzeppelin.com/contracts/5.x/api/access#AccessManager). This system is used by the vault to validate access to all the restricted methods. More information about the access manager configuration can be found in the [dedicated documentation](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/access-management.md). ## Redemption Delay Fusion allows Atomists to set a mandatory delay between deposit and redemptions of assets from the vault. In other words, if configured to a value higher than 0 the user would not be able to deposit and withdraw assets in the same block. That helps with preventing malicious attacks to sandwich a vault and take advantage of the events when the exchange of the vault token changes. By default the vaults are configured so that flash loans can't be used, but the Atomists can set the timeout to higher value to operate the Vault according to a specific strategy. ## Handling of Rewards As the vault delegates assets it may also happen, that it will accrue rewards or points from the protocols it connects to. The strategy and how to deal with those incentives may vary depending on the Atomist's strategy and the Plasma Vault allows for great flexibility in this regard.\ \ Plasma Vaults utilize a dedicated sub-module called `Rewards Manager` to handle the process of counting, claiming, passing rewards for further processing, and handling the proceeds from of the rewards for example auto compounding pw- or ve- rewards, automatic sale, or TWAP. - **Accounting** - vaults don't account for the accrued rewards by design. Usually, rewards would be issued in the reward token other than the vault's accounting token and it could lead to issues with accounting and vulnerabilities when calculating the exchange rate of the share token. - Dealing with claimed rewards - After the rewards have been claimed, they can be requested by another contract or an entity. - Phasing rewards back into the vault ## Fees There are two types of fees that can be charged in a Fusion Vault: - Performance fee - charged as a percentage of the increase of the exchange rate between vault's underlying asset and the vault token. A [high-water mark method](https://www.investopedia.com/terms/h/highwatermark.asp) is used. - Management fee - charged on the vault's annualized TVL. The Atomists configure both fees. The IPOR DAO also earns part of both fees to support its operations. See [here](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step.md). ## Configuration Basic configuration: - Name and token ticker - immutable - Underlying asset - immutable - Total supply cap - configurable by the Atomist ### Timelocks - configurable Each role (check the [access management](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/access-management.md)) has a timelock attached. For every action taken the role holder is subject to a timelock. The timelock value can be changed by granting the role again by authorized user. ### Restricting minting and redemptions (whitelist) - partially configurable by the Atomist Atomists can launch the vault with the whitelist, they can amend the addresses on the whitelist and also turn off the whitelist altogether. A whitelist can not be added to vaults already launched or made public. ### Restricting transfers - partially configurable by the Atomist Vault can be launched with restrictions on transfers of vault tokens. This restriction can be lifted by the Atomist after the launch of the vault. However if the restriction on transfers has already been lifted, or vault was launched without the restriction then the transferability can not be imposed. ### Withdrawing assets - immutable Depending on the trading strategy of the Vault, it can configured to have either instant or "scheduled" withdrawals. All vaults are launched hybrid as default, meaning they can support both instant and scheduled withdrawals. ### Fees - configurable Fees changes are subject to a timelock and caps hardcoded in the vault contract. ### [Access management](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/access-management.md) - configurable ## Operation ### Creating a Plasma Vault Vaults can be [created](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step.md) manually by deploying a configured version of the Fusion Vault using the repository or by using the factory. The detailed instruction on how to use the factory and it's UI can be found in the [Quick Start Guide](https://ipor.io/docs/build-on-fusion/developer-guide/quick-start-guide.md) ### Editing a Vault A vault's configuration can be edited by authorized users - see [Access Management](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/access-management.md) for more information. ### Creating transactions Step 1 : Define data structures ```solidity struct AaveV2SupplyFuseEnterData { address asset; uint256 amount; } struct Erc4626SupplyFuseEnterData { address vault; uint256 vaultAssetAmount; } struct FuseAction { address target; bytes data; } ``` Step 2: Prepare Data ```solidity address usdcAddress = 0xFF970A61A04b1cA14834A43f5de4533eBDDB5CC8; // Arbitrum USDC Address AaveV2SupplyFuseEnterData memory aaveData = AaveV3SupplyFuseEnterData({ asset: usdcAddress, amount: 1000 // amount to supply }); Erc4626SupplyFuseEnterData memory erc4626Data = Erc4626SupplyFuseEnterData({ vault: 0xabcdefabcdefabcdefabcdefabcdefabcdef, // Adres vaulta vaultAssetAmount: 500 // amount to supply }); FuseAction[] memory actions = new FuseAction[](2); actions[0] = FuseAction({ target: address(aaveV3SupplyFuse), // AaveV3SupplyFuse data: abi.encodeWithSignature("enter((address,uint256))", aaveData) // params to call the method }); actions[1] = FuseAction({ target: address(erc4626SupplyFuse), // Erc4626SupplyFuse contract address data: abi.encodeWithSignature("enter((address,uint256))", erc4626Data) // params to call the method }); ``` Step 3: Invoke method ```solidity plasmaVault.execute(actions); ``` --- Source: https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fuse.md # What is a Fuse? > What a Fuse is, how it adapts vault calls to an external protocol, and the fuse whitelist registry. > Fuses are one of three pillars on which Fusion stands. Fuses are the remedy providing permissionlessness, transparency, security, and speed of development. **Fuses** are small contracts that are attached to vaults to perform atomic actions on integrated protocols. All Fuses must meet the following requirements: - **Stateless** — They have no memory, no configuration, and they store no data. Thanks to that they can be used by multiple vaults at the same time without the risk of interfering with one another. - **Non-upgradable** — Fuses, by nature, are simple contracts that can not be altered. That assures a Plasma Vault’s actions can be trusted and Fuses can be shared without additional risk. Should the destination market’s ABI change, a new Fuse needs to be deployed.\* - **Standard ABI** — One of the tasks of the Fuse is to bring the interface of the market down to a standard ABI. Fuses implement two core functions: Enter and Exit that, depending on context deploy or withdraw assets, take a loan or repay it, etc. On top of that some Fuses can implement instantWithdraw — a function with predefined params to pull the assets from the market without the need for Alpha’s interaction. This is relevant if the Vault allows for instant redemptions of shares. - **Configurability** — Because Fuses are stateless, any configuration is delegated to the vault. The Fuse is built to accept the calls with the configuration. ## Types of Fuses Fuses, by design, are limited to specific uses. One protocol may allow many use cases such as providing liquidity, trading derivatives, staking, etc. Outside of functions that can be performed, there are other kinds of actions that need to be performed such as checking balance or claiming incentives. Below is the detailed list of kinds of fuses used by Fusion. ### Functional fuses These bi-directional fuses allow for action and its reversion. What that means depends on the protocol but some examples would include: - **Provide** and **withdraw** liquidity from a DEX or a Credit Market - **Borrow** against collateral and **repay** the loan - **Open** and **close** a derivative such as an option, an interest rate swap, or a perpetual future ### Balance Fuses Each project may require slightly different steps to price assets that are deposited into it by the vault. Vault may be depositing liquidity and at the same time borrowing against collateral. Balance fuse provides a standard way to account for the balance that is then taken when calculating the exchange of the vault's shares. When supporting a given protocol, a balance fuse is the mandatory fuse to provide. See also [here](https://ipor.io/docs/build-on-fusion/developer-guide/balance-fuses.md). ### Rewards Fuses Each Vault comes standard with a Rewards module. It is responsible for claiming the rewards on behalf of the Vault and allows to pass the claimed incentives to a dedicated agent for processing. If the rewards are sold, the proceeds can be deposited back to the rewards manager and vested into the vault. Claiming of the rewards is done via a specialized fuse, that when invoked, will handle the logic of claiming the rewards. ### Swap Fuses Swapping in the context of Fusion is not reversible. Therefore the swap fuses have slightly different interfaces. They allow for the swapping of two approved assets. ### Custom Fuse Besides the typical fuses listed above, custom fuses can be created and used by the vault. Since fuses follow a delegate call, the fuse custom function can also be executed. This can extend the functionality of the vault to accommodate new workflows. It is important to note that custom fuses must be thoroughly tested, and possibly audited before use. ## Developing a Fuse The Fusion DAO is dedicating efforts to provide lots of quality fuses. However, if you would like to see a fuse developed that is not on the DAO's backlog, you may want to develop it yourself. If you're the protocol administrator and wish Fusion to integrate with you, this is the fastest way to integrate. You can find detailed instructions on the [dedicated section](https://ipor.io/docs/build-on-fusion/integrating-a-new-market.md). ### Currently available fuses developed by IPOR Labs The readme of below repository has the latest list of deployed fuses ## Fuse Whitelist Registry The IPOR DAO maintains a global Fuse Whitelist Registry that tracks the status of all Fuses (`ACTIVE`, `DEPRECATED`, `REMOVED`). The Whitelist is [here](https://app.ipor.io/fusion-terminal/fuse-whitelist/ethereum/fuses) available in Fusion Terminal. --- Source: https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-atomist.md # What is an Atomist? > The Atomist role: who configures a vault's risk and market boundaries. > An Atomist is a strategy designer. Atomists are curators that design the strategy of the vault. They construct their investment universe by selecting assets, actions, and markets via Fuses and substrates. Atomists can commission an external [Alpha](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-alpha.md) or run their own internal Alpha using their own optimization and risk parameters to automate the Vault.\ \ An Atomist might be one of the following profiles: - Risk Curators - Asset Managers - Crypto native Funds - TradFi Funds - Protocols - DAO Treasuries - and so on Fusion is particularly suitable for [institutional](https://ipor.io/docs/fusion-for-institutions.md) use. --- Source: https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-alpha.md # What is an Alpha? > The Alpha role: who executes strategy transactions within an Atomist's configured boundaries. Most fundamentally, the Alpha is a role granted by the [Atomist](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-atomist.md). You can think of the Alpha as the active management function of a fund. The privilege that an Alpha has is preparing and executing transactions on behalf of the Fusion Vault. Alphas can be smart contracts, AI agents, EOAs, or automated services that hold their private keys. Each vault can have multiple Alphas so it is important that, if multiple Alphas are connected to a particular vault, they should be coordinated so that they don't interfere with one another. The transactions an Alpha can perform are defined and limited by the vault's strategy. An Alpha can only execute transactions for which the necessary fuses have been connected to the vault. This ensures that an Alpha cannot misuse the vault's assets. --- Source: https://ipor.io/docs/build-on-fusion/atomists/benefits-for-atomists.md # Benefits for Atomists > Why an asset manager would run their strategy as a Fusion vault instead of building custom infrastructure. ## Architecture advantages Fusion infrastructure was developed to address the needs of both traditional finance (TradFi) and decentralized finance (DeFi) asset managers (Atomists). It offers several key technological advantages: - No-code Strategy Deployment - Modularity - Onchain-enforced Security - Infrastructure neutrality - Admin Dashboard - intuitive GUI for Atomists - Support Atomists can select from multiple vault configurations to match their needs: - Public Vault: Visible on the IPOR Fusion webapp, fostering community trust and network effects. - Private Vault: Hidden from the webapp, ideal for exclusive strategies. - Whitelisted: Restricted access for select participants, balancing privacy and collaboration. - Open: Fully accessible, encouraging widespread adoption and liquidity. Atomists can build multiple strategies - Fusion Vaults - for different base assets, risk profiles, Fuses, etc. Atomists can also build Funds of Funds - ERC-4626 vaults, which sit above multiple Fusion Vaults and can deploy across a diverse range of strategies. Whitelisting and permissioning can be a compliance-friendly tool for Atomists to meet regulatory considerations. ### No-code Strategy Deployment Atomists can design and deploy complex strategies without coding expertise, using an intuitive interface to configure vaults and Fuses. This accelerates strategy implementation and reduces operational overhead. ### Modularity IPOR Fusion's polymorphic architecture design enables Atomists to mix and match components — such as base assets, markets, and Fuses to create tailored Fusion vaults. This "controlled composability" enables significantly improved transparency and significantly enhanced security when compared to existing solutions. This modular design enables strategy updates over time while maintaining the security of smart contracts. ### Onchain-enforced Security Security is embedded in smart contracts, ensuring vault operations are transparent and trustless. This eliminates reliance on unverifiable offchain logic, providing peace of mind and optimized yield with minimized risk exposure. > In IPOR Fusion, anything that can be onchain is onchain. Unlike Fusion, many other onchain asset management solutions build contract calls offchain. They usually use a sidechain construction to validate them, but the calls can be unbounded and potentially malicious. Validation is mostly a blackbox. Fusion offers a restricted onchain investment universe thanks to the Fuse system. All possible assets, markets, and actions are defined by the Atomist, setting limits on what the strategy is allowed to do. Put differently, a Fusion vault is a walled garden - a safe onchain environment where even an AI Agent can play, without being able to go beyond the limits of the strategy. Fusion Vault managers can use offchain logic or delegate the asset management automation function (Alpha) to anyone. Alphas can't instruct Fusion Vaults to perform operations that are not encoded in the onchain Vault logic. ### Infrastructure neutrality IPOR Fusion Atomists are empowered to exercise full control over their asset management workflows, including the ability to establish fully private vaults and tailor their strategies according to their specific requirements. They may also customize the fee structure to suit their business models and extend these vaults as offerings to their existing clientele. Onchain strategies facilitated by IPOR Fusion can further attract new clients based on their risk profiles. From a business perspective, IPOR Labs imposes no exclusivity constraints, allowing Atomists the flexibility to collaborate with other infrastructure providers. > Fusion is a neutral infrastructure. IPOR Labs builds functionality for asset managers to succeed, it does not compete with Atomists. ### Admin dashboard An intuitive GUI enables Atomists to manage permissions, monitor vault performance, and adjust strategies via Web3 wallet interactions, enhancing operational control. Fusion is fully permissionless and vaults can be built and configured at will. IPOR Labs can also guide Atomists through an onboarding phase and even help wire up a vault. After the onboarding phase, the IPOR Labs team can transfer operational control over a Fusion Vault to the Atomist. From that point on, the Atomist is in full control. ### Support IPOR Labs provides comprehensive onboarding assistance to Atomists, guiding them through a structured process to articulate and implement their strategies effectively. IPOR Labs collaborates closely, recommending optimal approaches and can connect them with appropriate Alpha builders where necessary. Both DeFi and TradFi managers may leverage pre-existing Alpha solutions or, with sufficient technical expertise, create their own, ensuring a tailored and supported entry into DeFi. ## Verified Fuses As an Atomist, your responsibility is to create the vault's strategy. Part of that is selecting Fuses that will be used by the Alpha to operate the vault. All interactions with external parties are governed by the fuses. It is therefore vital that you verify the integrity of the Fuses. IPOR DAO keeps a record of the Fuses and their verification status. Also, each Fuse, on this list is open-sourced and verified on Etherscan. ## Alphas Actions that an Alpha can take are limited by the connected Fuses and substrates, actions such as swaps are constrained by the fuse configuration that you, as an Atomist set up when adding or modifying the Fuse list. Configuration is Fuse-specific, but generally, you can limit the tokens that can be used or slippage in case of swapping. ## Timelocks When creating a vault, the Atomist has to decide what the "minimum timelock" should be. This value defines how much time has to pass, from when the Atomist initiates changes to the vault's configuration until those changes can take effect. The minimum timelock will define how fast the Atomist can enact the changes, at the same time it will communicate to vault shareholders how much time will they have to act if they wish to move assets. The timelock can also be set to 0 in which case, all the changes would be instant. ## Access Management Access management in IPOR Fusion is handled by the [OpenZeppelin Access Manager](https://docs.openzeppelin.com/contracts/5.x/api/access#AccessManager). Roles are assigned during vault creation but some can be changed later. Please refer to a dedicated [Access Management](https://ipor.io/docs/build-on-fusion/atomists/benefits-for-atomists.md) page --- Source: https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step.md # Vault configuration step-by-step > The full vault setup guide: fuses, substrates, price oracle, pre-hooks, scheduled withdrawals, instant withdrawal order and fees. Below best practices and vault setup algorithm is a guide you can use to configure your own Fusion Vault. All settings described below can be accomplished by using the [**Build on Fusion web application**](https://app.ipor.io/build-on-fusion)**.** There is also a [Quick Start Guide](https://ipor.io/docs/build-on-fusion/developer-guide/quick-start-guide.md) and a [Video Documentation](https://www.youtube.com/playlist?list=PLTda9D8MCj4QafXFkFPR_i27CakEUdBeg) available. ## Access Management See [here](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/access-management.md). ## Strategy Strategy Configuration: Defining the vault’s strategy is the primary responsibility of Atomists and Fuse Managers. The following instructions provide a step-by-step guide to configuring the most critical aspects of the strategy settings. ![Image](https://ipor.io/docs/assets/build-on-fusion/screenshot-2025-06-05-at-2-40-13-pm-830af1.png) __ **Setting up Fuses:** Configuring fuses is the most critical process in defining the vault’s strategy and must be executed carefully. A list of available fuses for supported blockchains is available in the [whitelist](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fuse.md) contract or the IPOR Labs repository [(https://github.com/IPOR-Labs/ipor-fusion)](https://github.com/IPOR-Labs/ipor-fusion). Below is a step-by-step guide to configuring the key aspects of fuse settings. ### 1. Balance Fuses Fuses are paired as "Balance Fuses" and "Functional Fuses." Balance Fuses track the vault’s asset balances after transactions, while Functional Fuses perform actions. Each fuse is identified by a unique marketId, assigned during deployment. All Functional Fuses must be paired with a Balance Fuse. If a Balance Fuse reads no balance, use the ZeroBalanceFuse [(https://github.com/IPOR-Labs/ipor-fusion/blob/main/contracts/fuses/ZeroBalanceFuse.sol)](https://github.com/IPOR-Labs/ipor-fusion/blob/main/contracts/fuses/ZeroBalanceFuse.sol). - ERC20 Balance Fuse: Tracks ERC20 token balances held directly by the vault. Include this fuse in most vaults to monitor ERC20 assets. - Standard Balance Fuses: Market-specific fuses, including: - ERC4626 Balance Fuses: Configurable in two ways: - Separate ERC4626 per Market: Tracks each market’s balance individually for easier monitoring. - Single ERC4626 for All Markets: Simplifies integration and reduces gas costs but tracks balances as a single sum.\ Best Practices: - Always pair Functional Fuses with a corresponding Balance Fuse or ZeroBalanceFuse. - Use separate ERC4626 fuses for complex strategies requiring granular balance tracking. ### 2. Functional Fuses Each market integration requires at least one Balance Fuse and typically one or more Functional Fuses. Some markets support multiple Functional Fuses for additional functionality (e.g., Morpho supports Deposit, Borrow, and Flash Loan fuses, plus an ERC4626 fuse for MetaMorpho deposits). Non-standard fuses include: - Universal Swapper Fuse: A flexible interface for complex transactions (e.g., aggregators, staking, DEX interactions). It validates: - Whitelisted assets (only substrate-defined assets). - Whitelisted markets (e.g., DEXes, aggregator proxy contracts, staking contracts). - Beneficiaries (default: the vault). - Allowed method signatures. - ERC4626 Fuse: Enables deposits to any ERC4626 vault, including IPOR Fusion vaults. - Custom Fuses: Built for unique scenarios (e.g., airdrops). Non-whitelisted custom fuses trigger alerts in the IPOR Fusion interface. - Rewards Fuses: Used by the rewards manager to harvest token incentives.\ Best Practices: - Whitelist all assets and markets for Universal Swapper transactions to ensure safety. - Add custom fuses to the [whitelist](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fuse.md) to avoid user alerts. ### 3. Fuse Configuration - Substrates: Configure substrates (e.g., asset or market addresses) based on fuse requirements. Consult individual fuse documentation if managing substrates manually (outside the IPOR Fusion interface). Common substrates include asset addresses (e.g., for DEXes, Universal Swapper) or market addresses (e.g., for Morpho, ERC4626). - Price Feeds: All Balance Fuses, except ZeroBalanceFuse, rely on the Price Oracle and its feeds. Ensure matching price feeds are configured (see "Price Oracle" section below). Price feeds can be set via the IPOR Fusion interface. - Dependency Graph: Fusion caches asset balances for gas efficiency, updated when Alpha adjusts allocations or balances are manually refreshed. For some markets (e.g., DEXes), update related balances (e.g., ERC20 after a swap). Configure the dependency graph by selecting a market and defining additional balances to update.\ Best Practices: - Verify substrate compatibility with each fuse to avoid misconfiguration. - Configure the dependency graph for markets requiring multi-balance updates (e.g., DEX swaps). ### 4. Price Oracle Vaults include a standard Price Oracle middleware provided by Fusion, with verified price feeds from reputable sources (e.g., Chainlink). Additional price feeds or custom middleware can be added as needed.\ Best Practices: - Ensure price feeds match the assets and markets used by Balance Fuses. - Use verified price feeds to maintain reliability and security. ### 5. Pre-Hooks See the dedicated pre-hooks documentation for configuration details [here](https://ipor.io/docs/build-on-fusion/developer-guide/configuring-pre-hooks.md). ### 6. Scheduled Withdrawals Fusion vaults support two withdrawal types: Scheduled and Instant (both can be used at the same time). To disable scheduled withdrawals, set the withdrawal window to 0. Otherwise, define the withdrawal window (in seconds) before requests expire. Alpha should prepare assets well before expiration to allow LPs time to claim.\ Best Practices: - Set a withdrawal window that balances LP convenience and vault stability. - Ensure Alpha prepares assets early to avoid expiration issues. ### 7. Instant Withdrawal Order Unallocated assets and specific fuses configured for instant withdrawals are available immediately. Define the order of markets for instant withdrawals via the IPOR Fusion interface. Important: Avoid including markets where withdrawals could cause liquidations (e.g., if assets are used as collateral for borrowing).\ Best Practices: - Exclude collateralized markets from instant withdrawals to prevent liquidations. - Use timelocks for changes to instant withdrawal configurations. ### 8. Fees There are two types of fees: - Performance fee - charged as a percentage of the increase of the exchange rate between vault's underlying asset and the vault token. A [high-water mark method](https://www.investopedia.com/terms/h/highwatermark.asp) is used. - Management fee - charged on the vault's annualized TVL. The fees can also be split and sent to several different addresses. By default, each vault charges a fixed management fee and performance fee that goes to the Fusion DAO. The Atomist can choose between 3 fee tiers during the vault creation process: | Tier | Management Fee | Performance Fee | | ---- | -------------- | --------------- | | A | 0.05% | 10% | | B | 0.3% | 2% | | C | 0.5% | 0% | > **Note:** The fee tier cannot be changed after the vault has been created. Atomists can define additional fees by specifying addresses and rates, ensuring total fees do not exceed 5% (management) or 50% (performance). Fees are displayed in the vault overview for LPs. Best Practices: - Use a multisig wallet for fee management to enhance security. - Clearly communicate fee structures to LPs to maintain transparency. ### 9. On- and Offboarding Contributions [What are On- and Offboarding Contributions?](https://ipor.io/docs/fusion-for-depositors/user-guide/vault-fees/onboarding-and-offboarding-contributions.md) [Decision aid for Atomists](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/on-and-offboarding-contributions.md) --- Source: https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/access-management.md # Access Management > How OpenZeppelin Access Manager governs vault roles, and how to grant, revoke and time-lock them. ## Overview IPOR Fusion utilizes OpenZeppelin's AccessManager to restrict function access through a role-based system. The roles below are ordered from highest to lowest authority. (Developer note: The list of roles is available in the GitHub repository: ) ![Image](https://ipor.io/docs/assets/build-on-fusion/screenshot-2025-06-05-at-2-37-40-pm-a6bee3.png) __ ![Image](https://ipor.io/docs/content-images/08856daef7ac.jpg) __ ## Grant Delays (The Waiting Room) When [timelocks](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/timelocks-and-execution-delays.md) are enabled, adding a new account to an important role follows a strict procedure to prevent the sudden injection of foreign keys into governance. When a new account is granted an important role, its membership does not activate immediately — it waits out that role's grant delay first (recommended: 14 days for `OWNER`, 3 days for the configuration tier). This closes the "inject a key into governance" path: even a grant that completes successfully produces an account that cannot act yet. The rule itself is protected too. Changing a grant delay via `setGrantDelay` arms only after a hardcoded 5-day minimum setback (`minSetback`) — and reducing one takes the larger of 5 days and the size of the reduction. Nobody, including a legitimate administrator, can shorten the waiting room and walk a new key straight in. Note that grant delays are `ADMIN`-gated: they must be configured before `ADMIN` is renounced, or they become permanently unavailable. _Developer Note:_ Re-granting an existing member — for example raising their execution delay — is not subject to the grant delay. This is deliberate: it keeps hardening instantaneous. ## Admin Role An account with this role has the rights to manage the IporFusionAccessManager in general. It is the highest role, capable of managing all roles including `ADMIN_ROLE` and `OWNER_ROLE`. This is a technical role used during the bootstrapping phase of a vault. In a fully secured, timelocked vault deployment, the `ADMIN` role is ultimately **renounced**. _Note:_ When a vault is created in supervised mode, the `ADMIN` role must be **manually renounced** (after making the `OWNER` self-administered) to remove the "skeleton key" that could override all security mechanisms instantly. ## Owner Role The highest administrative role, defined during the vault's bootstrapping process. The account with this role has rights to manage Owners, Guardians, Atomists, and configure execution delays (timelocks). - Self-managed (if `getRoleAdmin(OWNER) == OWNER`, the Owner can change itself to another Owner) - Single user (recommended use of multisig for this role) **Best practices** - **14-Day Timelock:** The Owner role should be configured with a 14-day execution delay to ensure all top-level administrative changes are publicly visible well in advance. - **Strict Key Separation:** Use a highly secure, dedicated multisig wallet. The accounts holding the Owner role must be strictly separated from accounts holding operational roles (like Atomist or Alpha) and must be completely distinct from Guardian keys. - **Cold Wallet Usage:** Treat the Owner multisig effectively as a cold wallet used only for structural vault changes. ## Atomist Role This role serves as the primary managing accounts for the vault, overseeing most day-to-day settings, such as configuring Fuse Managers, Alphas, fees, and other parameters. - Configurable by the Owner - Allows multiple users #### Best practices - Use multiple Atomists to ensure redundancy. - Apply timelocks to selected Atomist actions whenever feasible. ## Alpha The account with this role has rights to execute the strategy on the vault using execute method, typically as an automated strategy manager. - Configurable by the Atomist - Allows multiple users Depending on the level of automation, the following roles can be assigned to the same wallet managed by Alpha in the IPOR Fusion system: ### CONFIG_INSTANT_WITHDRAWAL_FUSES_ROLE (900) This role configures fuses, such as credit market deposit fuses, to enable instant withdrawals, allowing liquidity providers (LPs) to withdraw assets from the vault immediately. The role holder defines the order of configured markets to ensure asset availability for LPs. A key requirement is that the market (a collection of fuses linked to an external platform) must be fully liquid from the vault’s perspective. If liquidity is used as collateral for borrowing, instant withdrawals could trigger liquidation, so such markets should not be used. For complex vault strategies involving adding or removing credit positions, assign this role to Alpha for efficiency. Alternatively, a dedicated address or Atomist can manage it. #### Best Practices - Ensure markets selected for instant withdrawals are highly liquid to avoid liquidation risks. - Use timelocks for changes to fuse configurations to allow review by Guardians or LPs. ### WITHDRAW_MANAGER_REQUEST_FEE_ROLE (901) This role sets the request fee, charged when an LP submits a withdrawal request from a scheduled withdrawal vault. The fee is applied at the time of the request, not redemption. For strategies with algorithmically adjusting fees, assign this role to Alpha. Alternatively, Atomists can manage it based on the vault’s strategy. #### Best Practices - Use a multisig wallet for managing this role to enhance security. - Monitor fee adjustments to align with the vault’s strategy and LP expectations. ### WITHDRAW_MANAGER_WITHDRAW_FEE_ROLE (902) This role sets the withdrawal fee, analogous to the request fee but charged during instant withdrawals. #### Best Practices - Align withdrawal fees with the vault’s operational strategy. - Use a multisig wallet for secure management. ### UPDATE_MARKETS_BALANCES_ROLE (1000) This role manually updates cached market balances for deposits or withdrawals if automation (e.g., via pre-hooks) is not enabled. This is necessary for less active vaults to ensure accurate balance reporting. For efficiency, assign this role to an automated service. #### Best Practices - Automate balance updates with pre-hooks when possible to reduce manual intervention. - Grant this role to a secure, automated service to ensure timely updates. ### UPDATE_REWARDS_BALANCE_ROLE (1100) Similar to the previous role, this role updates the balances of incentives claimable by the vault through the rewards manager. For automated workflows, assign this role to Alpha. #### Best Practices - Integrate with automated reward tracking systems to streamline updates. - Use a secure wallet or service for this role to prevent unauthorized access. ### CLAIM_REWARDS_ROLE (600) This role allows claiming rewards on behalf of the vault. For practical reasons, assign this role to Alpha to automate reward collection. #### Best Practices - Use a secure, automated system like Alpha to ensure timely reward claims. - Monitor reward claims to verify correct distribution. ### TRANSFER_REWARDS_ROLE (700) This role enables the transfer of claimed rewards to the rewards claim manager. In the IPOR Fusion Plasma Vault, reward management (e.g., selling, staking, or transferring) can be handled by a dedicated module. If no such module exists, Alpha can manage rewards manually. Assigning this role to Alpha allows it to transfer rewards to itself for processing. #### Best Practices - Use a dedicated rewards management module when available to streamline operations. ## Guardian Role This role serves as the emergency brake for the vault. The Guardian has the authority to reject time-locked actions and to [pause](https://ipor.io/docs/build-on-fusion/developer-guide/pause-functionality.md) or unpause the vault in case of an emergency. - Configurable by the Owner - Allows for multiple users - **Cannot be timelocked:** Guardians must always retain a 0-day execution delay to function as an instant emergency brake. **Guardian Capabilities & Limitations:** - **Veto Configuration Changes:** The Guardian can unilaterally cancel pending operational and configuration transactions scheduled by the Owner, Atomist, or Fuse Manager (any function gated through the access manager's target-function-role map). - **Emergency Pause:** The Guardian can instantly pause the vault, freezing all execution actions (including user deposits and withdrawals). - **LIMITATION - No Role Management Veto:** Crucially, role-management calls (`grantRole`, `revokeRole`, `setGrantDelay`) are OpenZeppelin admin functions. **Guardians CANNOT cancel these actions.** Only the scheduler themselves or an `ADMIN` can cancel role changes. For permission changes, the timelock provides a _detection-and-exit window_ for depositors, not a Guardian veto. #### **Best Practices** - **Instant Reaction:** Guardians must hold a **0-day execution delay** so they can react instantly to emergencies. - **Key Separation:** Guardian keys must be independent and separate from Owner keys. The emergency brake must fail independently of the roles it is meant to brake. - **Monitoring is Mandatory:** Because Guardians cannot veto role changes, robust on-chain monitoring for `RoleGranted` and `RoleRevoked` events is required to alert depositors of unauthorized permission changes during the exit window. - If using automated risk monitoring, consider granting the Guardian role to an emergency mechanism to enable automatic vault pausing. ## Fuse Manager Role The account with this role has rights to manage the FuseManager contract, add or remove fuses, balance fuses and reward fuses. - Configurable by the Atomist - Allows for multiple users #### Best Practices - For a more decentralized setup, use a dedicated, time-locked account to manage fuses, as they impact the strategy. ## Claim Rewards Role Account with this role has rights to claim rewards from the PlasmaVault using and interacting with the RewardsClaimManager contract.If PlasmaVault has a dedicated smart contract to handle the harvested rewards, the role should be granted to that contract. - Configurable by the Atomist - Allows for multiple users ## Transfer Rewards Role An account with this role has rights to transfer rewards from the PlasmaVault to the RewardsClaimManager.If PlasmaVault has a dedicated smart contract to handle the harvested rewards, the role could be granted to that contract. - Configurable by the Atomist - Allows for multiple users ## Rewards Claim Manager Role Technical role for the RewardsClaimManager contract. Account with this role has rights to claim rewards from the PlasmaVault. For practical reasons, it can be granted to the same entity holding either an Alpha or Atomist role.Configurable by the AtomistAllows for multiple usersPerformance Fee Manager RoleThe account with this role has rights to manage the performance fee, define the performance fee rate, and manage the performance fee recipient.Self managedAllows for multiple usersManagement Fee Manager RoleThe account with this role has rights to manage the management fee, define the management fee rate, and manage the management fee recipient.Self-managedAllows for multiple usersWhitelist RoleThe account with this role has rights to deposit/mint and withdraw/redeem assets from the Plasma Vault.Configurable by the AtomistAllows for multiple usersConfig Instant Withdrawal Fuses RoleAn account with this role has rights to configure instant withdrawal fuses order. ## Technical Roles (Must remain at 0-day delay) Certain roles act as the internal plumbing of the IPOR Fusion system. These roles are held by system contracts (or automated keepers) and are essential for the fundamental operation of the vault. Applying an execution delay (timelock) to any of these roles will break the vault's core mechanics. The following roles **must always remain at a 0-day execution delay** and should never have a minimal execution delay (floor) set: - `TECH_PLASMA_VAULT` (3) - `TECH_CONTEXT_MANAGER` (5) - `TECH_WITHDRAW_MANAGER` (6) - `TECH_VAULT_TRANSFER_SHARES` (7) - `TECH_REWARDS_CLAIM` (601) - `TECH_PERF_FEE` (400) and `TECH_MGMT_FEE` (500) _(Only when held by the internal FeeManager/plumbing on factory vaults. If held by governance, these require a 3-day delay)._ ## **PreHooksManager** Role As outlined in the [pre-hook configuration](https://ipor.io/docs/build-on-fusion/developer-guide/configuring-pre-hooks.md), all changes made by the PreHooksManager must be subject to a timelock. This delay allows liquidity providers (LPs) and other administrators to respond if pre-hooks are set incorrectly. #### Best practices - Implement a sufficiently long timelock for PreHooksManager actions. - Use a multisig wallet to administer pre-hooks for enhanced security. ## **Whitelist / Open Vault** By default, each new vault in the IPOR Fusion system is initialized with a whitelist, restricting minting and redeeming of shares to whitelisted addresses only. Atomists can add addresses to the whitelist or disable it entirely, making the vault open to all users. Once the whitelist is disabled, it cannot be re-enabled. #### Best Practices - Retain the whitelist during the testing period, even if you plan to open the vault to all users. - Use a secure multisig wallet for Atomists managing the whitelist to enhance security. ## Cross-Chain Access Management For Fusion vaults that utilize cross-chain strategies, the access management model is extended to secure the asynchronous nature of remote capital deployment. This includes dedicated attestation and emergency recovery roles: - **Attestation Roles:** Independent Proposer and Approver roles are required to validate and recognize remote Net Asset Value (NAV) on the source chain. - **Emergency Roles:** Rescue Admin and Rescue Guardian roles provide a bifurcated, time-delayed break-glass mechanism for severe bridge or transport failures. To maintain maximum security, the protocol strictly enforces that these paired roles (Proposer/Approver and Admin/Guardian) must be held by separate, independent addresses. For a complete breakdown of these specialized roles and their operational responsibilities, please refer to the [**Governance and Operating Roles**](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/cross-chain-vault-integration.md) section in the Cross-Chain Vault Integration: Business & Operations Guide. --- Source: https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/timelocks-and-execution-delays.md # Timelocks and Execution Delays > How execution delays protect depositors from unilateral configuration changes, and how to size them. This guide explains the conceptual model, governance rules, and operational safeguards of **timelocks (execution delays)** in IPOR Fusion. ## 1. Executive Summary: What is a Timelock? A **timelock** (technically referred to as an **execution delay**) is a mandatory, onchain "cooling-off" period enforced between the time an administrative action is proposed and the time it actually takes effect on the blockchain. In IPOR Fusion, no single administrative key can immediately alter critical vault parameters (such as changing performance fees, updating assets, or modifying Fuses) if a timelock is active. This design enforces complete transparency and provides a vital window for depositors and Guardians to react before any high-impact change is executed. ## 2. The Core Value Proposition Timelocks are not meant to slow down routine operations, but rather to establish a robust line of defense for depositors and operators. They solve three primary security problems: | **Risk Mitigated** | **How Timelock Solves It** | | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Admin Key Compromise** | If an Atomist or Owner private key is stolen, the attacker cannot drain or hijack the vault instantly. They must schedule their malicious transaction, triggering public alerts. | | **Human Error** | If an operator inputes an incorrect fee percentage (e.g., 50% instead of 5%), the mistake is caught while sitting in the queue and can be cancelled before execution. | | **User Transparency** | Depositors are never surprised by sudden policy shifts. If a vault owner increases performance fees, depositors have the entire timelock window to withdraw their funds if they disagree. | ## 3. The Three Shields of Vault Security Timelocks turn governance from something that _can_ happen instantly into something that _must_ happen slowly and in the open. To achieve this, the system relies on three distinct defensive shields working together. **Shield 1: The Notice Period (Execution Delay)** A protected role cannot act on the spot. It must publicly announce an operation and may carry it out only after its delay elapses (e.g., 14 days for the Owner, 3 days for the Atomist). The pending operation is visible on-chain throughout this period. **Shield 2: The Waiting Room (Grant Delay)** When a new account is granted an important role, its membership does not activate immediately — it waits out that role's grant delay first (recommended: 14 days for `OWNER`, 3 days for the configuration tier). This closes the "inject a key into governance" path: even a grant that completes successfully produces an account that cannot act yet. The rule itself is protected too. Changing a grant delay via `setGrantDelay` arms only after a hardcoded 5-day minimum setback — and reducing one takes the larger of 5 days and the size of the reduction. Nobody, including a legitimate administrator, can shorten the waiting room and walk a new key straight in. Note that grant delays are `ADMIN`-gated: they must be configured before `ADMIN` is renounced, or they become permanently unavailable. Re-granting an existing member — for example raising their execution delay — is not subject to the grant delay. This is deliberate: it keeps hardening instantaneous. **Shield 3: The Minimum Threshold (Floors)** Without a minimum threshold, a timelock could theoretically be bypassed in minutes by removing a role and granting it back with a zero-day waiting period. The Access Manager prevents this by enforcing a hard floor (a minimum execution delay) for critical roles. The contract will reject any attempt to grant a role with a delay shorter than its established floor. Crucially, lowering this floor is itself an Owner action, meaning it also requires a 14-day public notice. _Developer Note:_ Setting a floor is **not retroactive**. It constrains future grants only. If an account already holds a role, setting a new floor does not increase their current delay. To apply the new floor to existing accounts, they must be explicitly re-granted their roles. > **The Golden Rule:** Tightening security is fast; loosening security is slow. Raising any protection (e.g., increasing a delay) takes effect immediately, allowing a vault to be hardened the moment a problem is suspected. Conversely, every weakening of security is visible long before it lands. ## 4. Timelock Levels and Configuration Timelocks are highly granular and can be configured at two distinct levels to fit your organization's security posture: ### A. Account-Role Level (Individual Delays) You can apply different timelock durations to different accounts, even if they hold the exact same administrative role. - **Operational Example**: A vault owner might grant the Atomist role to a **multi-signature cold wallet** with a 0**-second delay** (for rapid emergency adjustments), while granting the same Atomist role to a **single-signature hot wallet** or automated keeper with a 2**-day delay** for routine rebalancing. ### B. Minimal Role Delay (The Safety Floor) To prevent key administrators from overriding security thresholds, the system supports a "Minimal Role Delay". Once set, no account can be granted that specific role with a delay lower than the established floor. - **Operational Example**: If the Minimal Role Delay for the Atomist role is set to 1 day, any attempt by a compromised Owner account to grant an instant, 0-day Atomist role will be automatically rejected by the access manager. ## 5. Who Can Set, Edit, and Remove Timelocks? The editing and removal of timelocks is governed by the **Role Admin Hierarchy**. Under this model, only the designated "Admin" of a specific role has the authority to grant that role or modify its execution delay: ``` ┌───────┐ │ Admin │ ┌──────────────────────┐◄──────┘ │ OWNER ROLE │ └──────────┬───────────┘ │ Admin of │ ├──────────────────────────────────────┐ ▼ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────────┐ │ ATOMIST ROLE │ │ GUARDIAN ROLE │ │ PRE HOOKS ROLE │ └────────┬────────┘ └─────────────────┘ └──────────────────┘ │ Admin of ├───────────────────┐ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ │ ALPHA ROLE │ │FUSE MANAGER ROLE│ └─────────────────┘ └─────────────────┘ ``` - **Owners Only**: The Owner administers the Atomist and Guardian . Only Owners can set, edit, or remove timelocks on Atomists or Guardians. - **Atomists Only**: The Atomist administers operational roles like Alpha or Fuse Manager. Only the Atomists can configure timelocks for those roles. - **Self-Governance**: The Owner role is self-administered. Only existing Owner accounts can modify the delay settings of other Owner accounts. ## 6. The "Admin Timelock" Constraint A common security vulnerability in DeFi occurs when an administrator with a timelock simply uses their admin power to change their own timelock to 0 seconds, bypassing the safety window. IPOR Fusion closes this loophole using **Self-Referential Security**: > **Rule**: Administrators are strictly bound by their own timelocks. If a vault Owner is subject to a 14-day timelock (which is the strictly recommended default for this role), they cannot instantly change their own timelock or the timelock of any other user. Any attempt to modify a timelock, grant a role, or change minimal role delays must itself be scheduled as a proposed transaction and wait out the 14-day cooling-off period before taking effect. ## 7. The Guardian: The Emergency Brake While a timelock prevents malicious changes from occurring instantly, it is only effective if there is a mechanism to stop a malicious transaction while it sits in the queue. This is the responsibility of the [**Guardian**](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/access-management.md). The Guardian acts as the vault’s emergency security sentinel: - **The Sentinel Power**: Guardians have the unilateral authority to **cancel** any pending scheduled operational and configuration transaction in the access manager's queue. - **Instant Cancellation**: Guardians are granted roles with a 0**-day delay**, enabling them to intervene instantly. - **Safety Isolation**: Guardians can _only_ cancel pending actions; they cannot schedule new administrative configurations or authorize movements of capital. If a monitoring bot or offline cold wallet detects an unauthorized transaction in the queue, the Guardian executes a cancellation. The malicious transaction is instantly deleted, and the compromised key is rendered harmless while the operators coordinate a key rotation. ## 8. Enabling Timelocks on an Existing Vault (High-Level) Activating timelocks is a configuration change, not a redeployment. No funds move, no migration is required, and the vault keeps operating normally throughout the process. Before enabling timelocks, the Vault Owner must make several key decisions: - **Owner Notice Period:** Starting at 14 days is the recommended default. Raising a delay is always immediate, so starting lower and tightening later costs nothing, but lowering it takes time. - **Guardian Line-up:** Guardians may be individual keys held by people who react within hours. They may also be third-party security providers. Providers that monitor the mempool can react within the same block. Guardians should hold no other role, and their keys must be strictly separate from the Owner's keys. - **Key Separation:** The Owner should operate via a dedicated multisig that is rarely used (effectively a cold wallet). Timelocks protect against rushed malicious actions; they do not protect against a stolen key. Separation limits the damage if a single key is compromised. - **Monitoring:** Someone must actively watch for on-chain alerts (`RoleGranted`, `OperationScheduled`) and know how to respond. Without active monitoring, the 3-day and 14-day notice windows provide no actual protection. - **Re-granting is Required:** Remember that simply setting minimum thresholds (floors) does not magically update the delays of accounts that already hold those roles. During setup, every existing account must be explicitly re-granted its role to apply the target execution delay. ## 9. Frequently Asked Questions (FAQ) **Are everyday user operations delayed by timelocks?** No. Everyday operations such as deposits, withdrawals, and redemptions remain immediate. Timelocks govern rule changes and administrative parameters, not user activity. **Can a change be announced and then quietly executed much later?** No. An announced operation expires 7 days after its earliest execution date. If it is not carried out within that execution window, it lapses entirely. The whole announcement process must then be restarted from scratch. **Why does the automated Alpha (Keeper) operator have no timelock?** The Alpha operator is fast _because_ it is strictly boxed in by rules that only the slow roles can change. It moves funds only within the limits, substrates, and protocols explicitly pre-approved by the Atomist and Fuse Manager. Delaying the Alpha would break daily rebalancing and yield harvesting without adding protection, as the dangerous power lies in changing the boundaries, not operating within them. **What happens if Guardians pause a vault?** The emergency [pause](https://ipor.io/docs/build-on-fusion/developer-guide/pause-functionality.md) is a full freeze. It halts all execution actions, including user deposits and withdrawals. It is designed as an emergency brake for genuine incidents, not a convenience switch, and it is lifted once the situation is resolved. **What stops an attacker from removing a role and re-granting it instantly?** The Minimum Threshold (Shield 3). The contract rejects any grant below the established floor. Lowering that floor first costs the Owner their own 14-day notice period, in plain sight. --- Source: https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/timelocks-and-execution-delays/timelocks-and-execution-delays-developer-reference.md # Timelocks and Execution Delays: Developer Reference > Contract-level reference for configuring and reading timelock parameters. This document provides a deep technical breakdown of the implementation, contract interactions, state machine, and programmatic execution of timelocks within the IPOR Fusion protocol. It is intended for smart contract engineers, audit teams, and automation developers. For high-level conceptual guidance, refer to the [Curator Manual](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/timelocks-and-execution-delays.md). ## 1. Smart Contract Architecture The timelock framework in IPOR Fusion is built natively into `IporFusionAccessManager`, which extends and customizes OpenZeppelin's `AccessManager` contract. Every restricted function across the IPOR Fusion ecosystem (including `PlasmaVault`, `PlasmaVaultGovernance`, and market connectors) is decorated with the `onlyAuthorized` modifier. This modifier queries the `IporFusionAccessManager` to verify if the caller is authorized and whether they must satisfy an execution delay. ## 2. The Transaction Lifecycle State Machine A scheduled operation transitions through four distinct state phases inside `IporFusionAccessManager`: ``` ┌──────────────┐ │ Unset │ └──────┬───────┘ │ schedule() called ▼ ┌──────────────┐ │ Pending │ ◄─── block.timestamp < scheduledTime └──────┬───────┘ │ block.timestamp >= scheduledTime ▼ ┌──────────────┐ │ Ready │ ─── cancel() called ──► [ Unset ] └──────┬───────┘ │ execute() called ▼ ┌──────────────┐ │ Executed │ (Removed from state / closed) └──────────────┘ ``` The execution lifecycle of a delayed operation is mathematically bounded by: `T_{scheduled} = T_{proposal} + D_{delay}` Where: - `T_{proposal}` is the block timestamp when `schedule()` is transactionally processed. - `D_{delay}` is the configured `executionDelay` of the calling account-role pairing. - `T_{scheduled}` is the earliest timestamp at which `execute()` can successfully resolve. ## 3. Operation Hashing & Identification Every scheduled transaction is tracked using a unique `bytes32` digest called the `operationId`. The `operationId` is computed by hashing the components of the execution target: `\text{operationId} = \text{keccak256}(\text{abi.encode}(caller, target, data))` Where: - `caller`: The address initiating the action. - `target`: The address of the destination contract being called. - `data`: The exact encoded execution calldata (function selector + parameters). This hashing mechanism guarantees that an authorized account can only execute the **exact** payload that was originally audited and scheduled. Any alteration to the calldata parameters will result in a completely different `operationId` and fail verification. ## 4. Programmatic Administration: Set, Edit, and Remove Developers can programmatically manage individual timelocks or set system floors through the access manager's admin interface. Because these actions are protected, they are subject to any execution delays assigned to the administrator address itself. ### A. Setting or Editing an Individual Delay To set or edit a delay on a specific account, call `grantRole` with the target `executionDelay`: ``` function grantRole( uint64 roleId, address account, uint32 executionDelay ) external; ``` - **Behavior**: - If the account does not yet possess `roleId`, the role is granted with the specified `executionDelay`. - If the account already possesses `roleId`, calling this updates their individual execution delay to the new value. - **Emits**: `RoleGranted(roleId, account, executionDelay, newMember)` ### B. Removing an Individual Timelock To remove a timelock entirely (enabling instant execution), grant the role with a delay of `0`: ``` accessManager.grantRole(Roles.ATOMIST_ROLE, operatorAddress, 0); ``` - **Result**: `operatorAddress` can now directly call Atomist functions on target contracts without going through the `schedule()` workflow. ### C. Restricting Bypasses via Minimal Role Delays To establish a global safety floor that prevents any administrator from granting zero-delay configurations, set a minimal delay floor: ``` function setMinimalExecutionDelaysForRoles( uint64[] calldata roleIds, uint32[] calldata delays ) external; ``` - **Validation**: Once configured, any subsequent call to `grantRole()` that attempts to set an `executionDelay` lower than the registered floor will transactionally revert with the custom error `TooShortExecutionDelayForRole(roleId, executionDelay)`. - **Emits**: `MinimalExecutionDelaySet(roleId, delay)` per updated role. ## 5. Technical API Reference ### A. Scheduling an Operation To propose a transaction when subject to a timelock, an account must invoke `schedule`: ``` function schedule( address target, bytes calldata data, uint48 when ) external returns (bytes32 operationId, uint32 delay); ``` - **Parameters**: - `target`: The destination contract address. - `data`: The full encoded payload of the transaction to execute. - `when`: The intended execution timestamp. This value must be equal to or greater than `block.timestamp + D_{delay}`. - **Returns**: - `operationId`: The unique cryptographic hash identifying the proposal. - `delay`: The exact delay (in seconds) that must elapse before execution. ### B. Executing a Scheduled Operation Once the delay period has passed, any account can trigger the execution of the scheduled operation by calling `execute`: ``` function execute( address target, bytes calldata data ) external payable returns (bytes memory); ``` - **Execution Constraints**: - Reverts with `AccessManagerNotReady(operationId)` if `block.timestamp < T_{scheduled}`. - Reverts with `AccessManagerExpired(operationId)` if the current time exceeds the expiration threshold (`T_{scheduled} + \text{PERIOD\_OF\_GRACE}`, where the standard Grace Period is typically `5\text{ days}`). - Executes the payload using a low-level solidity `call`. If the target reverts, `execute` bubbles up the revert data. ### C. Cancelling an Operation Authorized role administrators or accounts holding the `GUARDIAN_ROLE` can wipe a pending operation from state: ``` function cancel( address target, bytes calldata data ) external returns (uint32); ``` - **Behavior**: Clears the execution timestamp of the `operationId` from the storage mapping, reverting its status to `Unset`. A cancelled operation can never be executed. To run the transaction again, it must be scheduled anew. - **Security Guard (Cancel Semantics)**: `AM.cancel` succeeds only for the **scheduler**, a member of the `ADMIN_ROLE`, or a member of the role returned by `getRoleGuardian(getTargetFunctionRole(target, selector))`. - **CRITICAL LIMITATION**: This creates two distinct behaviors in the Fusion Access Manager: - **Vault Configuration Targets (Cancelable):** For functions on the Vault (e.g., `addFuses`), initialization assigns `GUARDIAN` as the role guardian in the function mapping. Thus, Guardians **can** cancel these. - **Access Manager Targets (Not Cancelable by Guardian):** Role management calls (`grantRole`, `revokeRole`, `setGrantDelay`) are targeted at the Access Manager itself. These selectors are not in the custom function mapping, so `getTargetFunctionRole` returns the default OpenZeppelin `ADMIN_ROLE`, whose role guardian is unset. - _Conclusion:_ Once `ADMIN` is renounced, a scheduled permission change can be cancelled **only by the account that scheduled it**. ### D. Enforcing Safety Floors The access manager supports establishing minimum execution delays on a per-role basis to prevent administrative oversight or fast-path exploit pathing: ``` function setMinimalExecutionDelaysForRoles( uint64[] calldata roleIds, uint32[] calldata delays ) external; ``` - **Constraints**: - `roleIds` and `delays` arrays must match in length. - Once configured, calling `grantRole()` with an execution delay below the specified floor will revert. ## 6. Security Architecture Notes #### Self-Referential Timelocks (Admin Constraint) The administrative capabilities of the `IporFusionAccessManager` are completely governed by its own permission rules. If an administrative account (e.g., `OWNER_ROLE`) has an individual delay, it is strictly bound by that delay when performing administrative actions: ``` // This call will fail if the owner attempts immediate execution: accessManager.grantRole(Roles.ATOMIST_ROLE, newAtomist, 0); // Instead, the delayed owner MUST call: accessManager.schedule( address(accessManager), abi.encodeWithSelector(accessManager.grantRole.selector, Roles.ATOMIST_ROLE, newAtomist, 0), block.timestamp + ownerDelay ); ``` #### Reentrancy & Context Preservation - To prevent exploitation of state checks, `execute()` implements a reentrancy guard or execution lock during the execution of the call. - The access manager preserves the execution context using `msg.sender` routing. When a target contract receives a call, it verifies that `msg.sender` is the `IporFusionAccessManager` address, and reads the originating caller context. ## 7. Code Examples & Scripts #### Scenario: Programmatic Scheduling and Execution of a Performance Fee Update Below is a hardhat/ethers-style script demonstrating how an automation bot or multisig relayer interacts with the timelocked workflow to update performance fees on a `PlasmaVault` via `PlasmaVaultGovernance`. ``` import { ethers } from "hardhat"; async function main() { const [operator] = await ethers.getSigners(); // Addresses of deployed contracts const accessManagerAddress = "0x...AccessManagerAddress"; const governanceAddress = "0x...PlasmaVaultGovernanceAddress"; const vaultAddress = "0x...PlasmaVaultAddress"; // Get contract instances const accessManager = await ethers.getContractAt("IporFusionAccessManager", accessManagerAddress); const governance = await ethers.getContractAt("PlasmaVaultGovernance", governanceAddress); // 1. Prepare the exact calldata payload for the target execution const feeAccount = "0x...FeeCollectorAddress"; const performanceFeeBasisPoints = 1500; // 15.00% performance fee const targetCalldata = governance.interface.encodeFunctionData("configurePerformanceFee", [ vaultAddress, performanceFeeBasisPoints ]); console.log("Preparing to schedule fee update..."); // 2. Fetch the current execution delay of the operator for this role const executionDelay = await accessManager.getExecutionDelay(operator.address); const blockNumber = await ethers.provider.getBlockNumber(); const currentBlock = await ethers.provider.getBlock(blockNumber); const executionTime = currentBlock.timestamp + Number(executionDelay); // 3. Schedule the transaction const scheduleTx = await accessManager.schedule( governanceAddress, targetCalldata, executionTime ); const receipt = await scheduleTx.wait(); // Extract the operationId from the Scheduled event const event = receipt.events?.find((e) => e.event === "OperationScheduled"); const operationId = event?.args?.operationId; console.log(`Successfully scheduled. Operation ID: ${operationId}`); console.log(`Execution is locked until block timestamp: ${executionTime}`); // 4. Fast-forward simulation (Wait Phase) // In a real environment, you would wait executionDelay seconds. // In tests, you can fast-forward the EVM: // await ethers.provider.send("evm_increaseTime", [Number(executionDelay)]); // await ethers.provider.send("evm_mine", []); // 5. Execute the transaction after the delay has passed console.log("Execution delay satisfied. Initiating execution..."); const executeTx = await accessManager.execute( governanceAddress, targetCalldata ); await executeTx.wait(); console.log("Fee configuration successfully executed!"); } main() .then(() => process.exit(0)) .catch((error) => { console.error(error); process.exit(1); }); ``` ## 8. Enabling Timelocks: Canonical Call Order Enabling timelocks on an existing vault is a sequence of permission updates on the existing `IporFusionAccessManager`. No funds move and no redeployment is required. **Batch vs. Step-by-Step Execution:** Executing all calls atomically in a single batch (via a governance multisig) is highly recommended. A wrong order in a batch reverts everything harmlessly. If executing sequentially, you must finish everything a role must do _before_ raising that role's delay, otherwise you lock the remainder of your setup sequence behind the timelock you just created. The **canonical call order** is load-bearing and must be executed as follows: 1. **Guardians:** `grantRole(2, , 0)` for each new guardian, then `revokeRole(2, )`. Do this first as they are the emergency brake. 2. **Migration (if needed):** Grant every governance role to the target multisig at a `0` delay (raised later). Revoke the old account afterwards (with `ATOMIST` last, since it administers other roles). 3. **Grant Delays:** While `ADMIN` still has members, call `setGrantDelay` (e.g., `14 days` for `ADMIN`/`OWNER`, `3 days` for governance tier). Note: These arm only at T+5 days due to the OpenZeppelin 5-day `minSetback`. 4. **Floors:** Call `setMinimalExecutionDelaysForRoles` on the vault (e.g., 14 days for `OWNER`, 3 days for `ATOMIST` and `FUSE_MANAGER`). 5. **Re-grants (CRITICAL):** Setting a floor is **not retroactive**. It does not magically update the delays of accounts that already hold those roles. Every existing membership must be explicitly re-granted its role to apply the target delay, bottom-up (3-day tier first, then `ATOMIST`, then `OWNER` at 14 days). Raising delays takes effect immediately. 6. **Self-Admin and Renounce:** Call `setRoleAdmin(1, 1)` to repoint the admin of `OWNER` to `OWNER` itself. Finally, call `renounceRole(0, )` as the **final call**. _Developer Note:_ Never renounce `ADMIN` without repointing `OWNER` first, or `OWNER` membership and delays will freeze permanently. ## 9. Layout Variants and Post-Execution Verification Because the entire configuration lives onchain, the timelock state must be verified post-execution. **Layout Variants** Depending on when the vault was deployed, the starting state dictates the available protections: - **Factory (Current):** `ADMIN` has no members, and `OWNER` is already self-administered. The rollout skips grant delays and the renounce steps. - **Legacy (Live ADMIN):** Governance multisig holds `ADMIN`. Requires the full sequence including `setGrantDelay` and renouncing. - **Legacy (Dead ADMIN):** `ADMIN` is renounced, but `getRoleAdmin(OWNER) == ADMIN`. _Warning:_ This offers partial protection. The `OWNER` delay can never be raised and grant delays are unreachable. The complete fix requires migrating to a new vault. --- Source: https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/vault-governance-and-depositor-led-security-best-practices.md # Vault Governance & Depositor-Led Security Best Practices > Role hierarchy, execution delays and an optional Aragon Depositor DAO for checks and balances against a compromised or malicious Owner. ## 1. Introduction: The Mechanics of Decentralized Checks and Balances The IPOR Fusion architecture uses a system of complementary, interlocking roles and optional, structured timelocks to achieve checks and balances. While the system defines an **Owner** role with top-level administrative privileges, this power can be dynamically restricted, which is the primary focus of this document. In a fully secured deployment, the Owner's authority is bounded by temporal barriers and defensive mechanisms, preventing any single administrative entity from acting unilaterally or compromising depositor assets. Restricting and balancing this administrative power to protect depositors is the primary objective of the governance framework detailed in this document. Operational and protective power is distributed across the following roles: - **Owner**: The primary administrative authority in the system. The Owner governs the access control manager, dictates which accounts hold administrative roles, and configures the execution delays (timelocks) for other roles. Crucially, the Owner's constructive actions can be restricted by the Guardian and configured temporal parameters, ensuring they cannot bypass the system's checks and balances. - **Atomist**: The primary risk and configuration manager. Operating under the oversight of the Owner, the Atomist manages economic and risk boundaries. The Atomist configures price oracle middleware, sets overall supply caps, and dictates market allocation limits. To maintain a strict separation of concerns, the Atomist does not manage technical integration parameters such as substrates or fuses. - **Fuse Manager**: The specialized technical integration manager. Operating under the oversight of the Atomist, the Fuse Manager is dedicated strictly to protocol integrations. The Fuse Manager manages which operation fuses (e.g., supply, borrow, or swap) are supported by the vault, attaches position-tracking balance fuses to specific market IDs, configures callback handlers, and manages market substrates (allowed assets, pools, and positions). - **Alpha**: The strategic executor. Operating with maximum agility, the Alpha is responsible for active capital routing. Using only the whitelisted fuses, substrates, and parameters configured by the Fuse Manager, the Alpha routes capital across DeFi protocols in real-time to harvest yield. - **Guardian**: The emergency protective backstop. The Guardian is purely defensive. It cannot execute strategies or alter configurations, but it can instantly trigger global contract [pauses](https://ipor.io/docs/build-on-fusion/developer-guide/pause-functionality.md) or veto pending, time-locked operational and configuration transactions scheduled by other roles. - **Pre Hooks Manager**: The technical authority over pre-execution validation checks. Configures which pre-hooks (e.g., rate limiters, validation checks) execute before specific target functions to enforce strict safety boundaries. - **Withdraw Manager Request Fee**: A technical role dedicated to configuring the fee rates charged to depositors when scheduling a withdrawal request. - **Withdraw Manager Withdraw Fee**: A technical role dedicated to configuring and adjusting the fee rate charged to users withdrawing directly from unallocated balances. - **Price Oracle Middleware Manager**: Manages price validation thresholds and maps individual assets to their respective oracle price feeds, ensuring the oracle middleware returns accurate valuation data. ### 1.1 Temporal Segregation: Optional Roles and Execution Delays The fundamental mechanism of checks and balances in IPOR Fusion relies on _configurable, optional_ execution delays (timelocks). By default, the access control manager allows for immediate, zero-delay execution of administrative and operational actions. However, deploying vaults with non-zero execution delays is a recommended security best practice for decentralized setups. When configured, if the Owner, Atomist, or Fuse Manager initiates a change — such as updating fee parameters, setting market limits, or granting new substrates or removing a balance fuse — the access control manager enforces a mandatory temporal buffer. During this delay, the proposed action sits in a transparent, pending state onchain. This structural delay serves a vital purpose: it gives the defensive Guardian role a reliable window to analyze the pending transaction. If the proposed change is malicious, accidental, or the result of a key compromise, the Guardian can execute an instant, zero-delay veto to cancel the operational and configuration transaction. ### 1.2 Strategic Agility vs. Structural Guardrails Capital efficiency is highly dependent on the speed at which a vault can react to shifting market conditions. If a vault must wait days for a governance vote to exit a protocol when yields collapse, it suffers significant opportunity costs. Fusion resolves the tension between responsiveness and safety by separating **structural vault management** from **active strategy execution**: - **Capital Security** is maintained because the structural parameters of the vault—governed by the Owner, Atomist, and Fuse Manager—can be bound by configured timelocks. When activated, these parameters cannot be altered instantly, giving depositors a reliable window to evaluate changes or withdraw their funds. - **Operational Responsiveness** is maintained because the Alpha role operates with a zero-delay timelock. As long as the Alpha's actions conform to the pre-approved, strictly bounded "sandbox" defined by the enabled fuses, whitelisted substrates, and market limits, strategy execution occurs at block speed. ### 1.3 Tailoring Parameters to Depositor Coordination Dynamics The optimal balance of parameters is determined by the depositor profile and vault access model, which dictates the coordination capacity of the participants: - **Open Public Vaults**: These vaults are permissionless and open to a fragmented, uncoordinated depositor base. Because especially retail depositors face high coordination hurdles, they cannot easily organize a rapid veto or collective exit on short notice. Consequently, these setups highly benefit from configured, long timelocks on constructive administrative actions to guarantee depositors a reliable exit window before changes take effect. - **Closed Institutional (Whitelisted) Vaults**: These vaults restrict entry to a pre-whitelisted, highly sophisticated set of large-ticket depositors. These depositors have direct communication channels and high coordination capacity and these vaults can securely operate with zero-delay or very short timelock profiles to maximize operational agility and market responsiveness. ## 2. Aragon Depositor DAO: Institutionalizing Depositor Power To give depositors a direct voice, we recommend establishing an external Depositor DAO. While optional and not natively built into the core smart contracts, introducing an external Depositor DAO is a powerful best practice. [Aragon](https://aragon.org/) is one popular protocol that enables this, and we use it throughout this document as our running example. Membership and voting power in this Aragon-based Depositor DAO are natively tied to the vault's share tokens (minted by the vault upon deposit). ### 2.1 Aragon DAO as the Vault's Guardian The Aragon DAO is granted the Guardian role in the access control manager. This role serves as the vault’s primary security veto and emergency circuit breaker. **Guardian Capabilities:** - **Veto and Cancellation**: The Guardian can cancel the Owner's operational and configuration transactions during their timelock (any function gated through the access manager's target-function-role map). Role-management calls (`grantRole` / `revokeRole`) are OpenZeppelin admin functions and are NOT guardian-cancellable — only the scheduler or an `ADMIN` can cancel those. - **Emergency Pausing**: In the event of a suspected exploit or key compromise, the Aragon DAO can instantly pause target contracts, freezing all execution actions. **Limits of the Guardian:** The Guardian is an emergency backstop for operational actions and pausing. It is not a defense against a compromised Owner's role escalation: it cannot cancel role grants/revocations and can itself be removed by the Owner. Defending against Owner compromise relies on (a) making the Owner a multisig with an execution delay, (b) the depositor exit window during timelocks, and — for a hard on-chain veto — (c) retaining a trusted `ADMIN` (via `cloneSupervised`) rather than renouncing it. Note that `grantDelay` is not configurable after `ADMIN` is renounced. ### 2.2 Voting Safeguards and Composability Because the Guardian role holds these critical emergency powers, securing the underlying voting mechanism is paramount. Using live token balances for onchain voting creates a severe vulnerability where capital can be temporarily acquired or borrowed (e.g., via flash loans) to force malicious proposals through governance. **The Solution: Checkpointed Voting** To defend against this, the core token framework natively routes voting-related queries to an active votes plugin if enabled, implementing the following safeguards and trade-offs: - **Historical Checkpoints:** The Aragon DAO must be configured with a voting plugin that queries historical votes at a snapshot checkpoint (e.g., the state of balances before the proposal was submitted) rather than the active, live state. - **DeFi Composability Trade-offs:** While delegation allows passive depositors to assign their voting rights, it does not solve the challenges of deep DeFi composability. If vault shares are deposited into an external protocol (e.g., as collateral), the external contract becomes the token holder of record. Because checkpointing snapshots the contract's aggregate balance, the original depositor loses their voting power unless the external protocol implements bespoke delegation logic. - **Future-Proofing for Composability:** Currently, IPOR Fusion vault shares are primarily held directly by depositors, making standard checkpointing highly functional. However, if deep composability becomes a priority as the ecosystem matures, token-level checkpointing can be bypassed entirely. For instance, using an Aragon **LockToVote** plugin, users would simply lock their shares in a dedicated voting contract to acquire voting power, ensuring governance scales seamlessly with external DeFi integrations. ## 3. Preserving the Balance of Power (Anti-Subversion) A common flaw in standard role hierarchies is that the Owner role retains the right to unilaterally revoke roles, which would allow a compromised or malicious owner to strip the Aragon DAO of its Guardian role. Timelocks make an Owner's actions — including revoking the Guardian — visible on-chain during the delay, but they do not let the Guardian veto them. The Owner is the admin of the Guardian role and can remove it after the delay; the Guardian cannot cancel its own removal. Timelocks provide detection and a depositor exit window, not a Guardian veto over role management. ### 3.1 Optional Timelocks as an Exit Window Any administrative action initiated by the Owner (such as granting or revoking roles) can be subjected to an optional, long-duration execution delay (e.g., 14 days) configured via the access control manager. - **The Detection Window**: If a malicious Owner attempts to revoke the Aragon DAO's Guardian role, and a timelock is active, the transaction must be scheduled first. - **The Reaction**: During this delay the Aragon DAO can detect the pending revocation on-chain. It cannot cancel it as the Guardian — `revokeRole` is an admin function, cancelable only by the scheduler or an `ADMIN` — but the delay guarantees a rage-quit / exit window: depositors (and the DAO) can redeem before the Guardian is removed. If an onchain veto of this action is required, the DAO must retain `ADMIN` (deploy via `cloneSupervised`), not merely hold the Guardian role. ### 3.2 Graded Timelocks for Centralized and Decentralized Owners Depending on the operational model and depositor base of the vault, the Owner role can be securely assigned in one of two configurations, aligning execution delays directly with the coordination profile of the participating entities: 1. **Decentralized Institutional MultiSig (Short or 0-Day Timelock) — Ideal for Closed Institutional Vaults**: The Owner role can be assigned to a highly decentralized, multi-institutional MultiSig consisting of a threshold of 4/6 or 5/8 keys consisting of e.g.: - Core vault developers (2 keys). - Independent, highly reputable partner protocols or DAOs (2 keys). - Professional third-party custodians or security firms (2 keys). Because this configuration distributes key management among independent, highly reputable entities, the risk of a single-party exploit, key compromise, or collusive attack is virtually non-existent. Under this setup, the Owner role can operate with a 0-day timelock, allowing for rapid administrative reactions and maximum responsiveness when market conditions pivot. 2. **Economic Owner / Asset Manager (Optional Long Timelock) — Ideal for Retail-Focused Public Vaults**: Alternatively, the vault's economic owner (the core asset manager or developer team) may choose to retain direct administrative control of the Owner role (e.g., via their own team MultiSig or EOA keys) to ensure operational independence. If this centralized approach is taken, binding the Owner role with a long execution timelock (e.g., 14 days) is highly recommended. This timelock ensures that any administrative change proposed by the team is visible onchain for a substantial period, giving the Aragon Depositor DAO (acting as the Guardian) a clear veto window to spot and cancel operational transactions or utilize the exit window before role changes are executed. ### 3.3 Optional Co-Ownership and Rage-Quit Guarantees The real protection against a malicious Owner or Atomist relies on a combination of factors: a decentralized MultiSig Owner, a long timelock ensuring detection, and a guaranteed rage-quit exit window for depositors. For absolute worst-case protection and a true on-chain veto, the Aragon DAO must either retain the `ADMIN` role (via `cloneSupervised`) or be configured as an additional Owner. If this administrative configuration is used, the Aragon DAO's Owner actions can be subjected to a long execution timelock (e.g., 21 to 30 days) to prevent coordination issues or sudden governance takeovers. This optional long timelock provides several fundamental security and game-theoretic advantages: 1. **Defense Against Hostile Takeovers and Capital Accumulation**: While checkpointed voting prevents instantaneous flash loan exploits, it does not prevent a wealthy hostile entity from gradually purchasing a large volume of vault shares on the open market. If this entity accumulates a majority voting share (greater than 50%), they could pass a malicious DAO proposal to alter critical vault parameters or redirect fees. A long timelock (21 to 30 days) forces any approved proposal to sit in a pending state, giving the core development team, partner protocols, and remaining depositors ample time to detect the hostile takeover and coordinate a counter-strategy. 2. **Ensuring a Minority Exit (Rage-Quit) Window Tailored to Depositor Coordination Dynamics**: In decentralized systems, a voting majority may choose to steer the protocol in a direction that is highly detrimental or unacceptable to the minority. An optional long timelock provides a guaranteed escape window, but its necessity and duration are strictly aligned with the coordination capabilities of the depositor base: - **Retail-Focused (Open Public) Vaults**: Dissenting retail depositors cannot coordinate quickly to execute counter-governance. They require a long timelock (typically 21 to 30 days) as an absolute guarantee that they can redeem their shares and exit the vault cleanly before the proposed governance parameters go live. - **Closed Institutional Vaults**: Because of the whitelisted, high-coordination nature of the depositors, a lengthy timelock is often counterproductive. Dissenting institutions can quickly communicate and use off-chain agreements or rapid multisig vetoes, allowing these vaults to safely deploy shorter timelock profiles (e.g., 7 to 14 days) if desired. 3. **Mitigating Coordination Errors and Governance Quorum Failures**: DAO governance processes can occasionally suffer from low voter turnout, rushed voting windows, or coordination errors where a flawed proposal is inadvertently passed. A long timelock acts as an essential sanity buffer, ensuring that even if a problematic proposal successfully passes a vote, it cannot be executed instantly. This delay provides dissenting members and the Guardian a crucial window to analyze the transaction, sound the alarm, and deploy emergency overrides before permanent changes are finalized. 4. **Resolution of Dual-Deadlock Scenarios (Long-Term Unwinding)**: This slow-path recovery mechanism is designed specifically to resolve a catastrophic **dual-deadlock** scenario where **both** of the following conditions are simultaneously met: - The Alpha is permanently offline or abandoned, leaving the vault unable to adjust active positions. - The normal administrative entities (Owner and Atomist) have also abandoned the vault, lost access to their signing keys, or become completely unresponsive. Conversely, if only the Alpha is offline or inactive, the Owner/Atomist can hire a new Alpha service provider to re-activate capital routing. If only the Owner or Atomist loses access or abandons the vault, the active Alpha continues executing the automated capital routing strategies without interruption. Only when _both_ entities are entirely incapacitated does this Aragon DAO co-ownership path become the necessary fail-safe. Over the course of the 21-to-30-day delay, the Aragon DAO can reassign the Alpha role to a backup keeper. 5. **Strategic Asymmetry: Guardian (0-Day Delay) vs. Owner Timelock Profiles**: A robust governance model requires a fundamental timing asymmetry: - **Defensive Actions (The Guardian Role)**: Must always have zero delay (0-day timelock). When pausing an exploit or canceling a compromised Owner transaction, the Aragon DAO must act instantly to preserve vault safety, regardless of whether the vault is retail-focused or institutional. - **Constructive/Structural Actions (The Owner Role)**: The timelock is dependent on the Owner configuration: - _Under Option A (Decentralized MultiSig)_: Structural changes can be executed with a short or 0-day delay because the multi-entity signer structure itself acts as the preventative collusion buffer. - _Under Option B (Economic/Centralized Owner) or Aragon DAO ownership_: Structural changes are best bound by a long delay (21 to 30 days), ensuring that absolute transparency and exit rights are guaranteed to uncoordinated participants before changes go live. ### 3.4 Key Separation and Operational Hygiene Timelocks constrain _actions_; they do not protect against a _compromised key_. A robust governance model requires strict separation of key infrastructure to limit the blast radius of a security breach: - **The Owner as a Cold Wallet:** The `OWNER` role should reside on a dedicated multisig that is separate from day-to-day governance. It should be used rarely, effectively functioning as a cold wallet. Signer keys must be generated from independent seed phrases, and signers should never reuse these devices for operational signing (e.g., as an Atomist or Alpha). - **Independent Emergency Brakes (Guardians):** Guardians require rapid reaction times, meaning they are typically operated as "hot keys." Because of this risk profile, a Guardian must _never_ hold any other role within the vault (e.g., they cannot also be an Atomist). The emergency brake must fail independently of the roles it is designed to brake. - **Avoid Role Consolidation:** Granting the `OWNER` role and operational roles (like `ATOMIST` or `FUSE_MANAGER`) to the same multisig collapses the security tiers. A single quorum compromise would instantly escalate to top-level administrative control, bypassing the layered defense design entirely. ### 3.5 Monitoring as a Mandatory Security Control As established, Guardians cannot veto role-management changes (such as a compromised Owner granting a new zero-delay malicious admin role). For these actions, the timelock serves entirely as a detection-and-exit window. Because of this architectural reality, **on-chain monitoring is not an optional extra—it is a structural requirement of the security model.** The Aragon DAO, core developers, and sophisticated depositors must actively monitor the Access Manager for `RoleGranted`, `RoleRevoked`, and `OperationScheduled` events. If an unauthorized role change is scheduled, the 14-day timelock only protects depositors if an alert is fired, recognized, and acted upon (via a mass rage-quit or emergency pause) before the delay expires. ## 4. The Graded Timelock and Security Matrix (Reference Policy) To achieve optimal operations, security settings must scale with the risk profile of each role. We define a graded hierarchy where execution delays (timelocks), grant delays (waiting rooms), and floors (minimum delays) correspond directly to the signing threshold, risk profile, and decentralization of the entity holding the role. > **CRITICAL WARNING - Technical Roles:** Certain roles act as the internal plumbing of the IPOR Fusion system (e.g., `TECH_PLASMA_VAULT` (3), `TECH_CONTEXT_MANAGER` (5), `TECH_WITHDRAW_MANAGER` (6), `TECH_VAULT_TRANSFER_SHARES` (7), `TECH_REWARDS_CLAIM` (601), and the factory `TECH_PERF_FEE`/`TECH_MGMT_FEE` (400/500) when held by the internal FeeManager). **Applying an execution delay to any of these system roles will break the vault's core mechanics.** They must permanently remain at a 0-day execution delay with no floor. | | | | | | | | | ---------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | ----------------- | ----------- | ------------------ | --------------- | ---------------------------------------------------------------------------------------------------------------- | | Role Category & Names | Suggested Holder | Execution Delay | Grant Delay | Floor (Min. Delay) | Guardian Veto? | Operational Purpose & Notes | | **Owner (Option A)**`OWNER` | 4/6 Institutional MultiSig | **0 - 24 Hours** | 14 Days | 14 Days | **Yes** | Top-level config. Low delay is safe due to the multi-institutional collusion buffer. | | **Owner (Option B)**`OWNER` | Asset Manager MultiSig | **14 Days** | 14 Days | 14 Days | **Yes** | Traditional admin control. Long delay guarantees a safe depositor exit window. | | **Governance Tier**`ATOMIST`, `FUSE_MANAGER`, `PRE_HOOKS_MANAGER`, `PRICE_ORACLE_MW`, Gov-held `FEES` | 3/5 Developer MultiSig | **3 Days** | 3 Days | 3 Days | **Yes** | Day-to-day vault configuration, managing market limits, total supply caps, price oracles, and integration fuses. | | **Guardian**`GUARDIAN` | Aragon DAO / Independent Keys | **0 Days** | None | None | **No** (Direct) | Emergency pausing and transaction cancellation. Must remain instant to function. | | **Operational Tier**`ALPHA`, `CLAIM_REWARDS`, `TRANSFER_REWARDS`, `UPDATE_BALANCES` | Automated Keeper / EOA (1 Active, 1 Standby) | **0 Days** | None | None | **No** | High-speed strategy execution and asset routing within pre-approved boundaries. | | **Withdrawal Routing**`CONFIG_INSTANT_WITHDRAWAL_FUSES` | Automated Keeper / EOA | **0 Days** | None | None | **Yes** | Orders instant withdrawals. Must be 0-day to instantly bypass a failing external venue. | | **Technical Plumbing**`TECH_PLASMA_VAULT` (3), `TECH_CONTEXT_MANAGER` (5), `TECH_WITHDRAW_MANAGER` (6), `TECH_VAULT_TRANSFER_SHARES` (7) | System Contracts | 0 Days(MANDATORY) | None | None | **No** | Internal contract routing. **Any delay here breaks the vault.** | ## 5. Cross-Chain Governance and Security Integrating cross-chain strategies into a Fusion vault introduces asynchronous accounting and bridge dependencies. To protect depositors and maintain the integrity of the vault's share price against cross-chain risks, the system introduces dedicated attestation and emergency recovery roles with strict separation of powers. ### 5.1 Cross-Chain Checks and Balances The cross-chain architecture mandates a bifurcated control model to prevent single points of failure across bridging operations: - **Two-Role NAV Attestation:** To prevent a single compromised key from artificially inflating the source vault's Net Asset Value (NAV), remote yield recognition requires two distinct roles. The **Proposer** queries the remote chains and submits the observation, while an independent **Approver** verifies and confirms the state. - **Bifurcated Emergency Recovery:** For severe incidents, such as a permanent bridge blacklisting, the system relies on a delayed rescue module. The **Rescue Admin** schedules emergency recovery actions, but is bound by a strict minimum 24-hour execution delay. During this window, an independent **Rescue Guardian** possesses the unilateral authority to veto and cancel the pending action before any state changes occur. ### 5.2 Cross-Chain Security and Timelock Matrix The following matrix outlines the required configurations, execution delays, and security bounds for cross-chain specific roles. These parameters work in tandem with the core vault security policy to ensure safe asynchronous operations. | Role Category & Names | Suggested Holder | Execution Delay | Grant Delay | Floor (Min. Delay) | Guardian Veto? | Operational Purpose & Notes | | ---------------------------------------- | ------------------------------------ | --------------- | ----------- | ------------------ | ------------------------ | ---------------------------------------------------------------------------------------------- | | **Cross-Chain Attestation** `PROPOSER` | Automated Keeper / EOA | 0 Days | None | None | No | Queries remote chains and proposes NAV observations. Constrained by staleness and rate limits. | | **Cross-Chain Attestation** `APPROVER` | Automated Keeper / EOA (Independent) | 0 Days | None | None | No | Independently verifies and approves the proposed NAV. Constrained by large-change thresholds. | | **Emergency Recovery** `RESCUE_ADMIN` | Multisig / Controlled Contract | 24 Hours | 14 Days | 24 Hours | Yes (by Rescue Guardian) | Schedules and executes emergency recovery actions. Delay provides a window for veto. | | **Emergency Recovery** `RESCUE_GUARDIAN` | Independent Multisig | 0 Days | None | None | No (Direct) | Unilaterally vetoes and cancels pending rescue actions. Must remain instant to function. | _Note: To maintain maximum protocol security, the Proposer/Approver and Rescue Admin/Rescue Guardian pairs must be operated by completely independent entities. An Atomist must ensure these addresses never overlap during configuration._ ## 6. Summary: A Unified Framework for Fusion Vaults By combining checkpointed voting, optional role-based execution delays, and a MultiSig matrix, IPOR Fusion vaults can achieve maximum onchain decentralization and Aragon DAO-led depositor security without sacrificing the agility required to capture market yields. Setting strict boundaries around constructive, risk-increasing modifications while keeping defensive, de-escalation pathways completely unencumbered ensures that the system is both highly secured against internal subversion and highly responsive to systemic market failures. --- Source: https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/substrates.md # Substrates > What substrates are and how they scope which assets and markets a fuse is allowed to touch. In IPOR Fusion, the Atomist defines the "walled garden" in which the strategy logic (Alpha) can operate. While Fuses define _how_ to interact with a protocol (e.g., "supply to Aave"), Substrates define _where_ and with _what_ specifically those Fuses are allowed to interact. #### What are Substrates? Substrates are specific identifiers or permissioned parameters granted to a Market within a Fusion Vault. They act as the granular configuration that tells the vault which underlying components of an external protocol are "visible" and "authorized." Think of a Market (like Aave V3) as a building. The Fuse is the door you use to enter. Substrates are the specific rooms inside that building that the Atomist has unlocked for the Alpha. Common examples of Substrates include: - Asset Addresses: Specific ERC20 tokens allowed for supply/borrow. - Sub-Market IDs: Specific pool IDs or market identifiers within a larger protocol (e.g., a specific Morpho Blue market). - Target Limits: Constraints on asset amounts or specific function selectors allowed for execution. #### Why are Substrates necessary? Substrates serve two primary purposes: 1. Security: They prevent an Alpha from interacting with unauthorized, risky, or unverified pools within a protocol. 2. Accounting: The Plasma Vault uses Substrates to know which balances it needs to track. If a Substrate isn't configured, the vault won't "see" the assets held in that sub-market, ensuring the vault's Net Asset Value (NAV) and share price remain accurate and protected. #### Configuration Step-by-Step As an Atomist, you configure Substrates after adding a Fuse to your vault. This is done via the `grantMarketSubstrates` method. **1. Identify the Market ID** Every external protocol integration in Fusion has a unique `uint256` Market ID defined in the `IporFusionMarkets` library. - _Example:_ `AAVE_V3 = 1`, `COMPOUND_V3_USDC = 2`, `MORPHO_BLUE = 5`. **2. Define the Substrate Data** The data required for a substrate varies depending on the Market type. - For Lending Markets (Aave, Spark, etc.): The substrate is typically the address of the underlying asset (e.g., the USDC token address). - For Complex Markets (Morpho Blue, Uniswap V3): The substrate might be a specific Market ID or a pool address. - For Async Actions: Substrates can include encoded limits (`ALLOWED_AMOUNT_TO_OUTSIDE`) or permitted function selectors (`ALLOWED_TARGETS`). **3. Grant Permissions** Using the Vault's management interface (or directly via the `PlasmaVault` contract), the Atomist calls: `grantMarketSubstrates(uint256 marketId, bytes[] calldata substrates)` This registers the list of authorized IDs for that specific market. #### Technical Example: Morpho Blue If you are setting up a vault to supply USDC to a specific Morpho Blue market, you wouldn't just grant access to "Morpho." You would: 1. Identify the Morpho Market ID (the unique hash for the specific collateral/loan pair). 2. Add this ID as a Substrate to the Morpho Blue Market in your vault. 3. The vault now knows to track the balance of the `Id` and allows the Alpha to call `enter` or `exit` for that specific pool. #### Summary for Atomists - Fuses = Actions (Supply, Withdraw, Swap). - Markets = Protocols (Aave, Morpho, Gearbox). - Substrates = Specifics (USDC, Market ID `0x123...`, Function selectors). Without the correct Substrates, your Alpha will not be able to execute trades, even if the Fuse is correctly installed. --- #### Related Resources - [Video: Explaining Substrates (YouTube)](https://www.google.com/search?q=https://youtube.com/watch%3Fv%3DzYXwfeUp7Og) --- Source: https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/vault-ownership-changes.md # Vault Ownership Changes > How to safely transfer or rotate the Owner and other administrative roles on a live vault. ## Transfer via Fusion Web App 1. Grant the Owner role to another address. 2. Test with the new address whether the action was successful. 3. If so, renounce your own role. ![Image](https://ipor.io/docs/assets/build-on-fusion/image-5-26174d.png) __ ## Transfer via Smart Contract For the core `PlasmaVault`, control is managed through role-based access control via `IporFusionAccessManager` rather than traditional ownership. You can transfer control by: 1. **Granting roles**: Use `grantRole()` to assign roles like `OWNER_ROLE`, `ADMIN_ROLE`, or `ATOMIST_ROLE` to new addresses 2. **Revoking old roles**: Remove roles from previous controllers using the access manager The role hierarchy must be respected (e.g., `ADMIN_ROLE` can grant `OWNER_ROLE`) --- Source: https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault.md # Curating a Fusion vault > Ongoing vault-curation topics: share price, contributions, performance, oracle choice, caps and market impact. This section will focus on some topics that are important for designing the strategy and determining the necessary parameters: - [share-price-dynamics.md](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/share-price-dynamics.md "mention") - [on-and-offboarding-contributions.md](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/on-and-offboarding-contributions.md "mention") - [understanding-performance-of-a-vault.md](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/understanding-performance-of-a-vault.md "mention") - [choosing-the-right-price-oracle.md](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/choosing-the-right-price-oracle.md "mention") - [asynchronous-reward-compounding.md](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/asynchronous-reward-compounding.md "mention") - [dependency-graphs.md](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/dependency-graphs.md "mention") - [managing-redemption-delays.md](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/managing-redemption-delays.md "mention") - [deposit-caps](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/deposit-caps.md "mention") - [yield-scalability-and-market-impact.md](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/yield-scalability-and-market-impact.md "mention") - [integrating-pendle-pt-tokens.md](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/integrating-pendle-pt-tokens.md "mention") --- Source: https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/share-price-dynamics.md # Share Price Dynamics > A Guide (not only) for Atomists This document aims to provide Atomists with a comprehensive understanding of fusion vault share price behavior and its influencing factors, thereby equipping them to answer user inquiries more effectively. ## What is the share price? The share price in a DeFi vault represents the vault's Net Asset Value (NAV) per share. It increases as the vault's underlying assets generate yield through automated strategies, allowing users to redeem their shares for a greater value than their initial deposit. ## Influencing factors There are numerous events that influence the share price. Some depend on user interactions with the vault, others on the execution of the underlying strategies (Alpha’s actions), and still others on market developments and asset prices. The most important influencing factors will be listed below and illustrated with some examples. ### Yield Generated from Strategies - Explanation: The primary driver of share price appreciation is the successful execution of the vault's yield-farming strategies. As the vault earns interest, trading fees, or other rewards from its deployed assets, the total value locked (TVL) in the vault increases, directly raising the NAV per share. - Example: A vault depositing USDC into Aave to earn lending interest will see its share price increase as the accrued interest on the USDC is reinvested. ![Image](https://ipor.io/docs/assets/build-on-fusion/unknown-1-3840dc.png) __ ### Gas Fees Explanation: Gas fees for Alpha actions do not affect the share price; they are covered by a gas tank funded by either the Atomist or Alpha. Transaction costs are financed through asset management and performance fees. ### Borrow cost - Explanation: In vaults that employ leveraged strategies, borrow costs (interest paid on borrowed assets) directly impact the share price. These costs are typically accrued continuously (e.g., every block) and reduce the net yield generated by the vault's strategies. - Example: Consider a vault that borrows ETH to amplify its yield-farming position. If the borrowed ETH incurs an interest rate that is calculated and applied per block, these continuous deductions will eat into the vault's profits. If the underlying asset's price, which contributes to the vault's NAV, is only updated once a day (like wstETH for example), there can be a mismatch. The share price will reflect the continuous reduction from borrow costs in real-time, while the positive impact of the invested asset's daily price appreciation will only be visible after its price update. This can lead to a perceived short-term stagnation or slight decrease in share price, even if the underlying asset is gaining value, until the asset price update factors in (this can be continuous, daily, or less frequently depending on the asset issuer). ![Image](https://ipor.io/docs/assets/build-on-fusion/unknown-2-7f7c76.png) __ ### Swap Costs - Explanation: DEX fees, typically incurred when a strategy necessitates an asset swap, negatively affect the share price. The share price is also impacted by the swap's exchange rate, which is determined by the volume of assets swapped and the liquidity depth of the DEX pool. However, a swap doesn't always result in a lower share price; positive slippage can occur, leading to a higher Net Asset Value (NAV) post-swap. - Example: In a leveraged looping vault (wstETH/ETH), the share price is reduced by transaction costs incurred when ETH is borrowed and swapped for wstETH. The impact of these swap-related costs on the share price increases with the leverage of the strategy. Deposit and withdrawal operations typically involve leverage and de-leverage actions. To protect existing users from these costs, they can be counterbalanced by imposing on- and offboarding contributions. ![Image](https://ipor.io/docs/assets/build-on-fusion/unknown-3-73550d.png) __ _A user deposit made without a onboarding contribution led to a leverage action, which subsequently caused a drop in share price._ ### On- and Offboarding contributions - Explanation: Fusion Vaults have optional implement on- and offboarding contributions by adjusting the number of vault shares. These are selected by the Atomist to give the best user experience depending on the vault strategy. During deposits, fewer shares are minted, and during withdrawals, shares are burned. Both actions reduce the total number of shares relative to the Net Asset Value (NAV), consequently increasing the share price. ### Other Strategy Costs Explanation: Expenses deemed strategic, including those associated with token minting or burning, or the deposit/withdrawal of funds from external vaults, may arise from transactions initiated by the Alpha. Such expenditures directly diminish the share price. ### Claiming and Compounding Token Rewards Explanation: In strategies that generate yield via token rewards from external protocols, Alphas may regularly or irregularly claim these rewards. This action increases the vault's NAV, consequently increasing the share price. When these tokens are then swapped for the underlying asset (compounding), the resulting swap fees can cause a slight share price change (see “Swap Costs”). ### Asset price movements - Explanation: The share price of vaults whose strategy consists entirely or partially of investing in assets other than the vault's base (accounting) asset fluctuates depending on the price fluctuations of the respective assets. Even minimal price fluctuations in otherwise highly correlated assets such as stablecoins can cause significant short-term share price fluctuations, especially in a highly leveraged vault. - Example: If the vault is denominated in USDC and the strategy is to swap USDC for scrvUSD and loop 20x, even a price fluctuation of 0.0001 USDC/crvUSD can cause a share price change of 0.2%. ![Image](https://ipor.io/docs/assets/build-on-fusion/unknown-4-a51d9a.png) __ - The type of oracle employed by a vault is critical. While market price oracles can lead to share price volatility, hard-coded share price oracles (particularly for pegged assets) mitigate or eliminate such fluctuations. However, this stability comes with the risk that a genuine depreciation might not be reflected in the vault's pricing, potentially triggering a vault run. ### Impermanent Loss (for liquidity provision strategies) - Explanation: If a vault's strategy involves providing liquidity to an Automated Market Maker (AMM) pool with volatile assets, impermanent loss can occur. This happens when the price ratio of the deposited assets diverges significantly from the initial deposit, leading to a temporary (or permanent if withdrawn) loss in dollar value compared to simply holding the assets. - Example: A vault providing liquidity to an ETH/USDC pool on Uniswap will experience impermanent loss if the price of ETH rises sharply against USDC. The vault would end up with a higher proportion of USDC and a lower proportion of ETH than if it had just held both assets separately, potentially lowering the vault's overall NAV and thus its share price. ### Smart Contract Risk and Exploits - Explanation: Although not a direct influencing factor on development of share price, smart contract vulnerabilities or exploits can lead to a sudden and drastic decline in share price due to loss of funds within the vault. This risk is inherent in DeFi. - Example: If a vault holding large amounts of USDT in a particular lending protocol's smart contract is exploited, and funds are drained, the vault's TVL would plummet, causing its share price also to drop. ### Vault Fees Explanation: Fusion vaults charge small performance and management fees by minting shares for recipients like Atomists and the IPOR DAO. This process effectively lowers the share price. see also: [General share price calculation rules](https://ipor.io/docs/build-on-fusion/developer-guide/general-share-price-calculation-rules.md) --- Source: https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/on-and-offboarding-contributions.md # On- and Offboarding Contributions > How to handle depositors' contributions moving into and out of the vault's accounting. > **Note:** Read first: [What are On- and Offboarding Contributions?](https://ipor.io/docs/fusion-for-depositors/user-guide/vault-fees/onboarding-and-offboarding-contributions.md) This document is intended to serve as a decision-making aid for Atomists who are considering whether or not to charge on- or offboarding contributions in their Fusion vault. In principle, any Fusion vault can charge on- and offboarding contributions. They can either be set when the vault is created or added later. The amount of the contributions can also be changed. ## When can it make sense to charge contributions? There are some fusion vaults that contain strategies whose execution is associated with costs. The classic example is a leveraged looping vault. For example, the user deposits asset A, which is then deposited by the vault as collateral on a credit market to borrow asset B, which is then swapped into asset A and also deposited on the credit market. Each swap in these loops is associated with costs, the amount of which depends on the A/B exchange rate and the DEX fees. Transaction costs are not considered here. These costs are socialized in the vault and reflected in the share prices. If a new looping vault is set up, which must first grow, each new user deposit causes the leverage to initially decrease and then increase again through further looping, incurring costs that are socialized. This leads to the growth of the share price being lower than it should be based on the profitability of the strategy. In extreme cases, it can even lead to share prices falling even though the strategy is profitable: ![Image](https://ipor.io/docs/assets/build-on-fusion/unknown-bffd12.png) __ _Example: falling share price despite positive 7d APY_ This result can be frustrating for existing users, as they pay for new users to join the vault. A vault with a declining share price can also discourage new users. On- and offboarding contributions in such vaults would be a way to create more fairness between individual users, as they lead to an increase in the share price. The amount of the contribution should roughly correspond to the costs that experience shows when opening a new leveraged position. However, charging contributions also has disadvantages, as they could be perceived as a hindrance by users themselves or could impair the composability of the vault. Ultimately, each Atomist must assess the vault's goals and target audience and, based on this analysis, decide whether or not to charge a contribution. If fairness and a rising share price are particularly important, the Atomist could even choose to slightly overcharge, so that the share price still does not decrease even with unfavorable swap conditions. If integrability is particularly important, the Atomist could also charge a low contribution or even waive a contribution altogether. ### Preventing Arbitrage through Predictable Rebasing Vaults that utilize rebasing assets, such as `stETH` in a leveraged looping strategy, often exhibit predictable share price movements. Because the underlying protocol distributes yield through a daily rebase at a fixed time, the share price effectively follows a "stair-step" pattern, as illustrated in the chart below. ![Image](https://ipor.io/docs/assets/build-on-fusion/image-4-e94c42.png) __ Without onboarding contributions, opportunistic users can time their deposits to occur just minutes before a scheduled rebase, capturing immediate appreciation without having their capital at risk for a meaningful duration. This behavior socializes the accrued yield across a larger number of shares than contributed to the actual yield generation, directly diluting the returns of long-term participants. By implementing a small onboarding contribution, Atomists can ensure that the cost of entry offsets the immediate arbitrage gain from the rebase event. This protective measure aligns the incentives of all vault participants and preserves the integrity of the share price for those providing continuous liquidity. --- Source: https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/understanding-performance-of-a-vault.md # Understanding Performance of a Vault > How to read and interpret a Fusion vault's realized performance. The performance of a Fusion vault can be measured and displayed in two ways: - Strategy APY - Share Price ## Strategy APY The Strategy APY indicates the short-term performance of the strategy. Depending on the strategy's elements, this may also be merely a forecast. For example, if part of the strategy's yield consists of token rewards that can only be claimed and compounded at a later date, it is impossible to predict what value these tokens will have. The current value of the respective token is used to calculate the Strategy APY. The actual realized performance of the strategy can then be higher or lower than forecast depending on the token price. ## Share Price The second way to display vault performance is the share price. The share price is the **exchange rate** that determines how much of the underlying asset a single vault share token is currently worth. It essentially represents the **value of one share of ownership** in the vault's total pool of assets. #### Key Concepts - **Shares**: When a user deposits an underlying asset (like USDC, ETH) into a Fusion vault, they receive vault share tokens in return. These tokens represent their proportional ownership of the vault's total assets. - **Total Value Locked (TVL) / Total Assets:** This is the collective amount of the underlying asset held by the vault, including the initial deposits plus any accrued profits from the vault's automated yield-generating strategies. - **Calculation:** The share price is calculated by dividing the vault's Total Assets by the Total Supply of Vault Shares: ![Image](https://ipor.io/docs/assets/build-on-fusion/image-fa03f6.png) __ [This document](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/share-price-dynamics.md) explains which factors influence the share price. ## Relationship between Strategy APY and Share Price For the reasons mentioned above, Strategy APY and share price do not always move synchronously. It can even happen that they temporarily move in different directions. For example, if the vault uses a strategy involving leveraged looping, and the exchange rate (e.g., stETH/ETH) fluctuates, this will affect the share price if the vault uses a market price oracle to calculate it. For instance, if the stETH/ETH exchange rate drops from 1.00 to 0.999 and the vault is leveraged 10x, then, to put it simply, the share price will decrease by 10 x 0.1% = 1%. However, the performance of Strategy APY and share price generally coincides over the long term. In individual cases, however, larger deviations may occur. Unfortunately, this cannot be completely avoided due to the numerous factors influencing the share price. --- Source: https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/choosing-the-right-price-oracle.md # Choosing the right price oracle > This document is intended to serve as a decision-making aid for Atomists when selecting the appropriate price oracle. As an Atomist, the choice between a **Market Price Oracle** and a **Fundamental Oracle** (e.g., wstETH/stETH conversion rate) defines the vault’s internal accounting logic. This decision directly dictates how the **Share Price** is calculated and how users experience volatility and liquidity. #### At a Glance: Impact on Vault Mechanics | **Feature** | **Market Price Oracle** | **Fundamental Oracle** | | ------------------------ | --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | | **Share Price Behavior** | Directly reflects secondary market volatility and depegs. | Decoupled from market noise; tied to programmatic asset backing. | | **UX Impact** | Real-time transparency of liquid value. | "Synthetic stability" that prevents panic during market dips. | | **Arbitrage Risk** | Sophisticated actors can "snipe" the vault during dips to dilute long-term yield. | Neutralizes predatory arbitrage by ensuring shares are minted at intrinsic value. | | **Primary Use Case** | Transparent value tracking for liquid assets. | High-leverage looping strategies (e.g., LST/ETH). | --- #### 1. Market Price Oracles: Transparency & Liquidity Market oracles (like Chainlink) reflect what you would receive if you sold the asset immediately. - **Impact on Share Price:** Every market fluctuation—including "scam wicks" or temporary liquidity imbalances—is immediately visible in the vault’s share price. While this provides absolute transparency, it can lead to high volatility in leveraged vaults. - **User Experience:** Informed users can track the exact market value of their investment. However, uninformed users may be deterred by seeing their portfolio "crash" during a temporary de-peg. - **The "Sniping" Risk:** If the share price drops due to a market dip, new users can enter the vault cheaply. Unless onboarding contributions are adjusted, this dilutes the realized returns of existing depositors. #### 2. Fundamental Oracles: Stability & Protection Fundamental oracles ignore market prices in favor of the programmatic exchange rate (e.g., how much stETH backs one wstETH). - **Impact on Share Price:** The share price remains stable even if the secondary market panics. This creates a "hold-to-maturity" environment where the vault's internal value is protected from external liquidity shocks. - **User Experience:** This provides a much smoother UX, preventing psychological panic and unnecessary offboarding during market stress. - **The Exit Liquidity Gap:** A stable share price can be misleading during a crisis. While the vault says a user is "in the green," the actual underlying liquidity might be insufficient to fulfill a withdrawal at that price. This can create a "first-out" advantage where early withdrawers drain liquid reserves. ## Best Practices for Atomists For Leveraged Looping strategies, **fundamental oracles** are generally preferred. They prevent liquidation risks caused by "market noise" and stop savvy traders from acquiring cheap shares during temporary depegs. **Market oracles** prioritize absolute transparency and are best when users need to see the real-time liquid value of their investment. They are particularly suitable when the vault is private or targets sophisticated investors who understand the underlying protocol risk. **Protecting the Net Asset Value (NAV) with dynamic contributions** The choice of oracle requires different **automated contribution strategies** to protect the vault's NAV: 1. With **Market Oracles:** The vault (**automatically executed by Alpha**) should increase [onboarding contributions](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/on-and-offboarding-contributions.md) during a depeg dip to ensure new entrants do not exploit the lower share price at the expense of existing users. 2. With **Fundamental Oracles:** The vault should increase [offboarding contributions](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/on-and-offboarding-contributions.md) if the market price deviates from the fundamental rate. This ensures exiting users compensate the vault for the "liquidity gap" rather than leaving the remaining depositors to shoulder the cost. **Dynamic contributions**, the amount of which is constantly adjusted by the Alpha based on exchange rate oracle prices, ensure that users can only withdraw the current market value of their position. This ensures that the share price is not affected by withdrawals. --- Source: https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/asynchronous-reward-compounding.md # Asynchronous Reward Compounding > How reward claiming and compounding work when they can't happen atomically with a strategy action. In sophisticated DeFi strategies, yield is often composed of **Synchronous Yield** (intrinsic interest accrual) and **Asynchronous Rewards** (external incentives). For an Atomist curating a Fusion Vault, the temporal gap between earning a reward and compounding it into the vault's `totalAssets()` creates a dynamic where the share price may temporarily deviate from the strategy's "true" economic value. This gap results in one of two effects depending on TVL fluctuations: **Dilution** or **Concentration**. ### The Compounding Gap #### Synchronous Accrual Base lending protocols (like Aave or Morpho) usually provide synchronous yield. When a Fusion Vault calls `updateMarketsBalances()`, the vault's share price immediately reflects the interest earned or the costs incurred (e.g., borrowing fees). #### Asynchronous Accrual Many incentive programs (e.g., $ARB, $OP, or $MORPHO) accrue rewards on external distributor contracts. These assets are "invisible" to the vault's exchange rate until the Atomist: 1. **Claims** tokens via the `RewardsClaimManager`. 2. **Converts** them to the underlying asset via the `UniversalTokenSwapper`. 3. **Re-deposits** them, effectively increasing `totalAssets()`. ### Temporal Effects: Inflow vs. Outflow Because the share price only accounts for assets currently tracked within the vault's storage, the value of pending (unclaimed) rewards exists "off-balance-sheet." #### 1. Reward Dilution (Capital Inflow) If a large deposit occurs after a reward has been earned but before it is compounded, the new capital receives a pro-rata share of rewards it did not help earn. This is particularly noticeable in leveraged strategies where the vault has already realized the synchronous _cost_ of the leverage (borrowing fees) but has not yet realized the asynchronous _upside_ (incentives). #### 2. Reward Concentration (Capital Outflow) Conversely, if a significant portion of the TVL is withdrawn before the compounding point, the remaining shareholders benefit from "positive dilution." The rewards earned by the total capital are now distributed among a smaller pool of shares, making the compounding event accretive to the remaining users. ### Technical Example: 7-Day Compounding Cycle Consider a Fusion Vault utilizing a leveraged supply strategy. **Initial State:** - **TVL:** 1,000,000 USDC - **Total Supply:** 1,000,000 shares (Price: 1.0000) - **Strategy:** 3% APY borrow cost to farm a reward token yielding 5% APY. **Accrual Period (7 Days):** The vault maintains the position for one week. **Synchronous Cost (C):** ```math C = \frac{Assets \times Rate_{borrow} \times Days}{365} = \frac{1,000,000 \times 0.03 \times 7}{365} \approx 575.34 ``` **Asynchronous Reward (R):** ```math R = \frac{Assets \times Rate_{reward} \times Days}{365} = \frac{1,000,000 \times 0.05 \times 7}{365} \approx 958.90 ``` **State at Day 7 (Pre-Compounding):** The borrow cost is realized via `updateMarketsBalances()`, but the reward is pending. - **Total Assets:** 999,424.66 USDC - **Share Price:** 0.99942 #### Scenario A: Large Inflow (Dilution) A user deposits 4,000,000 USDC right before compounding. - **New Total Supply:** `1,000,000 + (4,000,000 / 0.99942) \approx 5,002,321` shares. - **Post-Compounding Price:** After adding the 958.90 USDC reward: `Price = \frac{4,999,424.66 + 958.90}{5,002,321} \approx 1.00001` _Note: The original users lose nearly all their net yield to the new capital inflow\._ #### Scenario B: Large Outflow (Concentration) Users withdraw 500,000 USDC right before compounding. - **New Total Supply:** 500,000 shares remaining. - **Post-Compounding Price:** After adding the 958.90 USDC reward to the remaining 499,424.66 USDC assets: `Price = \frac{499,424.66 + 958.90}{500,000} \approx 1.00076` _Note: The remaining users receive a higher share price because they capture the rewards earned by the capital that just exited._ ### Strategic Management for Atomists Atomists should manage the compounding gap to ensure fairness and strategy stability. #### 1. Compounding Frequency Increasing the frequency of reward realization (e.g., daily instead of weekly) minimizes the window for both dilution and concentration, keeping the share price closer to the strategy's fair value. If rewards can be claimed at specific time intervals, the compounding period should correspond to these intervals. Otherwise, fluctuations in the share price can occur, which could be exploited through timed depositing and withdrawing, leading to yield leakage from the vault. #### 2. Onboarding Contributions The `FeeManager` can be used to set a [**Onboarding Contribution**](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/on-and-offboarding-contributions.md). This fee acts as an "entry contribution" that can offset the dilution of existing shareholders, effectively pricing in the value of pending rewards for new participants. #### 3. Scaling and Velocity Atomists should monitor TVL Velocity. Strategies with high asynchronous components should be scaled carefully. Sudden spikes in TVL can be managed using `setTotalSupplyCap()`, allowing the vault to grow in stages that align with compounding cycles. #### 4. Vesting Claimed Rewards Compounding a claimed reward straight into the vault adds it to `totalAssets()` in one block, so the share price jumps at every claim. A depositor who enters just before a claim and exits right after captures part of a reward the vault earned over the whole claim interval. The `RewardsClaimManager` removes the jump: it releases claimed rewards into `totalAssets()` linearly over a vesting period the Atomist sets. **How vesting works** - The vault counts `RewardsClaimManager.balanceOf()` in `totalAssets()`. With a vesting time of 0, that is the manager's whole balance of the vault's underlying asset. With a vesting time above 0, it is only the part vested so far. - `updateBalance()` moves the vested part to the vault and starts a new linear vest of everything the manager still holds, over the full vesting time. - Only the vault's underlying asset vests. Other tokens in the manager are not counted in `totalAssets()` until they are converted to the underlying asset and sent back to the manager. - `transferVestedTokensToVault()` is public. It moves the vested part to the vault without changing `totalAssets()`. **Roles** | Function | Role | Who holds it | | ----------------------------- | ------------------------------------ | --------------------------------------------------------------- | | `setupVestingTime(seconds)` | `ATOMIST_ROLE` (100) | Atomist | | `claimRewards(...)` | `CLAIM_REWARDS_ROLE` (600) | Alpha | | `transfer(token, to, amount)` | `TRANSFER_REWARDS_ROLE` (700) | Alpha or a conversion account; cannot move the underlying asset | | `updateBalance()` | `UPDATE_REWARDS_BALANCE_ROLE` (1100) | Alpha | The Atomist is the admin of roles 600, 700 and 1100 and grants them in the vault's `IporFusionAccessManager`. **Setup** 1. Set the vesting time with `setupVestingTime`. Match it to the claim interval: if rewards are claimed every 36 hours, vest over about 36 to 48 hours. A longer period gives a smoother share price but delays the reward, and depositors who exit leave the unvested part to those who stay. 2. Grant `TRANSFER_REWARDS_ROLE` and `UPDATE_REWARDS_BALANCE_ROLE` to the Alpha (or the account that converts rewards). **Each claim cycle** 1. Claim through `RewardsClaimManager.claimRewards`. Claim fuses send the claimed tokens to the manager. For `MerklClaimFuse`, keep the reward token out of the `doNotTransferToRewardManager` list; a token on that list stays in the vault and is compounded at once. For wrapped Merkl tokens use `MerklClaimWrapperFuse` (see Checks). 2. If the reward token is not the underlying asset, `transfer` it to the conversion account, convert it to the underlying asset, and send the proceeds back to the `RewardsClaimManager` address. 3. Call `updateBalance()`. The new balance starts vesting. **Checks** - `getVestingData()` returns `vestingTime`, `updateBalanceTimestamp` (0 means vesting never started), `transferredTokens` and `lastUpdateBalance`. - `setupVestingTime` can revert in the middle of a vest when the new time would cut the already-released amount. Call `updateBalance()` first, then change the time. - `MerklClaimFuse` forwards the balance change of the token named in the claim. Some Merkl reward tokens are wrappers that unwrap on transfer and pay out a different token (for example a wrapped Aave aToken that delivers the aToken itself). With `MerklClaimFuse` the claimed token's balance does not change and nothing reaches the manager. Use `MerklClaimWrapperFuse` for these tokens: its `claim` takes the list of tokens that actually arrive (`receivedTokens`), measures their balance change and forwards it to the manager. Each received token must be granted as a substrate-as-asset on the fuse's `MARKET_ID`, and the fuse must be added to the manager with `addRewardFuses`. - Rewards held in the conversion account are outside the vault and are not counted in `totalAssets()` until they come back to the manager. Keep the round trip short. --- Source: https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/dependency-graphs.md # Dependency Graphs > How Fusion's cached balance dependency graph works and when to configure it for a market. Dependency graphs in IPOR Fusion are a mechanism that defines relationships between markets where one market's balance calculation depends on another market's balance. They ensure accurate asset valuation and prevent double-counting when markets have nested or interconnected positions. ### Purpose Dependency graphs serve three critical purposes in Fusion: 1. **Prevent Asset Double-Counting**: When a market holds assets that are themselves tracked in another market (e.g., LP tokens staked in a gauge), dependency graphs ensure the underlying assets aren't counted twice in `totalAssets()` . 2. **Ensure Atomic Balance Updates**: When a market balance changes, all dependent markets are automatically updated to maintain consistency across the vault's accounting system. 3. **Support Complex Market Relationships**: Enable sophisticated DeFi strategies where positions span multiple protocols (e.g., lending markets depending on underlying asset markets, or LP token markets depending on constituent tokens). ### Implementation The dependency graph system is implemented through: - **Storage Structure**: A mapping from each market ID to an array of dependent market IDs. - **Configuration Functions**: `updateDependencyBalanceGraphs()` for setting up relationships. - **Query Functions**: `getDependencyBalanceGraph()` for retrieving dependencies. --- Source: https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/integration-maintenance-and-deprecation.md # Integration Maintenance and Deprecation > How to safely wind down or replace a protocol integration a vault depends on. ## Purpose and Scope This document outlines critical security best practices for the ongoing maintenance and monitoring of Fuses, Market Substrates, and Balance Fuses within Fusion vaults. It highlights the severe security risks associated with leaving unused or deprecated integrations active and provides actionable guidelines for Atomists and Fuse Managers to minimize attack vectors on existing deployments. ## The Risk of Dormant Integrations In the modular architecture of IPOR Fusion, Fuses and Market Substrates allow vaults to interact directly with external DeFi protocols. While this deep composability is a core strength, it inherently expands the smart contract surface area. A common and highly critical DeFi vulnerability involves the **state manipulation of dormant integrations**. Attackers frequently use flash loans to artificially alter the balances or prices within a deprecated external pool. If a vault still actively queries this legacy pool for its accounting, the attackers can exploit this discrepancy to manipulate the vault's perceived total assets, allowing them to drain significant value from the vault. This underscores a vital DeFi security principle for IPOR Fusion vault operators: **Integrations must be actively maintained, and anything that is no longer in use must be explicitly removed.** ## The Critical Role of Balance Fuses Balance Fuses serve as the accounting layer of IPOR Fusion. They query external protocols to calculate the vault's net position, which directly dictates the vault's `totalAssets()` and, consequently, the share price for all depositors. If a vault maintains a connection to an unused or deprecated Balance Fuse: 1. **Accounting Manipulation:** Attackers can use flash loans to manipulate the state of the external pool. If your vault's Balance Fuse still queries this pool, the vault will register an artificial spike or drop in `totalAssets()`. 2. **Share Price Arbitrage:** A manipulated `totalAssets()` value allows attackers to mint shares at an artificially low price or redeem them at a highly inflated price, draining the underlying assets from legitimate users. For this reason, if a vault is no longer utilizing a specific market, the `ATOMIST_ROLE` or `FUSE_MANAGER_ROLE` **must** ensure the position is fully exited and the corresponding Balance Fuse is immediately removed via `PlasmaVaultGovernance.removeBalanceFuse()`. ## Managing Market Substrates Substrates define the specific assets, pools, or external vault parameters permitted for a given market. Leaving unused substrates granted creates unnecessary risk: - If a whitelisted token or pool experiences a smart contract issue (e.g., an underlying bridge is compromised or a pool is hacked), and the substrate is still active, the vault remains exposed to potential contagion. - Attackers might find ways to route malicious logic through forgotten pools that remain authorized by the vault's configuration. Substrates that are no longer part of the vault's active strategy must be explicitly revoked using `PlasmaVaultGovernance.revokeMarketSubstrate()`. ## Actionable Guidelines for Vault Managers To maintain a robust security posture and minimize the attack surface, vault operators (`ATOMIST_ROLE` and `FUSE_MANAGER_ROLE`) must adhere to the following lifecycle management practices: ### 1. Principle of Least Privilege (Minimal Attack Surface) Only grant the exact substrates and fuses required for the vault's _current_ strategy. Do not whitelist assets, grant market IDs, or add operation fuses "just in case" they might be needed in the future. ### 2. Routine Integration Audits Regularly review the `CFG_FUSES_ARRAY`, active balance fuses, and granted market substrates. Cross-reference these with the active strategies being executed by the `ALPHA_ROLE`. If a strategy is paused, abandoned, or migrated, its supporting infrastructure must be dismantled. ### 3. Safe Deprecation of Markets When retiring a market from a vault's strategy, follow this strict sequence to avoid locking funds or leaving vulnerabilities behind: 1. **Exit Positions:** The `ALPHA_ROLE` must execute the `exit()` operations on the relevant operation fuses (e.g., Supply Fuses) to withdraw all assets from the target external protocol, returning the liquidity to the Vault's idle balance. 2. **Remove Operation Fuses:** Call `PlasmaVaultGovernance.removeFuses()` to remove the supply/borrow/swap fuses associated with the retired market. 3. **Verify Dust Threshold:** Ensure the remaining balance in the external protocol is at or below the acceptable dust threshold. 4. **Remove Balance Fuse:** Call `PlasmaVaultGovernance.removeBalanceFuse()` to detach the accounting layer from the deprecated market. _(Note: IPOR Fusion enforces that a balance fuse cannot be removed if it still reports a significant balance to protect user funds)._ 5. **Revoke Substrates:** Call `PlasmaVaultGovernance.revokeMarketSubstrate()` to remove the allowed parameters and tokens for that market. ### 4. Monitor the Fuse Whitelist Registry The IPOR DAO maintains a global [Fuse Whitelist Registry](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fuse.md) that tracks the status of all Fuses (`ACTIVE`, `DEPRECATED`, `REMOVED`). Vault managers should actively monitor this registry. If a Fuse used by your vault is marked as `DEPRECATED` or `REMOVED` by the DAO (due to external protocol upgrades or discovered vulnerabilities), you must migrate away from it and remove it from your vault immediately. ## Conclusion Smart contract composability requires active and vigilant maintenance. By ruthlessly pruning unused fuses, outdated balance trackers, and dormant substrates, vault operators can effectively protect user funds and prevent accounting manipulation attacks. A clean, minimal vault configuration is a secure vault configuration. --- Source: https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/managing-redemption-delays.md # Managing Redemption Delays > How the mandatory deposit-to-redemption delay works and how to configure it against sandwich attacks. A critical decision for any Atomist when curating a Fusion vault is whether to implement a **Redemption Delay**. While this feature is a powerful security tool, it introduces significant trade-offs regarding how the vault interacts with the broader DeFi ecosystem. ### What is a Redemption Delay? A redemption delay is a mandatory waiting period enforced between a user's deposit and their ability to withdraw or transfer their shares. In IPOR Fusion, this can be configured from 0 seconds (disabled) up to a maximum of 7 days. When enabled, the vault records the timestamp of a user's last deposit. Any attempt to `withdraw`, `redeem`, or `transfer` shares before the delay period has passed will result in an `AccountIsLocked` revert. The redemption delay parameter is set during the vault creation process in the Fusion Factory. Once the vault is created, this value is **immutable**. Atomists cannot change the delay period later, so careful consideration of the integration trade-offs is required before deployment. ### The Security Motivation: Breaking Atomicity In DeFi, an **atomic transaction** is a sequence of operations that must all succeed or fail together within a single block. Flash loan attacks rely entirely on this property: an attacker borrows funds, manipulates a vault's share price, and repays the loan—all in one block. By requiring even a 1-second delay, the vault forces the user to wait at least until the next block. This makes flash loan attacks impossible because the loan cannot be repaid in the same transaction it was taken. #### Pros and Cons at a Glance | Feature | Pros | Cons | | ------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------- | | **Security** | Hard protection against flash loans and price manipulation. | Does not prevent "sandwich attacks" that span across blocks. | | **Integrations** | Simple to understand for retail users. | Breaks "Money Lego" composability; causes issues with Zaps and Liquidators. | | **User Experience** | Prevents "in-and-out" gaming of the vault. | Can be frustrating for users expecting instant liquidity. | ### Integration Issues with DeFi Protocols Implementing a redemption delay, even one as short as 1 second, can cause "silent" failures for other protocols treating your Fusion Vault as a building block. #### 1. Zaps and Aggregators Many DEX aggregators and "Zap" contracts bundle multiple actions. A user might swap ETH to USDC and deposit into your vault in one click. If the Zap contract needs to "pull back" a tiny amount of shares for fee coverage or slippage adjustment in the same transaction, the entire sequence will fail. #### 2. Liquidation Friction and Collateral Utility If a lending protocol accepts your vault shares as collateral, a redemption delay creates a major risk. During a liquidation, the protocol needs to seize and redeem those shares for the underlying asset immediately to cover debt. If the vault enforces a delay, the liquidation fails, potentially leading to **bad debt** for the lending protocol. While bad debt is a risk for the lender, the indirect consequence for the Fusion vault is **reduced collateral utility**. Risk managers at lending protocols are likely to reject vault shares with redemption delays or apply much higher "haircuts" (lower LTVs), making your vault less attractive for power users and institutional integrators. #### 3. Yield Optimizers and Bots Automated rebalancing bots often deposit into a vault and immediately check solvency or re-calculate a strategy. If these bots need to move funds out in the same block (common in volatile markets), they will get stuck in a revert loop. ### The Alternative: On-boarding and Off-boarding Contributions If your goal is to protect the vault from manipulation without breaking its composability, consider using **On-boarding and Off-boarding Contributions** (Deposit and Withdrawal fees). In IPOR Fusion, these are shares minted or burned during the entry/exit process. #### How Fees Protect the Vault Instead of a time-based lock, you can implement a small fee (e.g., 0.1%). This "tax" on atomicity makes flash loan attacks and sandwich attacks economically unviable because the cost of the fee typically exceeds the potential profit from the manipulation. - **Composability stays intact**: Zaps and Liquidators can still interact with the vault instantly. - **Protection remains**: Flash loaners are deterred by the upfront cost. ### Recommendation for Atomists - **For Private/Curated Vaults**: If you expect your vault to be used primarily by retail users through a frontend, a **short redemption delay (e.g., 1 hour)** is a robust security measure. - **For Ecosystem Building Blocks**: If you want your vault to be used as collateral in lending markets or included in yield aggregators, set the **Redemption Delay to 0** and utilize **On-boarding/Off-boarding Contributions** to provide security while maintaining high composability. --- Source: https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/deposit-caps.md # Deposit Caps > Why and how to cap total vault deposits. A Deposit Cap (technically referred to as the **Total Supply Cap**) is a core security and risk management parameter that defines the maximum number of shares a Fusion Vault can issue. It serves as a vital circuit breaker to limit protocol exposure and protect vault participants from specific attack vectors. ## Overview In IPOR Fusion, the Deposit Cap is enforced at the share-minting level. By limiting the total supply of shares, the Atomist indirectly controls the maximum Total Value Locked (TVL) in the vault. Every vault should ideally be configured with a deposit cap that aligns with the strategy's current liquidity capacity and the desired risk profile. ## Security Rationale Setting an appropriate cap is a primary defense mechanism against several DeFi risks: ### 1. Mitigating Flash Loan and Share Price Attacks Vaults that offer **instant deposits and redemptions** without charging an onboarding/offboarding contribution (entry/exit fees) are potentially vulnerable to share price manipulation. - **The Vector:** An attacker could use a flash loan to significantly inflate the vault's assets or manipulate external price feeds used by balance fuses. If they can enter and exit in the same block for free, they can exploit temporary discrepancies in share price calculation. - **The Defense:** While [Redemption Delays](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/managing-redemption-delays.md) are the primary defense against same-block attacks, a **Deposit Cap** bounds the maximum potential impact. It ensures that even if a manipulation is attempted, the attacker cannot use an unlimited amount of capital to exploit the vault's share price calculation. ### 2. Strategy Capacity and Liquidity Management Many DeFi protocols have finite liquidity. If a Fusion vault grows too large for its underlying protocol integrations, it may suffer from excessive slippage during rebalancing or be unable to exit positions quickly during market stress. A cap ensures the vault stays within the "sweet spot" of the underlying strategy's liquidity. ### 3. Risk Contamination In the early stages of a new strategy, a cap allows the Atomist to observe the performance and oracle stability with a controlled amount of capital before scaling up. ## Technical Implementation ### Role Requirements Only accounts with the `ATOMIST_ROLE` are authorized to modify the supply cap. ### Setting the Deposit Cap The cap is set using the `setTotalSupplyCap` function within the `PlasmaVaultGovernance` contract: ``` function setTotalSupplyCap(uint256 cap_) external restricted; ``` **Important Note on Denomination:** Unlike many other protocols, the cap in IPOR Fusion is denominated in **Shares**, not underlying assets. Because the share price increases over time as yield accrues, the asset-equivalent value of a fixed share cap will also increase. The precision of shares is calculated as: `Share\ Decimals = Underlying\ Asset\ Decimals + 2` ### Management Interface Atomists can manage these limits through the IPOR Fusion Web App in the Vault Management section. 1. Navigate to the **Curation** tab of your vault. 2. Locate the **Vault Limits** section. 3. Enter the new cap value in the underlying asset denomination (the UI automatically handles the conversion to share decimals for the transaction). 4. Execute the transaction. ## Best Practices for Atomists ### 1. The Inverse Relationship with Delays The importance of a strict deposit cap is inversely proportional to your **Redemption Delay**. If your vault has a `redemptionDelay` of 0 and no entry/exit contributions, a tight cap is your absolute primary line of defense against share price manipulation. > For more information on managing waiting periods, see [Managing Redemption Delays](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/managing-redemption-delays.md). ### 2. Frequency of Balance Updates The enforcement of the cap happens during the `deposit` and `mint` flows. However, the calculation of available "headroom" depends on an accurate share price. **Reminder:** Atomists must ensure that `updateMarketsBalances` is called regularly (manually or via keepers). If market balances are stale, the share price might be incorrect, leading to a cap enforcement that doesn't reflect the true value of the vault. ### 3. Strategy Capacity Monitoring Regularly monitor the capacity of the underlying strategy. If the integrated protocols or pools reach their own liquidity limits, the Fusion vault's cap should be adjusted accordingly. While the cap can be increased as the strategy demonstrates deeper liquidity, it should be lowered if market conditions change or if protocol limits are reached to maintain desired slippage parameters. --- Source: https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/deposit-caps/economics-of-deposit-caps.md # Economics of Deposit Caps > The economic reasoning for choosing a specific deposit cap. In modular asset management layers like IPOR Fusion, deposit caps are not merely safety boundaries to prevent smart contract risk; they are critical economic instruments. For **Atomists** and **Alphas**, managing deposit caps is an essential part of maintaining a vault's yield profile, protecting depositors from share price distortions, and managing rebalancing friction. This page explores the economic implications of deposit caps, with a particular focus on the mathematical and structural phenomena that occur in vaults when deposit caps are adjusted. ## The Economic Function of Deposit Caps As described in the core architecture of the protocol in **IPOR Fusion Modular DeFi Vault Infrastructure** and **IPOR Fusion Modular DeFi Vault Infrastructure\_2**, each PlasmaVault accepts a single underlying asset and issues shares. To manage this capital efficiently, deposit caps serve several vital economic functions: 1. **Preventing Yield Dilution:** Many DeFi yield strategies have capacity constraints (e.g., limited liquidity pools, borrowing caps, or falling APRs as TVL increases). Deposit caps prevent excess capital from diluting the annualized percentage yield (APY) of existing depositors. 2. **Managing Onboarding Friction:** When new capital enters a vault, it remains idle as a base asset until the strategy executes a rebalance. During this transition phase, the net APY of the vault can experience a temporary drag. 3. **Controlling Slippage Costs:** Deploying large amounts of capital into a strategy in a single transaction can cause severe slippage, which ultimately harms the share price of all vault depositors. ### The Onboarding Contribution and Share Price Mismatch In vaults configured with an **onboarding contribution** (an entry fee or contribution designed to offset the rebalancing, deployment, and slippage costs of deploying new capital), managing deposit caps requires extreme precision. While this onboarding fee is designed to protect existing depositors from capital deployment friction, a rapid influx of deposits can create a temporary **share price mismatch**. ### Why the Mismatch Occurs The core formula for the valuation of vault shares is: Share Price = Total Assets / Total Supply Because the PlasmaVault is an ERC4626-compliant contract, deposits directly modify this ratio: 1. **Immediate Fee Accrual:** When a new user deposits, their onboarding contribution is immediately realized by the vault. If the contribution is added directly to the vault's assets (or minted as fee shares that are burned or reallocated), the overall vault's Total Assets relative to the outstanding Total Supply increases, which runs up the share price. 2. **Delayed Execution:** The Alpha (strategy manager) does not execute a deployment or rebalance transaction for every single micro-deposit due to gas optimization and execution batching. Therefore, there is a time lag between individual deposits and the actual execution of the underlying strategy. 3. **The Share Price Run-Up:** If the deposit cap is opened too wide, multiple depositors will enter consecutively while the strategy remains undeployed. Because early depositors paid onboarding contributions that raised the share price, subsequent depositors are forced to enter at an artificially higher share price before their capital is actually yielding the target rate. ## Economic Example: Leverage stETH Loop Vault Let us analyze a concrete scenario in a leveraged looping vault to visualize this economic distortion. ### Vault Parameters - **Underlying Asset:** stETH - **Initial TVL:** 1,000 stETH - **Target Leverage:** 10x (utilizing recursive borrowing) - **Onboarding Contribution:** 25 bps (0.25% or 0.0025) - **State:** The vault is currently at its cap of 1,000 stETH and fully leveraged. The Atomist decides to raise the deposit cap by 1,000 stETH to a new cap of 2,000 stETH in a single step. Depositors rapidly fill this new capacity before the Alpha executes the next leveraging transaction. ### The Share Price Distortion Sequence | **Initial State** | Deployed (10x Leverage) | 1,000.000 | 1,000.00 | 1.00000 | Base benchmark. | | ------------------------------------------- | ----------------------- | --------- | -------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | | **Depositor 1** (Deposits 1st 10 stETH) | 10 stETH Idle | 1,009.975 | 1,010.00 | 1.00002 | Enters near fair value. The 25 bps fee (0.025 stETH) remains as asset value. | | **Depositor 2** (Deposits 2nd 10 stETH) | 20 stETH Idle | 1,019.950 | 1,020.00 | 1.00005 | Enters at a slightly inflated price. Receives marginally fewer shares than Depositor 1. | | **Depositor 50** (Deposits 50th 10 stETH) | 500 stETH Idle | 1,498.480 | 1,500.00 | 1.00101 | Price continuously compounds upward as idle cash accumulates. | | **Depositor 100** (Deposits 100th 10 stETH) | 1000 stETH Idle | 1,996.535 | 2,000.00 | **1.00173** | **Distortion Peak:** Enters at a \~17.3 bps higher share price than the initial state, before any new yield is generated. | ### The Impact - **Depositor 1** bought shares at a clean 1.00000 rate. - **Depositor 100** bought shares at 1.00173, receiving fewer shares per deposited stETH. - Once the vault reaches 2,000 stETH and the Alpha executes the leverage loop (increasing the exposure from 10,000 stETH to 20,000 stETH), swap fees and slippage of that loop will pull the share price back down. - This means **Depositor 100** immediately absorbs a disproportionate share of the slippage penalty because they entered at an inflated price, while their capital was not yet deployed. ## Best Practices for Atomists: Gradual Capacity Scaling This share price behavior can never be entirely resolved in a pool-based architecture, but its economic impact can be minimized through disciplined operational management. Instead of opening the cap by a massive amount all at once, Atomists should practice **Gradual Capacity Scaling**: ``` [Current Cap: C] │ ▼ Raise Cap by 10% increment (New Cap: C + 0.1C) │ ▼ [Wait for Deposits to Fill] ───► [Vault holds idle base assets] │ ▼ Alpha Executes Strategy/Deployment (Vault reaches Target Leverage) │ ▼ Share Price and Exposure Stabilize │ ▼ Raise Cap by another 10% increment of current capacity ``` ### Operational Rules of Thumb: 1. **Scale in Increments:** For any large planned vault expansion, raise the cap in step-by-step increments rather than all at once. A standard recommendation is to scale in increments of 10% of the current capacity (for example, raising the cap in 100-token steps if the current capacity is 1,000 tokens). 2. **Coordinate with the Alpha:** Only raise the next increment after the Alpha has successfully executed the leverage-up, rebalance, or deployment transaction. This ensures that newly onboarded capital is active and earning yield before the next wave of deposits is allowed to enter. 3. **Calibrate Onboarding Fees:** Ensure the [Onboarding Contribution](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/on-and-offboarding-contributions.md) is optimized to reflect the true onboarding cost. --- Source: https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/yield-scalability-and-market-impact.md # Yield Scalability and Market Impact > How a strategy's yield degrades as vault size grows, and how to plan around market impact. In Decentralized Finance, yield is rarely a static figure. For an **Atomist** curating a Fusion Vault, selecting the market with the highest "headline" APR is only the first step. To truly optimize a vault's performance, one must account for **Market Impact**—the effect that the vault’s own capital has on the equilibrium of the target protocol. This page explains why Fusion vaults often distribute capital across multiple markets, even when one appears to offer superior returns, and how to approach allocation limits through the lens of yield scalability. ## The Scalability of Yield Most DeFi yield strategies (particularly lending via Aave, Compound, or Morpho) are not infinitely scalable. The APR offered by these protocols is a function of the **Utilization Rate** (`U`). The Utilization Rate is defined as: ```math U = \frac{\text{Total Borrows}}{\text{Total Liquidity}} ``` As a Fusion vault supplies more assets to a market, the **Total Liquidity** increases. If the **Total Borrows** remain constant, the Utilization Rate decreases, which in turn moves the market down the interest rate curve, reducing the APR for all suppliers in that pool. This phenomenon is known as **Yield Slippage**. ## Interest Rate Curves and "The Kink" Most lending protocols utilize a "kinked" interest rate curve. This model ensures there is always liquidity available for withdrawers while incentivizing borrowing up to an optimal point (`U_{opt}`). The interest rate `R_t` typically follows a two-part slope: 1. **Before the Kink (**`U < U_{opt}`**):** A shallow slope where interest increases slowly to encourage borrowing. 2. **After the Kink (**`U > U_{opt}`**):** A steep slope where interest rises sharply to discourage further borrowing and attract new suppliers. ### The Impact of Large Allocations When a market is operating "above the kink," it offers an elevated APR because liquidity is scarce. However, these markets are also the most sensitive to new capital. If an [Alpha](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-alpha.md) sees a market offering a headline APR of 12%, it might only take a relatively small deposit to push the utilization back below the kink, causing the APR to drop precipitously to a base rate (e.g., 4%). ## Marginal Yield vs. Average Yield The goal of a Fusion vault is often to maximize the aggregate yield of the **Total Assets** (`A_{total}`) across all integrated markets. The Alpha must calculate the **Marginal Yield**—the yield generated by the _next_ dollar allocated—rather than relying solely on the current headline yield. ### The Mathematical Rationale for Splitting To illustrate the impact of yield slippage, let's assume the following interest rate model: - **Optimal Utilization (**`U_{opt}`**):** 90% - **Slope 1 (Below Kink):** 4% max - **Slope 2 (Above Kink):** 60% max An Alpha has **$2,000,000 USDC** to allocate between two markets: - **Market A (thin liquidity):** - Total Liquidity: $10,000,000 - Total Borrows: $9,500,000 - Current Utilization: **95%** (Operating high on the steep slope). - Current Headline Supply APR: **29.07%** - **Market B (deep liquidity):** - Current Headline Supply APR: **6.00%** (Stable; deep enough that a $2M deposit has negligible impact). **Scenario 1: Single Allocation (The Yield Trap)** The Alpha chases the 29.07% headline rate and allocates the full $2,000,000 to Market A. - New Liquidity in Market A: $12,000,000 - New Utilization: $9,500,000 / $12,000,000 = **79.16%** - Because utilization has fallen _below_ the 90% kink, the market crashes down to the shallow slope (Slope 1). - New Supply APR on Market A drops to **2.51%**. - **Total Annual Yield:** $2,000,000 `\times 2.51\%` = `\mathbf{\$50,200}` **Scenario 2: Distributed Allocation (Optimal Splitting)** The Alpha calculates the capacity of Market A and decides to split the capital, allocating $400,000 to Market A and $1,600,000 to Market B. - **Market A ($400,000):** New Liquidity is $10.4M. Utilization drops slightly to **91.35%**. Because it stays _above_ the kink, the new Supply APR remains strong at **9.93%**. - Yield from A: `400,000 \times 9.93\% = \$39,720` - **Market B ($1,600,000):** Earns the stable **6.00%**. - Yield from B: `1,600,000 \times 6.00\% = \$96,000` - **Total Annual Yield:** `\$39,720 + \$96,000 = \mathbf{\$135,720}` By strategically splitting the allocation to respect the target market's "kink," the distributed strategy generates **over 2.7x more yield** ($135,720 vs. $50,200) than simply dumping capital into the market with the highest headline APR. ## Examples Good examples of split asset allocation for yield optimization are the stablecoin lending optimizers of the IPOR Fusion DAO, like the [IPOR USDC Prime](https://app.ipor.io/fusion/ethereum/0x43ee0243ea8cf02f7087d8b16c8d2007cc9c7ca2): ![Image](https://ipor.io/docs/assets/build-on-fusion/image-1-581ad2.png) __ --- Source: https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/integrating-pendle-pt-tokens.md # Integrating Pendle PT Tokens > Considerations specific to holding and pricing Pendle PT tokens in a Fusion vault. Integrating Pendle Principal Tokens (PT) into an IPOR Fusion vault enables fixed-yield strategies. However, because PTs are yield-bearing assets with unique pricing and maturity mechanics, Atomists must follow a specific configuration workflow to ensure the vault correctly accounts for these assets. This guide covers the three pillars of PT integration: **Tracking**, **Valuation**, and **Execution**. ### 1. Asset Tracking By default, a Fusion Vault only "sees" the assets explicitly defined in its configuration. If an Alpha strategist swaps vault collateral for a Pendle PT, the asset will not appear in the vault's balance or the UI unless it is registered. #### Adding Tracked Assets Atomists must add the specific PT ERC20 address to the **Tracked Assets** list. - **Why:** This ensures the vault's `totalAssets()` logic includes the PT balance. - **Action:** Use the `PlasmaVaultGovernance` interface to add the PT contract address to the vault’s tracked ERC20 tokens (Market ID 7). ### 2. Valuation (Price Oracles) Pendle PT tokens are not typically supported by standard Chainlink price feeds. Without a valid price feed, the vault cannot calculate its Total Value Locked (TVL) or the share price, often leading to a "0.00" display or transaction reverts. #### Custom Price Feeds Atomists must configure a **Custom Price Feed** via the `PriceOracleMiddleware`. - **Mechanism:** PT tokens should be priced based on the underlying Pendle Market. - **Configuration:** Instead of a direct spot price, use a specialized oracle that pulls the PT price from the **Pendle Market contract**. This is then registered in the `PriceOracleMiddleware` under the **Custom Price Feeds** section. Navigate to the `Price Feed` section in the Fusion interface to provide the Pendle Market address to derive the PT price relative to the underlying asset (e.g., PT-sDAI priced against sDAI). Price feeds can be created with the [factory](https://app.ipor.io/build-on-fusion/price-feed/ethereum/pt). ### 3. Substrate Setup for Swapping For the `UniversalTokenSwapper` to handle PT tokens, the Atomist must explicitly grant substrates for both the asset and the routing infrastructure. 1. **The PT Token:** Granted as an allowed asset (Type 1). 2. **The Pendle Router:** Granted as an allowed target for the swapper executor (Type 2). ### 4. Execution: Swapping vs. Minting A common point of confusion is the difference between the **Pendle Fuse** and the **Universal Token Swapper**. #### The Pendle Fuse The specialized Pendle Fuse is designed for **primary market operations**: - **Minting:** Converting an underlying asset into PT and YT. - **Redeeming:** Converting PT back to the underlying asset _at maturity_. - **Limit:** This fuse does not handle market swaps. #### Swapping via Universal Token Swapper To buy or sell PT tokens on the open market (secondary market) before maturity, you must use the **Universal Token Swapper** (Market ID: 12). ### 5. Technical: Substrate Encoding for Swapping The `UniversalTokenSwapper` uses a typed substrate system. When configuring substrates for Pendle PTs via `grantMarketSubstrates`, use the following encoding logic provided by the `UniversalTokenSwapperSubstrateLib`: | **Substrate Type** | **ID (Type Byte)** | **Usage for Pendle** | | ------------------ | ------------------ | ---------------------------------------------------------------------- | | **Token** | `0x01` | **PT Token Address:** Allows the swapper to spend/receive the PT. | | **Target** | `0x02` | **Pendle Router Address:** Allows the swapper to call the Router. | | **Slippage** | `0x03` | **Max Slippage:** Defines the USD-value delta allowed for the PT swap. | #### Encoding Format Substrates are `bytes32` values where the first byte is the Type ID: - **Token/Target:** `[1-byte Type][11-byte zero padding][20-byte Address]` - **Slippage:** `[1-byte Type][31-byte Slippage Value in WAD]` ### 6. Substrate Configuration Checklist To successfully curate a vault using Pendle PTs, ensure the following substrates are granted: | **Market** | **Market ID** | **Required Substrate** | | ----------------------- | ------------- | -------------------------------------------------- | | **ERC20 Vault Balance** | 7 | The PT Token Address (to track holdings) | | **Universal Swapper** | 12 | The PT Token Address (Type 1: Allowed token) | | **Universal Swapper** | 12 | The Pendle Router Address (Type 2: Allowed target) | | **Price Oracle** | N/A | Custom PT-to-Asset feed derived from Pendle Market | ### Atomist Pro-Tips #### Handling Maturity When a PT token reaches maturity, its price effectively becomes 1:1 with the underlying asset. However, the vault doesn't automatically "exit" the position. The Alpha must execute a `redeem` action via the Pendle Fuse or swap it out to move the capital back into a liquid state or a new PT vintage. #### Decimal Sensitivity PT tokens often have specific decimal configurations. Always verify the `underlyingDecimals` in the `PriceOracleMiddleware` match the PT's contract to avoid massive over- or under-valuation of the vault. #### Testing on Forks Before deploying to mainnet, always simulate the Pendle swap and balance update on a local fork (Anvil). Ensure that after the swap, `totalAssets()` correctly reflects the PT position and that the `updateMarketsBalances` function handles the custom oracle without reverting. --- Source: https://ipor.io/docs/build-on-fusion/alpha/benefits-for-alphas.md # Benefits for Alphas > Why running strategy execution as an Alpha (automation, risk management, IP protection) beats manual operation. ## **Optimized Yield Through Automation** - Alphas allow for **intelligence-driven execution** — strategies like looping, arbitrage, carry trades, leveraged farming, etc. can run automatically. - Because the Alpha runs off-chain, you can build more complex, custom logic (e.g. when to loop, when to deleverage) without bloating on-chain contracts. ## **Risk Management & Rebalancing** - Alphas can continuously monitor and rebalance the vault based on market conditions, slippage, or rate changes. - They help enforce risk parameters defined by the Atomist, ensuring guardrails are respected. ## **Modular and Composable Strategy Execution** - With Fuses, there is no need to re-deploy or upgrade the core vault contract to change strategies — Alpha just calls different fuses. - This modularity ensures flexibility: new protocol integrations or strategies can be added without touching/upgrading the vault core. ## **Efficiency & Capital Deployment** - Alphas reduce operational burden: instead of a user or strategist manually executing each action, the Alpha automates it. - They help maximize capital efficiency: routing assets to the best yields, minimizing gas waste, optimizing timing, etc. ## **Security and Transparency** - While the Alpha handles strategy off-chain, all its actions are still executed on-chain through Fuses / the Plasma Vault, so there is strong on-chain guardrail. - Because vault logic and fuses are non-upgradable (immutable), the system avoids certain classes of upgrade risks. ## **Custom Strategy Development While Preserving Intellectual Property** - Because Alphas operate off-chain, a strategist can keep proprietary strategy logic private (i.e. not exposed on-chain). - This is appealing for Atomists who want to deploy advanced strategies without making all the logic public. ## **Points / Reward Handling** - Vaults in Fusion accrue “points” (some form of reward accounting), and an Alpha can handle distribution logic of these points (off-chain). - This means more flexible / custom reward schemes (frequency, conditions, backend logic) are possible. ## **Better Withdrawal Management** - For vaults with scheduled withdrawals, the Alpha can prepare and execute the necessary “exit” operations before releasing funds to users. - This helps manage liquidity efficiently and protects the vault from sudden large withdrawal shocks. --- Source: https://ipor.io/docs/build-on-fusion/alpha/running-an-alpha.md # Running an Alpha > Manual vs. automated Alpha operation, the SDK-driven transaction path, and handling accrued points. ## Manual Alpha Operations The simplest case of Alpha is appointing an EOA to run the operations to manually using the interface. The app.ipor.io website has an interface for interacting with smart contracts via widgets. Widgets abstract the fuse functionality and provide a consistent interface for executing transactions. If the interface is unavailable for the fuse you want to interact with, you can always build the transaction by hand. Fusion implements a diamond proxy pattern so that the vault implements the function calls from the connected fuses. ## Automated Alpha The core philosophy of IPOR Fusion is to build the vaults in such a way as to enable automation without sacrificing transparency and security. In principle, there is no difference between a manual and an automated Alpha. They both have the same privileges and from the perspective of the vault so there is no difference whatsoever. The main difference is the interface through which management is done. Since the automated Alpha doesn't need UI it needs to build all its transactions via the provided [SDK](https://ipor.io/docs/build-on-fusion/alpha/sdk.md), or by communicating directly with smart contracts. When operating an Alpha there are certain security precautions one needs to take. Because the Alpha has direct access to the vault, albeit limited by the fuses and validations, it can still manage the assets freely. Natively, the Alpha architecture does not require any form of consensus. Of course, if this is your choice, you may implement the logic the have the decision-making process decentralised and more sophisticated. ## Handling Points One particular scenario when operating vaults as Alpha is accounting for points. Thanks to the structure of Fusion, all the points are accrued by the vault. If you need to distribute those points or rewards based on those points it has to be handled by your backend logic. Service providers like Merkl can also forward points to the users of the vault. If you need to show points on your vault's page on the IPOR web app, and this particular type of points is not yet supported, reach out to the IPOR DAO via Discord, where you can request adding that integration. It's up to the individual Atomist/Alpha. --- Source: https://ipor.io/docs/build-on-fusion/alpha/running-an-alpha/best-practices-for-alphas.md # Best Practices for Alphas > Gas efficiency, leveraged-looping risk, accounting, withdrawal orchestration and security practices for an Alpha bot. The **Alpha** role (assigned via `ALPHA_ROLE`) is the operational engine of a Fusion Vault. As an Alpha, your primary responsibility is the execution of yield strategies and the management of vault liquidity. Unlike the Atomist, who configures the "physical" constraints of the vault, the Alpha operates within those constraints to maximize risk-adjusted returns for depositors. This guide provides technical tips and best practices for running an efficient Alpha bot or manual strategy. ## 1. Optimize for Atomicity and Gas Efficiency The `execute(FuseAction[] calldata calls_)` function is designed for atomic batching. Every action within the `calls_` array is executed via `delegatecall` in the vault's context. - **Batching for Gas Efficiency:** Combine related operations (e.g., swapping tokens, then supplying them to Aave V3) into a single `execute` call. This reduces overhead and ensures that the vault never holds intermediary assets across blocks. - **Optimal Transaction Sizing:** Avoid overly long execution chains that might exceed block gas limits. Estimate gas fees for execution and evaluate them against the likelihood of sustained rate changes. - **All-or-Nothing Execution:** If any `FuseAction` fails—due to slippage or substrate violations—the entire transaction reverts. Use this to build complex "Zaps" or arbitrage loops with zero principal risk to the vault. ## 2. Leveraged Looping Strategies Leveraging can significantly boost yield but introduces specific risks to the vault's Net Asset Value (NAV). - **Slippage Management:** Slippage is the primary "performance killer." - Prefer **native staking/unstaking** or **wrapping** over DEX swaps whenever possible. - Use **aggregators** to find the best routes. The `UniversalSwapper` fuse provides additional validation for aggregator-provided transactions. - For large positions, **TWAP in and out**. Building a massive leveraged position in a single block can cause high slippage. Smaller, incremental steps allow the market depth to recover. - **Simulate Market Depth:** Before executing, understand the current market depth and rate dynamics. Simulate slippage on-chain or via off-chain forks to ensure you aren't leaving "free money" for MEV sandwich bots. - **Avoid Swaps via Flash Loans:** When moving between positions with similar assets, use a **Flash Loan** (e.g. via `MorphoFlashLoanFuse`) to transition atomically without incurring swap fees or slippage. - **Flash Loan Capacity Limits:** Sometimes the liquidity available for a single flash loan is insufficient to move an entire position. In these cases, split the position into smaller operations and execute the transaction using two or more flash loans to bypass the liquidity constraints. - **Cross-Asset Volatility:** Be highly cautious when leverage looping with different underlying assets (e.g., supplying one stablecoin as collateral while borrowing a different stablecoin). The leverage multiplier amplifies any price divergence between the two assets (leverage × stable_1_price / stable_2_price), which will cause abrupt jumps in the vault's share price. - **Off-Chain Calculation Buffer:** If calculating state changes off-chain, add a buffer to account for the time elapsed between calculation and on-chain execution. Additional interest will accrue during this delay. This is particularly critical in markets with high utilization. Keep in mind that moving a leveraged position (e.g., 10x leverage) out of such a market will accrue 10x more borrow interest during the delay than the base rate suggests. ## 3. Managing Accounting and Performance Fees Performance fees are calculated on realized gains during `execute()` and `updateMarketsBalances()`. - **Understand the High-Water Mark:** IPOR Fusion utilizes High-Water Mark (HWM) logic. Performance fees are only minted when `TotalAssets_{after} > HighWaterMark`. - **Strategic Balance Updates:** Call `updateMarketsBalances(uint256[] marketIds)` periodically. This synchronizes internal accounting with external protocol interest. - **Prevent Inflation Attacks:** Update the share price (`\frac{TotalAssets}{TotalSupply}`) frequently enough to ensure accuracy and prevent share price inflation attacks, especially in public vaults. - **Oracle Selection and Share Price Jumps:** Prefer fundamental oracles (e.g., wstETH-ETH) whenever possible to avoid artificial share price jumps. If utilizing market-priced oracles, be aware that deleveraging costs will be immediately reflected in the share price, making it inherently more volatile. If an asset is new or has limited DEX liquidity but maintains a 1:1 redemption peg, consider suggesting a hardcoded price oracle to the Atomist. ## 4. Liquidity and Withdrawal Orchestration - **Unallocated Buffer:** Maintain a buffer of assets in an instantly liquid strategy (e.g., Lending Optimizers). This allows the vault to fulfill smaller withdrawals instantly without the gas cost of deleveraging a complex position. - **Scheduled Withdrawal Flexibility:** Do not ignore the flexibility of scheduled withdrawals. Sometimes it is more economical to use the next incoming deposit to pay down vault debt rather than manually deleveraging via a swap. - **The `releaseFunds` Responsibility:** For scheduled withdrawals, Alphas must call `releaseFunds()` on the `WithdrawManager`. Monitor the queue and rebalance the vault _before_ releasing funds to ensure liquidity is present. - **Burn Request Fees Proportionally:** When preparing funds for scheduled withdrawals and utilizing the `BurnRequestFeeFuse`, ensure that you burn the offboarding (request) fees in proportion to the funds being prepared. - **Dynamic Fees:** If granted the role, the Alpha can manage the **Request Fee** and **Withdrawal Fee**. Set these dynamically to match your expected cost of unwinding positions, preventing users from "socializing" the cost of their exits. ## 5. Deleveraging and Risk Execution The Alpha executes deleveraging actions based on market conditions, but must always operate within the risk framework established by the Atomist. - **Bite the Bullet:** Deleveraging often incurs trade costs (swaps/fees). In high-risk scenarios (e.g., price volatility approaching an Atomist-defined threshold), it is better to "bite the bullet" and deleverage at a loss than to risk a liquidation event that threatens the vault's principal. - **Cost vs. Performance:** Decisions to deleverage must balance execution costs (slippage and gas) against the cumulative negative carry of an inverted position. While using new deposits to pay down debt is an efficient way to deleverage, it is unlikely to occur when rates are inverted, as smart depositors will avoid a vault with negative performance. Alphas must proactively calculate the "breakeven" time—where the cost of a forced swap today is lower than the projected loss from holding the inverted position—and execute accordingly while remaining within the Atomist's safety bounds. ## 6. Security and Risk Mitigation - **Comprehensive Simulation:** Always simulate the transaction off-chain and verify the final balances before broadcasting. Specifically, simulate share price changes to ensure the execution does not cause unintended share price jumps. - **Strict Slippage:** Always populate `minOutAmount` or `maxSharesBurned` when making a swap. Never use `0` in production. When building automated bots, it is highly recommended to configure tightly bound, low slippage tolerances. - **Oracle Pre-Hooks:** Use the `ValidateAllAssetsPricesPreHook` before `execute()` to block operations if the `PriceOracleMiddleware` detects a price deviation beyond your threshold (e.g., 1-2%). - **Monitoring Health Factors:** For borrow positions (e.g. Euler V2, Morpho), monitor the Health Factor (`HF`) of sub-accounts using the `balanceOf` query in the corresponding Balance Fuse. ## 7. Technical Role Constraints - **Governance Separation:** Internal functions (fee % changes, adding fuses) are restricted to the Atomist. Focus on capital allocation and execution logic. - **Bot Robustness:** Ensure your automated Alpha has robust error handling, monitors gas price spikes, and maintains a sufficient ETH balance for operations. **Summary Checklist for Alpha Operations** | **Task** | **Frequency** | **Target Contract** | | ------------------------------ | -------------------- | --------------------- | | `updateMarketsBalances` | e.g. Hourly/Daily | `PlasmaVault` | | `releaseFunds` | Per Withdrawal Cycle | `WithdrawManager` | | `execute` (Rebalance/Compound) | As needed | `PlasmaVault` | | `claimRewards` | Based on Accrual | `RewardsClaimManager` | --- Source: https://ipor.io/docs/build-on-fusion/alpha/sdk.md # SDK > Install, connect and execute with the Python SDK; the CLI, MCP server, agent skills, examples and module reference. The official Python SDK for IPOR Fusion (`pip install ipor-fusion`; [PyPI](https://pypi.org/project/ipor-fusion/), [source](https://github.com/IPOR-Labs/ipor-fusion.py)). Use it to create vaults, construct contract calls, encode calldata and submit transactions through a configured signer — the only one of Fusion's public interfaces that can write, not just read (see MCP and the API for read-only surfaces). For the full first-vault walkthrough, see Deploy your first Fusion vault. For revert selectors and the role table, see Common errors. ### Install ```bash pip install ipor-fusion ``` ### Connect and execute ```python from ipor_fusion import Web3Context, PlasmaVault, AaveV3SupplyFuse from web3 import Web3 # 1. Create a Web3 context with your provider and private key ctx = Web3Context.from_url( url="https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY", private_key="0x...", ) # 2. Wrap the PlasmaVault contract vault = PlasmaVault(ctx, Web3.to_checksum_address("0xVAULT_ADDRESS")) # 3. Build a fuse action (e.g. supply USDC to Aave V3) fuse = AaveV3SupplyFuse(Web3.to_checksum_address("0xFUSE_ADDRESS")) action = fuse.supply( asset=Web3.to_checksum_address("0xUSDC_ADDRESS"), amount=1_000_000, # 1 USDC (6 decimals) ) # 4. Execute on-chain (execute() returns a Call; .send() signs and submits it) receipt = vault.execute([action]).send() ``` Fuse, factory and manager addresses per chain are published in [`ipor-abi`](https://github.com/IPOR-Labs/ipor-abi) (`mainnet/mainnet--fusion/addresses.json`) — see also Addresses. A fuse must also be registered on the vault; `vault.get_fuses().call()` lists the registered ones. Amounts are raw on-chain integers (`Amount`, `Shares` in `ipor_fusion.types`); the SDK never scales by decimals. ### Read, send, or simulate Every wrapper method returns a `Call` instead of executing immediately. The same `Call` powers all three modes — this is the SDK's read-only-vs-transaction-sending surface: ```python from ipor_fusion import VaultSimulator total = vault.total_assets().call() # eth_call -> Amount, no key needed receipt = vault.execute([action]).send() # signed tx -> TxReceipt, needs a private key payload = vault.execute([action]).calldata # raw bytes for an external signer # Simulate first via eth_simulateV1 (no local node); alpha is the account allowed to call execute() sim = VaultSimulator(ctx.web3, vault=vault.address, alpha=Web3.to_checksum_address("0xALPHA")) sim.observe("before", vault.total_assets()) sim.execute([action]) sim.observe("after", vault.total_assets()) result = sim.run() if result.all_success: print(result.get("after") - result.get("before")) ``` `.send()` signs locally and requires a private key in the `Web3Context`; `.call()` and `.calldata` need none — sending through a keyless context raises `ValueError`. ### CLI: `fusion` The SDK ships a `fusion` CLI for **inspecting** Plasma Vaults from the terminal — it does not deploy, configure or execute; that's the SDK's job above. ```bash # Install with CLI extras (pipx keeps dependencies isolated) pipx install 'ipor-fusion[cli]' # Configure an RPC provider (auto-detects chain ID) fusion config set-provider https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY # Inspect a vault (auto-saves to config on first use) fusion vault info 0xB8a451107A9f87FDe481D4D686247D6e43Ed715e --chain-id ethereum # List saved vaults fusion vault list # Inspect a Morpho Blue market or MetaMorpho vault fusion market morpho-blue 0xMARKET_ID --chain ethereum fusion market meta-morpho 0xVAULT_ADDRESS --chain ethereum ``` ### MCP: `fusion-mcp` Two ways to reach Fusion from an MCP-compatible client — see MCP for the hosted server's full tool/resource/prompt reference. - **Hosted, no install:** `https://mcp.ipor.io/mcp` — public, unauthenticated, read-only. - **Local, from the SDK:** `pipx install 'ipor-fusion[mcp]'` ships a `fusion-mcp` server that exposes the same CLI over MCP, against your own RPC providers and local config, plus the resources `fusion://glossary`, `fusion://architecture`, `fusion://invariants` and `fusion://quickstart`, and the prompts `quickstart`, `deploy_vault`, `analyze_vault`, `trace_oracle_pricing` and `explain_fuse`. ```json { "mcpServers": { "ipor-fusion": { "command": "fusion-mcp", "type": "stdio" } } } ``` ### Agent skills [`skills/ipor-deploy-vault/SKILL.md`](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/skills/ipor-deploy-vault/SKILL.md) teaches a coding agent the full clone -> roles -> market -> access posture -> deposit -> execute walk, with the invariants and the revert selectors, before it writes vault code — the same text as `fusion://invariants` / `fusion://quickstart` and Common errors, one text with several delivery paths. One install per machine: ```bash # Claude Code -- plugin with the skill and the hosted MCP server /plugin marketplace add IPOR-Labs/ipor-fusion.py /plugin install ipor-fusion@ipor-fusion # Codex CLI, Gemini CLI, Cursor -- the skill; add the MCP server as shown above npx skills add IPOR-Labs/ipor-fusion.py -g -a codex # or gemini-cli, cursor ``` ### Vault construction examples Runnable, canonical examples for building and configuring a vault from scratch live in [`examples/`](https://github.com/IPOR-Labs/ipor-fusion.py/tree/main/examples). They preview and simulate through `eth_simulateV1` — nothing is ever signed or broadcast. - [Simple Aave V3 supply vault](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/simple_aave_v3_supply_base.py) — start here for vault creation, role bootstrap, and configuring a single supported market. - [Advanced Euler V2 credit-market vault](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/advanced_euler_v2_credit_market_base.py) — continue here for composing multiple functional fuses, typed Euler substrates and sub-accounts, and an ordered collateral -> borrow -> repay -> unwind lifecycle. For a strategy bot that operates an existing vault end to end, see [`ipor-fusion-alpha-example`](https://github.com/IPOR-Labs/ipor-fusion-alpha-example). ### Architecture The SDK uses a **fuse adapter pattern**: Fuses encode protocol-specific calls into `FuseAction` objects (pure calldata, no state); `PlasmaVault` batches and executes `FuseAction` sequences on-chain via `execute()` (atomically); `Web3Context` manages provider connections, signing and transaction dispatch; `Call` is the lazy result of every wrapper method. ``` Fuse.method() --> FuseAction --> PlasmaVault.execute([actions]) --> Call --> .send() / simulate ``` #### Core modules (`ipor_fusion.core`) | Module | Purpose | | -------------------------------------------------------- | ------------------------------------------------------------------------------------ | | `Web3Context` | Provider connection, signing, tx dispatch, gas estimation | | `Call` | Pre-encoded contract call; `.call()`, `.send()`, `.calldata`, `.build_transaction()` | | `PlasmaVault` | ERC-4626 vault — execute, deposit, withdraw, fuse and market configuration | | `VaultSimulator` | Batch `execute` + reads through `eth_simulateV1`, multi-block, no local node | | `FusionFactory` | Deploy a new vault (`clone`, `clone_supervised`) | | `AccessManager` | Role-based access control | | `RewardsManager` | Claim and vest rewards | | `WithdrawManager` | Time-windowed withdrawal requests | | `FeeManager` | Deposit, performance, and management fee configuration | | `PriceOracleMiddleware` / `PriceOracleMiddlewareManager` | Asset price feeds and per-vault overrides | | `ERC20` | Token reads and approvals | #### Supported protocols (`ipor_fusion.fuses`) Aave V3, Morpho, Euler V2, Uniswap V3, Ramses V2, Compound V3, Gearbox V3, ERC-4626, Fluid Instadapp, Merkl, plus a Universal Token Swapper fuse. Full class list in the [README](https://github.com/IPOR-Labs/ipor-fusion.py#supported-protocols-ipor_fusionfuses). #### Supported networks Ethereum, Arbitrum, Base, Unichain, Plasma, Avalanche, Katana, Monad and HyperEVM. ### Development and contributing Contributor and coding-agent instructions (commands, conventions, invariants, domain rules) live in [`AGENTS.md`](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/AGENTS.md) in the repository. --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/quick-start-guide.md # Quick Start Guide > Video walkthrough of creating and configuring a vault via the webapp, plus the SDK/agent path for programmatic deployment. > **Warning:** The Fusion Terminal UI was rebuilt in August 2026 (new Vault Wizard, reorganized vault management: General Settings, Access Manager, Integrations, Scheduled Ops, Withdrawals, Fees, Price Oracle, Prehooks, Allocations, Alpha Config, and vault customization moved to its own Brand & Info section). The video walkthroughs below predate this rebuild — the concepts still apply, but menus, labels and page layout in the live app no longer match the videos step-by-step. ### SDK / agent path Building programmatically, or an AI agent? Skip the videos below and go straight to Deploy your first Fusion vault — the executed, copy-pasteable eleven-transaction walk (clone, roles, market setup, access posture, deposit, execute) using the Python SDK, plus factory addresses per chain. ### Creating a vault To create a vault use the vault factory. This is the first step in preparing your strategy. Once the vault is created it still needs to be whitelisted if you want to have it included in the IPOR webapp interface. [VIDEO](https://www.youtube.com/watch?v=_3wjQf9iMY4&list=PLTda9D8MCj4QafXFkFPR_i27CakEUdBeg&index=1) ### Vault Setup Documentation Playlist: 1. Create vault [VIDEO](https://youtu.be/xxdiy6j75VQ?si=LIfnjHqNFgHNGY5S) 2. General settings [VIDEO](https://www.youtube.com/watch?v=NL7lMRXSjf4&list=PLTda9D8MCj4QafXFkFPR_i27CakEUdBeg&index=2) 3. Access manager [VIDEO](https://youtu.be/vi7bEMcnbbs?si=VNgrXGpjTJQg883w) 4. Integrations [VIDEO](https://youtu.be/0DL98lOzBvs?si=W_gspKW5qrwtaHFI) 1. Fuses [VIDEO](https://youtu.be/lHBWjRYRa2o?si=KSPEjUF8NreNIBa9) 2. Substrates [VIDEO](https://youtu.be/zYXwfeUp7Og?si=M9ImdV-Yhdi0LaGp) 1. for the information as to what are the specific substrates for each fuse it is still best to check the test files for a specific fuse. The interface will be improved to include that information directly in the front end. 5. Scheduled operations [VIDEO](https://youtu.be/tfoUAhiKJBA?si=DzLHsI-XT_IZ2dt0) 6. Withdrawals 1. Instant [VIDEO](https://youtu.be/p2WXHJHMMrg?si=I9wW1v-OAu7q0-Yl) 2. Scheduled [VIDEO](https://youtu.be/7Aoke_3iMNQ?si=KSAv_Z4EZ0-eCllH) 7. Fees [VIDEO](https://youtu.be/cZPpg96R9bE?si=gjjBAadAU85hof5P) 8. Price Oracle [VIDEO](https://youtu.be/DiKjA-dQ7GE?si=RC_iTfTMsbZuq6vb) 9. Prehooks - [VIDEO](https://youtu.be/DhtYHEmO4Ek?si=2PSttK-ZnOGeWFi-), [Documentation](https://ipor.io/docs/build-on-fusion/developer-guide/configuring-pre-hooks.md) 10. Price feeds [VIDEO](https://youtu.be/8UZ6Yp512Ng?si=GBDPE9g-DwlOAKOZ) ### Running Alpha This section describes how to set up and run the "Alpha" bot, which interacts with the smart contracts of your vault in the IPOR Fusion protocol. The bot uses the official IPOR Fusion SDK for Python. To run and develop the bot, you will need two main repositories: - IPOR Fusion Python SDK (ipor-fusion.py): This is the official Software Development Kit (SDK) for interacting with the protocol.\ - IPOR Fusion Alpha Example (ipor-fusion-alpha-example): This is a ready-to-run example bot that demonstrates how to use the SDK. This is the best starting point.\ #### How to run the bot as fast as possible 🚀 To run a basic version of the bot in the shortest possible time, follow the steps below using the ipor-fusion-alpha-example repository. Clone the example repository: ``` $ git clone https://github.com/IPOR-Labs/ipor-fusion-alpha-example.git $ cd ipor-fusion-alpha-example ``` Configure environment variables: Copy the .env.example file to a new file named .env. ``` $ cp .env.example .env ``` Then, open the .env file and fill it with your credentials: ``` PROVIDER_URL: Your blockchain node provider URL (e.g., from Infura or Alchemy) PRIVATE_KEY: The private key of your wallet that will manage the vault. PLASMA_VAULT_ADDRESS: The smart contract address of your IPOR Plasma vault. ``` Install project dependencies: Make sure you have Python (version 3.11 or newer) and poetry installed. ``` $ poetry install ``` Run the bot: ``` $ poetry run python main.py ``` The bot will connect to the blockchain network, initialize the connection to your vault, and start executing the default strategy every 60 seconds. #### How to customize the bot for your own strategy? 🛠️ The example bot is designed for easy modification. To implement your own logic: - Edit the main strategy logic: Open the alpha_bot.py file and modify the do_fusion() method. This is where you should place the code for your custom strategy (e.g., conditions for opening/closing positions, flashloan logic, looping). - Change the execution frequency: Open the main.py file and change the interval value in the scheduler section to adjust how often the bot executes its strategy. - Add your own variables: If your strategy requires additional parameters, add them to the .env file and read them in the bot's code (e.g., in alpha_bot.py). #### Where to find information during development? 📖 While creating your own strategy or extending the bot, use the following resources: - Official IPOR Documentation: The main knowledge base about the protocol, smart contracts, and their functions. - SDK Source Code (ipor-fusion.py): Analyzing the SDK's code will help you understand what functions and classes are available under the hood and how to use them. - Example Repository (ipor-fusion-alpha-example): The best source for practical usage patterns of the SDK. #### How to debug? 🐛 Debugging is crucial for creating a stable and secure bot. Here are some recommended methods: - Local Testing with Anvil: The example repository includes a Docker Compose configuration that runs a local blockchain instance (Anvil). This allows you to test interactions with smart contracts without incurring real gas costs. Start the local environment with the command: ``` $ docker-compose up -d ``` The bot will automatically connect to the local Anvil instance. - Unit and Integration Tests: The repository includes a test suite. Run them using poetry run pytest. Write your own tests for new features to ensure they work correctly. - Logging: Add more detailed logs in the do_fusion() method in the alpha_bot.py file using the built-in logging module. This will help you trace what your bot is doing and what decisions it's making step-by-step. - Interactive Debugger: Use a debugger, such as the one built into VS Code or IntelliJ IDA, to set breakpoints in the code and analyze the application's state in real-time. #### Frontend If you would like the vault to be listed on the Fusion frontend, please contact IPOR Labs via Discord ticket. --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/mcp.md # MCP > Connect to the hosted Fusion MCP server: tools, resources, prompts and a worked example for inspecting vaults. ## MCP Model Context Protocol server for IPOR Fusion. Use it to inspect deployed vaults, resolve addresses and research markets from any MCP-capable client (Claude, Cursor, custom agents). This server is **read-only inspection and research** — it does not create or configure vaults. For that, use the Python SDK (see also Deploy your first Fusion vault). ### Connect **Transport:** Streamable HTTP **Server URL:** `https://mcp.ipor.io/mcp` Add it through the MCP settings of your client — do not open the URL as a normal webpage. Quick add (Claude Code): ``` claude mcp add --transport http ipor-fusion https://mcp.ipor.io/mcp ``` Manual `mcpServers` config (Claude Desktop, Cursor, and similar clients): ```json { "mcpServers": { "ipor-fusion": { "url": "https://mcp.ipor.io/mcp" } } } ``` For a locally installed alternative, the same server ships bundled with the Python SDK: [Install the SDK-bundled Fusion MCP server](https://github.com/IPOR-Labs/ipor-fusion.py#mcp-server). ### Tools | Tool | What it does | | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `vault_info(vault_address, chain_id, block_number=0)` | Full on-chain state of a Plasma Vault: asset, TVL, supply cap, fees, managers, fuses, balance fuses, substrates, alpha config, health check. | | `vault_oracle_mapping(vault_address, chain_id, block_number=0)` | Resolves how a vault prices every configured asset, recursing through composed and derived price feeds (Chainlink, ERC4626 share price, Morpho collateral, middleware fallback). | | `vaults_list()` | All IPOR Fusion vaults from the public API: chain, address, name, asset, APY, TVL. | | `fusion_addresses_list(chain_id)` | The full `{contract name: address}` map for one chain, sourced from `ipor-abi`. | | `fusion_address_names(chain_id=0)` | Discover which contract names exist, across all chains or for one chain. | | `fusion_address_lookup(query, chain_id=0)` | Resolve a contract by name (substring) or by address, across all Fusion deployments. | | `market_morpho_blue(market_id, chain_id, block_number=0, no_api=false)` | Inspect a Morpho Blue market: params, on-chain state, borrow/supply APY, supplying MetaMorpho vaults. | | `market_meta_morpho(vault_address, chain_id)` | Inspect a MetaMorpho V1 or Morpho Vault V2: roles, fees, allocations/adapters, per-market caps and headroom. | ### Resources (`fusion://`) | Resource | Contents | | ----------------------- | ------------------------------------------------------------------------------------------------------------ | | `fusion://glossary` | Canonical terms — Atomist, Alpha, Fuse, Plasma Vault, and the rest of the vocabulary used across these docs. | | `fusion://architecture` | How the pieces of a Fusion vault fit together. | | `fusion://invariants` | Common revert selectors and the role table an agent should know before sending a transaction. | | `fusion://quickstart` | The executed vault-deploy walk (also mirrored in the SDK and the Deploy your first Fusion vault page). | ### Prompts | Prompt | Use it to | | ---------------------- | ----------------------------------------------------- | | `quickstart` | Orient a fresh agent to Fusion. | | `deploy_vault` | Walk through creating and configuring a vault. | | `analyze_vault` | Inspect an existing vault's configuration and health. | | `trace_oracle_pricing` | Follow a vault's price-feed chain end to end. | | `explain_fuse` | Explain what a specific Fuse does. | ### Worked example: inspect a vault ```python # 1. Get the vault's full on-chain state vault_info( vault_address="0x...", chain_id=8453, # Base ) # -> asset, total_assets, total_supply, fees, fuses, balance_fuses, substrates, alpha config # 2. Understand how it prices its assets vault_oracle_mapping( vault_address="0x...", chain_id=8453, ) # -> per-asset price source, feed type, and the resolved price for each configured asset ``` Combine the two to answer "what is this vault holding, and can I trust its price feeds?" without reading a single line of source. ### Rules for agents - This server is for deployed-state inspection and research only. - Use the Python SDK for vault creation and transaction construction. - Resolve production addresses through `fusion_address_lookup` / `fusion_addresses_list`, not by guessing or copying from tests. - An address returned here does not, by itself, prove a Fuse or component is compatible with a particular vault, market or strategy. --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/deploy-your-first-fusion-vault.md # Deploy your first Fusion vault > The executed eleven-transaction SDK walk to clone, configure and fund a Fusion vault from scratch. The path from nothing to a vault with a live position is eleven transactions, all signed by the account that will own the vault. There is no shortcut in the SDK: every one of them is mandatory. The MCP invariants resource (`fusion://invariants`) says what reverts when a step is skipped. Copy the walk below and change only the addresses. ### Install ```bash pip install ipor-fusion # SDK (Python 3.10+) curl -L https://foundry.paradigm.xyz | bash && foundryup # anvil, for fork tests anvil --fork-url --chain-id 8453 # then point the SDK at :8545 ``` The hosted read-only server at `https://mcp.ipor.io/mcp` and the bundled `fusion-mcp` server inspect vaults; neither deploys, configures, deposits or executes. Those go through the SDK below. ### The walk: clone, roles, market, access posture, deposit, execute Base, USDC into Aave V3. Executed end to end on a Base fork with this SDK: all eleven transactions land, the vault's idle USDC goes from 0 to the deposit through `deposit()`, and its aToken balance rises after `execute`. Swap the four addresses for another chain or market (see Addresses); keep the order. ```python import os from eth_account import Account from web3 import Web3 from ipor_fusion import ( ERC20, AccessManager, IporFusionMarkets, PlasmaVault, Roles, Web3Context, ) from ipor_fusion.core import FusionFactory from ipor_fusion.fuses import AaveV3SupplyFuse # A Base RPC, or an anvil fork of Base: anvil --fork-url --chain-id 8453 w3 = Web3(Web3.HTTPProvider("http://localhost:8545")) OWNER_PRIVATE_KEY = os.environ["OWNER_PRIVATE_KEY"] # .send() signs locally; .call() previews need no key owner = Account.from_key(OWNER_PRIVATE_KEY).address # owns, configures and operates the vault ctx = Web3Context(w3, chain_id=8453, signer=owner, private_key=OWNER_PRIVATE_KEY) FACTORY_PROXY = "0x1455717668fA96534f675856347A973fA907e922" # IporFusionFactoryProxy, Base USDC = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" SUPPLY_FUSE = "0x26fD6EF391E98C78CfCA27e00c3d15be4D941625" # SupplyFuseAaveV3, Base BALANCE_FUSE = "0xf53f3EaFfDf67539256365cA7299540A98b60BA9" # BalanceFuseAaveV3, Base # 1. Deploy. Clone addresses are CREATE2-deterministic: .call() previews them for # free, .send() with the same arguments creates the vault and its managers. factory = FusionFactory(ctx, FACTORY_PROXY) clone = factory.clone( asset_name="My Vault", asset_symbol="MV", underlying_token=USDC, redemption_delay_seconds=0, owner=owner, ) instance = clone.call(ctx) clone.send(ctx) vault_address = instance.plasma_vault access_manager_address = instance.access_manager # 2. Roles. The clone grants `owner` only OWNER_ROLE. ATOMIST first: it administers the rest. am = AccessManager(ctx, access_manager_address) am.grant_role(Roles.ATOMIST_ROLE, owner, 0).send(ctx) am.grant_role(Roles.FUSE_MANAGER_ROLE, owner, 0).send(ctx) am.grant_role(Roles.ALPHA_ROLE, owner, 0).send(ctx) # 3. Market, in this order: fuses -> substrates -> balance fuse. vault = PlasmaVault(ctx, vault_address) vault.add_fuses([SUPPLY_FUSE]).send(ctx) usdc_substrate = bytes(12) + bytes.fromhex(USDC[2:]) # address right-aligned in bytes32 vault.grant_market_substrates(IporFusionMarkets.AAVE_V3, [usdc_substrate]).send(ctx) vault.add_balance_fuse(IporFusionMarkets.AAVE_V3, BALANCE_FUSE).send(ctx) # 4. Access posture. A fresh clone is private and deposit() reverts until one of these. am.grant_role(Roles.WHITELIST_ROLE, owner, 0).send(ctx) # (a) own bot: whitelist the depositor # vault.convert_to_public_vault().send(ctx) # (b) outside money: ATOMIST-only, one-way # 5. Fund and run the first strategy step. The depositor must already hold the USDC. amount = 1_000 * 10**6 ERC20(ctx, USDC).approve(vault_address, amount).send(ctx) vault.deposit(amount, owner).send(ctx) vault.execute([AaveV3SupplyFuse(SUPPLY_FUSE).supply(asset=USDC, amount=amount)]).send(ctx) ``` Notes on the walk: - `clone` versus `clone_supervised`: same arguments; the supervised variant is gated by a maintenance role. Use `clone`. - The balance fuse above is the `BalanceFuseAaveV3` entry of the registry for Base and is verified working on a fresh clone. Vaults already in production may register a different one for the same market; to match them, read `PlasmaVault(ctx, address).get_balance_fuses()` on such a vault. - Substrate layouts are market-specific. For Aave V3 the substrate is the asset address right-aligned in 32 bytes; other markets use typed layouts, decoded by `ipor_fusion.substrates` and documented in the fuse libraries of the [contracts repository](https://github.com/IPOR-Labs/ipor-fusion). - Give the bot its own key: grant `ALPHA_ROLE` to the bot's address instead of `owner`, and keep the owner key offline. ### Creation is not configuration Creating a vault deploys the Fusion vault infrastructure; it does not make the vault strategy-ready. See Vault configuration step-by-step for the full configuration surface (price oracle, scheduled withdrawals, fees, and more) beyond the minimal market setup shown above. ### Pointers - Factory proxy addresses for every supported chain: Addresses - Fuse addresses by name and chain: [`ipor-abi`](https://github.com/IPOR-Labs/ipor-abi), or the hosted MCP server's `fusion_address_lookup` - The SDK runs this exact walk in one `eth_simulateV1` batch: `tests/test_simulate_vault_from_scratch_base.py` in [`ipor-fusion.py`](https://github.com/IPOR-Labs/ipor-fusion.py) - A strategy bot that operates an existing vault: [`ipor-fusion-alpha-example`](https://github.com/IPOR-Labs/ipor-fusion-alpha-example) --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/addresses.md # Addresses > Canonical IporFusionFactoryProxy addresses per chain, verified against the ipor-abi registry. Canonical per-chain deployment addresses for the IPOR Fusion vault factory. This table is the source you should resolve `IporFusionFactoryProxy` from before following Deploy your first Fusion vault — never hardcode an address from a test or an example without checking it here first. ### Factory proxies per chain `clone()` goes to the proxy column. The implementation column is listed only so you recognise and avoid it — calling it directly reverts `DaoFeePackagesArrayEmpty()`. Verify against [`ipor-abi`](https://github.com/IPOR-Labs/ipor-abi) before use; the registry is the source of truth and is regenerated on release. | Chain | Chain id | `IporFusionFactoryProxy` (use) | `IporFusionFactoryImpl` (reverts) | Verified | | --------- | -------- | -------------------------------------------- | -------------------------------------------- | ------------------------ | | Ethereum | 1 | `0xcd05909C4A1F8E501e4ED554cEF4Ed5E48D9b852` | `0xf19C1E9f6616F6056AF1e322A86fDaAaAf0263f5` | implementation slot | | Unichain | 130 | `0xC9b4E839e86284C558791C13Bda97999fc49aF63` | `0xf5Bc40C192D51ED93ADD6557884766772FA72589` | implementation slot | | TAC | 239 | `0x26b5561E2E0e7d7977431E92740903Ef3cB7194b` | `0x7DDd0bBB59eFB4b7791cE5E1Cf1587F083aE4Ef5` | implementation slot | | Botanix | 3637 | `0x7c9857f22D0cc6523C8e88BFDCbf411AB8300fF5` | `0xddb0EFB2a7a5C02e01b5A1f85C0a1110d68EeC26` | registry only | | Base | 8453 | `0x1455717668fA96534f675856347A973fA907e922` | `0x610152A79BE7F2Aa3aA70520c9331c18fe8D33b7` | clone executed on a fork | | Plasma | 9745 | `0x70d41759FBF90fB63c88197217cB08F93a1c65CB` | `0x3A42bD6fEa94421025Ae2ed01CE6f137ac785abD` | implementation slot | | Arbitrum | 42161 | `0x134fCAce7a2C7Ef3dF2479B62f03ddabAEa922d5` | `0x87f94ac9aF79261F0BC73582114f805F55Cd0b25` | clone executed on a fork | | Avalanche | 43114 | `0xa00b6379833D77fA9C9497b32dae00dF39Ac751e` | `0x399596cFccFEbBb60f8652bece8586a6Bb4199ab` | implementation slot | | Ink | 57073 | `0xEC53f69Bd1D991a2F99e96DE66E81D0E42A61D8D` | `0xe7372BC46b79e0c87AfE5286c41c20687018E425` | implementation slot | | Katana | 747474 | `0xc29b8D591d6a3f109Ca7ba384F2e00162866D37B` | `0x4a4De6e86AD0d0546F55B595cA75f55803D940bA` | registry only | "Implementation slot" means the proxy's EIP-1967 implementation slot was read and matches the registry's `IporFusionFactoryImpl`; "registry only" means the pair was taken from `ipor-abi` without an on-chain read. ### Fuse addresses Fuse addresses are not in this table — they are market- and chain-specific (for example `SupplyFuseAaveV3` and `BalanceFuseAaveV3` on Base). Resolve them by registry name and chain in [`ipor-abi`](https://github.com/IPOR-Labs/ipor-abi), or with the hosted MCP server's `fusion_address_lookup(name, chain_id=...)`. The SDK class for a registry name swaps the parts: `SupplyFuseAaveV3` is `AaveV3SupplyFuse`. --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/common-errors.md # Common Errors > Revert selectors and the role table for the errors most likely to block a Fusion vault deployment. Revert selectors and setup errors an agent or developer is likely to hit while deploying or operating a Fusion vault (see Deploy your first Fusion vault), with the cause and the fix for each. Same table as `fusion://invariants` on the MCP server and the SDK README, kept in sync with both. ### Revert table | Selector | Revert | What happened | Fix | | ----------------------------------------------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `0x8745fbfd` | `DaoFeePackagesArrayEmpty()` | `clone()` was sent to `IporFusionFactoryImpl` | Send it to `IporFusionFactoryProxy` for that chain — see Addresses | | `0x9996b315` | `AddressEmptyCode(address)` | `execute()` touched a market with no balance fuse | `add_balance_fuse(market_id, balance_fuse)` before the first `execute` on that market | | `0x068ca9d8` | `AccessManagedUnauthorized(address)` | The caller lacks the role the function requires: `FUSE_MANAGER` for `add_fuses`, `grant_market_substrates`, `add_balance_fuse`; `ALPHA` for `execute`; `WHITELIST` for `deposit` and `mint` on a private vault | `AccessManager.grant_role(role, account, 0)` from the role's admin (`OWNER` grants `ATOMIST`, `ATOMIST` grants the rest); for a reverting `deposit`, whitelist the depositor or convert the vault to public | | `ValueError: Private key required for sending transactions` | SDK, before any transaction | `.send()` on a `Web3Context` without a key | `Web3Context(w3, chain_id, signer=..., private_key=...)` or `Web3Context.from_url(url, private_key=...)` | ### Role table | Role | ID | Grants | Granted by | | ------------------- | --- | ---------------------------------------------------------------------------------- | -------------------------------------------- | | `OWNER_ROLE` | 1 | Everything below, via the access manager | Set at vault creation (the `clone()` caller) | | `ATOMIST_ROLE` | 100 | Vault configuration authority; administers `FUSE_MANAGER`, `ALPHA` and `WHITELIST` | `OWNER` | | `ALPHA_ROLE` | 200 | Can call `execute` | `ATOMIST` | | `FUSE_MANAGER_ROLE` | 300 | Can call `add_fuses`, `grant_market_substrates`, `add_balance_fuse` | `ATOMIST` | | `WHITELIST_ROLE` | 800 | Can `deposit` / `mint` into a private vault | `ATOMIST` | A fresh clone grants the owner only `OWNER_ROLE` — every configuration and `execute` call from that account reverts `AccessManagedUnauthorized` until `ATOMIST_ROLE` is granted first (it administers the rest), matching step 2 of Deploy your first Fusion vault. ### Related invariants - Clone from `IporFusionFactoryProxy`, never from `IporFusionFactoryImpl` — only the proxy carries the fee configuration. - Register all three of `add_fuses`, `grant_market_substrates` and `add_balance_fuse` before the first `execute` on a market. Any order between them works; what is not optional is that all three precede `execute`. - A fresh clone is private: `deposit` and `mint` revert until either the depositor holds `WHITELIST_ROLE` (keeps the vault private) or an Atomist calls `convert_to_public_vault()` (opens deposits to every address, and cannot be reverted). - Fuses are immutable and addresses are per chain — resolve `(chain, name)` in [`ipor-abi`](https://github.com/IPOR-Labs/ipor-abi); never reuse an address across chains. --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/smart-contracts.md # Smart Contracts > DeepWiki-hosted architecture reference for the ipor-fusion smart contracts. An AI-generated documentation based on the IPOR Labs GitHub repository is available on [DeepWiki](https://deepwiki.com/IPOR-Labs/ipor-fusion). --- Source: https://ipor.io/docs/build-on-fusion/integrating-a-new-market.md # Integrating a New Market > Add a protocol to IPOR Fusion as a new market, whether it is your own protocol or one you integrate for another team: write and deploy the fuses, open a market id pull request, and IPOR reviews the fuses for the Fuse Whitelist Registry. This section is for you if you want IPOR Fusion vaults to be able to use a protocol (a lending market, a DEX, a yield vault) that Fusion does not support yet. It may be your own protocol, or one you integrate for another team. You write the fuses in your own repository and deploy them. IPOR does not write or deploy them for you; the IPOR team reviews the deployed fuses and adds them to the Fuse Whitelist Registry. ## Why integrate a protocol - **Every Fusion vault can use the protocol.** Once your fuses are deployed, any atomist on that chain can add them to a vault and allocate deposits to the protocol, without waiting for IPOR to build the integration. - **Vaults using your fuses show on the IPOR frontend without warnings.** After the whitelist review, your fuses are listed in the Fuse Whitelist Registry and in [Fusion Terminal](https://app.ipor.io/fusion-terminal/fuse-whitelist/ethereum/fuses). IPOR is adding warnings for vaults that use fuses outside the registry; vaults that use only whitelisted fuses are shown without them. ## When an existing fuse is enough If the protocol exposes an ERC4626 vault, an existing fuse may already cover it. The generic [`Erc4626SupplyFuse`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626SupplyFuse.sol) is a fuse for ERC4626 vaults whose addresses an atomist grants as substrates of the market. Check that the vault behaves as that fuse expects; for example, at commit `632350d` `exit` does nothing when the vault reports a `maxWithdraw` of `0` (see [Developing a Fuse](https://ipor.io/docs/build-on-fusion/developer-guide/developing-a-fuse.md)). In that case you do not write or deploy a fuse: an atomist grants that vault as a substrate of an ERC4626 market of the vault that uses the deployed `Erc4626SupplyFuse`, after checking the exceptions above. In that case no market id pull request and no whitelist review are needed, because the whitelist review applies to new fuses. Use this section when no existing fuse covers the protocol. ## What a full market contains A market integration is more than one action fuse. It is a market id, the action fuses, a balance fuse that values the position, the encoding of the [substrates](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/substrates.md), and the price feeds the valuation needs. Optional parts are instant withdraw, claim fuses and a dependency balance graph. [What a Market Integration Contains](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/market-components.md) describes each part. [Coding Standard](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/coding-standard.md) and [Security Requirements](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/security-requirements.md) describe what the deployed code is expected to look like. [Whitelist Review](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/whitelist-review.md) describes the pull request, the review request and what happens after them. ## The six steps 1. **Develop the fuse family in your own repository.** Licensing of your code is your choice. Deployed fuses cannot be changed, so settle the design before you deploy. 2. **Open a pull request to [`IPOR-Labs/ipor-fusion`](https://github.com/IPOR-Labs/ipor-fusion) and get the market id confirmed.** The pull request adds only the market id constant with a description of the market substrates. Its description links to the repository where the code of your fuses is maintained and, if the documentation is kept outside that repository, to the documentation. Third-party markets use ids from 400_001 to 400_999. Use the next free number in that range (check `IporFusionMarkets.sol` on `main` and the open pull requests for constants already taken); the IPOR team confirms it in the pull request. Wait for that confirmation before you deploy: `MARKET_ID` is immutable, so fuses deployed with a different id must be redeployed. 3. **Deploy on each chain with the confirmed id and verify the sources.** Deploy the fuses on the chains you need and verify the source code of every fuse in the block explorer of each chain (for example Etherscan or Basescan). The review needs the verified source. Then add the deployed addresses to the pull request. 4. **Request the whitelist review on Discord.** Open a ticket in the [IPOR Discord](https://discord.com/invite/bSKzq6UMJ3) and send the IPOR team the link to your pull request and, for every deployed fuse, the link to its verified source in the block explorer of its chain (for example Etherscan or Basescan). The ticket is your request for the whitelist review; the pull request alone does not start it. 5. **Review.** The IPOR team reviews the deployed, verified code before adding the fuses to the Fuse Whitelist Registry. The outcome is an entry in the registry or a request for changes in the pull request. 6. **Configure in vaults.** After the registry entry the fuses are visible in the registry and in [Fusion Terminal](https://app.ipor.io/fusion-terminal/fuse-whitelist/ethereum/fuses) (the link opens the Ethereum list). Atomists (the administrators of a vault, see [What is an Atomist?](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-atomist.md)) then add the fuses to their vaults and configure them. > **Warning:** Deployed fuses cannot be changed: a fix or a new version means a new deployment with new addresses. The market id stays the same, so no new pull request is needed; send the new addresses and their verified sources to the IPOR team in a ticket in the [IPOR Discord](https://discord.com/invite/bSKzq6UMJ3) for review. Vaults already using the old address must migrate. > **Note:** The Fuse Whitelist Registry is a reference list for Fusion Terminal and atomists; it is not enforced on-chain, and a vault can add any fuse address. ## Before you request the review - The fuses are deployed and their sources verified in the block explorer of each chain you support. See [What a Market Integration Contains](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/market-components.md). - The code follows the [Coding Standard](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/coding-standard.md). Tests and fork-test results at a pinned block are recommended, not required. - The risks of the venue and the consequences of the substrate configuration are described in the repository of your fuses. See [Security Requirements](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/security-requirements.md). - The market id was confirmed by the IPOR team in your pull request before you deployed, and the pull request lists the deployed addresses. See [Whitelist Review](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/whitelist-review.md). --- Source: https://ipor.io/docs/build-on-fusion/integrating-a-new-market/market-components.md # What a Market Integration Contains > The components of a new market integration: action fuses, a balance fuse, claim fuses, a substrate library, price feeds and a market id, with the reference families to copy from. A market integration is a family of contracts that you write in your own repository and deploy yourself. This page lists the components, the interface each one implements, and what must be checkable on-chain. For the process around them, start with the [overview](https://ipor.io/docs/build-on-fusion/integrating-a-new-market.md). For the coding rules, see the [coding standard](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/coding-standard.md) and [security requirements](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/security-requirements.md). For how a single fuse is built, see [Developing a Fuse](https://ipor.io/docs/build-on-fusion/developer-guide/developing-a-fuse.md). Two families in the Fusion repository show the pattern, as read at commit `632350d`: [`contracts/fuses/erc4626`](https://github.com/IPOR-Labs/ipor-fusion/tree/main/contracts/fuses/erc4626) is the simple one (a supply fuse and a balance fuse), and [`contracts/fuses/aave_v4`](https://github.com/IPOR-Labs/ipor-fusion/tree/main/contracts/fuses/aave_v4) is a full lending market (supply, borrow and collateral fuses, a balance fuse, a substrate library, a README and tests). ## Components at a glance | Component | Interface | Required | Reference | | -------------------------- | ------------------------------------- | ------------------------------------------------------------ | ----------------------------------------- | | Action fuses (enter, exit) | `IFuseCommon` | Yes | `Erc4626SupplyFuse`, `AaveV4SupplyFuse` | | Instant withdraw | `IFuseInstantWithdraw` | Optional | `Erc4626SupplyFuse`, `AaveV4SupplyFuse` | | Transient variants | `enterTransient()`, `exitTransient()` | Optional | `Erc4626SupplyFuse` | | Balance fuse | `IMarketBalanceFuse` | Yes, or `ZeroBalanceFuse` | `Erc4626BalanceFuse`, `AaveV4BalanceFuse` | | Claim fuse | none specific | Optional | `MorphoClaimFuse` | | Substrate library | none specific | When a substrate carries more than an address | `AaveV4SubstrateLib` | | Price feed | `IPriceFeed` | When the middleware has no price source for an asset | none specific | | Market id | constant in `IporFusionMarkets` | Yes | none specific | | README | none | Yes, covering the market, the substrates and the venue risks | `aave_v4/README.md` | ## Action fuses An action fuse moves the vault into or out of a position. An action fuse is typically named `Fuse`, such as `AaveV4SupplyFuse`, with one contract per file and the file named after the contract. The fuse implements [`IFuseCommon`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/IFuseCommon.sol#L5-L9), which has one function, `MARKET_ID()`. The vault engine itself requires only that function: it reads `MARKET_ID()` from the fuse and delegatecalls the encoded call, so the action functions are reached by the [Alpha](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-alpha.md) (the role that executes strategy transactions on the vault) through the call data of a `FuseAction`. A vault runs only fuses that were added to it; any other address reverts with `UnsupportedFuse`. The reference families do not implement `IFuse`, which declares `enter(bytes)` and `exit(bytes)`. They expose typed functions instead, for example `enter(Erc4626SupplyFuseEnterData)` and `exit(AaveV4SupplyFuseExitData)`. > **Note:** The ERC4626 example is the shortest one to read, but it is not a model for every requirement. It does not reject market id `0` in the constructor (the guard is shown on `AaveV4SupplyFuse`), and it does not set the allowance back to zero after approving (shown on `AguaSupplyFuse`). Its `enter`, `exit` and transient functions have no NatSpec; the Aave V4 fuses show the expected level. ### Instant withdraw Implementing [`IFuseInstantWithdraw`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/IFuseInstantWithdraw.sol#L4-L13) is optional. An action fuse that implements it exposes `instantWithdraw(bytes32[] params)`, where `params[0]` is the amount in the underlying asset and the following params are specific to the fuse. The layouts differ per family: ERC4626 uses `params[1]` as the vault address; Aave V4 uses `params[1]` to `params[4]` for asset, spoke, reserve id and a reserved slot. During a user withdrawal the vault sets `params[0]` to the amount still needed and delegatecalls `instantWithdraw` on each configured fuse in order, until the amount still needed is covered. The call is not wrapped in `try/catch`, so a revert inside it reverts the user withdrawal. This is why the reference fuses catch only the venue withdraw call on this path and report a failure with an event. In the ERC4626 example the catch covers only `vault.withdraw`: the substrate check and the `maxWithdraw` read are not caught, and `instantWithdraw` passes `maxSharesBurned = 0`, which switches the burned-shares limit off on that path. A zero requested or clamped amount returns `0` without an event. ### Transient variants `enterTransient()` and `exitTransient()` read their inputs from `TransientStorageLib`, keyed by the fuse `VERSION`, call the same logic, and write the outputs back to transient storage. Both reference families provide them. ## Balance fuse Every market needs a balance fuse, because the vault engine asks it for the market balance. It implements [`IMarketBalanceFuse`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/IMarketBalanceFuse.sol#L4-L10): `balanceOf()` returns the balance of the vault in the market in USD with 18 decimals (WAD). Use this exact signature. The interface does not declare `balanceOf()` as `view`; the reference implementations declare it `view`. You may declare it `view`, as the reference implementations do. The vault calls it by delegatecall in the context of the vault and does not catch a revert, so a reverting balance fuse blocks the balance update. The fuse reads its substrates with `PlasmaVaultConfigLib.getMarketSubstrates(MARKET_ID)`, prices each asset through the Price Oracle Middleware and converts the result to WAD. An atomist registers it with `addBalanceFuse(marketId, fuse)`, which reverts with `BalanceFuseMarketIdMismatch` if the fuse `MARKET_ID()` differs from the market id. ### ZeroBalanceFuse [`ZeroBalanceFuse`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/ZeroBalanceFuse.sol#L6-L26) always returns `0` and takes the market id in its constructor. Use it only for a market whose fuse holds no assets and creates no separate position of its own, with the position valued on another market through a dependency graph. The LitePSM market works this way: it holds nothing itself, the sUSDS position is valued on a separate market, and a dependency graph links the two. Never use it for a position you cannot value, because it hides the position from the vault balance. You deploy it from the unchanged Fusion source with your own market id. It has `MARKET_ID` but no `VERSION` and does not reject market id `0`; those requirements apply to the fuses you write. ## Prices The balance fuse prices assets through the [Price Oracle Middleware](https://ipor.io/docs/build-on-fusion/developer-guide/price-oracle-middleware.md), which returns USD prices with 18 decimals. For an asset with no registered source the middleware falls back to a Chainlink feed registry if one is configured, and otherwise reverts; it also reverts for a price that is zero or negative. A vault created by the Fusion factory reads prices through its own Price Oracle Middleware Manager: the vault's price-manager role sets a source per asset there with `setAssetsPriceSources(assets, sources)`, and an asset without a vault-specific source falls back to the shared middleware, whose owner registers sources with `setAssetsPricesSources(assets, sources)`. A balance fuse that prices an asset neither of them can price reverts. If an asset needs a custom source, implement [`IPriceFeed`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/price_oracle/price_feed/IPriceFeed.sol#L4-L23) (`decimals()` and `latestRoundData()`). The middleware reads the feed's decimals and price, so report decimals correctly. A third-party feed must not be manipulable within one transaction. ## Substrates A [substrate](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/substrates.md) is a `bytes32` value that an atomist grants to a market; fuses check substrates before moving funds. Plain address substrates are checked with `isSubstrateAsAssetGranted`, other encodings with `isMarketSubstrateGranted`. When a substrate carries more than an address, put the encoding and decoding in a substrate library, as [`AaveV4SubstrateLib`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/aave_v4/AaveV4SubstrateLib.sol#L44-L64) does: a type flag in the top byte, then the fields, with reserved bits that must be zero. It looks permissions up in constant time and rejects non-canonical words, so a hand-encoded word that does not match the canonical encoding never grants anything. Aave V4 uses one market id for all Spokes; the substrates select the Spoke and the reserve. ## Claim fuses If the venue pays out rewards, add a claim fuse. In the Fusion repository, claim fuses live in `contracts/rewards_fuses//`; in your repository the location is your choice. A claim fuse is registered in the vault's `RewardsClaimManager` with `addRewardFuses` (fuse manager role), not with the vault's `addFuses`. The claim role calls `RewardsClaimManager.claimRewards`, which reverts with `FuseUnsupported` for a fuse that is not registered there and then calls `PlasmaVault.claimRewards`, which delegatecalls the fuse; the fuse forwards the claimed rewards to the `RewardsClaimManager`. As [`MorphoClaimFuse`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/rewards_fuses/morpho/MorphoClaimFuse.sol#L66-L105) does, it checks that the distributor is granted as a substrate before claiming and exposes `VERSION` and `MARKET_ID`. ## Market id Third-party markets use ids from 400_001 to 400_999. Use the next free number in that range; the IPOR team confirms it in the pull request. The id is added as one constant in [`IporFusionMarkets`](https://github.com/IPOR-Labs/ipor-fusion/blob/main/contracts/libraries/IporFusionMarkets.sol), the library where Fusion markets are listed and described. Every fuse must expose `MARKET_ID()`, because when a fuse is added the Fuse Whitelist Registry reads `MARKET_ID()` inside `try/catch`, and a fuse without it is silently skipped for the per-market list. `MARKET_ID` is immutable, so a fuse deployed with an id that changes later must be redeployed. ## Dependency balance graphs When one action changes the balance of two markets, for example the vault's own token holdings (the `ERC20_VAULT_BALANCE` market) and your market, the markets need a [dependency balance graph](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/dependency-graphs.md). The atomist sets it with `updateDependencyBalanceGraphs(marketIds, dependencies)`. A call overwrites the dependencies of each listed market, and dependencies are directional. When a market balance is refreshed, the markets it depends on are refreshed in the same update. Describe the graph your market needs in the pull request. ## What must be verifiable on-chain The IPOR team reviews the code that is deployed, so the following must be checkable from the chain: - The source of every fuse is verified in the block explorer of its chain, and the verified source carries the exact compiler settings of the deployment (see the [coding standard](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/coding-standard.md)). - `VERSION()` returns the fuse's own address, `MARKET_ID()` equals the constant from the pull request, and the constructor arguments are the ones listed in the pull request. - The fuse has no storage variables other than ERC-7201 namespaced slots, and no roles, owner, admin keys, pause or upgrade mechanism; it is not a proxy. - On every chain you use the same source code and the same compiler settings. The runtime bytecode can still differ, because immutable values (`VERSION`, `MARKET_ID`, venue addresses) are written into it. List these expected differences, and any other difference such as a different compiler or EVM version, in the pull request. Deployed fuses cannot be changed: a fix or a new version means a new deployment with new addresses. The market id stays the same, so no new pull request is needed; send the new addresses and their verified sources to the IPOR team in a ticket in the [IPOR Discord](https://discord.com/invite/bSKzq6UMJ3) for review. Vaults already using the old address must migrate. ## README in your repository Keep a README next to the fuses. It describes the market, the substrates and the venue risks (see [Security Requirements](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/security-requirements.md)). A good one follows the sections of the [Aave V4 README](https://github.com/IPOR-Labs/ipor-fusion/blob/main/contracts/fuses/aave_v4/README.md): overview, market structure, key components, substrate configuration with the validation matrix, operations, balance calculation, security considerations, price oracle setup and tests. Link it from the pull request; see [Whitelist Review](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/whitelist-review.md). --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/developing-a-fuse.md # Developing a Fuse > Anatomy of an action fuse and its balance fuse, shown on the ERC4626 supply fuse: data structs, enter, exit, transient variants, instant withdraw, events and errors. > **Note:** If you are integrating a new market, start with [Integrating a New Market](https://ipor.io/docs/build-on-fusion/integrating-a-new-market.md). It describes the whole process and the rules for the fuses you write. This page explains how a single fuse is built. A fuse is a small stateless contract that the vault runs by `delegatecall`. This page walks through the generic ERC4626 fuses of the public [`IPOR-Labs/ipor-fusion`](https://github.com/IPOR-Labs/ipor-fusion) repository, read at commit `632350d`: [`Erc4626SupplyFuse`](https://github.com/IPOR-Labs/ipor-fusion/blob/main/contracts/fuses/erc4626/Erc4626SupplyFuse.sol) (an action fuse) and [`Erc4626BalanceFuse`](https://github.com/IPOR-Labs/ipor-fusion/blob/main/contracts/fuses/erc4626/Erc4626BalanceFuse.sol) (its balance fuse). Excerpts are short and link to the exact lines. Where the example differs from what the [Coding Standard](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/coding-standard.md) asks of new fuses, this page says so. ## The shape of an action fuse An action fuse moves the vault into or out of a position on an external venue. The [Alpha](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-alpha.md) (the role that executes strategy transactions on the vault) runs it through `PlasmaVault.execute`. The vault runs the call only for a fuse address that was added to that vault with `addFuses(address[])`, reads `MARKET_ID()` from the fuse and then delegates the encoded call. Because of the `delegatecall`, `address(this)` inside the fuse is the vault, and storage reads see the vault's storage. ```solidity contract Erc4626SupplyFuse is IFuseCommon, IFuseInstantWithdraw { ``` Source: [`Erc4626SupplyFuse.sol#L37`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626SupplyFuse.sol#L37) `IFuseCommon` has one function, `MARKET_ID()`. `IFuseInstantWithdraw` is optional. The reference fuses do not implement `IFuse` (`enter(bytes)` and `exit(bytes)`); they expose typed functions, such as `enter(Erc4626SupplyFuseEnterData)`. The contract holds two immutables, and nothing else is stored: ```solidity address public immutable VERSION; uint256 public immutable MARKET_ID; constructor(uint256 marketId_) { VERSION = address(this); MARKET_ID = marketId_; } ``` Source: [`Erc4626SupplyFuse.sol#L81-L87`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626SupplyFuse.sol#L81-L87) - `VERSION` is the address of the fuse contract itself, not of the vault. It is the first parameter of every event and the key of the transient storage. - `MARKET_ID` identifies the market the fuse belongs to. It is immutable, so a fuse deployed with a wrong id must be redeployed. This constructor does not reject `marketId_ == 0`. IPOR requires new fuses to do so, because the vault engine uses market id `0` as an empty slot. The guard is shown on `AaveV4SupplyFuse`: ```solidity /// @notice Constructor for AaveV4SupplyFuse /// @param marketId_ The Market ID associated with the Fuse constructor(uint256 marketId_) { if (marketId_ == 0) { revert AaveV4SupplyFuseInvalidMarketId(); } VERSION = address(this); MARKET_ID = marketId_; } ``` Source: [`AaveV4SupplyFuse.sol#L123-L131`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/aave_v4/AaveV4SupplyFuse.sol#L123-L131) ## Data structs `enter` and `exit` take a struct, so the Alpha encodes the call data once and the fuse decodes it without manual parsing. ```solidity /// @notice Data structure for entering - supply - the ERC4626 vault struct Erc4626SupplyFuseEnterData { /// @dev ERC4626 vault address address vault; /// @dev amount to supply, this is amount of underlying asset in the given ERC4626 vault uint256 vaultAssetAmount; /// @dev minimum amount of shares expected to receive from the deposit uint256 minSharesOut; } ``` Source: [`Erc4626SupplyFuse.sol#L15-L23`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626SupplyFuse.sol#L15-L23) ```solidity /// @notice Data structure for exiting - withdrawing - the ERC4626 vault struct Erc4626SupplyFuseExitData { /// @dev ERC4626 vault address address vault; /// @dev amount to withdraw, this is amount of underlying asset in the given ERC4626 vault uint256 vaultAssetAmount; /// @dev maximum number of vault shares that can be burned during the withdraw, 0 means no limit uint256 maxSharesBurned; } ``` Source: [`Erc4626SupplyFuse.sol#L25-L33`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626SupplyFuse.sol#L25-L33) Both structs carry a caller-supplied limit: `minSharesOut` on enter and `maxSharesBurned` on exit, where `0` means no limit. ## enter `enter` returns early, without an event, when the requested amount is `0`. Next it checks that the vault is a granted substrate of the market: ```solidity if (!PlasmaVaultConfigLib.isSubstrateAsAssetGranted(MARKET_ID, data_.vault)) { revert Erc4626SupplyFuseUnsupportedVault("enter", data_.vault); } ``` Source: [`Erc4626SupplyFuse.sol#L94-L96`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626SupplyFuse.sol#L94-L96) The substrates of this fuse are the addresses of the ERC4626 vaults the atomist allowed. The check comes before any approval or deposit. Then `enter` limits the amount to the asset balance of the vault, again returning `0` without an event if nothing is left, and moves the funds: ```solidity ERC20(underlyingAsset).forceApprove(data_.vault, finalVaultAssetAmount); uint256 shares = IERC4626(data_.vault).deposit(finalVaultAssetAmount, address(this)); if (shares < data_.minSharesOut) { revert Erc4626SupplyFuseInsufficientShares(shares, data_.minSharesOut); } emit Erc4626SupplyFuseEnter(VERSION, underlyingAsset, data_.vault, finalVaultAssetAmount); ``` Source: [`Erc4626SupplyFuse.sol#L109-L117`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626SupplyFuse.sol#L109-L117) In this excerpt, `underlyingAsset` is the asset of the ERC4626 vault and `finalVaultAssetAmount` is the requested amount limited to the balance of the vault. The fuse approves exactly the amount it deposits, deposits to `address(this)` (the vault), reverts with `Erc4626SupplyFuseInsufficientShares` when fewer shares than `minSharesOut` are received and emits the event with the amount that was actually supplied. This example does not set the allowance back to zero after the deposit. IPOR requires new fuses to do that; the pattern is shown on `AguaSupplyFuse` (`forceApprove(vault, amount)`, deposit, `forceApprove(vault, 0)`). ## exit `exit` and `instantWithdraw` share one internal function, `_exit`. It does the following: - returns `0` without an event when the requested amount is `0`; - reverts with `Erc4626SupplyFuseUnsupportedVault` when the vault is not a granted substrate, on the instant-withdraw path too; - limits the amount to `maxWithdraw(address(this))` of the vault, and returns `0` without an event when that is `0`. A zero `maxWithdraw` is therefore a silent no-op: it is neither a revert nor a failure event. The `maxWithdraw` read is not inside a `try` block, so a revert of that call propagates. When called as `exit`, the Alpha decides the limit: a non-zero `maxSharesBurned` makes the fuse revert with `Erc4626SupplyFuseExcessiveSharesBurned` if more shares were burned. A failed vault `withdraw` is not caught on this path either, so the whole action reverts. ## Transient variants `enterTransient()` and `exitTransient()` take no arguments. They read their inputs from transient storage under the key `VERSION`, call the same `enter` or `exit` logic and write the result back to transient storage. ```solidity function enterTransient() external { bytes32[] memory inputs = TransientStorageLib.getInputs(VERSION); address vault = TypeConversionLib.toAddress(inputs[0]); uint256 amount = TypeConversionLib.toUint256(inputs[1]); uint256 minSharesOut = TypeConversionLib.toUint256(inputs[2]); uint256 suppliedAmount = enter(Erc4626SupplyFuseEnterData({vault: vault, vaultAssetAmount: amount, minSharesOut: minSharesOut})); bytes32[] memory outputs = new bytes32[](1); outputs[0] = TypeConversionLib.toBytes32(suppliedAmount); TransientStorageLib.setOutputs(VERSION, outputs); } ``` Source: [`Erc4626SupplyFuse.sol#L120-L131`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626SupplyFuse.sol#L120-L131) `exitTransient` follows the same pattern with `maxSharesBurned` as the third input. ## instantWithdraw `instantWithdraw` is optional. The vault calls it when a user withdrawal needs more assets than the vault holds, for every fuse configured with `configureInstantWithdrawalFuses`, in the configured order, until the missing amount is covered. The first parameter is always the amount in the underlying asset; the other parameters belong to the fuse. For the ERC4626 fuse `params[1]` is the vault address: ```solidity /// @dev params[0] - amount in underlying asset, params[1] - vault address function instantWithdraw(bytes32[] calldata params_) external override { uint256 amount = uint256(params_[0]); address vault = PlasmaVaultConfigLib.bytes32ToAddress(params_[1]); _exit(Erc4626SupplyFuseExitData(vault, amount, 0), true); } ``` Source: [`Erc4626SupplyFuse.sol#L150-L157`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626SupplyFuse.sol#L150-L157) The vault does not wrap this call in `try`/`catch`, so a revert inside `instantWithdraw` reverts the user withdrawal. That is why the example catches the one call that can fail because of the venue, the vault `withdraw`, and reports the failure with an event instead: ```solidity if (catchExceptions_) { try IERC4626(vault_).withdraw(finalVaultAssetAmount_, address(this), address(this)) returns ( uint256 shares_ ) { if (maxSharesBurned_ > 0 && shares_ > maxSharesBurned_) { revert Erc4626SupplyFuseExcessiveSharesBurned(shares_, maxSharesBurned_); } shares = shares_; emit Erc4626SupplyFuseExit(VERSION, IERC4626(vault_).asset(), vault_, finalVaultAssetAmount_, shares); } catch { /// @dev if withdraw failed, continue with the next step emit Erc4626SupplyFuseExitFailed(VERSION, IERC4626(vault_).asset(), vault_, finalVaultAssetAmount_); } ``` Source: [`Erc4626SupplyFuse.sol#L186-L198`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626SupplyFuse.sol#L186-L198) Three things to note about this example: - Only the vault `withdraw` is inside `try`. The substrate check and the `maxWithdraw` read in `_exit`, and the `asset()` reads for the events in both branches, are outside the `catch`, so this path can still revert. The `Erc4626SupplyFuseExcessiveSharesBurned` check cannot fire here, because `instantWithdraw` passes `maxSharesBurned = 0`. - `instantWithdraw` passes `maxSharesBurned = 0`, so on the automatic instant-withdraw path the limit on burned shares is off. This differs from `exit`, where the Alpha can set a limit. - A failed withdraw emits `Erc4626SupplyFuseExitFailed` and continues; a zero amount or a zero `maxWithdraw` returns `0` without any event. ## Events and errors Events carry the fuse `VERSION` as the first parameter and are named with the fuse name as prefix. Errors are custom errors with the same prefix. The example declares no `indexed` parameters; IPOR requires the same of new fuses. ```solidity event Erc4626SupplyFuseEnter(address version, address asset, address vault, uint256 vaultAssetAmount); ``` Source: [`Erc4626SupplyFuse.sol#L46`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626SupplyFuse.sol#L46) ```solidity error Erc4626SupplyFuseUnsupportedVault(string action, address asset); ``` Source: [`Erc4626SupplyFuse.sol#L69`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626SupplyFuse.sol#L69) The enter event reports the amount after limiting it to the available balance, so it shows what happened and not only what was requested. The example also declares `Erc4626SupplyFuseExit`, `Erc4626SupplyFuseExitFailed`, `Erc4626SupplyFuseInsufficientShares` and `Erc4626SupplyFuseExcessiveSharesBurned`. The NatSpec on the `enter`, `exit` and transient functions of this example is minimal; the Aave V4 fuses show the level of NatSpec described in the [Coding Standard](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/coding-standard.md). ## Substrates and vault configuration A [substrate](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/substrates.md) is a `bytes32` value that an atomist grants to a market with `grantMarketSubstrates(marketId, substrates)`. Each call replaces the whole set of substrates of that market. A fuse checks the substrate before it moves funds. A plain address is checked with `PlasmaVaultConfigLib.isSubstrateAsAssetGranted`, and a richer encoding with `isMarketSubstrateGranted`. When a substrate carries more than an address, put the encoding and decoding in a substrate library, as `AaveV4SubstrateLib` does. The usual order for an atomist is: add the fuses with `addFuses`, set the balance fuse, grant the substrates, make sure the vault's price manager or the shared [Price Oracle Middleware](https://ipor.io/docs/build-on-fusion/developer-guide/price-oracle-middleware.md) has a price source for every asset, add a claim fuse, if any, to the vault's `RewardsClaimManager` with `addRewardFuses`, and then optionally configure instant withdraw and the [dependency balance graph](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/dependency-graphs.md) with `updateDependencyBalanceGraphs`. The [What a Market Integration Contains](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/market-components.md) section lists these components in detail. ## The balance fuse Each market needs a balance fuse. It implements `IMarketBalanceFuse`: ```solidity interface IMarketBalanceFuse { /// @notice Get the balance of the Plasma Vault in the market in USD /// @dev Notice! Every Balance Fuse have to implement this exact function signature, because it is used by Plasma Vault engine /// @return balanceValue The balance of the Plasma Vault in the market in USD, represented in 18 decimals function balanceOf() external returns (uint256 balanceValue); } ``` Source: [`IMarketBalanceFuse.sol#L5-L10`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/IMarketBalanceFuse.sol#L5-L10) `balanceOf()` returns the balance of the vault in the market in USD with 18 decimals (WAD). Every balance fuse must use this exact signature, because the vault engine calls it. The interface does not declare `balanceOf()` as `view`, although the reference implementations do. You may declare it `view`, as they do. The vault calls it by `delegatecall` and does not catch a revert, so a reverting balance fuse blocks the balance update. `Erc4626BalanceFuse` reads the substrates with `PlasmaVaultConfigLib.getMarketSubstrates(MARKET_ID)`. For each vault it converts the shares held by the vault to assets, prices the asset through the Price Oracle Middleware and adds the value in WAD. It returns `0` immediately when the market has no substrates. ```solidity for (uint256 i; i < len; ++i) { vault = IERC4626(PlasmaVaultConfigLib.bytes32ToAddress(vaults[i])); vaultAssets = vault.convertToAssets(vault.balanceOf(plasmaVault)); asset = vault.asset(); (price, priceDecimals) = IPriceOracleMiddleware(priceOracleMiddleware).getAssetPrice(asset); balance += IporMath.convertToWad(vaultAssets * price, IERC20Metadata(asset).decimals() + priceDecimals); } return balance; ``` Source: [`Erc4626BalanceFuse.sol#L70-L78`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626BalanceFuse.sol#L70-L78) This fuse does not check for a zero price itself; the middleware rejects a zero or negative price. `convertToAssets` ignores withdrawal limits, as the valuation rule asks, but it also leaves out fees that an ERC4626 vault charges on withdrawal (EIP-4626). For a venue that charges an exit fee, value the position at what the exit pays; see [Security Requirements](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/security-requirements.md). `ZeroBalanceFuse` is a balance fuse that always returns `0`. It is only for a market that creates no separate position of its own, with the position valued on another market. Never use it for a position that you cannot value, because it hides the position from the vault balance. ## Where to go next - [Integrating a New Market](https://ipor.io/docs/build-on-fusion/integrating-a-new-market.md): the process, from writing the fuses to the Fuse Whitelist Registry. - [What a Market Integration Contains](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/market-components.md): every contract a market integration can contain. - [Coding standard](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/coding-standard.md) and [security requirements](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/security-requirements.md): the rules for the fuses you write. - [Whitelist Review](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/whitelist-review.md): what to prepare for the review of the deployed code. --- Source: https://ipor.io/docs/build-on-fusion/integrating-a-new-market/coding-standard.md # Coding Standard > What IPOR requires from the code of a third-party fuse family: structure, statelessness, safety checks, errors, events, NatSpec, compiler settings and formatting, plus recommended tests. This page lists what the IPOR team requires when it reviews the deployed code of your fuses. In this section "IPOR requires" and "IPOR expects" both mean a rule that the review applies: a fuse that does not meet it receives a request for changes in the pull request. "Recommended" marks what is optional. Each rule is marked as an IPOR requirement or shown in the code of the reference fuses in [`IPOR-Labs/ipor-fusion`](https://github.com/IPOR-Labs/ipor-fusion), read at commit `632350d`. Where a reference fuse does not follow a rule, the page says so. For a walkthrough of a working fuse, see [Developing a Fuse](https://ipor.io/docs/build-on-fusion/developer-guide/developing-a-fuse.md). For the safety rules behind several of the items below, see [Security Requirements](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/security-requirements.md). > **Note:** The review is based on what is on-chain: the source code verified in the block explorer of each chain. Write the code so that it can be read and checked in that form. ## Naming and file layout An action fuse written for a new market is typically named `Fuse`, for example `AaveV4SupplyFuse`, `AaveV4BorrowFuse` and `AaveV4CollateralFuse`. Use one contract per file and name the file after the contract. The reference families follow this layout: see [`AaveV4SupplyFuse`](https://github.com/IPOR-Labs/ipor-fusion/blob/main/contracts/fuses/aave_v4/AaveV4SupplyFuse.sol) and [`Erc4626SupplyFuse`](https://github.com/IPOR-Labs/ipor-fusion/blob/main/contracts/fuses/erc4626/Erc4626SupplyFuse.sol). Every fuse exposes `MARKET_ID()`. The `IFuseCommon` interface has exactly this one function ([source](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/IFuseCommon.sol#L5-L9)). When a fuse is added to the Fuse Whitelist Registry, the registry reads `MARKET_ID()` and lists the fuse under that market id; a fuse without `MARKET_ID()` is silently skipped for the per-market list, so IPOR requires it ([source](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/whitelist/FuseWhitelistLib.sol#L550-L564)). The parts of a market integration are described in [What a Market Integration Contains](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/market-components.md). ## Statelessness and delegatecall A fuse runs by `delegatecall` in the vault context. Inside a fuse function `address(this)` is the vault, and reads of storage see the vault's storage (`PlasmaVault.execute` delegatecalls the encoded call). For this reason IPOR requires fuses to be stateless: - The only variables are immutables: `VERSION`, `MARKET_ID` and, where the venue is fixed, venue addresses. There are no mutable storage variables. - Any other state lives in ERC-7201 namespaced storage slots, accessed through a library. Fusion uses this pattern for the `AsyncExecutor` address and for the transient storage slot. - `VERSION` is set to `address(this)` in the constructor, so it is the address of the fuse contract itself and not of the vault. The fuse emits it in events and uses it as the transient storage key. The reference declaration and constructor of the ERC4626 fuse are in [lines 81-87](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626SupplyFuse.sol#L81-L87). ## Reject market id zero IPOR requires the constructor to revert when `marketId_ == 0`. The vault engine uses market id 0 as the empty slot when it lists and refreshes markets, so a fuse with market id 0 would be skipped. `AaveV4SupplyFuse` shows the guard with the custom error `AaveV4SupplyFuseInvalidMarketId`, and a unit test asserts the revert ([constructor](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/aave_v4/AaveV4SupplyFuse.sol#L123-L131)). > **Warning:** `Erc4626SupplyFuse` and `Erc4626BalanceFuse` do not have this guard at `632350d`. Do not copy their constructors as they are; add the check yourself. ## Check substrates before moving funds A substrate is a `bytes32` value that an atomist grants to a market. The fuse checks it before it moves any funds: the grant check comes before every approve, deposit, supply or withdraw. Plain address substrates are checked with `isSubstrateAsAssetGranted`; other encodings with `isMarketSubstrateGranted`. Both are in `PlasmaVaultConfigLib`. When a caller supplies an asset together with a venue position, also check that the asset matches the asset of the granted position before moving funds. `AaveV4SupplyFuse` compares the reserve underlying with the asset ([lines 145-148](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/aave_v4/AaveV4SupplyFuse.sol#L145-L148)). The ERC4626 fuse checks the grant at the start of `enter` ([lines 94-96](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/erc4626/Erc4626SupplyFuse.sol#L94-L96)). If a substrate carries more than an address, put its encoding and decoding in a substrate library, as `AaveV4SubstrateLib` does: a type flag in the top byte, then the fields, with reserved bits that must be zero. ## Token transfers and approvals - Use `SafeERC20` and approve the exact amount with `forceApprove`. - IPOR requires the allowance to be set back to zero after the venue call, so that no residual allowance remains. `AguaSupplyFuse` shows the pattern `forceApprove(vault, amount)`, deposit, `forceApprove(vault, 0)` ([lines 83-87](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/agua/AguaSupplyFuse.sol#L83-L87)). > **Warning:** The allowance reset is a requirement of the standard, not a feature of the ERC4626 and Aave V4 examples. `Erc4626SupplyFuse.enter`, `AaveV4SupplyFuse.enter` and `AaveV4BorrowFuse.exit` approve the exact amount but do not reset it at `632350d`. ## Errors and events - **Errors** are custom errors named with the fuse name as a prefix, for example `AaveV4SupplyFuseInvalidMarketId`. Do not use revert strings. - **Events** are named with the fuse name as a prefix and carry the fuse `VERSION` as the first parameter. - **Events report what actually happened.** Emit the amount after clamping to the balance or limit, not only what was requested. The requirement is that events show the outcome; it is not that every event has an amount field. `AaveV4SupplyFuseEnter`, for example, reports the received shares. - **No `indexed` parameters.** IPOR requires that event parameters are not indexed; all parameters go into the data section. The reference fuses declare their events without `indexed`. Some other Fusion contracts, for example `FusionFactory`, still use it, so this is a rule for new fuses and not a description of all existing code. ## NatSpec Write NatSpec in English: `@title`, `@notice`, `@param`, `@return` and `@custom:revert` on external and public functions, and `@param` on events and errors. The Aave V4 fuses show this level of documentation. The `enter`, `exit`, `enterTransient` and `exitTransient` functions of `Erc4626SupplyFuse` have no NatSpec at `632350d`. A fuse README in your repository should follow the sections of the [Aave V4 README](https://github.com/IPOR-Labs/ipor-fusion/blob/main/contracts/fuses/aave_v4/README.md): overview, market structure, key components, substrate configuration with the validation matrix, operations, balance calculation, security considerations, price oracle setup and tests. ## Compiler settings and size - **Pragma.** IPOR sets no requirement on the pragma version of your code; you choose it. Fusion interfaces and libraries such as `IFuseCommon` or `PlasmaVaultConfigLib` declare `pragma solidity 0.8.30`, so a file that imports them must be compiled with solc 0.8.30. - **Reproducible bytecode.** The deployed code is read from the chain, so the compiler settings you used for the deployment must reproduce the deployed bytecode. List them in the pull request: the solc version, the EVM version, the optimizer setting and runs, and any per-chain profile. - **Same source on every chain.** Use the same source code and the same compiler settings on every chain. The runtime bytecode can still differ because immutable values (`VERSION`, `MARKET_ID`, venue addresses) are written into it. List these expected differences, and any other difference, in the pull request. - **No `via_ir`.** IPOR does not accept `via_ir` when compiling fuses. At commit `632350d`, Fusion's own [`foundry.toml`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/foundry.toml#L1-L28) sets solc 0.8.30, `optimizer_runs` of 10000000 and `evm_version` cancun, with an `arbitrum` profile on paris, and no `via_ir`. - **EIP-170.** The deployed runtime bytecode of every fuse must fit the limit of 24,576 bytes. If the code is too large, reduce it in the code, for example by splitting logic into libraries, and not with compiler flags. ## Formatting and linting Fusion formats Solidity with Prettier and `prettier-plugin-solidity` ([`.prettierrc.js`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/.prettierrc.js#L1-L19): tab width 4, print width 120, double quotes, no bracket spacing, the slang parser). It lints with solhint, extending `solhint:recommended` ([`.solhint.json`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/.solhint.json#L1-L13)). Following both is a recommendation. Code that follows these files is easier to read. ## Recommended: tests > **Note:** Recommended, not required. Tests are not a condition of the review. They are the quickest way to show that your fuses behave as this page describes. Fusion's own tests use Foundry (`forge test`). Good tests prove the following: - **Every branch** of every fuse function runs, including the early returns for zero amounts. - **Every custom error** is asserted by its selector with `vm.expectRevert`, for example the market id zero guard in the constructor. - **Every event** is asserted with `vm.expectEmit`, including the amounts after clamping. - **Fork tests against the real venue.** Run them on a pinned block so results are reproducible. The Aave V4 fork tests pin an Ethereum mainnet block with `vm.createSelectFork` ([`AaveV4ForkTestBase.sol`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/test/fuses/aave_v4/AaveV4ForkTestBase.sol#L94)). - **The balance fuse against the vault.** After `enter` and `exit`, the balance fuse and the vault's `totalAssets()` agree. - **Edge cases.** Instant withdraw, slippage limits, zero and dust amounts, tokens with different decimals, and a substrate that was not granted. A public repository with the tests and the fork-test results is recommended, and the pull request description may link to it. See [Whitelist Review](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/whitelist-review.md) for what the pull request contains. --- Source: https://ipor.io/docs/build-on-fusion/integrating-a-new-market/security-requirements.md # Security Requirements > Security requirements for the fuses of a new market: vault control of positions, limits on every action, allowances, valuation without silent failures, price sources, venue risks and what the IPOR team does not accept. These are the requirements the IPOR team applies when it reviews the deployed code of a new market. They complement the [Coding Standard](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/coding-standard.md). Where a requirement is an IPOR rule and not something the Fusion code enforces, the text says "IPOR requires"; the Coding Standard explains what that means. Fuses run by `delegatecall` in the context of the vault, so a mistake in a fuse is a mistake in the vault. See [What a Market Integration Contains](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/market-components.md) for the parts of an integration. ## The vault controls its own positions IPOR requires that a fuse never hands control of a vault position to an external party. A fuse must not call `setManager`, `setDelegate` or an equivalent, and must not approve an operator or position manager on the venue. The vault stays the only owner and manager of its positions. Assets leave the venue to the vault and never to a caller-supplied recipient. The reference withdraw and borrow functions use `address(this)`, the vault, as the receiver. ## Limits on every action Every function that moves value takes minimum or maximum parameters from the caller: for example `minSharesOut` on a deposit, `maxSharesBurned` or `minAmount` on a withdrawal, or `minSharesRepaid` on a repayment. IPOR requires this for every such function except `instantWithdraw` (see below). Do not hard-code percentages or slippage tolerances in the fuse; the [Alpha](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-alpha.md), the role that executes strategy transactions on the vault, chooses the limits for each call. > **Note:** A limit that is optional in the parameters can be switched off by the caller. In `Erc4626SupplyFuse`, `maxSharesBurned = 0` means no limit, and `instantWithdraw` passes `0`. Treat a limit that is off as a risk you describe in your README. Implementing `instantWithdraw` is optional. When you implement it, the vault sets `params[0]` to the amount it still needs; the other params are the values the atomist configured. IPOR does not require a bound there. Describe in your README how your fuse bounds the instant-withdraw path. ## Allowances are revoked after use IPOR requires that after the venue call the fuse sets the allowance of the external spender back to zero, so no residual allowance remains. `AguaSupplyFuse` shows the pattern: `forceApprove(vault, amount)`, the deposit, then `forceApprove(vault, 0)`. See the [allowance cleanup in `AguaSupplyFuse`](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/agua/AguaSupplyFuse.sol#L83-L87). The ERC4626 and Aave V4 examples approve the exact amount but do not set the allowance back to zero. They do not demonstrate this requirement. ## No silent failures in valuation The balance fuse must report what the vault holds, or fail. - The balance fuse does not catch a revert from the venue. - It does not return `0` for a position it cannot value. A zero hides the position from the vault balance. - `ZeroBalanceFuse` is only for a market that creates no separate position. Never use it for a position you cannot value. The vault calls `balanceOf()` on the balance fuse by `delegatecall` and does not catch a revert, so a reverting balance fuse blocks the balance update. `try/catch` is allowed only where it is described. The one documented place is the instant-withdraw path, around the call to the venue withdraw, with an event that reports the failure. The vault does not wrap `instantWithdraw` in `try/catch`, so a revert there reverts the user withdrawal, which is why the reference fuses catch only that one call. Reads and substrate checks stay outside `try/catch`. In `Erc4626SupplyFuse` the `maxWithdraw` read is outside it and a zero result is a silent return, not a failure event; do not copy that into a balance fuse. ## Valuation matches the exit IPOR requires the balance fuse to value the whole position at what an exit pays for it. The Aave V4 balance fuse, for example, is net of total debt, including the accrued risk premium. A valuation above what the exit pays inflates the share price for everyone in the vault. Value the position, not what the venue lets the vault withdraw at the moment: do not cap the valuation with withdrawal limits such as the ERC4626 `max*` functions. They can return `0` while the venue is paused or a cap is reached, and a position that still exists must not be valued at `0`. ## A robust price source The Price Oracle Middleware rejects a price that is zero or negative and reverts for an asset it cannot price. A custom price feed implementing [`IPriceFeed`](https://github.com/IPOR-Labs/ipor-fusion/blob/main/contracts/price_oracle/price_feed/IPriceFeed.sol) must not be manipulable within one transaction and must report its decimals correctly. Do not price an asset from the spot price of a single pool. ## Venue risks and substrates in the README Describe the risks of the venue in the README of your fuse repository: upgradeable contracts, admin keys, pauses, withdrawal delays, caps and actions that anyone can take on the vault position. The [Aave V4 README](https://github.com/IPOR-Labs/ipor-fusion/blob/main/contracts/fuses/aave_v4/README.md) and the `SPOL_UNSTAKE` NatSpec in [`IporFusionMarkets.sol`](https://github.com/IPOR-Labs/ipor-fusion/blob/main/contracts/libraries/IporFusionMarkets.sol) are examples. An [Atomist](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-atomist.md), the administrator of a vault, grants and revokes [substrates](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/substrates.md). IPOR requires the consequences for open positions to be documented in the README, as the Aave V4 README does in [Grant changes and open positions](https://github.com/IPOR-Labs/ipor-fusion/blob/632350d6a31afbe7a306f0e6458bb4794c18c624/contracts/fuses/aave_v4/README.md#L87-L101). The fuse does not enforce them. ## Checked on-chain The review is based on the deployed code. For each fuse the IPOR team checks that: - the fuse has no roles, owner, admin keys, pause or upgrade mechanism, and is not a proxy; - venue addresses are immutable or come from granted substrates, and the fuse checks the grant before it moves funds; - no code path gives up control of a position or sends the assets of the vault to an arbitrary recipient. > **Warning:** The IPOR team does not accept fuses with: > > - an arbitrary recipient of assets, or an action other than `instantWithdraw` with no limit; > - a transfer of control over a vault position to a third party; > - state outside ERC-7201 namespaced storage; > - admin keys or upgradeability in the fuse; > - no README that describes the venue risks; > - a token that the balance fuse values has no price source in the Price Oracle Middleware and none described in the pull request. A fuse that does not meet these requirements receives a request for changes in the pull request. See [Whitelist Review](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/whitelist-review.md). --- Source: https://ipor.io/docs/build-on-fusion/integrating-a-new-market/whitelist-review.md # Whitelist Review > How to request a Fuse Whitelist Registry entry for a new market: the market id pull request, a copyable pull request description, the review request on Discord, the review, the possible outcomes and what happens after the entry. You write your fuse family in your own repository and deploy it yourself. IPOR does not deploy third-party fuses. The only pull request to the Fusion repository is a small one that adds your market id with a description of the market substrates, and links to the repository of your fuses and to their documentation. To request the whitelist review, open a ticket in the [IPOR Discord](https://discord.com/invite/bSKzq6UMJ3) with the link to that pull request and the links to the verified sources of your fuses. This page explains what that pull request contains, how to request the review, what the review is, and what happens next. For the overall process, start with the [overview](https://ipor.io/docs/build-on-fusion/integrating-a-new-market.md). ## The order 1. Open the market id pull request and wait until the IPOR team confirms the number. 2. Deploy the fuses with that number on every chain you want listed and verify the source of every fuse in the block explorer of its chain (for example Etherscan or Basescan). 3. Add the deployed addresses, the compiler settings and the deployment dates to the pull request. 4. Request the review on Discord. Before you request the review, the fuse repository has a README that describes the market, the substrates and the venue risks (see [Security Requirements](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/security-requirements.md)), and you know the compiler settings of each deployment (see the [Coding Standard](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/coding-standard.md)). ## The market id pull request The pull request changes one file, [`contracts/libraries/IporFusionMarkets.sol`](https://github.com/IPOR-Labs/ipor-fusion/blob/main/contracts/libraries/IporFusionMarkets.sol), the library where Fusion markets are listed and described. It adds one constant and makes no other change in the repository. Open it against the `main` branch of `IPOR-Labs/ipor-fusion`. - **The number.** Third-party markets use ids from 400_001 to 400_999. Use the next free number in that range; the IPOR team confirms it in the pull request. - **The name.** Use an `UPPER_SNAKE_CASE` name that contains the venue name. - **The match.** `MARKET_ID` is immutable in a deployed fuse, so the constant must equal the value your fuses were deployed with. - **The NatSpec.** Describe the market in the NatSpec of the constant. The `SPOL_UNSTAKE` constant, added in [commit `7963151`](https://github.com/IPOR-Labs/ipor-fusion/commit/79631512ea1090b819e49c428bbaead7a6eb5790), is the model: the market, the venue addresses, the substrate type and values, the balance fuse semantics, the required configuration, the exit semantics and a security warning. Deploy only after the IPOR team has confirmed the number in the pull request. If the id changes after you have deployed, the fuses must be redeployed. Questions about the request go in the pull request thread. The NatSpec in `IporFusionMarkets.sol` looks like this: ```solidity /// @dev ExampleVenue supply market (Ethereum mainnet) - values the vault's deposits in ExampleVenue pools. /// @dev Fuses (Ethereum mainnet deployments): /// - ExampleVenueSupplyFuse (enter / exit / instantWithdraw): 0x... /// - ExampleVenueBalanceFuse (balance fuse of this market): 0x... /// @dev External protocol (): /// - ExampleVenue pool (substrate of this market): 0x... /// @dev Substrate type: address /// @dev Substrate values: pool addresses the vault is allowed to supply to /// @dev Balance fuse semantics: sums the vault's pool positions, priced with the Price Oracle Middleware. /// @dev Required configuration: /// - ExampleVenueBalanceFuse as the balance fuse, pool addresses granted as substrates; /// - dependency graph: this market -> ERC20_VAULT_BALANCE; /// - price sources for the pool asset in the Price Oracle Middleware. /// @dev Exit semantics: exit reverts when the pool has no liquidity for the requested amount. /// @dev SECURITY: the pool is upgradeable by its admin; see . /// @dev Documentation: uint256 public constant EXAMPLE_VENUE_SUPPLY = ; ``` The addresses and the number above are placeholders. Open the pull request with the number, and fill in the addresses once the fuses are deployed. For several chains, repeat the fuse address lines per chain, or list the addresses in the pull request description and keep the NatSpec to the substrate and configuration lines. ## The pull request description At commit `632350d` public ipor-fusion has no pull request template, so the template lives here. Copy it into the description when you open the pull request, and fill in the deployment lines after you deploy. ```markdown ## Market - Market id constant: `` = `` - Venue: - Fuse repository (where the code is maintained): - Fuse documentation, if kept outside that repository: - Fuse source commit: ## Deployments (one block per chain) - Chain: - [ ] ``:
- - [ ] ``:
- - Deployment date of each fuse: ## Fuse types - [ ] Action fuse(s): - [ ] Balance fuse: - [ ] Claim fuse(s), if any: - [ ] Price feed(s), if any: ## Build - [ ] Compiler: solc , EVM version , optimizer , runs , per-chain profile - [ ] Constructor arguments per fuse: - [ ] Differences between chains beyond VERSION, MARKET_ID and venue addresses: ## Substrates - [ ] Substrate type and encoding:
- [ ] Values to grant: ## Vault configuration - [ ] Price feeds required for every valued token: - [ ] Dependency graph: - [ ] Instant withdraw: ## Venue risks - [ ] Upgradeability, admin keys, pauses, withdrawal delays, caps: ## Optional - [ ] Tests and fork-test results: ``` Two details are worth knowing. The registry rejects a deployment timestamp of zero, so state the deployment date of each fuse. And the registry reads `MARKET_ID()` from every fuse it lists: a fuse without it is silently skipped in the per-market list. Every fuse must expose `MARKET_ID()`, and its value must equal the constant in your pull request. ## Request the review on Discord Opening the pull request does not start the review. When the fuses are deployed with the confirmed id, verified, and listed in the pull request, open a ticket in the [IPOR Discord](https://discord.com/invite/bSKzq6UMJ3) and include: - the link to the market id pull request; - for every fuse on every chain, the link to its verified source in the block explorer (for example Etherscan or Basescan). ## The review The IPOR team reviews the deployed, verified code before adding the fuses to the Fuse Whitelist Registry. ## Outcomes The review ends in one of two ways: - **Whitelisted.** The fuses are added to the Fuse Whitelist Registry. - **Changes requested.** The IPOR team asks for changes in the pull request. Deployed fuses cannot be changed: a fix or a new version means a new deployment with new addresses. The market id stays the same, so no new pull request is needed; send the new addresses and their verified sources to the IPOR team in a ticket in the [IPOR Discord](https://discord.com/invite/bSKzq6UMJ3) for review. Vaults already using the old address must migrate. ## After the fuses are whitelisted The market id pull request is merged after a positive review of the deployed code, at the same time as the registry entry. Once the entry exists, the fuses are visible in the Fuse Whitelist Registry and in [Fusion Terminal](https://app.ipor.io/fusion-terminal/fuse-whitelist/ethereum/fuses) (the link opens the Ethereum list). The registry contract, [`FuseWhitelist`](https://github.com/IPOR-Labs/ipor-fusion/blob/main/contracts/fuses/whitelist/FuseWhitelist.sol), can be read by market id (`getFusesByMarketId`), by type (`getFusesByType`) and by address (`getFuseByAddress`). > **Warning:** The Fuse Whitelist Registry is a reference list for Fusion Terminal and atomists; it is not enforced on-chain, and a vault can add any fuse address. Adding the fuses to a vault is a separate step, done by the atomist of that vault: 1. add the action fuses with `addFuses`; 2. set the balance fuse of the market; 3. grant the market substrates with `grantMarketSubstrates`; 4. make sure a price source exists for every asset, in the vault's Price Oracle Middleware Manager (`setAssetsPriceSources`) or in the shared middleware behind it; 5. optionally configure instant withdraw and the dependency graph; 6. if the market has a claim fuse, add it to the vault's `RewardsClaimManager` with `addRewardFuses`. The state of a registry entry can change later, for example to deprecated or removed. See [What a Market Integration Contains](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/market-components.md) for how these pieces fit together, and the [Fuse Whitelist Registry](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fuse.md) section for how to monitor it. ## Common reasons for a request for changes - The deployed bytecode cannot be matched to the source and compiler settings given in the pull request. - `MARKET_ID` differs from the constant in the pull request. The other grounds are listed in [Security Requirements](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/security-requirements.md) and the [Coding Standard](https://ipor.io/docs/build-on-fusion/integrating-a-new-market/coding-standard.md). --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/balance-fuses.md # Balance Fuses > What a Balance Fuse tracks and how it pairs with a Functional Fuse for a market. #### Short Summary **Balance fuses shift accounting and validation from opaque, manual, and mutable off-chain spreadsheets to small, auditable, onchain modules that read vault state and market data, enforce whitelists/constraints, and produce verifiable outputs.** That architectural change gives permissionless verification, immutable audit trails, and automated enforcement — properties that Excel cannot provide. --- > How do Balance Fuses in IPOR Fusion work, and why do they offer more security than Excel spreadsheets in offchain accounting (as seen in other protocols like Stream Finance)? IPOR Fusion’s **balance fuses** are a concrete example of how onchain, composable guards can replace fragile off-chain bookkeeping (like Excel) and give vaults provable, auditable accounting and behavior. Below is explained what they are, how they work (at a technical level you can audit), and exactly why that is materially more secure than maintaining off-chain spreadsheets. ## What a “balance fuse” is (short) A **balance fuse** in IPOR Fusion is an onchain, market-specific fuse module whose job is to _determine and/or validate balances for a market or integration_ and to enforce constraints the vault relies on when routing assets through external protocols. Balance fuses are one type of “fuse” in the Fusion architecture — small, purpose-built, immutable onchain components that the vault calls when performing actions. ## How they work — mechanics you can audit 1. **Onchain interface** — balance fuses implement a defined interface (e.g. `IMarketBalanceFuse`) exposing functions such as a market-balance query (get user/market balance in USD or shares). That means external actors (and auditors) can call and inspect exactly how balances are derived. 2. **Vault-level accounting remains authoritative** — The fuse itself _never holds funds or persistent accounting state_; the vault remains the single source of truth for tokens/shares. The fuse is a verification/adapter layer that reads vault state, reads market/substrate data (oracles, onchain positions), and returns validated numbers or allows/blocks actions. This reduces complexity and centralizes accounting to an auditable smart contract. It allows also for instant withdrawals (if configured for the vault) with accurate share valuation. 3. **Market-specific logic & whitelisting** — a balance fuse is written for a particular market/substrate and can include checks like allowed assets, allowed method signatures, and validation constraints. Vaults can be configured only to accept [whitelisted](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fuse.md)/verified fuses and markets, and non-whitelisted custom fuses trigger alerts in the Fusion UI. That restricts what external integrations can do. 4. **Price oracles & middleware tie-ins** — balance fuses integrate with Fusion’s price oracle middleware and market substrate configs so the numeric balances they return are grounded in onchain price feeds and standardized market identifiers (not an off-chain spreadsheet cell someone updated). 5. **Immutable, auditable code** — fuses are immutable (non-upgradable) pieces of code: you can review their logic onchain or in the project repo and reason about exactly how a balance was computed. Every call and event is logged on the blockchain. ## Why this is more secure than Excel/off-chain accounting (concrete comparisons) **1) Immutability vs. silent edits** - Excel: a spreadsheet cell can be changed, copied, or deleted without an immutable audit trail. A malicious or accidental edit can silently change reported balances. - Balance fuse: logic lives onchain and is immutable (or at least upgrade paths are explicit and auditable). Any change requires a transaction and is visible onchain. **2) Single source of truth vs. manual reconciliation** - Excel: reconciliation requires manual imports/exports from multiple protocols and human consolidation — error-prone and inconsistent. - Fusion: the vault is the authoritative contract; fuses read the vault and onchain markets directly and return validated numbers. No manual patching of “what the ledger says.” **3) Permissioned behavior vs. ad-hoc scripts** - Excel: operators often use ad-hoc scripts or spreadsheets to decide swaps/allocations; those scripts can call unsafe contracts or be manipulated. - Balance fuses: constrain what external protocols/methods are allowed (whitelists, allowed signatures) and can refuse actions that would break rules. Non-whitelisted fuses trigger UI alerts. **4) Onchain verifiability vs. opaque off-chain proofs** - Excel: even with csv exports, a counterparty or auditor must trust that the exported file was correct; proving the file maps to onchain state is extra work. - Balance fuse: anyone can call the same onchain functions, re-derive balances from onchain data, and verify results match what the vault used — cryptographically verifiable. **5) Event logs & monitoring vs. manual logs** - Excel: change history depends on systems (file history, emails); detection of tampering or mistakes is slow. - Balance fuse + vault: every call, rebalancing, or state change emits events onchain. The system can emit alerts when a non-whitelisted fuse is used or when constraints are violated, enabling automated monitoring. ## Practical examples (what a balance fuse prevents) - A bad agent tries to report inflated collateral or misprice an Illiquid token in a spreadsheet to justify an unsafe leverage step → onchain fuse uses oracle data and vault accounting and rejects the action. - A manager wants to route funds into a non-whitelisted market with custom call signatures → vault/fuse whitelists prevent the call or trigger alarms before funds move. --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/general-share-price-calculation-rules.md # General share price calculation rules > How a Plasma Vault's share price is computed and what can move it. ### Core calculation architecture The foundation of asset calculation begins with the \_getGrossTotalAssets() function, which aggregates three primary components. The first component is the direct vault balance, representing the raw underlying asset balance held directly in the vault contract, retrieved via IERC20(asset()).balanceOf(address(this)) and representing immediately available liquidity. The second component encompasses market-specific assets, which represent the total value of all positions across integrated DeFi protocols, calculated through PlasmaVaultLib.getTotalAssetsInAllMarkets() where each market maintains its own balance tracking via specialized Balance Fuses. The third component, which is optional, includes reward claims representing the value of claimable rewards from integrated protocols, retrieved via IRewardsClaimManager(rewardsClaimManagerAddress).balanceOf() and only included if a rewards claim manager is configured. All asset valuations are standardized to USD using a hierarchical price oracle system. The primary layer consists of the PriceOracleMiddlewareManager, which manages custom price feed sources for specific assets, provides fallback to PriceOracleMiddleware when custom feeds are unavailable, converts all prices to standardized 18-decimal USD format, and implements gas-efficient price caching mechanisms. The secondary layer is the PriceOracleMiddleware, which handles Chainlink Feed Registry integration, provides fallback pricing for assets without custom feeds, ensures consistent 18-decimal USD price format, and validates price feed data integrity and freshness. The price conversion process converts all external prices to 18-decimal USD using IporMath.convertToWad(), maintains precision through standardized decimal handling, and implements price validation to prevent zero or negative values. Each integrated DeFi protocol is represented by a unique market ID with dedicated balance tracking through the Balance Fuse system. Each market employs a specialized Balance Fuse contract such as Erc4626BalanceFuse, which calculates market-specific asset values in USD, implements protocol-specific balance calculation logic, and returns standardized 18-decimal USD values. Markets are defined by protocol-specific identifiers called substrates, which include asset addresses, pool identifiers, and protocol parameters, enabling complex multi-asset market structures and supporting various DeFi protocol types including lending, AMMs, and yield farming. The balance update mechanism updates market balances through the updateMarketsBalances() function, implements dependency resolution for interconnected markets, ensures atomic balance updates across related protocols, and calculates deltas to minimize storage operations. ### Gas optimization and efficiency The system implements several mechanisms to reduce gas consumption and improve efficiency. Market balance storage ensures that market values are stored in underlying token amounts rather than USD, with price conversions only occurring during balance updates, thereby reducing gas costs for simple operations like deposits and withdrawals. Batch market updates allow multiple market balances to be updated in a single transaction, with dependency resolution preventing redundant calculations and delta-based updates minimizing storage writes. The delegatecall pattern enables Balance Fuses to use delegatecall for gas-efficient execution, eliminating external contract call overhead while maintaining security through controlled execution context. All market values are ultimately converted to the vault's underlying asset denomination through a precise conversion process. The USD to underlying asset conversion divides market USD values by the underlying asset USD price using the formula (USD_Value \* 10^18) / underlying_asset_price, maintaining precision through careful decimal handling. Decimal standardization ensures that all calculations use consistent decimal precision, with the underlying asset decimals offset applied (DECIMALS_OFFSET = 2) to ensure compatibility across different asset types. ### Balance update workflow The complete balance update process follows a carefully orchestrated sequence. Market dependency resolution identifies all markets requiring balance updates, resolves market dependencies to ensure proper update order, and prevents circular dependency issues. Price oracle integration retrieves the current USD price for the underlying asset, validates price feed data integrity, and handles price feed failures gracefully. Balance Fuse execution runs each market's Balance Fuse via delegatecall, collects USD-denominated market values, and implements protocol-specific calculation logic. The final conversion and storage phase converts USD values to underlying asset amounts, updates market-specific storage, calculates and applies total asset deltas, and triggers asset distribution protection checks. ### Security and validation The system implements multiple security layers to ensure data integrity and system reliability. Price validation ensures that all prices are validated for positive values, includes price feed staleness checks, and provides fallback mechanisms for price feed failures. Balance integrity is maintained through asset distribution protection limits, market balance consistency checks, and dependency validation. Access control is enforced through role-based access to balance update functions, controlled execution context for delegatecalls, and comprehensive audit trails through event emissions. --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/accounting-and-pps-protection.md # Accounting and PPS Protection > How the vault protects its price-per-share against manipulation and accounting edge cases. A critical challenge for multi-protocol yield aggregators is maintaining an accurate and manipulation-resistant Price Per Share (PPS). This page explains the risks associated with "Auto-Accrual" accounting and how IPOR Fusion's architecture provides robust protection against these attack vectors. ### The Pitfalls of Auto-Accrual Accounting Some early vault designs utilized an "Auto-Accrual" model. In this model, the vault automatically updates its `totalAssets()` on every transaction (deposit, withdrawal, or transfer) by looping through and querying every integrated market. While this ensures that yield is always "up-to-date," it introduces major vulnerabilities: 1. **Intra-block PPS Manipulation**: Since `totalAssets()` updates on every "touch," an attacker can donate assets to an underlying strategy, observe an immediate rise in the vault's PPS, and exploit this higher valuation (e.g., by borrowing against the inflated shares) all within the same block. 2. **The "Weakest Link" Problem**: The entire vault's security is tied to its most manipulable strategy. If a single integrated market can be manipulated, the entire vault's accounting is affected instantly. 3. **PPS Inflation via Donation**: Anyone can artificially pump the PPS by directly transferring assets to external protocols the vault uses, causing immediate and uncontrolled revaluation of all vault shares. ### The Fusion Solution: Explicit Reporting IPOR Fusion solves these issues by decoupling user transactions from yield accrual. The `PlasmaVault` uses an **Explicit Reporting** model. #### 1. Cached Balances instead of Live Loops In a PlasmaVault, the `totalAssets()` call does **not** loop through integrated markets on-the-fly. Instead, it aggregates: - The direct `IERC20(asset).balanceOf(vault)` (idle assets). - **Cached values** from storage (`PlasmaVaultLib.getTotalAssetsInAllMarkets()`). - Optionally, pending rewards. Because the market balances are cached, an external donation to an external protocol or a change in interest rates does not affect the vault's PPS until those balances are explicitly updated and written to storage. Conversely, a direct donation to the vault contract itself is visible but protected by mathematical safeguards. #### 2. Controlled Balance Updates Balance updates in Fusion are deliberate and triggered only by authorized operations or roles via `_updateMarketsBalances()`: - **Alpha Strategy Execution**: Whenever an Alpha executes a strategy via `execute()`, the vault automatically updates the balances of all affected markets at the end of the transaction. This ensures that the vault's accounting reflects the new position state immediately after a deliberate change. - **Instant Withdrawals**: If an instant withdrawal requires the vault to source liquidity from external markets, the system triggers a balance update for those markets to reflect the exit and ensure accurate share pricing for the redeeming user. - **Alpha-Driven Reporting**: For passive yield (interest accrual), accounts with the `UPDATE_MARKETS_BALANCES_ROLE` (Alphas) periodically trigger balance refreshes. This is asynchronous to user deposits, eliminating intra-block manipulation vectors. #### 3. Oracle-Based Isolation Unlike designs that rely on raw balances of LP tokens or receipt tokens, Fusion's **Balance Fuses** return values converted through the `PriceOracleMiddleware`. Manipulating a raw balance in an external protocol does not translate 1:1 to the vault's `totalAssets` unless the oracle price also reflects that change. ### Additional Safeguards #### Redemption Delay (Withdraw Delay) To further neutralize flash loan attacks and sandwiching, Fusion vaults utilize a **Redemption Delay**. Configured via the `IporFusionAccessManager`, this delay enforces a minimum time (e.g., 24 hours) that must pass between a deposit and the subsequent ability to withdraw or redeem those shares. This ensures that capital is "at risk" and prevents attackers from entering and exiting the vault within the same block or price window. See also: [managing-redemption-delays.md](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/managing-redemption-delays.md "mention") #### Mathematical Safeguards (Virtual Offsets) For direct donation attacks on the vault contract itself, Fusion implements ERC-4626 virtual offsets. The internal share calculation uses a multiplier and an offset to prevent "inflation attacks": `shares = assets \cdot \frac{supply + 10^k}{totalAssets + 1}` Where `10^k` represents the `_SHARE_SCALE_MULTIPLIER` (typically 100). This makes the cost of manipulating the PPS via small-scale donations prohibitively expensive. ### Comparison of Accounting Models | **Aspect** | **Auto-Accrual** | **Explicit (IPOR Fusion)** | | ----------------------- | ---------------------------------- | ---------------------------------- | | **Yield Accrual** | Automatic, every transaction | Triggered (Alpha, Withdraw) | | **PPS Update** | Per-transaction, via loops | Per-operation/reporting | | **Donation Protection** | Vulnerable | **Resistant** | | **Flash Loan Exploit** | Possible | **Prevented (via Delay & Cache)** | | **Security Scope** | Weakest link across all strategies | Isolated via Oracles & Triggers | | **Withdrawal Safety** | Vulnerable to intra-block swings | **Protected via Redemption Delay** | ### Implementation Summary By utilizing **cached balances**, **operation-specific triggers**, and a **redemption delay**, Fusion ensures that the vault's accounting is a product of verified protocol state rather than side effects of user actions. This architecture makes the Fusion Vault significantly more robust against sophisticated MEV and price manipulation attacks. --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/price-oracle-middleware.md # Price Oracle Middleware > How the price oracle middleware resolves asset prices and how to add or override a feed. ## Purpose and scope The Price Oracle Middleware system provides standardized asset valuation and conversion for the PlasmaVault ecosystem. It is centered around the `PriceOracleMiddlewareWithRoles` contract, which acts as a centralized price hub, and the `PriceOracleMiddlewareManager`, which provides a vault-specific interface for price queries and validation. The system is responsible for: - Providing asset prices in a unified quote currency (USD) with 18 decimals [contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol42-46](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol#L42-L46) - Managing custom price feed sources (e.g., Pendle PT, Curve, ERC4626) [contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol125-135](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol#L125-L135) - Falling back to the Chainlink Feed Registry when custom sources are not defined [contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol19-21](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol#L19-L21) - Implementing price change validation to protect vaults from extreme volatility or oracle manipulation [contracts/managers/price/PriceOracleMiddlewareManagerLib.sol43-48](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/managers/price/PriceOracleMiddlewareManagerLib.sol#L43-L48) ## System architecture The architecture separates global price discovery from vault-specific price management and validation. ### Logic flow and code entities ![Image](https://ipor.io/docs/assets/build-on-fusion/image-2-bb20c5.png) __ **Architecture description**: 1. **PlasmaVault** and its **Balance Fuses** interact with the `PriceOracleMiddlewareManager` assigned to the vault [contracts/vaults/PlasmaVault.sol75](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/vaults/PlasmaVault.sol#L75-L75) 2. The **PriceOracleMiddlewareManager** handles vault-specific configuration, such as custom asset sources and price validation logic stored via `PriceOracleMiddlewareManagerLib` [contracts/managers/price/PriceOracleMiddlewareManagerLib.sol64-75](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/managers/price/PriceOracleMiddlewareManagerLib.sol#L64-L75) 3. **PriceOracleMiddlewareWithRoles** serves as the protocol-wide price aggregator, managing specialized feeds like **PtPriceFeed** for Pendle tokens [contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol140-150](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol#L140-L150) ## Core components ### 1. PriceOracleMiddlewareWithRoles This contract provides the "Source of Truth" for asset prices. It normalizes all outputs to 18 decimals (WAD) [contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol76-77](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol#L76-L77) - **Quote Currency**: Hardcoded to the Chainlink USD address `0x...0348` [contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol42](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol#L42-L42) - **Custom Sources**: Allows administrators to map specific assets to custom `IPriceFeed` implementations [contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol112-114](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol#L112-L114) - **Pendle Integration**: Features specialized logic to deploy and manage `PtPriceFeed` instances for Pendle Principal Tokens [contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol140-160](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol#L140-L160) ### 2. PriceOracleMiddlewareManager A per-vault manager that wraps the global middleware with validation and vault-specific overrides. - **getAssetPrice**: The primary entry point. It checks for a vault-specific source in `PriceOracleMiddlewareManagerLib` before falling back to the global middleware [contracts/managers/price/PriceOracleMiddlewareManager.sol103-118](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/managers/price/PriceOracleMiddlewareManager.sol#L103-L118) - **Validation**: Implements `validatePriceChange` which compares the current price against a `lastValidatedPrice`. If the delta exceeds `maxPriceDelta`, the transaction reverts [contracts/managers/price/PriceOracleMiddlewareManagerLib.sol43-48](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/managers/price/PriceOracleMiddlewareManagerLib.sol#L43-L48) ## Specialized price feeds The system supports various specialized feeds to handle complex DeFi assets. ### Pendle PT Price Feed (`PtPriceFeed`) Calculates the price of Pendle Principal Tokens using Pendle's TWAP oracle and the price of the underlying asset from the middleware [contracts/price_oracle/price_feed/PtPriceFeed.sol12-18](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/price_feed/PtPriceFeed.sol#L12-L18) | Feature | Implementation Detail | | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | TWAP Window | Minimum 5 minutes, recommended 15 minutes [contracts/price_oracle/price_feed/PtPriceFeed.sol23](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/price_feed/PtPriceFeed.sol#L23-L23) | | Calculation | `(PtToAssetRate * UnderlyingAssetPrice) / scalingFactor` [contracts/price_oracle/price_feed/PtPriceFeed.sol128](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/price_feed/PtPriceFeed.sol#L128-L128) | | Metadata | Returns Chainlink-compatible `latestRoundData` [contracts/price_oracle/price_feed/PtPriceFeed.sol109-113](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/price_feed/PtPriceFeed.sol#L109-L113) | ### Feed factory pattern Factories like `PtPriceFeedFactory` and `CurveStableSwapNGPriceFeedFactory` are used to deploy standardized feed instances that the middleware can then consume [contracts/factory/price_feed/PtPriceFeedFactory.sol6-10](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/factory/price_feed/PtPriceFeedFactory.sol#L6-L10) ## Price validation mechanism The validation system prevents the vault from transacting at "stale" or manipulated prices by enforcing a maximum allowed deviation. ![Image](https://ipor.io/docs/assets/build-on-fusion/image-3-4ccd77.png) __ - **Configuration**: Managed via `updatePriceValidation` which sets the `maxPriceDelta` for an asset [contracts/managers/price/PriceOracleMiddlewareManagerLib.sol139-152](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/managers/price/PriceOracleMiddlewareManagerLib.sol#L139-L152) - **Execution**: Usually triggered via a Pre-Hook (`ValidateAllAssetsPricesPreHook`) before vault actions like `execute` or `deposit` [contracts/handlers/pre_hooks/pre_hooks/ValidateAllAssetsPricesPreHook.sol18-23](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/handlers/pre_hooks/pre_hooks/ValidateAllAssetsPricesPreHook.sol#L18-L23) ## Access control and roles The system utilizes a hierarchy of roles defined in `Roles.sol` to secure configuration. | Role | Entity | Permission | | -------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `ADMIN_ROLE` | `AccessManager` | Highest level; manages all roles [contracts/libraries/Roles.sol11-13](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/libraries/Roles.sol#L11-L13) | | `ATOMIST_ROLE` | `PlasmaVault` | Can update the `priceOracleMiddleware` address [contracts/libraries/Roles.sol44-45](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/libraries/Roles.sol#L44-L45) | | `PRICE_ORACLE_MIDDLEWARE_MANAGER_ROLE` | `PriceOracleMiddlewareManager` | Manages asset price sources and validation deltas [contracts/libraries/Roles.sol102-105](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/libraries/Roles.sol#L102-L105) | | `SET_ASSETS_PRICES_SOURCES` | `PriceOracleMiddlewareWithRoles` | Global permission to set price sources [contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol27](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol#L27-L27) | | `ADD_PT_TOKEN_PRICE` | `PriceOracleMiddlewareWithRoles` | Permission to deploy Pendle PT feeds [contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol28](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol#L28-L28) | ## Data normalization All prices returned by the middleware system are normalized to 18 decimals (WAD) to ensure consistency across the IPOR Fusion protocol. - **Normalization Formula**: If a feed has `N` decimals, the price is scaled by `10^{(18-N)}` [contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol76-77](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol#L76-L77) - **Batch Processing**: `getAssetsPrices` allows fetching multiple asset prices in a single call, returning arrays of prices all in 18-decimal format [contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol92-107](https://github.com/IPOR-Labs/ipor-fusion/blob/c26a0a9d/contracts/price_oracle/PriceOracleMiddlewareWithRoles.sol#L92-L107) --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/pause-functionality.md # Pause Functionality > What pausing a vault does, who can trigger it, and its effect on in-flight operations. ## Introduction The pause functionality in IPOR Fusion serves as an emergency security mechanism designed to instantly halt specific smart contract operations. It is a defensive tool used to protect vault assets and prevent malicious state mutations during critical events, such as suspected exploits, severe oracle failures, or extreme market volatility. ### The Circuit Breaker Concept In decentralized finance, a circuit breaker acts as a fail-safe that stops execution when abnormal conditions are detected. When the pause function is triggered in IPOR Fusion, it immediately closes access to critical operational functions on the affected contract. This freezes state-changing operations—such as strategy execution or market balance updates—preventing any further asset movement or configuration changes until the threat is assessed and resolved. ### What is a Target Contract? To understand how pausing works in IPOR Fusion, it is essential to understand the concept of a **target contract**. Because IPOR Fusion uses a modular, factory-based architecture, the protocol consists of many independent deployments rather than a single monolithic system. A target contract refers to any specific smart contract governed by the `IporFusionAccessManager`. Most commonly, a target contract is an individual `PlasmaVault` instance. However, it can also refer to supporting infrastructure, such as a specific `WithdrawManager`, `FeeManager`, or `RewardsClaimManager`. When a pause is initiated, the Access Manager "closes" the route to that specific target contract, effectively halting its operations. ### Design Philosophy: Isolation and Immediacy The design of the pause mechanism is built on two core principles: 1. **Risk Isolation:** Unlike monolithic protocols that require a global freeze, IPOR Fusion's pause mechanism is localized. Pausing one target contract (e.g., `PlasmaVault A`) strictly halts operations for that specific vault. It does not disrupt `PlasmaVault B`, nor does it affect the broader `FusionFactory` deployment infrastructure. This isolation ensures that unrelated vaults and unaffected strategies can continue operating normally. 2. **Immediate Execution:** Because pausing is strictly a defensive maneuver, it is designed to be executed instantly. While typical structural or configuration changes in IPOR Fusion are subject to execution delays (timelocks) to protect users, emergency pauses bypass these delays to mitigate market anomalies, ongoing attacks, or critical failures immediately. ## Technical Mechanism ### AccessManager Integration In IPOR Fusion, the pause state is not handled by a traditional, standalone `Pausable` modifier residing on the vault itself. Instead, it is centrally managed by the `IporFusionAccessManager`, which extends OpenZeppelin's standard `AccessManager`. This architectural choice consolidates security controls. By moving the pause logic to the Access Manager layer, the protocol ensures that the ability to freeze a contract is cryptographically tied to the exact same system that governs role hierarchies, execution delays, and access control. Only accounts granted the `GUARDIAN_ROLE` (Role ID: 2) have the authority to trigger this defensive state. ### The `updateTargetClosed()` Function To initiate a pause, an authorized Guardian calls the `updateTargetClosed()` function directly on the `IporFusionAccessManager`. Vaults created with Fusion Factory v9 can also be paused through `PlasmaVaultPauser`, a small contract that holds the Guardian role. Its owner whitelists an account for one vault; that account can then pause that vault once. The pauser can only close a vault, never reopen it: reopening stays with a Guardian account calling `updateTargetClosed(vault, false)`. ``` function updateTargetClosed(address target, bool closed) external ``` - **`target`**: The address of the specific smart contract to be paused (e.g., the `PlasmaVault`). - **`closed`**: A boolean flag. Setting this to `true` initiates the pause; setting it to `false` removes the pause. When `closed` is set to `true`, the Access Manager acts as a firewall. It instantly begins reverting any incoming calls to functions on the `target` contract that are protected by the `restricted` modifier. This effectively blocks strategy execution via `execute()`, market balance updates, and administrative configurations, locking down the contract's state. ### Execution Timing IPOR Fusion heavily utilizes time-locked operations; structural changes typically require an execution delay to give depositors a window to react. However, because pausing is an emergency defensive maneuver, it must bypass these standard timelocks to be effective against active threats. During the initialization of a vault ecosystem, the `IporFusionAccessManagerInitializerLibV1` explicitly configures the `GUARDIAN_ROLE` with a zero-day execution delay (`executionDelay: 0`). Because of this, when a Guardian calls `updateTargetClosed()`, the transaction does not need to be scheduled in the queue—it is executed and enforced in the very same block. ## Operational Impact When a Guardian triggers a pause on a target contract, the effects are immediate and strictly scoped to functions utilizing the `restricted` modifier on that specific address. ### Halted Operations For a standard `PlasmaVault` target, pausing the contract halts the following core operations: - **Strategy Execution:** The `ALPHA_ROLE` can no longer call the `execute()` function. This prevents the vault from interacting with external protocol fuses (e.g., supplying, borrowing, or swapping assets). - **Market Accounting:** The `updateMarketsBalances()` function is blocked, freezing position valuations and preventing performance fee minting based on potentially manipulated oracle data. - **Governance & Configuration:** The `ATOMIST_ROLE` and `OWNER_ROLE` cannot alter the vault's state. Operations such as adding or removing fuses, granting market substrates, and updating fee configurations are temporarily frozen. - **Withdrawal Management:** If the `WithdrawManager` is the paused target, the `ALPHA_ROLE` is blocked from calling `releaseFunds()`, halting the progression of scheduled withdrawals. ### User Impact In IPOR Fusion, standard ERC4626 user functions are mapped to the `PUBLIC_ROLE` or `WHITELIST_ROLE` within the Access Manager. Consequently, these functions are protected by the `restricted` modifier and are strictly halted when the vault is paused: - **Deposits and Minting:** Users cannot add funds or mint new shares (`deposit()`, `mint()`, `depositWithPermit()`) while the vault is paused. - **Withdrawals and Redemptions:** Instant withdrawals (`withdraw()`, `redeem()`) and scheduled redemptions (`redeemFromRequest()`) are blocked. This ensures that during a suspected exploit or severe oracle failure, malicious actors cannot drain assets from the vault. - **Share Transfers:** If share transfers were previously enabled via `enableTransferShares()`, the `transfer()` and `transferFrom()` functions will revert, locking the vault shares to their current owners until the pause is lifted. ### Unaffected Systems A paused target contract does not equate to a complete system shutdown. The following operations remain unaffected: - **Read-Only State Queries:** Users, external protocols, and UI interfaces can still safely query read-only functions such as `totalAssets()`, `balanceOf()`, and the standard ERC4626 `preview` functions. - **Isolated Vault Infrastructure:** Because pausing is localized to the specific target contract address, other `PlasmaVault` instances deployed from the same `FusionFactory` remain fully operational. - **Independent Managers:** If only the `PlasmaVault` is paused, users may still theoretically initiate new withdrawal requests via `WithdrawManager.requestShares()`, though they will be unable to finalize the redemption on the vault until it is unpaused. ## The Pause Lifecycle The pause lifecycle involves three distinct phases: triggering the freeze, managing the paused state, and securely resuming normal operations. ### Triggering a Pause A pause is strictly a reactive security measure. The workflow for initiating a pause is as follows: 1. **Detection:** A threat is detected. This could be an anomaly identified by off-chain monitoring systems, an alert from an integrated protocol regarding an ongoing exploit, or severe deviations in oracle price feeds. 2. **Authorization:** An account or multisig holding the `GUARDIAN_ROLE` (Role ID: 2) verifies the threat. 3. **Execution:** The Guardian calls `IporFusionAccessManager.updateTargetClosed(targetContractAddress, true)`. 4. **Enforcement:** The transaction executes immediately (due to the 0-day delay), and the Access Manager begins reverting all restricted calls to the target contract. ### State Resolution While a target contract is paused, its internal state is frozen, but the external environment (e.g., market prices, integrated protocol states) continues to evolve. - **Pending Operations:** If there are time-locked operations scheduled in the `IporFusionAccessManager` queue (e.g., a pending fee configuration change initiated by an `ATOMIST`), these operations remain in the queue. If their execution time arrives while the target is paused, the execution will revert. **However, once the target contract is unpaused, these pending operations can be successfully executed, provided they have not been explicitly canceled by the Guardian.** - **Veto Power:** During the paused state, the `GUARDIAN_ROLE` retains the authority to call `AccessManager.cancel()`. This allows the Guardian to actively clear malicious or compromised operational transactions from the timelock queue while the vault remains safely frozen. ### Resuming Operations Unpausing a target contract requires careful assessment to ensure the threat has been neutralized and the vault state remains solvent. 1. **Assessment:** The vault's operating team (typically the Owner, Atomist, or Guardian) evaluates the incident, verifies that external protocols are secure, and confirms that price oracles are reporting accurate data. Because IPOR Fusion vaults are isolated and independently managed, this assessment responsibility lies strictly with the individual vault's administrators, not the Fusion DAO or the core development team. 2. **Execution:** An account holding the `GUARDIAN_ROLE` calls `IporFusionAccessManager.updateTargetClosed(targetContractAddress, false)`. 3. **Resumption:** The Access Manager lifts the restriction, allowing users to withdraw funds, Alphas to execute strategies, and normal ERC4626 operations to resume. Because unpausing restores access to potentially vulnerable operations, it should only be executed once the root cause of the initial threat has been fully resolved or mitigated via governance actions (e.g., removing a compromised fuse). --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/configuring-pre-hooks.md # Configuring Pre-hooks > How to attach pre-execution validation hooks (e.g. rate limits, price checks) to vault functions. Pre-hooks are very powerful feature of the Fusion Vaults. They allow an execution of an additional functions before invoking a primary action. Because the pre-hooks are very powerful functionality their management should **always be done by user with a long timelock.** IPOR web app will be alerting liquidity providers about the use of unverified pre-hooks. ## What is a pre-hook Fusion vault allows for an execution of a code when invoking restricted methods on the core vault. Pre-hooks are not available to methods on managers. Pre-hooks are smart contracts with an access to the memory of the contract and authority to execute functions. They can be used for various applications such as: - updating balance cache on markets - raising exceptions (effectively pausing functions) - triggering auto-withdrawals from complex strategies - etc. > Due to that power and flexibility it is important that the user allowed to modify the prehooks has timelock configured To add pre-hook to the vault use `setPreHookImplementaions` ```solidity PlasmaVaultGovernance(PLASMA_VAULT) .setPreHookImplementations(selectors, preHooks, substrates); ``` where `selectors` are the signatures of restricted methods on the vault, pre-hooks are addresses of implementations and substrates are the params required by the pre-hooks. Example implementation can be found in below test case: . It demonstrates the use of the pre-hook that rebalances the cache of the vault before deposit and withdrawal while ignoring balances with dust. List of the deployed prehooks: ### Bundled Pre-hooks IPOR Fusion web-app comes with some bunled prehooks that bring some valuable functionalities to the vaults. This list may not be exhaustive as there are new components being developed but below you can find some pre-hooks available at the time of writing this documentation and use cases for them. #### Function Pausing Pre-hook Under the prehooks section of the administrative panel `/edit` you can find `Pause Functions` . You can use this interface to [pause](https://ipor.io/docs/build-on-fusion/developer-guide/pause-functionality.md) individual functions of the fusion vaults. Underneeth a special pre-hook is used that simply raises an exception. By attaching it before a restricted method you essentially render it unable to execute. ![Image](https://ipor.io/docs/assets/build-on-fusion/function-pausing-7bd98f.png) __ #### Auto Rebalance Pre-hook Another prehook provided via the app.ipor.io interface is the auto rebalance prehook. Because rebalancing of the vault before deposit and withdrawals would cost additional gas, vaults for gas optimisation rely on cached balances that are refreshed each time the vault interacts with connected markets. You can force rebalancing before every deposit/withdraw action by using this pre-hook. ![Image](https://ipor.io/docs/assets/build-on-fusion/auto-rebalance1-32de48.png) __ ![Image](https://ipor.io/docs/assets/build-on-fusion/auto-rebalance2-6d46a7.png) __ #### Exchange rate validator Another example of what pre-hooks can be used for is validating of the changes in the exchange rate since the last rebalance. When this is enabled then pre-hook will keep track of the exchange rates and will block selected functions is the jump of the share exchange rate exeeds the defined threshold. This is useful in case you want to restrict access in the situaltions where vault is misconfigured or price oracles are experiencing issues. ![Image](https://ipor.io/docs/assets/build-on-fusion/exchange-rate-validator-2-950b20.png) __ ![Image](https://ipor.io/docs/assets/build-on-fusion/https-files-gitbook-com-v0-b-gitbook-x-prod-appspot-com-o-spaces-2fr8w71un6csi2mpkvqqk9-2fuploads-2f1ppbek7q4xmgkmojakry-2fexchange-20rate-20validator-201-pngalt-media-token-2053d134-3df3-412c-9274-dc0e7e001bc0-f23a34.avif) __ --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/security-and-audits.md # Security and Audits > IPOR's internal QA process, AI-assisted audit tooling, and the list of completed third-party audits with scope and reports. ## Code Security and Quality Assurance ### Internal Development Process IPOR Labs employs a multi-layered quality assurance process covering every stage of the feature lifecycle: 1. Unit and integration testing — every new feature and code modification requires test coverage. 2. Internal audits using specialized LLM models — as part of our code review process, we leverage proprietary auditing tools powered by state-of-the-art large language models (LLMs). These tools are specifically designed for smart contract analysis and enable detection of subtle logic bugs, state inconsistencies, and potential attack vectors that may escape traditional code review. 3. Code Review — every change undergoes a peer review process by team members, providing an additional layer of quality and security verification. ### Proprietary Audit Tools IPOR Labs developes in-house security audit tools powered by the latest AI models. These tools specialize in: - Deep business logic analysis of smart contracts (Feynman technique — questioning every line of code, operation ordering, and implicit assumptions) - State inconsistency detection — identifying situations where an operation mutates one piece of coupled state without updating dependent components - Combined multi-layer analysis — fusing results from different audit techniques in a feedback loop to discover bugs at intersections that no single technique would catch alone ### External Audit Tool Evaluation IPOR Labs actively tests and evaluates third-party automated smart contract security audit tools for potential inclusion in the pipeline: | Tool | Status | | --------------------------- | ---------------- | | Wake Arena BETA (Ackee) | Under evaluation | | AI Agent (Spearbit/Cantina) | Under evaluation | | MixBytes Audit Tools | Under evaluation | | Olympix | Under evaluation | | TestMachine | Under evaluation | ### Production Instance Auditing Beyond source code audits, IPOR Labs conducts systematic verification of production instances, covering: - Code — verifying deployed code matches previously audited versions - Configuration — reviewing vault configuration parameters, role permissions, and module settings - Markets — validating market configurations, limits, and risk parameters of active strategies ## Audits ### BlocSec Date: February 28, 2025 (v 1.0) _**Covers the currently live contracts**_ Report (Google Docs PDF): **Scope** - Updated IPOR Fusion: - Fusion Vault - Base Fuses - Rewards Manager - Access Management - Price Oracle Middleware - Prehooks - Context Manager - Withdraw Manager ### Protofire Date: September 6, 2024 (v 1.1) _**Covers the currently live contracts**_ Report (Google Docs PDF): [https://drive.google.com/file/d/1UZE7J-pTfHY-XtgZtVYMAOh4tHXTCCN2/view](https://drive.google.com/file/d/1UZE7J-pTfHY-XtgZtVYMAOh4tHXTCCN2/view?usp=sharing) **Scope** - IPOR Fusion: - Fusion Vault - Base Fuses - Rewards Manager - Access Management - Price Oracle Middleware --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/open-source-repository.md # Open-source Repository > Where the Fusion smart-contract source lives and how it's licensed. Fusion's codebase is fully open source and can be accessed in this GitHub repository: --- Source: https://ipor.io/docs/build-on-fusion/developer-guide/api.md # API > Base URL, endpoints, address-casing and error-format details for calling the public Fusion API directly. ## IPOR Static API — Developer Guide Public, read-only JSON API serving IPOR Fusion vault data, including the historical time series behind the charts on [app.ipor.io](https://app.ipor.io/). **Base URL:** `https://api.ipor.io` No API key. No authentication. No rate limit. No query parameters — every input is encoded in the URL path. > **Important:** the long-range history buckets (`1y`, `all`) are **intentionally stale** by days to weeks. A request for `-all` alone returns a series whose most recent point may be around three weeks old, with no error to indicate this. See Period buckets and freshness. This behaviour is by design and will not change; clients are expected to merge buckets. --- ### Quick start Chart a vault's APY over the last 30 days: ```bash # Note the lowercase address. Anything else 404s. curl --compressed \ 'https://api.ipor.io/v2/fusion/vault-history/1/0x43ee0243ea8cf02f7087d8b16c8d2007cc9c7ca2-30d' \ | jq '.history[-1] | {blockTimestamp, apy, tvl}' ``` ```json { "blockTimestamp": "2026-07-08T13:14:47Z", "apy": "3.2864762350246543", "tvl": "490462.27822644341523" } ``` Note that the most recent point is already approximately 21 hours old. Obtaining a series that extends to the present requires additionally fetching `-7d` and merging the two. The reference client performs this automatically. Discover vault addresses first: ```bash curl --compressed 'https://api.ipor.io/dapp/plasma-vaults-list' \ | jq '.plasmaVaults[] | {chainId, address, name, apr}' ``` --- ### Conventions **Addresses must be lowercase.** The API is static JSON objects on S3 behind CloudFront, so paths are object keys and are case-sensitive. A checksummed (mixed-case) address returns `404`. ``` 200 /v2/fusion/vault-history/1/0x43ee0243ea8cf02f7087d8b16c8d2007cc9c7ca2-7d 404 /v2/fusion/vault-history/1/0x43Ee0243eA8CF02f7087d8B16C8D2007cC9c7cA2-7d ``` This requires care, because **`/dapp/plasma-vaults-list` returns most of its addresses checksummed** (mixed-case). An address taken from the vault list and used unmodified in a history path will return 404. Apply `.toLowerCase()` before constructing any path. **Numbers are decimal strings, not JSON numbers.** `"tvl": "490462.27822644341523"`. The precision exceeds that of an IEEE-754 double. Parse them with a decimal library (`decimal.js`, `big.js`, `bignumber.js`). Passing them through `Number()` will discard low-order digits. Token amounts (`totalAssets`, `balance`) are raw base units and must be scaled by the asset's `assetDecimals`. **Timestamps are ISO-8601 UTC**, e.g. `"2026-07-09T09:14:47Z"`. **Every history point carries a `blockNumber`**, which is the correct key for joining, deduplicating, and ordering series. Prefer it over the timestamp. **Errors are XML, not JSON.** A miss — unknown vault, unsupported period, or a non-lowercase address — returns the raw S3 error document with `content-type: application/xml`: ```xml NoSuchKeyThe specified key does not exist.... ``` A client that calls `.json()` on any non-2xx response will throw a parse error rather than surface a clean 404. Branch on `response.status` before parsing. **Responses are gzipped** (`content-encoding: gzip`). Send `Accept-Encoding: gzip` (`curl --compressed`); browsers and `fetch` do this automatically. The uncompressed payloads are much larger — see Payload sizes. **CORS is open** (`access-control-allow-origin: *`, `GET` only). The header is returned when an `Origin` request header is present, so browser calls work directly with no proxy. --- ### Period buckets and freshness Both history endpoints take a period suffix on the last path segment: | Period | Coverage | | ------ | ------------------- | | `7d` | Trailing 7 days | | `30d` | Trailing 30 days | | `1y` | Trailing 365 days | | `all` | Full vault lifetime | Points are spaced roughly **hourly**. #### Why the data is spliced this way The API is not a database query layer. Every response is a **pre-rendered file written to S3** and served through a CDN. This is a deliberate design decision made for security and performance: there is no query surface to exploit or overload, and reads remain fast and inexpensive at any traffic level. The trade-off is that a file's contents are only as current as its last write, and rewriting a multi-megabyte object is costly. Consequently, **the older a file's data, the less frequently it is regenerated**. The `7d` file is small and is rewritten frequently. The `all` file is large and consists mostly of immutable history, so it is rewritten rarely. This is the reason the most recent point in a bucket lags real time by an amount that grows with the size of the bucket. Measured against vault `0x43ee0243ea8cf02f7087d8b16c8d2007cc9c7ca2` on Ethereum at `2026-07-09T10:00Z`: | Period | Points | Newest point | Trails real time by | | ------ | ------ | ------------------- | ------------------- | | `7d` | 168 | `2026-07-09T09:14Z` | **\~45 minutes** | | `30d` | 720 | `2026-07-08T13:14Z` | **\~21 hours** | | `1y` | 8,714 | `2026-07-06T13:14Z` | **\~2.9 days** | | `all` | 14,726 | `2026-06-17T13:14Z` | **\~22 days** | The exact lag varies by vault and by regeneration cycle. Do not depend on the specific values above. Depend instead on the ordering, which is invariant: `7d` is always the most current bucket and `all` is always the least current. **This is intended behaviour and will not change.** Rewriting the multi-megabyte `all` object every hour would provide no benefit, because its stale tail can be reconstructed inexpensively from the smaller, more current buckets. Clients are expected to perform this reconstruction. #### The merge rule To render a period accurately, fetch the requested bucket **plus every more current bucket that covers its stale tail**, then merge the point sets: | Requested | Fetch | | --------- | ------------------ | | `7d` | `7d` | | `30d` | `30d`, `7d` | | `1y` | `1y`, `30d`, `7d` | | `all` | `all`, `30d`, `7d` | Merge by `blockNumber`, sort ascending, and on a duplicate `blockNumber` retain the point from the more current bucket. The buckets overlap, so duplicates are expected and must be collapsed. Otherwise any aggregate computed over the series (averages, integrals, point counts) will double-count the overlap region. Applying this, all four periods become current to within \~1 hour: ``` 7d pts= 168 first=2026-07-02T11:14:47Z last=2026-07-09T10:14:47Z trails=0.2h 30d pts= 741 first=2026-06-08T14:14:47Z last=2026-07-09T10:14:47Z trails=0.2h 1y pts= 8783 first=2025-07-06T14:14:47Z last=2026-07-09T10:14:47Z trails=0.2h all pts= 15249 first=2024-09-30T21:15:11Z last=2026-07-09T10:14:47Z trails=0.2h ``` Tolerate a `404` on an individual bucket. A vault younger than a year has no `1y` object, but its `all` and `30d` objects exist. Treat the merge as successful if at least one bucket resolves. Propagate any non-404 failure rather than rendering a partial series without indication. --- ### Endpoints #### `GET /dapp/plasma-vaults-list` A compact vault directory (\~100 KB). Use this endpoint to enumerate vaults. It is preferable to `/fusion/vaults`, which is approximately 44 MB. ```jsonc { "timestamp": "2026-07-09T10:01:15.819Z", "version": "…", "plasmaVaults": [ { "name": "IPOR USDC Lending Optimizer Ethereum", "chainId": 1, "address": "0x43ee0243ea8cf02f7087d8b16c8d2007cc9c7ca2", // may be MIXED-CASE "apr": "3.286746235024654313", "totalAssets": "463267371354", // raw base units "assetAddress": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "assetSymbol": "USDC", "assetDecimals": 6, "marketIds": ["1", "11", "3", "4", "14"], "fuses": ["0x465D639EB964158beE11f35E8fc23f704EC936a2", "…"] } ] } ``` This is the authoritative list of vaults the API serves. Remember to lowercase `address` before using it in a history path. --- #### `GET /v2/fusion/vault-history/{chainId}/{vaultAddress}-{period}` Per-vault time series: APY, TVL, and allocation across markets. **This is the primary charting endpoint.** Subject to the merge rule. `vaultAddress` **must be lowercase**. ```jsonc { "history": [ { "blockNumber": 25444165, "blockTimestamp": "2026-07-02T10:14:47Z", "apy": "3.2864762350246543", "rewardsApy": "0.104", "vestingApy": null, "underlyingAssetApy": "3.11", "assetsToSharesRatio": "1.0412…", "tvl": "490462.27822644341523", // USD "totalBalance": "490648.346799", // underlying asset units "marketBalances": [ { "protocol": "aave-v3", "marketId": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "balanceType": "DEPOSIT", "balance": "11096.690979", "balanceUsd": "11092.48278088003383" } ] } ] } ``` `marketBalances` provides the data for the historical-allocation (stacked area) chart: each point records how the vault's assets were distributed across underlying protocols at that block. `apy` is net of fees; `underlyingAssetApy` and `rewardsApy` decompose it. Some vaults additionally expose `dexPositionBalances` (LP positions, with `token0`/`token1` USD amounts) and `rewardsVestingApy`. Treat all of these as optional and nullable. --- #### `GET /v2/fusion/market-history/{chainId}/{protocol}/{substrate}-{period}` Per-market time series: supply and borrow rates and market size for one market on one protocol. Use it to chart the yield of the venues a vault allocates into. Subject to the merge rule. - `protocol` — a protocol slug, e.g. `aave-v3`. - `substrate` — identifies the market within the protocol, **lowercase**. For lending pools this is the underlying asset address; for vault-shaped markets (`erc4626`, `meta-morpho`, `morpho-blue`) it is the market or vault address. ```jsonc { "points": [ { "blockNumber": 25444165, "timestamp": "2026-07-02T10:14:47Z", "supplyApy": "4.1034406162952586", "supplyBaseApy": "4.1034406162952586", "supplyRewards": [ { "assetAddress": "0xc00e94cb662c3520282e6f5717214004a7f26888", "rewardApy": "0.1008130660673186", "type": "INSTANT" } ], "borrowApy": "4.9405590449566654", "borrowBaseApy": "4.9405590449566654", "borrowRewards": [], "totalSupply": "2017881149.188354", "totalBorrow": "1869968394.182922" } ] } ``` `supplyApy` = `supplyBaseApy` + the sum of `supplyRewards[].rewardApy`. Point density is at least hourly and may be finer than the vault history. Two protocols use a substrate convention that differs from their market id: `spark` markets are keyed by the **DAI address**, and Harvest vaults use the protocol slug `harvest-erc4626`. --- #### `GET /fusion/vaults` The full vault and market snapshot, **\~44 MB uncompressed** (\~4 MB gzipped). It embeds a `history` array within every vault object, which accounts for most of the payload size. ```jsonc { "creationDate": "2026-07-09T10:58:00.019119154Z", "vaults": [ { "chainId": 1, "address": "…", "name": "…", "apy": "…", "apr30d": "…", "historicalApr": "…", "history": [ /* … */ ], "tvl": "…", "managedByIporAlpha": false, "alphaDisabled": false } ], "markets": [ { "chainId": 1, "protocol": "euler-v2", "marketId": "0xdc1a…", "supplyApy": "…", "supplyBaseApy": "…", "supplyRewards": [], "borrowApy": "…", "supplyApr30d": "…", "borrowApr30d": "…" } ] } ``` **Do not fetch this endpoint to read a single vault.** Use `/dapp/plasma-vaults-list` for enumeration and the `-history` endpoints for time series. Its principal use is the `markets[]` array, which provides current rates for every market on every chain in a single request. This is the sole reason the IPOR frontend retrieves it. --- #### `GET /fusion/vaults-customization-list` Atomist-supplied presentation metadata for vaults that have opted in. Only a minority of vaults appear; absence from this list is normal and not an error. ```jsonc [ { "chainId": 1, "vaultAddress": "0x8f5855D30610b176c972F844B93A28c6D1553416", "description": "x*y=k", "vaultLogoUrl": "https://api.ipor.io/fusion/vaults-customization/1/0x8f58…/vault-logo", "announcements": [] } ] ``` --- #### `GET /fusion/markets/{chainId}/{protocol}/{marketId}` _(v1)_ The v1 market-history endpoint. Returns market metadata alongside a points array of the same shape as v2: ```jsonc { "chainId": 1, "protocol": "aave-v3", "marketId": "0xa0b8…", "createdAt": "…", "points": [ /* same shape as market-history */ ] } ``` **v1 is limited to a trailing 30-day window.** It provides no period selector and returns no data older than 30 days. **Prefer v2 for new integrations.** `/v2/fusion/market-history/…` exposes the full history from vault creation through the `{period}` suffix, up to and including `all`. v1 remains appropriate only where a fixed 30-day window is sufficient and the merge rule is not required. --- ### Supported chains `chainId` appears in every history path. | Chain | `chainId` | | --------- | --------- | | Ethereum | `1` | | Arbitrum | `42161` | | Base | `8453` | | Unichain | `130` | | Ink | `57073` | | Plasma | `9745` | | Avalanche | `43114` | Chain support expands over time. Rather than hardcoding this table, derive the live set from `GET /dapp/plasma-vaults-list → plasmaVaults[].chainId`. --- ### Protocol slugs The `{protocol}` path segment takes a slug such as `aave-v3`, `compound-v3`, `morpho-blue`, `meta-morpho`, `euler-v2`, `spark`, `moonwell`, `gearbox-v3`, `fluid-instadapp`, `pendle`, or `erc4626`. **Do not hardcode the set.** New protocols and yield-bearing assets are added continuously, so any list reproduced here becomes inaccurate over time. Derive it at runtime: ```bash curl --compressed 'https://api.ipor.io/fusion/vaults' \ | jq -r '[.markets[].protocol] | unique | .[]' ``` Two slugs follow non-obvious conventions: `spark` markets use the **DAI address** as their substrate, and Harvest vaults use the slug `harvest-erc4626` rather than `erc4626`. --- ### Payload sizes and caching Orders of magnitude, uncompressed, for a mature Ethereum vault. Payloads grow with vault age and market count, so treat these as a guide to relative cost, not as fixed values: | Endpoint | `7d` | `30d` | `1y` | `all` | | ---------------- | -------- | -------- | ------ | ----------- | | `vault-history` | \~200 KB | \~850 KB | \~8 MB | **\~14 MB** | | `market-history` | \~100 KB | \~700 KB | \~5 MB | \~6 MB | | Endpoint | Size | | ----------------------------------- | ---------------------------- | | `/dapp/plasma-vaults-list` | \~100 KB (\~20 KB gzipped) | | `/fusion/vaults-customization-list` | \~15 KB | | `/fusion/markets/…` (v1) | \~400 KB | | `/fusion/vaults` | **\~44 MB** (\~4 MB gzipped) | Responses are served from CloudFront and carry `etag` and `last-modified`. Use conditional requests (`If-None-Match`) to avoid re-downloading unchanged objects. **Cache the long buckets.** An application that re-fetches `-all` at a short interval re-downloads approximately 14 MB to obtain data that is regenerated only rarely. The appropriate polling strategy follows from the freshness table: - Fetch `all` and `1y` **once** and cache them for hours or days. - Re-poll **only `7d`** (and `30d`) at your refresh interval. These objects are small and contain all recently added points. - Re-run the merge against the cached long bucket on each refresh. Revalidate the cached long buckets periodically with a conditional request rather than caching them indefinitely. Historical data is occasionally recomputed to correct defects, so an `all` object can change without gaining new points. See Data accuracy and corrections. --- ### Reference TypeScript client Dependency-free. Handles bucket merging, address normalisation, and the XML error case. Verified against the live API. ```ts /** * Minimal client for the IPOR static API (https://api.ipor.io). */ const BASE_URL = 'https://api.ipor.io'; export type Period = '7d' | '30d' | '1y' | 'all'; /** * Buckets to fetch for a requested period, ordered least-current to most-current. * On a duplicate blockNumber the last bucket takes precedence, so the most * current bucket must be listed last. */ const BUCKETS_TO_MERGE: Record = { '7d': ['7d'], '30d': ['30d', '7d'], '1y': ['1y', '30d', '7d'], all: ['all', '30d', '7d'], }; /** Numeric fields are decimal strings, not numbers — parse with care. */ type Decimal = string; export interface MarketBalance { marketId: string | null; protocol: string | null; balance: Decimal; balanceUsd: Decimal; balanceType: string | null; } export interface VaultHistoryPoint { blockNumber: number; blockTimestamp: string; // ISO-8601, e.g. "2026-07-09T09:14:47Z" apy: Decimal | null; rewardsApy: Decimal | null; vestingApy: Decimal | null; underlyingAssetApy: Decimal | null; assetsToSharesRatio: Decimal | null; tvl: Decimal; totalBalance: Decimal; marketBalances: MarketBalance[]; } export interface VaultHistoryResponse { history: VaultHistoryPoint[]; } export interface RewardApy { assetAddress: string; rewardApy: Decimal; type: string; } export interface MarketHistoryPoint { blockNumber: number; timestamp: string; supplyApy: Decimal | null; supplyBaseApy: Decimal | null; supplyRewards: RewardApy[]; borrowApy: Decimal | null; borrowBaseApy: Decimal | null; borrowRewards: RewardApy[]; totalSupply: Decimal | null; totalBorrow: Decimal | null; } export interface MarketHistoryResponse { points: MarketHistoryPoint[]; } /** A missing object. The API answers with an S3 XML body, not JSON. */ export class IporNotFoundError extends Error { constructor(readonly path: string) { super(`No data at ${path}`); this.name = 'IporNotFoundError'; } } async function getJson(path: string, signal?: AbortSignal): Promise { const response = await fetch(`${BASE_URL}${path}`, { signal }); // Unknown vault, unsupported period, or a non-lowercase address all land here. if (response.status === 404) throw new IporNotFoundError(path); if (!response.ok) { throw new Error(`GET ${path} failed: ${response.status}`); } // Guard against XML slipping through on a non-404 error status. const contentType = response.headers.get('content-type') ?? ''; if (!contentType.includes('application/json')) { const body = await response.text(); throw new Error(`GET ${path} returned ${contentType}: ${body.slice(0, 200)}`); } return (await response.json()) as T; } /** S3 keys are case-sensitive; `plasma-vaults-list` returns mixed-case addresses. */ const normalizeAddress = (address: string): string => address.toLowerCase(); /** * Concatenate buckets and sort by blockNumber ascending, retaining the LAST * occurrence of any repeated blockNumber. Callers pass buckets least-current * first, so an overlapping point is taken from the most current bucket * containing it. */ function mergeByBlockNumber( buckets: T[][], ): T[] { const byBlock = new Map(); for (const bucket of buckets) { for (const point of bucket) byBlock.set(point.blockNumber, point); } return [...byBlock.values()].sort((a, b) => a.blockNumber - b.blockNumber); } /** * Fetch every bucket for `period` and merge. Buckets are fetched concurrently; * a missing one is tolerated as long as at least one resolves, since not every * vault has a full `1y`/`all` history. */ async function fetchMerged< TPayload extends object, T extends { blockNumber: number }, >( period: Period, buildPath: (bucket: Period) => string, extract: (payload: Awaited) => T[], signal?: AbortSignal, ): Promise { const settled = await Promise.allSettled( BUCKETS_TO_MERGE[period].map((bucket) => getJson(buildPath(bucket), signal), ), ); const rejection = settled.find( (r): r is PromiseRejectedResult => r.status === 'rejected' && !(r.reason instanceof IporNotFoundError), ); if (rejection) throw rejection.reason; const resolved = settled .filter( (r): r is PromiseFulfilledResult> => r.status === 'fulfilled', ) .map((r) => extract(r.value)); if (resolved.length === 0) throw new IporNotFoundError(buildPath(period)); return mergeByBlockNumber(resolved); } /** * Vault APY / TVL / per-market allocation over time, hourly. * * The returned series is current to within ~1h regardless of `period`, because * the stale tail of the long buckets is backfilled from `30d` and `7d`. */ export function fetchVaultHistory(args: { chainId: number; vaultAddress: string; period: Period; signal?: AbortSignal; }): Promise { const address = normalizeAddress(args.vaultAddress); return fetchMerged( args.period, (bucket) => `/v2/fusion/vault-history/${args.chainId}/${address}-${bucket}`, (payload) => payload.history, args.signal, ); } /** * Supply/borrow APY and size for one market, hourly. */ export function fetchMarketHistory(args: { chainId: number; protocol: string; substrate: string; period: Period; signal?: AbortSignal; }): Promise { const substrate = normalizeAddress(args.substrate); return fetchMerged( args.period, (bucket) => `/v2/fusion/market-history/${args.chainId}/${args.protocol}/${substrate}-${bucket}`, (payload) => payload.points, args.signal, ); } export interface PlasmaVaultListItem { chainId: number; /** Mixed-case as returned; lowercase before using it in a history path. */ address: string; name: string; apr: Decimal | null; totalAssets: Decimal; assetAddress: string; assetSymbol: string; assetDecimals: number; marketIds: string[]; } export interface PlasmaVaultsList { timestamp: string; version: string; plasmaVaults: PlasmaVaultListItem[]; } /** ~100 KB. Preferred for enumerating vaults; `/fusion/vaults` is ~44 MB. */ export function fetchPlasmaVaultsList( signal?: AbortSignal, ): Promise { return getJson('/dapp/plasma-vaults-list', signal); } ``` #### Usage ```ts // Full lifetime APY series, current to within the hour. const history = await fetchVaultHistory({ chainId: 1, vaultAddress: '0x43Ee0243eA8CF02f7087d8B16C8D2007cC9c7cA2', // casing handled period: 'all', }); const series = history .filter((p) => p.apy !== null) .map((p) => ({ t: Date.parse(p.blockTimestamp), apy: Number(p.apy) })); // Underlying market rates. const aaveUsdc = await fetchMarketHistory({ chainId: 1, protocol: 'aave-v3', substrate: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', period: '30d', }); ``` --- ### Data accuracy and corrections **Vault APY figures are not guaranteed to be exact.** Two causes account for most discrepancies: - **Strategy changes.** A vault's strategy can be reconfigured over its lifetime. Historical points computed under a previous configuration will not always be directly comparable with later ones. - **Indexing bugs.** The pipeline that computes APY, TVL, and market balances is complex, and defects occur from time to time. **Corrections are applied retroactively.** When a bug is identified, the affected history is recomputed and the underlying S3 objects are rewritten. A series you fetched previously may therefore differ from the same series fetched later, and the corrected values are the authoritative ones. If you cache history, treat `etag` and `last-modified` as the signal to re-read rather than assuming historical points are immutable. This applies to the long buckets as well: an `all` object that has not gained new points may still have been rewritten to fix older ones. **Please report anything that looks wrong.** If you observe an APY, TVL, or allocation figure that does not match your own calculation or on-chain observation, report it in the IPOR Discord: **** Including the vault address, chain id, period, and the affected timestamps or block numbers will make the issue substantially faster to diagnose. Reports from integrators are a meaningful source of the corrections described above. --- ### Known limitations **`1y` and `all` are stale by design.** Described in Period buckets and freshness. Without merging, a chart will terminate weeks before the present. **APY values may be revised.** Historical points are not immutable; see Data accuracy and corrections. **Overlapping buckets contain duplicate `blockNumber` values.** Deduplicate during the merge. Note that the IPOR frontend's own implementation does not deduplicate. This has no visible effect on a line chart but produces incorrect results for any aggregate computation, so that implementation should not be treated as a reference for numeric work. **Addresses are case-sensitive in paths but returned checksummed in payloads.** Addresses obtained from the vault list will return 404 if used without normalisation. **404 responses return XML.** Check `response.status` before parsing the body. **No pagination, filtering, or date-range selection.** Buckets are retrieved in full. There is no mechanism to request a value between two arbitrary dates; fetch the enclosing bucket and slice the series client-side. **Two market-history versions coexist.** v1 (`/fusion/markets/…`) is limited to a trailing 30-day window. v2 (`/v2/fusion/market-history/…`) serves the full history from vault creation, selected by the `{period}` suffix. Use v2 unless a 30-day window is sufficient. **No published SLA or changelog.** This API serves app.ipor.io. It is public and stable in practice, but response shapes may acquire additional fields. Parse defensively: ignore unknown fields, and treat every documented field other than `blockNumber`, `blockTimestamp`/`timestamp`, `tvl`, and `totalBalance` as potentially null. --- ### Provenance Endpoint inventory derived from the IPOR webapp at `origin/develop` commit `6a734ab9d` — principally `src/config/constants.ts`, `src/fusion/api/vault-history/`, `src/fusion/api/markets/`, and `src/fusion/pages/list/list/usePlasmaVaultsList.ts`. All shapes, sizes, status codes, freshness figures, and the merge behaviour were verified against the live API on **2026-07-09**. Figures in the freshness and size tables are point measurements against vault `0x43ee0243ea8cf02f7087d8b16c8d2007cc9c7ca2` (Ethereum) and the `aave-v3` / `compound-v3` USDC markets. They characterise the regeneration cadence; they are not guarantees. Counts that move — how many vaults, markets, protocols, or chains exist — are deliberately omitted from this document. Query them from `/dapp/plasma-vaults-list` and `/fusion/vaults` instead --- Source: https://ipor.io/docs/fusion-for-institutions.md # Executive Summary: The Prime Brokerage Protocol of DeFi IPOR Fusion is **institutional grade vault infrastructure**, a modular, onchain prime brokerage protocol designed for regulated asset managers and institutional allocators. It provides an entire suite of vault technology and tools for managing digital asset strategies with institutional discipline, enabling segregated mandates, programmable risk controls, and transparent exposure verification. Unlike monolithic vault systems, Fusion utilizes a **mandate-adaptive architecture** that separates the **immutable non-custodial layer** from the configurable strategy layer. This allows institutions to extend their investment capabilities by adding markets or adjusting risk parameters without the operational risk of vault redeployment or opaque core contract upgrades. --- Source: https://ipor.io/docs/fusion-for-institutions/institutional-grade-infrastructure.md # Institutional-Grade Infrastructure Fusion is built on a foundation of strict asset segregation and standardized interoperability, mirroring the structure of **Separately Managed Accounts (SMAs)**. ## **Segregated Mandate Vehicles** Each **Fusion Vault** is an isolated **Mandate Vehicle** with: - **Dedicated Custody:** Assets are owned directly by the specific vault contract and cannot be commingled across different vehicles. - **Independent Configuration:** Every mandate has its own dedicated market whitelist, risk parameters, and fee structures. - [**ERC-4626**](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fusion-vault.md) **Compliance:** The use of the industry-standard tokenized vault interface ensures seamless integration with institutional custody solutions, reporting tools, and collateral management systems. - **Upgrade Safety:** Logic can be updated without the risk of corrupting existing vault data or asset balances, providing institutional-grade continuity. ## **Modular Execution Adapters (The Fuse System)** The protocol interacts with external DeFi venues (e.g., Aave, Morpho, Uniswap) via **Execution Adapters**, referred to as [Fuses](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fuse.md). These are immutable, stateless connectors that act as "pipes" between the vault and the market. - **Curated Universe:** The Vault Curator defines the authorized "investment universe" by whitelisting specific Fuses. Assets never leave this defined environment. - **Stateless Execution:** Fuses contain only the logic for protocol interaction; all assets and accounting remains within the vault's primary contract logic. --- Source: https://ipor.io/docs/fusion-for-institutions/governance-and-operational-control.md # Governance & Operational Control Fusion enables a clear **Separation of Duties** through a hierarchical [Role-Based Access Control](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/access-management.md) (RBAC) system. This ensures that strategy execution remains bounded by administrative guardrails. ## **Operational Roles** - **Portfolio Manager/Vault Curator (“**[**Atomist**](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-atomist.md)**”):** Acts as the primary strategy or mandate architect, defining the "Walled Garden" environment. They select the approved assets, Execution Adapters (Fuses), and risk bounds. - **Strategy Executor (“**[**Alpha**](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-alpha.md)**”):** Operates like a trader with **limited API keys**. They are free to execute active strategies and rebalance positions, but only within the pre-defined execution envelope. They cannot exfiltrate funds or interact with unauthorized protocols. - **Risk Manager:** Monitors exposure in real-time and adjusts safety parameters as market conditions evolve. This role can be integrated with professional external risk providers to provide continuous parameter optimization, market stress testing, and quantitative risk modeling. - **Emergency Controller (“Guardian”):** A specialized responder role capable of pausing operations or cancelling scheduled transactions with zero delay during market anomalies or security events. This role is designed to be integrated with real-time monitoring solutions to enable automated responses to detected threats. ## Execution Control & Delay Management Fusion provides granular control over how and when governance actions are finalized: - **Flexible Timelocks:** Different accounts assigned to the same role can have different execution delays. A cold-storage **Multisig** can be configured with zero delay for emergency responses, while an operational **EOA (Externally Owned Account)** could be subject to a mandatory 24-hour timelock for the same role. - **Global Safety Margins:** The **Owner** can enforce global minimum execution delays per role. This ensures that sensitive changes (e.g., modifying fee structures or adding new fuses) always provide a predictable audit window for stakeholders before completion. ## **Institutional Tooling & Automation** To support programmatic strategy execution, Fusion provides a comprehensive [**Python SDK**](https://ipor.io/docs/build-on-fusion/alpha/sdk.md). This allows Portfolio Managers to implement complex logic and automate rebalancing workflows without writing Solidity code, maintaining operational efficiency while staying strictly within the vault's secure execution envelope. ## **Transparency & Auditability** Every governance action, parameter change, and strategy interaction is recorded as a discrete onchain event. This provides a permanent, **event-level audit trail** for compliance officers, risk ratings agencies, insurers, and external regulators. #### --- Source: https://ipor.io/docs/fusion-for-institutions/programmable-risk-and-circuit-breakers.md # Programmable Risk & Circuit Breakers Fusion offers a multi-layered security framework that automates risk management through **risk surface enumeration**. ## **Market Allocation Limits** The system enforces maximum exposure caps per market. These limits are enforced at the smart contract level; if an operation would breach a cap, the transaction is rejected automatically. ## **Substrate-Based Allowlists** Access is restricted at the most granular level. An Atomist must explicitly grant permission for specific token addresses or market/pool identifiers ("[**Substrates**](https://ipor.io/docs/build-on-fusion/atomists/vault-configuration-step-by-step/substrates.md)**"**) before the vault can interact with them. ## **Automated Circuit Breakers (Pre-Hooks)** "Pre-Hooks" act as automatic circuit breakers that run immediately before any core vault operation. Some examples include: - **Price Freshness & Volatility:** Automatically reverts transactions if oracle data is stale or if asset prices have fluctuated beyond acceptable thresholds. - **NAV Integrity Protections:** Prevents transactions that would result in abnormal NAV shifts, protecting the vault against sandwich attacks or oracle manipulation. ## **Emergency Levers (Panic & Pause)** The protocol includes a suite of manual circuit breakers designed for rapid response: - **Global & Functional Pause:** The Guardian can pause the entire vault, or a single supporting contract such as the WithdrawManager, with no delay (see [Pause Functionality](https://ipor.io/docs/build-on-fusion/developer-guide/pause-functionality.md)). This effectively freezes the mandate’s state during periods of high uncertainty. - **Transactional Veto Power:** In the multi-step "Scheduled Redemption" flow, the Guardian has the authority to cancel pending requests before they reach the "Released" state. This serves as a critical stop-gap if a withdrawal request is deemed malicious or if market conditions make the exit detrimental to the remaining pool. - **Market-Specific Halting:** Curators can instantly revoke a specific Fuse's permission, effectively cutting off interaction with a failing protocol while keeping the rest of the vault’s operations intact. --- Source: https://ipor.io/docs/fusion-for-institutions/lifecycle-and-liquidity-management.md # Lifecycle & Liquidity Management Fusion supports sophisticated redemption mechanisms designed to balance user liquidity needs with strategy requirements and market conditions. ## **Multi-Pathway Redemptions** - **Instant Path:** Fulfills redemption requests immediately using unallocated cash or by triggering "Instant Withdrawal Adapters" that exit highly liquid positions in a pre-configured order of priority. - **Scheduled Path:** For larger redemptions or less liquid positions, a three-phase process (**Request → Release → Redeem**) allows the Portfolio Manager to exit or unwind positions accounting for market conditions for minimal economic impact. This also aligns with **Asset-Liability Matching (ALM)** and protects the vault against liquidity mismatches. ## **Real-Time NAV & Virtual Asset Accounting** Valuation is performed natively onchain, ensuring that entry and exit prices are always based on verifiable, current underlying asset values. - **Automated Valuation:** [**Balance Fuses**](https://ipor.io/docs/build-on-fusion/developer-guide/balance-fuses.md) query the vault's real-time positions in external protocols, while the [**Price Oracle Middleware**](https://ipor.io/docs/build-on-fusion/developer-guide/price-oracle-middleware.md) standardizes these values into a single USD-denominated Net Asset Value (NAV). - **Virtual Asset Accounting:** For complex institutional requirements, the protocol supports "Virtual Assets." This feature allows for the accounting of Real-World Assets (RWAs) or credit positions that may not have constant onchain price discovery, such as tokenized private credit, accrued off-chain interest, or illiquid structured products. - **Hybrid Accounting Models:** Curators or **trusted third parties** (such as external auditors or valuation agents) can manually update the balances or valuations of these virtual assets through a governed process. This ensures that the total NAV accurately reflects the mandate's true economic value, bridging the gap between high-frequency DeFi liquidity and the periodic reporting cycles of traditional asset classes. --- Source: https://ipor.io/docs/fusion-for-institutions/institutional-fee-structures-and-performance-tracking.md # Institutional Fee Structures & Performance Tracking Fusion provides a programmable fee engine that automates the accounting, accrual, and distribution of management and performance fees, aligning incentives between allocators and managers. ## **Fee Types** - **Management Fee (AUM-based):** An annualized fee calculated based on total AUM, accruing continuously (per block). - The **Performance Fee** is a success-based fee on net profits, aligning incentives with absolute returns. Governed by a **High Watermark** (HWM), it's paid only when the current NAV exceeds its prior peak. Realized at set intervals based on settled onchain valuations, compensation reflects sustained growth. A rolling structure, which can be manual or time-based, allows the HWM to be reset. - **Deposit & Redemption Fees:** Transactional fees that can be [**Socialized** ](https://ipor.io/docs/build-on-fusion/atomists/curating-a-fusion-vault/on-and-offboarding-contributions.md)(retained in the vault to benefit existing depositors) or **Administrative** (directed to a separate address, such as the vault owner, for operational costs). --- Source: https://ipor.io/docs/fusion-for-institutions/enterprise-features-and-compliance-controls.md # Enterprise Features & Compliance Controls The infrastructure is designed to adapt to varying regulatory and business requirements through specialized extension layers, enabling permissioning white-labeling and investor gatekeeping. ## **Investor Onboarding & Access Management** Fusion is built for maximum flexibility; while the protocol supports high-assurance permissioning, vault owners can choose to deploy either permissioned or permissionless **Mandate Vehicles**. - **Configurable Access Controls:** Access management is entirely at the discretion of the vault owner. Vaults can be configured as **permissionless** for broad market access, or **permissioned** for restricted institutional use cases. - **Onchain Approved Investor Lists:** For permissioned mandates, managers can utilize onchain allowlists via the Access Manager. This ensures that only verified wallets can contribute to the vault, providing a guarantee that capital originates from sanctioned-screened and KYC-verified sources. - **Secondary Market Control (Transferability):** Vault Curators manage share transferability through a streamlined global control mechanism. By default, shares remain non-transferable to ensure the integrity of private placement mandates. Curators maintain the flexibility to enable unrestricted global transfers when broad secondary market liquidity is desired, providing a clear and enforceable state for the vehicle's regulatory status. --- Source: https://ipor.io/docs/fusion-for-institutions/regulatory-alignment-mica-and-global-standards.md # Regulatory Alignment (MiCA & Global Standards) Fusion’s architecture is engineered to support the evolving regulatory landscape, including the **Markets in Crypto-Assets (MiCA)** regulation in the EU and equivalent standards in other jurisdictions. - **Asset Segregation:** The vault-per-mandate structure ensures segregation of client assets from the manager's assets, meeting core prudential requirements for asset managers. - **Transparent Reporting:** Onchain NAV and real-time balance reporting provide the high level of transparency required for regulated CASPs (Crypto Asset Service Providers) and investment firms. - **Prudential Safeguards:** Granular controls, automated circuit breakers and the Guardian role provide the "operational resilience" and "safekeeping" controls explicitly required under modern regulatory frameworks to prevent unauthorized or harmful strategy execution. - **Role-Based Compliance:** The separation of governance (Atomist) from execution (Alpha) allows for internal control frameworks that mirror traditional compliance hierarchies. - **Immutable Infrastructure:** Core custody logic and execution adapters are non-upgradeable, minimizing opaque upgrade risk and ensuring long-term predictability for regulators and auditors. --- Source: https://ipor.io/docs/ipor-derivatives.md # The IPOR Protocol Introduction > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). The IPOR Derivative Protocol is a set of protocols, smart contracts, and software that forms a set of decentralized applications focused on interest rate derivatives. The core IPOR infrastructure consists of three main parts: the IPOR Index (Index), Liquidity Pools with an Automated Market Maker (AMM), and Asset Management smart contracts. The first type of interest rate derivatives supported by the AMM are Interest Rate Swaps (Swap or IRS). ### **The IPOR Index (or indices)** The IPOR Index is a benchmark reference interest rate sourced from other DeFi credit protocols and is published on-chain based on the [heartbeat methodology](https://ipor.io/docs/ipor-derivatives/interest-rate-derivatives/ipor-publication.md). This component is the cornerstone of the IPOR protocol. In fact, there will be multiple IPOR Indices representing the risk-free interest rate for a corresponding asset, such as IPOR USDT, IPOR USDC, IPOR DAI, IPOR ETH, and so on. There will also be time-based rates such as IPOR USDC 1M, 3M, 6M, and so on for each asset as the yield curve develops. Risk-free rates in credit markets have long been a cornerstone of financial markets. This is why the IPOR can be referred to as "[The Heartbeat of DeFi](https://ipor.io/blog/so-why-is-ipor-the-heartbeat-of-defi-4ee63d2851d3)." The value of a benchmark rate comes from its ability to synthesize the credit markets into a single metric and serves as a public good upon which derivatives, financial instruments, and deals can be structured. The IPOR's value will depend on both the quantity and quality of assets based on the indices. The IPOR DAO will govern the evolution of the indices as public goods, which provide market transparency and utility. ### **Liquidity Pools and AMMs** The Liquidity Pools and AMM work together to form a collective community counterpart for trades. Decentralized depositors can earn a yield on deposits by providing a trade counterpart for market participants. In exchange, the liquidity providers receive a proportional share of net contract payouts, contract fees, and a leveraged risk-free return from the money markets. The AMM is a dynamic pricing mechanism that takes into account the current IPOR Index rate of a given asset and a number of market-driven data to price the instruments, and it sets the price proportional to the demand. The function of the AMM’s dynamic pricing is to manage the risk of the LP. ### **Derivative Contract and Swap** The derivative contracts are based on the IPOR rate and the AMM pricing to open a derivative contract between a market participant and the pool. The contract manages the agreement between the market participant and the LP and, once closed, allocates the parties the corresponding contract payoff. The first IPOR derivative is an interest rate swap that allows a market participant to Pay the fixed rate and Receive the floating rate (Payer) or Receive the fixed rate and pay the floating rate (Receiver). Interest rate swaps are some of the most widely traded derivatives in traditional markets, accounting for around ⅔ of the global derivatives market value (\~$10.5t), as they provide stability by allowing borrowers and lenders to control costs and forecast income. --- Source: https://ipor.io/docs/ipor-derivatives/who-uses-ipor-and-for-what.md # About IPOR ## Why IPOR? To learn more about the reason behind IPOR, how it fits into the DeFi landscape, and its function and place in the credit markets of the future **read on Medium**: [Why IPOR?](https://ipor.io/blog/why-ipor-in-a-credit-fueled-defi-market-stability-is-the-growth-driver-ae61204b15a3) ## IPOR Manifesto To better understand the purpose and ethos of the IPOR protocol, read the [full IPOR Manifesto](https://www.ipor.io/ipor-manifesto). ## Who Uses IPOR and for What? ### **IPOR as a transparent public good** First, the IPOR rates are meant to be a public good. The rate data may be freely viewed on the ipor.io website, the index rates are published on-chain via an oracle construction, and different data providers and services report the IPOR rates so the general public can have a transparent view of the benchmark interest rates in DeFi. The on-chain components are meant for other protocols to build upon. If a third party protocol developer would like to reference the on-chain index rates, they are free to do so in their smart contracts. One thing to note is that the on-chain publication of the indices are subsidized by the IPOR DAO as well as derivative contract takers. In case a protocol should want to subsidize publishing of the IPOR rates as well to provide more granular rates on chain (published more frequently) this is a welcome prospect! Please contact the development teams using the links indicated on ipor.io and see [Public Request to Publish IPOR](https://ipor.io/docs/ipor-derivatives/interest-rate-derivatives/ipor-publication.md). ### **Hedging Interest Rates (Fixing Your Rates)** IPOR is a composite of the interest rates from multiple credit markets. Therefore if you want to hedge your loans and cover basis risk you would need to distribute your loans between multiple markets to closely follow the IPOR. Or alternatively use products that use IPOR as an interest rate. You may also hedge the position on a single market however the index may move differently than the rates on a single market.\ \ _Example_: Let’s say you’re taking USDC loan using floating / adjustable rate. If the rate goes up, you will have to pay more interest on your loan. You will need a product that will protect you if the rate goes up. Hence you want to “pay fixed and receive floating“. This way if the interest rate goes up - you will pay more in interest on your loan, but this will be offset by the earnings on interest rate swap. Should the interest rates go down, your swap will lose but those losses will be offset by the lower interest on your loan. This way your interest rate is fixed and you don't need to worry about it changing. If you want to hedge a deposit then you reverse this structure: “receive fixed and pay floating“. This behavior might be typical for a lender who does not want to lose potential income in case the rate of return drops. NB: This will be tied to the term of the swap, and the initial IRS will be a maximum of 28 days. ### Arbitrage The IPOR treats each stablecoin as a different currency given their highly divergent rate behaviors. As the rate behaviors vary, there are often times when rates between stables may offer an opportunity to arbitrage between rates. Let us take an example. If one were to assume that they could redeem any two stables for the same value this would represent an opportunity to capture the different rates between divergent stablecoins. Stablecoin A currently has an IPOR rate of 2.5% and Stablecoin B an IPOR rate of 5.5%. The borrow and lend rates between markets may vary but let's simplify the example using the IPOR rates only. Step 1: A trader could borrow Stablecoin A and take a "pay fixed" contract to lock in the borrowing cost. Step 2: Trader exchanges Stablecoin A for Stablecoin B. Step 3: Trader lends Stablecoin B and locks in the lending rate with a "receive fixed" contract. Through the use of interest rate derivatives the trader is able to capture a risk free arbitrage between two stablecoins. ### **Speculation (and Leverage)** Speculators are able to also long or short interest rates. With IPOR Interest Rate Derivatives this is possible with leverage. Leverage on IPOR is not the same leverage you can find when trading equities. Although it shares a similar function of giving you exposure to a larger capital position than you could be exposed to if you were not leveraged, it is not exactly the same. IPOR leverage could be better described as collateralization. You simply put down a collateral deposit that will be used to settle your derivative at maturity. In traditional financial markets, when 2 parties enter an Interest Rate Swap they agree between each other on the “Notional“ amount. Because they are bound by the contract and they are both non-anonymous entities they can allow themselves to forego putting any money in custody (they trust each other and are bound by a legal contract). In crypto, to allow a trust-less transactions it is important to collect some form of collateral as a guarantee of payment at the smart contract level. The ratio between collateral and notional amount is what we call on our smart contracts “collateralizationFactor“ also known as leverage. In the v1 IRS the IPOR protocol limits your possible losses and profits to the amount equal to your deposit, this would be the only reason to use lower leverage than the maximum. If you’re not expecting high volatility in interest rates, it is rational to use maximum leverage for cash efficiency reasons. --- Source: https://ipor.io/docs/ipor-derivatives/ipor-faq/about-the-ipor-protocol.md # About the IPOR Protocol > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). 1. [What is the IPOR Protocol? How does the IPOR Protocol work?](https://ipor.io/docs/ipor-derivatives/ipor-faq/about-the-ipor-protocol.md) 2. [What does “IPOR” stand for?](https://ipor.io/docs/ipor-derivatives/ipor-faq/about-the-ipor-protocol.md) 3. [Why IPOR?](https://ipor.io/docs/ipor-derivatives/ipor-faq/about-the-ipor-protocol.md) 4. [What is IPOR’s mission?](https://ipor.io/docs/ipor-derivatives/ipor-faq/about-the-ipor-protocol.md) 5. [Is there an IPOR Protocol whitepaper?](https://ipor.io/docs/ipor-derivatives/ipor-faq/about-the-ipor-protocol.md) 6. [What are interest rate swaps?](https://ipor.io/docs/ipor-derivatives/ipor-faq/about-the-ipor-protocol.md) 7. [What can the IPOR Protocol be used for?](https://ipor.io/docs/ipor-derivatives/ipor-faq/about-the-ipor-protocol.md) 8. [What are liquidity provider tokens (ipUSDC/DAI/USDT) in the IPOR Protocol?](https://ipor.io/docs/ipor-derivatives/ipor-faq/about-the-ipor-protocol.md) 9. [Has the IPOR Protocol been audited?](https://ipor.io/docs/ipor-derivatives/ipor-faq/about-the-ipor-protocol.md) ### 1. What is the IPOR Protocol? How does the IPOR Protocol work? As a DeFi protocol, IPOR refers to a series of smart contracts that provide a benchmark interest rate and enable users to access Interest Rates Derivatives on the Ethereum blockchain. That is possible by combining three core pieces of infrastructure: the IPOR Index, the IPOR AMM and liquidity pools, and Asset Management smart contracts. Learn more about the [IPOR v1 Protocol architecture](https://ipor.io/blog/ipor-protocol-architecture-overview-f9d35ac47ad) in the blog. In October 2023, the IPOR Protocol was upgraded to v2, featuring a brand new infrastructure. Learn more about the main [IPOR v2 technological improvements](https://ipor.io/news/ipor-v2-architecture-for-growth-b1d36b5e05b7) in the blog. ### 2. What does “IPOR” stand for? IPOR is an abbreviation for Inter Protocol Over-block Rate. It derives its name from major indices from traditional finance like the LIBOR - the London Interbank Offered Rate, and the SOFR - Secured Overnight Financing Rate and adapts it to DeFi. The IPOR is a mid-market (not offered) rate that is sourced block-over-block, the closest proxy to real-time possible in blockchain. ### 3. Why IPOR? The IPOR Protocol is built on the premise that if decentralized finance (DeFi) is a global disruptive sandbox, credit will be the catalyst. For the DeFi credit markets to evolve into the fixed-income markets of tomorrow they must provide the same risk management tools that traditional financial (TradFi) institutions require. The IPOR Protocol delivers those with the IPOR indices and interest rate derivates such as swaps that reference the index. Interest rate derivatives provide stability for fixed-income players, allowing them to manage their interest rate risk. To learn more about why IPOR has the potential to be an important piece from the DeFi “money legos”, [read this article](https://ipor.io/blog/why-ipor-in-a-credit-fueled-defi-market-stability-is-the-growth-driver-ae61204b15a3). ### 4. What is IPOR’s mission? IPOR’s mission is to become the foundational layer of the DeFi credit markets. Calculated and published on-chain, the IPOR indices are a public good that anyone can reference and build upon. The methodology is transparent, public, and auditable. At the same time, the interest rate swaps that reference the IPORs can be used as an input to bootstrap the DeFi yield curve, a prerequisite for liquid and mature financial markets. The Index and Derivatives provide tools for other builders for more complex financial products. The [IPOR Manifesto](https://www.ipor.io/manifesto) states the founding principles at the center of the IPOR Protocol and outlines the philosophy to be followed in the process of achieving IPOR’s mission. ### 5. Is there an IPOR Protocol whitepaper? The IPOR Protocol conceptual whitepaper is available [here](https://ipor.io/docs/resources/resources/research-and-whitepapers.md). In addition, there are several quant whitepapers available [here](https://ipor-labs.notion.site/e592feae2660418a90c35434849f0c0b?v=d35d84b479204c26bc1bb30d2b8ace4a). ### 6. What are interest rate swaps (IRS)? Interest rate derivatives are financial instruments that allow a trader to take a position on the behavior of interest rates. Interest rate swaps are one type of interest rate derivative that involves the exchange of cashflows between two parties taking opposing interest rate positions such as pay fixed or pay floating rates. The IPOR IRS is the cornerstone derivative product of IPOR. The IRS allows a market participant to be a Payer or Receiver of fixed rates and take a contract against the liquidity pool. To learn more about interest rate swaps, access [this Docs page](https://ipor.io/docs/ipor-derivatives/automated-market-maker/ipor-swaps.md). ### 7. What can the IPOR Protocol be used for? The IPOR indices are public goods published on-chain, providing a transparent view of the benchmark interest rates in DeFi that anyone can reference. They can be used to view the current cost of credit, to benchmark risk-adjusted vs. risk-free rewards, or as a reference for other credit products, deals, or derivatives. The IPOR interest rate swaps can be used for hedging, arbitrage, or speculation of DeFi borrowing costs or lending yields. Learn more about the Protocol uses [here](https://ipor.io/docs/ipor-derivatives/who-uses-ipor-and-for-what.md). ### 8. What are liquidity provider tokens (ipUSDC/ipDAI/ipUSDT/ipstETH) in the IPOR Protocol? The liquidity provider tokens (ipTokens) are interest-bearing tokens representing liquidity deposited in the IPOR Protocol liquidity pools. Upon deposit, a user would exchange the native token, such as USDC for ipUSDC at the exchange rate at the time of deposit. The exchange rate between ipTokens tokens and the underlying liquidity tokens (USDC, USDT, DAI, stETH) is not 1:1 since ipTokens tokens accrue interest over time from [Sum of All Payoffs (SOAP)](https://ipor.io/docs/ipor-derivatives/automated-market-maker/soap.md). The ipToken can be exchanged for the underlying token at the time of withdrawal based on the current exchange rate. ### 9. Has the IPOR Protocol been audited? The IPOR Protocol has undergone multiple smart contract audits. This [dedicated Docs section](https://ipor.io/docs/ipor-derivatives/developers-docs/audits.md) contains a full list of completed IPOR Protocol and IPOR Token audits. Audit reports will become available there as soon as they are finalized. --- Source: https://ipor.io/docs/ipor-derivatives/ipor-faq/using-the-ipor-protocol.md # Using the IPOR Protocol > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). ## Providing Liquidity 1. [Why provide liquidity in the IPOR Protocol?](https://ipor.io/docs/ipor-derivatives/ipor-faq/using-the-ipor-protocol.md) 2. [What is SOAP?](https://ipor.io/docs/ipor-derivatives/ipor-faq/using-the-ipor-protocol.md) 3. [What are the risks of providing liquidity?](https://ipor.io/docs/ipor-derivatives/ipor-faq/using-the-ipor-protocol.md) 4. [How to provide liquidity?](https://ipor.io/docs/ipor-derivatives/ipor-faq/using-the-ipor-protocol.md) 5. [Are there any fees for providing liquidity?](https://ipor.io/docs/ipor-derivatives/ipor-faq/using-the-ipor-protocol.md) ## Trading 1. [Why trade on the IPOR Protocol?](https://ipor.io/docs/ipor-derivatives/ipor-faq/using-the-ipor-protocol.md) 2. [What are the risks associated with trading?](https://ipor.io/docs/ipor-derivatives/ipor-faq/using-the-ipor-protocol.md) 3. [How to trade on the IPOR Protocol?](https://ipor.io/docs/ipor-derivatives/ipor-faq/using-the-ipor-protocol.md) 4. [What are the fees associated with trading swaps on the IPOR Protocol?](https://ipor.io/docs/ipor-derivatives/ipor-faq/using-the-ipor-protocol.md) 5. [How are the trading fees used by the IPOR Protocol?](https://ipor.io/docs/ipor-derivatives/ipor-faq/using-the-ipor-protocol.md) ## Providing Liquidity FAQ ### 1. Why provide liquidity in the IPOR Protocol? Liquidity providers (LP) are Protocol service providers. An LP deposits an asset to the pool (currently USDC/USDT/DAI/stETH), and traders can open Interest Rate Swaps (IRS) against the pool (stETH swaps are in the works). For that service, LPs are rewarded with fees, Sum of all Payoffs (SOAP), and through yield generated by asset management smart contracts earning yield from external money markets. ### 2. What is SOAP? SOAP, or Sum of All Payoffs, is a snapshot of the unrealized P&L of all open positions against the pool. It is the amount that the Liquidity Pool would be liable to payout should all the swaps be closed immediately. You can learn more about SOAP [here](https://ipor.io/docs/ipor-derivatives/automated-market-maker/soap.md) and [here](https://ipor.io/blog/real-yield-and-risks-in-ipor-protocol-e987008f269e). ### 3. What are the risks of providing liquidity? As with any liquidity provision, supplying stables to IPOR is associated with certain degrees of risk. Outside of standard third-party risks, there are also economic risks to consider. Spread and utilization thresholds are the measures implemented by the AMM to control the risk of LPs. Refer to the [Docs section dedicated to spread calculation](https://ipor.io/docs/ipor-derivatives/automated-market-maker/spread.md) or to [this paper on pricing AMM risk](https://ipor-labs.notion.site/IPOR-SWAPS-Risk-Management-and-Market-Design-via-Stochastic-Control-d700071e2d3c47f6b3f5c2fb709d8041) for more information. You can also read [this blog post](https://ipor.io/blog/real-yield-and-risks-in-ipor-protocol-e987008f269e). ### 4. How to provide liquidity? The process of providing liquidity to the IPOR Protocol is similar to other DeFi protocols. The prerequisites are a Web3 wallet (Rabby or similar) credited with one of the IPOR Protocol-supported assets and some ETH for gas fees payment. ### 5. Are there any fees for providing liquidity? There are no fees when providing liquidity. A user will deposit a token and receive ipTokens tokens in return. These are interest-bearing tokens (AKA liquidity tokens) that represent liquidity deposited in the IPOR Protocol. Liquidity tokens can be redeemed for the underlying collateral at any point, given that the [utilization](https://ipor.io/docs/ipor-derivatives/automated-market-maker/liquidity-provisioning.md) allows that to happen. To prevent an early exit, a fee of 0.5% is charged on withdrawal which is then redistributed to the remaining holders of ipTokens within the same pool. An ETH-denominated fee (gas fee) is also charged for any operation performed on the Ethereum network, including any mainnet interactions with the IPOR Protocol. You can refer to the [Etherscan Gas Tracker](https://etherscan.io/gastracker) for the latest information about Ethereum gas fees. ## Trading FAQ ### 1. Why trade on the IPOR Protocol? The IPOR Protocol delivers a vanilla interest rate swap. Traders on the Protocol can open and receive fixed or floating swap contracts with 28, 60, and 90-day maturity on available markets. All swaps reference the IPOR Index, calculated on-chain by on-chain data supplied by the largest DeFi money markets, currently AAVE and Compound. IPOR Protocol traders may have different motivations, including hedging, arbitrage, or speculation. Refer to [this Docs section](https://ipor.io/docs/ipor-derivatives/who-uses-ipor-and-for-what.md) for more information about each. ### 2. What are the risks associated with trading? Outside of standard 3rd party risks related to potential exploits, for the duration of their open swap contracts, IPOR Protocol traders are exposed to uncertainty stemming from the volatility of the IPOR indices. Trader losses are capped at 100% of their provided collateral. ### 3. How to trade on the IPOR Protocol? To trade on the IPOR Protocol, it’s advisable to have at least a basic understanding of interest rate swaps. To learn how IPOR-based interest rate swaps work, consider [this Docs section](https://ipor.io/docs/ipor-derivatives/automated-market-maker/ipor-swaps.md). For a detailed overview of the IPOR DApp interface and how to open an interest rate swap, [watch this walkthrough](https://www.youtube.com/watch?v=diABlv__CH0). ### 4. What fees are associated with trading swaps on the IPOR Protocol? The IPOR Automated Market Maker charges several fees, including an opening fee (currently 1% of collateral), a base flat fee (currently $10), and an income fee (currently 10% of trader and liquidity provider profits). A refundable liquidation deposit (currently $25) is also charged upon opening an interest rate swap on the Protocol. For more information about swap fees, consider [this Docs section](https://ipor.io/docs/ipor-derivatives/automated-market-maker/ipor-swaps.md). ### 5. How are the trading fees used by the IPOR Protocol? The opening fee is paid to the Liquidity Pool as compensation for underwriting the derivative contract risk. The base flat fee is used to subsidize the oracle publications on-chain. The income fee is deposited in the IPOR DAO Treasury. For more information, check the [fee section in the Docs](https://ipor.io/docs/ipor-derivatives/automated-market-maker/ipor-swaps.md). --- Source: https://ipor.io/docs/ipor-derivatives/ipor-faq/swaps-vs-perps.md # Swaps VS Perps > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). 1. [What is the difference between an Interest Rate Swap and Trading Perpetual Futures?](https://ipor.io/docs/ipor-derivatives/ipor-faq/swaps-vs-perps.md) 2. [How do the objectives of Interest Rate Swaps and Perpetual Futures differ?](https://ipor.io/docs/ipor-derivatives/ipor-faq/swaps-vs-perps.md) 3. [How do the markets for these instruments differ?](https://ipor.io/docs/ipor-derivatives/ipor-faq/swaps-vs-perps.md) 4. [What about the settlement mechanisms?](https://ipor.io/docs/ipor-derivatives/ipor-faq/swaps-vs-perps.md) 5. [How is Profit and Loss (PnL) accrued?](https://ipor.io/docs/ipor-derivatives/ipor-faq/swaps-vs-perps.md) 6. [What is the payoff structure?](https://ipor.io/docs/ipor-derivatives/ipor-faq/swaps-vs-perps.md) 7. [What are other PnL considerations?](https://ipor.io/docs/ipor-derivatives/ipor-faq/swaps-vs-perps.md) 8. [How does leverage affect a position?](https://ipor.io/docs/ipor-derivatives/ipor-faq/swaps-vs-perps.md) 9. [How do liquidations occur?](https://ipor.io/docs/ipor-derivatives/ipor-faq/swaps-vs-perps.md) 10. [What happens to the funds or collateral after a liquidation in these instruments?](https://ipor.io/docs/ipor-derivatives/ipor-faq/swaps-vs-perps.md) ### 1. What is the difference between an Interest Rate Swap and Trading Perpetual Futures? While both swaps and futures are financial derivative instruments, an interest rate swap is a contract by which two parties agree to exchange interest rate payments, typically involving the swap of fixed interest rate payments for floating (variable) rate payments over a specified period. Unlike interest rate swaps, perpetual futures do not have an expiration or settlement date, allowing positions to be held indefinitely as long as the margin requirements are met. They often include a funding rate mechanism to maintain the price alignment with the spot market. ### 2. How do the objectives of Interest Rate Swaps and Perpetual Futures differ? Interest rate swaps are primarily used for hedging against interest rate risks and speculation about the directionality of interest rates. They allow parties to manage their exposure to fluctuations in interest rates. On the other hand, perpetual futures are used for speculation, leverage trading, and hedging, offering a way to bet on the future price movements of crypto assets without a set expiry date. ### 3. How do the markets for these instruments differ? Interest rate swaps are traded in the over-the-counter (OTC) market, primarily by institutional participants like banks, corporations, and investment funds. Protocols like IPOR are bringing this market to DeFi. Perpetual futures are traded on cryptocurrency exchanges and are accessible to both institutional and retail investors. ### 4. What about the settlement mechanisms? Interest rate swaps involve periodic settlements (in the case of IPOR this is 28d, 60d, or 90d swaps) based on the interest rate differential. Perpetual futures involve a unique funding rate mechanism that ensures the futures price tracks the underlying asset's spot price closely, requiring frequent (often hourly or x hours) payments between counterparties based on the position held and market conditions. ### 5. How is Profit and Loss (PnL) accrued? In interest rate swaps, PnL accrues through the difference between the fixed rate and the floating rate over the contract's life. If the fixed rate is higher than the floating rate, the party paying the fixed rate will incur a loss, while the party receiving the fixed rate gains, and vice versa. PnL is realized at predetermined intervals (like quarterly or annually) when the interest payments are exchanged. In perpetual futures, PnL is accrued based on the difference between the entry price and the contract's current market price. If a trader goes long and the price increases, they gain; if it decreases, they lose. For a short position, it's the opposite. PnL is realized when the position is closed or during the funding rate exchanges. ### 6. What is the payoff structure? The payoff structure in interest rate swaps is linear and based on the net difference between the agreed-upon fixed rate and the actual floating rate. The amount paid or received is the difference between these rates multiplied by the notional principal amount. Perpetual futures have a nonlinear payoff structure due to leverage. The payoff depends on the leverage used and the underlying asset's price movement. If the market moves in the trader’s favor, the leverage magnifies the profits. Conversely, a small adverse price movement can lead to significant losses or even liquidation if the margin is insufficient. ### 7. What are other PnL considerations? PnL in interest rate swaps can be negative. If the market moves against the position (e.g., a fixed-rate payer faces a declining interest rate environment), the party will have to pay the difference, resulting in a loss. PnL in perpetual futures can be realized anytime by closing the position. However, due to the perpetual nature of these contracts, traders can hold their positions as long as they meet margin requirements, leading to unrealized PnL until the position is closed or liquidated. ### 8. How does leverage affect a position? In interest rate swaps (IRS), assuming 500x leverage, users can deposit collateral up to 500 times less than the notional value. While this may seem like a significant amount of leverage, it's important to note that the PnL in IRS accrues over time, not instantaneously like in perpetuals. This capital efficiency is particularly useful for hedgers. Additionally, the P&L in IRS accumulates gradually over the maturity period (28d, 60d, or 90d in the case of IPOR). Even in the event of a sudden shock in interest rates, positive or negative PnL changes occur slowly. This gives traders ample time to react to changing and dynamic floating rate environments, reducing the likelihood of liquidation. In contrast, perpetuals constantly adjust your PnL based on the perpetual price on the exchange. There is no time value concept in perpetuals as there is in IRS. A 50% change in the interest rate on an IRS (e.g., moving from 2% to 1%) does not lead to liquidation, even at 500x leverage. However, in perpetuals, a 50% price movement with just 2x leverage can result in immediate collateral loss, often leading to liquidation well before that point. This fundamental difference highlights the distinct nature of leverage and risk between interest rate swaps and perpetuals. ### 9. How do liquidations occur? In interest rate swaps, liquidation typically occurs due to credit events, such as default or breach of contract terms, rather than market movements. If a party fails to meet its obligations, the swap may be terminated, and the defaulting party may be required to settle the outstanding amount based on the current market value of the swap. Collateral posted at the start or during the swap's life can be used to cover losses. In the case of IPOR swaps, liquidation occurs when the PnL of the trader's position is +/- 100% of the collateral. A position can also be closed by the trader at any time or is automatically closed at the swap's maturity (28, 60, 90 days). In perpetual futures, liquidation is triggered when a trader's margin balance falls below the maintenance margin requirement. This is often due to adverse price movements in the market. If the market moves against the trader’s position and the losses exceed the margin posted, the exchange automatically closes or liquidates the position to prevent further losses. ### 10. What happens to the funds or collateral after a liquidation in these instruments? In interest rate swaps, any collateral posted may be used to offset the losses incurred due to the default. Any remaining amount is returned to the party who posted it. In perpetual futures, the remaining margin after liquidation covers the losses incurred on the position. If the margin is insufficient to cover the losses, the platform's insurance fund may be used, depending on the exchange's policy. --- Source: https://ipor.io/docs/ipor-derivatives/ipor-index/what-is-the-ipor-index.md # What is the IPOR Index > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). ### The **IPOR Index (or indices)** There will be multiple IPOR Indices that represent different assets. For example, there may be an IPOR USDT, IPOR USDC, IPOR DAI, IPOR ETH, etc. Given that external protocols’ interest rates are fixed algorithmically based on overcollateralized loans, the IPOR serves as an adequate proxy for the Risk-Free (Rf) rate, as the collateral effectively mitigates default risk. #### **Index Adaptability and Modularity** The IPOR Index was imagined to be both adaptable and modular. The blockchain landscape and particularly DeFi markets are in constant flux, with protocols rapidly evolving, rising or falling in dominance, and new projects emerging. Given the constant change, the index must be able to adapt to market conditions and account for changes. The Index calculation is designed to be updatable and modular, able to account for new protocols to be considered for inclusion or removal, changes in weighting due to market dominance, changes to the third-party code base, or other potential significant changes. Updates to the Index will be made via a transparent and democratic on-chain governance process handled by the DAO. --- Source: https://ipor.io/docs/ipor-derivatives/ipor-index/working-with-the-ipor-index.md # Working with the IPOR Index > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). There are at least three ways to query IPOR Index. Each way to query an index has its intended use and has certain advantages. ## Reading IPOR **From the oracle contract** - It's the most gas efficient, as reading the values on-chain does not require complex calculations or calls to external contracts. - It provides additional params such as exponential moving average or exponential moving variance calculated on-chain - It allows for calculating the average IPOR rate between 2 points in time, thanks to the IBT. - IPOR swaps use this method to read the IPOR rate ``` getIndex(asset address) // pass address of ERC token for which to read IPOR ``` If you want to read the value of IPOR along with the most recent IBT value then use ``` getAccruedIndex(asset address, timestamp uint256) // pass address of ERC token for which to read IPOR, // and current timestamp ``` ### **From the index calculation contract** - It provides the real-time IPOR for a given block. ``` calculateIpor(asset address) // pass address of ERC token for which to calculate IPOR ``` **From the API** - Does not require a connection to the blockchain - It provides historical data. - Does not require any authentication, and it's free to query. Currently, the front-end application uses API for reading the IPOR to display the charts. A dedicated API will be provided. ## Publishing IPOR Because the calculation of IPOR is done on-chain in the calculation index, it is possible for specific DAO-appointed validators to run an on-chain update of the oracle contract. Albeit not the most gas efficient, it may be beneficial in some cases to force an update of IPOR if you rely on the most recent data in our integration. ``` updateIndex(asset address) ``` --- Source: https://ipor.io/docs/ipor-derivatives/ipor-index/ipor-steth-index.md # IPOR stETH Index Lido conducts a rebase approximately once a day, generally at a fixed time. After the rebase, it becomes possible to determine the Annual Percentage Rate (APR) given that we understand how Lido's account balance is computed. The LIDO documentation provides insights into calculating the staked Ethereum (StETH) account balance as: ``` balanceOf(account) = shares[account] * totalPooledEther / totalShares ``` - Where: - shares - A map representing the share amount of individual users. Upon depositing ether, this ether gets converted into shares and is added to the user's existing share count. - totalShares- The collective sum of shares across all user accounts listed in the shares map. - totalPooledEther Represents the aggregate of three distinct types of ether held by the protocol: - buffered balance: Ether retained on the contract, neither deposited nor designated for withdrawals. - transient balance: Ether sent to the official Deposit contract but not yet acknowledged in the beacon state. - beacon balance: The accumulated amount of ether in validator accounts. This quantity, relayed by oracles, is pivotal in determining the stETH total supply adjustments. For APR calculation, if we know the balance before and after the rebase, the equation is: ``` APR = 100% * 365 days * (beforeBalanceOf(account) - afterBalanceOf(account)) / beforeBalanceOf(account) ``` However, if a user's shares remain unchanged between rebases, the formula can be simplified by calculating exchange rates before and after ``` beforeStackingExchangeRate = beforeTotalPooledEther / beforeTotalShares afterStackingExchangeRate = afterTotalPooledEther / afterTotalShares APR = 100% * 365 days * (afterStackingExchangeRate - beforeStackingExchangeRate) / beforeStackingExchangeRate ``` For simplicity, we assume that the time between rebases was exactly 24 hours. #### How to calculate the APR at any given moment between rebases? To determine the APR at any specific time between rebases, we must ascertain the exchange rate at that particular moment. For this purpose, one can refer to the LIDO Oracle codebase and review the following method: ``` def simulate_rebase_after_report( self, blockstamp: ReferenceBlockStamp, el_rewards: Wei, ) -> LidoReportRebase: """ To calculate how much withdrawal request protocol can finalize - needs finalization share rate after this report. """ validators_count, cl_balance = self._get_consensus_lido_state(blockstamp) chain_conf = self.get_chain_config(blockstamp) simulated_tx = self.w3.lido_contracts.lido.functions.handleOracleReport( # We use block timestamp, instead of slot timestamp, # because missed slot will break simulation contract logic # Details: https://github.com/lidofinance/lido-oracle/issues/291 blockstamp.block_timestamp, # _reportTimestamp self._get_slots_elapsed_from_last_report(blockstamp) * chain_conf.seconds_per_slot, # _timeElapsed # CL values validators_count, # _clValidators Web3.to_wei(cl_balance, 'gwei'), # _clBalance # EL values self.w3.lido_contracts.get_withdrawal_balance(blockstamp), # _withdrawalVaultBalance el_rewards, # _elRewardsVaultBalance self.get_shares_to_burn(blockstamp), # _sharesRequestedToBurn # Decision about withdrawals processing [], # _lastFinalizableRequestId 0, # _simulatedShareRate ) logger.info({'msg': 'Simulate lido rebase for report.', 'value': simulated_tx.args}) result = simulated_tx.call( transaction={'from': self.w3.lido_contracts.accounting_oracle.address}, block_identifier=blockstamp.block_hash, ) logger.info({'msg': 'Fetch simulated lido rebase for report.', 'value': result}) return LidoReportRebase(*result) ``` Upon examining this method, it becomes evident that the crux of this simulation is the handleOracleReport function within the Lido contract. This function requires several arguments to execute the transaction. ``` /** * @notice Updates accounting stats, collects EL rewards, and distributes collected rewards * if beacon balance increased, performs withdrawal requests finalization * @dev periodically called by the AccountingOracle contract * * @param _reportTimestamp the moment of the oracle report calculation * @param _timeElapsed seconds elapsed since the previous report calculation * @param _clValidators number of Lido validators on Consensus Layer * @param _clBalance sum of all Lido validators' balances on the Consensus Layer * @param _withdrawalVaultBalance withdrawal vault balance on Execution Layer at `_reportTimestamp` * @param _elRewardsVaultBalance elRewards vault balance on Execution Layer at `_reportTimestamp` * @param _sharesRequestedToBurn shares requested to burn through Burner at `_reportTimestamp` * @param _withdrawalFinalizationBatches the ascendingly-sorted array of withdrawal request IDs obtained by calling * WithdrawalQueue.calculateFinalizationBatches. Empty array means that no withdrawal requests should be finalized * @param _simulatedShareRate share rate that was simulated by oracle when the report data created (1e27 precision) * * NB: `_simulatedShareRate` should be calculated off-chain by calling the method with `eth_call` JSON-RPC API * while passing empty `_withdrawalFinalizationBatches` and `_simulatedShareRate` == 0, plugging the returned values * to the following formula: `_simulatedShareRate = (postTotalPooledEther * 1e27) / postTotalShares` * * @return postRebaseAmounts[0]: `postTotalPooledEther` amount of ether in the protocol after report * @return postRebaseAmounts[1]: `postTotalShares` amount of shares in the protocol after report * @return postRebaseAmounts[2]: `withdrawals` withdrawn from the withdrawals vault * @return postRebaseAmounts[3]: `elRewards` withdrawn from the execution layer rewards vault */ function handleOracleReport( // Oracle timings uint256 _reportTimestamp, uint256 _timeElapsed, // CL values uint256 _clValidators, uint256 _clBalance, // EL values uint256 _withdrawalVaultBalance, uint256 _elRewardsVaultBalance, uint256 _sharesRequestedToBurn, // Decision about withdrawals processing uint256[] _withdrawalFinalizationBatches, uint256 _simulatedShareRate ) external returns (uint256[4] postRebaseAmounts) ``` Upon examining the output of this method, we observe that it provides two values that are particularly interesting to us: ``` * @return postRebaseAmounts[0]: `postTotalPooledEther` amount of ether in the protocol after report * @return postRebaseAmounts[1]: `postTotalShares` amount of shares in the protocol after report ``` If we divide these values, then we have the exchange rate at any point in time: ``` exchangeRate = postTotalPooledEther / postTotalShares ``` #### Calculating the 24-hour Window APR When trying to calculate the APR over 24 hours based on exchange rates: 1. **Obtain Current Exchange Rate**: Secure the exchange rate at the given time between rebases. 2. **Secure Historical Data**: Ensure we have data that dates back to at least more than 24 hours prior. 3. **Determine the Exchange Rate from 24 hours ago**: Retrieve the exchange rate from precisely 24 hours ago using the historical data. 4. **Calculate Current APR**: We can now determine the APR with the current and 24-hour-old exchange rates at our disposal. The formula is: ``` currentAPR = 100 * 365 * (currentExchangeRate - exchangeRate24HoursAgo) / exchangeRate24HoursAgo ``` #### Gathering Arguments for the handleOracleReport method reportTimestamp - This refers to the timestamp of the block for which we want to determine the exchange rate timeElapsed - Represents the duration from the last report to the desired time point. It can be easily computed using the equation: ``` timeElapsed = reportTimestamp - lastReportTimestamp ``` clValidators - Represents the total count of Lido validators currently on the Consensus Layer. clBalance - Refers to the aggregate balance of all Lido validators on the Consensus Layer. To retrieve these values: - Make a call to the Lido Keys API. Running a local instance of this API can be much faster than accessing the public one. The repository for the API can be found at [Lido Keys API GitHub](https://github.com/lidofinance/lido-keys-api). - Additionally, initiate a call to the Beacon Chain to fetch the list of validators. By comparing this list with the one from the Lido Keys, we can determine which validators are associated with Lido for a specific block. - clValidators - Count the number of Lido-associated validators. - clBalance - Aggregate the balances of these Lido validators withdrawalVaultBalance - This indicates the balance of the withdrawal vault on the Execution Layer at the given reportTimestamp One must query the Ethereum balance of the WithdrawalVault contract on the Execution Layer. elRewardsVaultBalance - vault balance on Execution Layer at reportTimestamp One must query the Ethereum balance of the [LidoExecutionLayerRewardsVault](https://docs.lido.fi/contracts/lido-execution-layer-rewards-vault) contract on the Execution Layer. sharesRequestedToBurn - shares requested to burn through Burner at reportTimestamp. A call should be made to the getSharesRequestedToBurn method of the [Lido Burner](https://docs.lido.fi/contracts/burner) contract. This method produces two output values: coverShares and nonCoverShares. The cumulative sum of these two outputs provides the sharesRequestedToBurn value." withdrawalFinalizationBatches - This is an array of withdrawal request IDs organized in ascending order. 1. It is derived by calling the calculateFinalizationBatches method of the WithdrawalQueue contract. 2. Within a simulation context, an empty array indicates no withdrawal requests pending finalization. simulatedShareRate - This refers to the share rate that Oracle projected when the report data was established. When conducting a simulation, the oracle assigns this parameter a value of 0. --- Source: https://ipor.io/docs/ipor-derivatives/interest-rate-derivatives/interest-rate-derivative.md # Interest Rate Derivative > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). Interest Rate Derivatives in IPOR refer to any derivative instrument that uses an IPOR Index as a contract reference. In the future, multiple types of derivative instruments and contracts could use the IPOR Index as a benchmark rate. #### **Interest Rate Swap** ![Image](https://ipor.io/docs/assets/ipor-derivatives/ipor-image-c2-921a99.jpg) The IPOR Interest Rate Swap (IRS) is the cornerstone derivative product of IPOR. The IRS allows a market participant to be a Payer or Receiver and take a contract with the liquidity pool. For more detailed information about participants and contracts, reference the glossary of terms. Once a Payer or Receiver agrees to a contract quoted by the AMM, they will pay the margin, the contract fee, and applicable network fees (i.e., in the case of Ethereum, some ETH must be used to pay for network gas fees) to enter into a derivative smart contract. The liquidity pool will post an equal margin in the same contract. Over time the contract will manage the positions and payouts and, once closed, will pay out the respective sum(s).\ \ **Common FAQ Regarding Interest Rate Derivatives** **What is “Pay fixed and receive floating” or “Pay floating and receive fixed“?**\ You are ' longing ' interest rates when you open a contract to “Pay fixed and receive floating.” Why? Because you are choosing to pay a fixed rate. Say the current IPOR Rate is 4%, and the floating rate goes up to, say, 5%. You are receiving the floating rate, which means that you are getting paid 5% but paying 4%. “Pay floating and receive fixed” is the opposite. **What is notional?** Notional is the total value of the position taken by the market participant. This should not be confused with collateral. The notional value of derivative contracts is higher than the market value depending on the amount of leverage. --- Source: https://ipor.io/docs/ipor-derivatives/interest-rate-derivatives/index-calculation.md # Index Calculation > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). ### Index Components The cornerstone of the IPOR Protocol is the index rates which is sourced from established and robust DeFi credit markets. Rates used to compile the index come from credit markets that: - are decentralized - work as on-chain smart contracts - are established - they have aggregated users and liquidity over time - have proven security track record The IPOR Oracle service sources the interest rates for every block for any given currency from appointed markets and compiles the IPOR Index rate. ### Index Formula The IPOR Index rate is essentially the market cost of money defined by a weighted average of rates sources at all money markets included in IPOR: ```math IPOR(Borrow) = \frac{\sum_{i \in I} w^b_i \cdot r_i}{W_{borrow}}\\ IPOR(Supply) = \frac{\sum_{i \in I} w^s_i \cdot r_i}{W_{supply}} ``` ```math IPOR = \frac{IPOR(Borrow) + IPOR(Supply)}{2} ``` IPOR Borrow is the weighted average of the rate to borrow. IPOR Supply is the weighted average of the rate to lend. Weight is the total amount borrowed or supplied on a given market. Finally, IPOR is the simple average between those two. ### **Standarizing the rate** It is important to note, that the rate that money markets such as AAVE and Compound quote is not always the actual rate, but rather an APY that accocunts for compounding. In order to be able to compare apples for apples the rate is "deflated" to the actuall rate and then compounding is done via the [IBT](https://ipor.io/docs/ipor-derivatives/interest-rate-derivatives/ibt.md) ### Updating the Index The IPOR is meant to evolve to become the representation of the fair market cost of money. Given the speed of innovation in DeFi and the free flow nature of capital across protocols and chains, it is expected that new platforms will be added, and some platforms will be removed over time. The index methodology may need to be changed or updated, and decisions must be made about how to transition from one construction to another. The IPOR DAO will govern decisions like these. #### Listing When adding a new market to the index, the new rate mustn't cause a sudden jump in the rate. To smooth the process of onboarding new platforms, IPOR oracle will be increasing their weight block over block in a span of the DAO-appointed phase-in period linearly from 0% to 100% of its standard weight as determined by the liquidity in a given protocol. #### Delisting Delisting of the protocol can happen in 2 ways: - Standard delisting - the process is generally the reverse of listing a new protocol. Weight is reduced from 100% to 0% over the appointed phase-out time. - Emergency delisting - should there be a justified reason to remove the protocol listed as a part of IPOR in an emergency mode (ex. due to hack, fraud, etc.) admin of the oracle may invoke an emergency delisting with immediate consequences. --- Source: https://ipor.io/docs/ipor-derivatives/interest-rate-derivatives/ipor-publication.md # IPOR Publication > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). Because gas cost is a serious issue on the Ethereum blockchain, the protocol can not afford the luxury of publishing the IPOR rate to the blockchain every block. Instead, we need to be pragmatic about the IPOR publication so that it is sustainable and useful. ### Heartbeat, time, and volatility Should no trades occur on the IPOR Protocol, the oracle will keep the "pulse" by publishing IPOR. This publication will occur depending on volatility and time since the last publication. This way, if the volatility is significant but only for a short while, the oracle will not be overwhelmed by a large number of publications. At the same time, if the rate is not changing much, the publication will still take place, just less often. "Pulse" is controlled by function: ```math requiredIndexDiff = \frac{ tresholdNumerator_{g} }{ (\Delta T/60) } ``` thresholdNumerator is gas dependent. The higher the current gas price the higher the enumerator. If the product of the multiplication of IPOR changes since the last publication and the number of minutes since the publication took place equals 5, then the publication is triggered. **For example:** if we expect publication after 5 minutes since the last update, we expect the IPOR to jump by 1% in that time. However, if we look at a longer period, a much smaller move is sufficient to trigger a publication. One basis point change in IPOR requires 8 hours and 20 minutes of time to trigger an update. ### --- Source: https://ipor.io/docs/ipor-derivatives/interest-rate-derivatives/ibt.md # IBT > Interest Bearing Token > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). IBT in IPOR is not an ERC20 token. Instead, it's a measure of interest rate over time saved in the token. This allows us to track the floating interest rate between 2 points in time. IBT is used by the swap AMM to price the floating leg and can be used by anybody who would like to know what the "average" floating rate has been between two blocks. ### How is IBT calculated? At inception, the value of the IBT price is set to 1. At every IPOR publication, the IBT price is updated to reflect the accumulating rate. Rate is added without compounding using the following formula: ```math IBT_{new} = IBT_{old} \cdot e ^{\frac{IPOR \cdot \Delta T}{T_{Year}}} ``` Where IBT is the price at the rebalancing - _n_ is the current rebalancing, _n-1_ is the moment of the last rebalancing. Delta T is the time that has passed between 2 rebalancings. IBT is a valuable measurement of the closely approximated, on-chain value of the Inter-Protocol Offered Rate (floating) over time. ### Continuous compounding Above formula is of course a formula for continuously compounding interest rate. This is the standard accross IPOR Protocol. It's worth noting that AAVE currently uses compounding every second and Compound "compounds" interest every day. Because of the different rate of compounding there is a difference how APR converts to APY however markets already price those difference in since the main number that is refered to is actually APY. --- Source: https://ipor.io/docs/ipor-derivatives/interest-rate-derivatives/indicative-term-sheet.md # Indicative Term Sheet > Here is an example of how an indicative term sheet might look for an IPOR IRS if it were to be issued in TradFi: > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). | Item | Description | | ------------------------------------------ | ---------------------------------------------------------------------------------------------- | | Party A (Floating Rate Payer): Trader | Trader (Ethereum address: 0xF4C4820c3f9edDa4e78Ea5aceB67968d76E93F99) | | Party B (Fixed Rate Payer): Liquidity Pool | IPOR USDC Liquidity Pool (Ethereum address: 0xC52569b5A349A7055E9192dBdd271F1Bd8133277) | | Notional min/max | No min, max dependent on liquidity pool | | Notional amount | e.g. USDC 100,000,000 | | Collateral | e.g. USDC 10,000 | | Maturity | 28 days | | Cancellable | Yes | | Trade date | e.g. Jul 31, 2022 10:34 (1631529296) | | Block number | e.g. 13217560 | | Transaction Hash | e.g. 0xaef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39 | | Maturity date | e.g. Aug 28, 2022 10:34 (1633948496) | | Calculation agent | Automated Market Maker (AMM) | | Fixed rate | Quoted by AMM, fixed at contract opening: e.g. 3.598% (IPOR USDC Index + Spread) | | Fixed rate day count | n/28 | | Floating Rate | IPOR - Continuous - USDC (Oracle Ethereum address: 0x421C69EAa54646294Db30026aeE80D01988a6876) | | Floating Rate Determination Date | e.g. Jul 31, 2022 10:34 (1631529296) | | Floating Rate Payment Dates | At maturity, cancellation, or liquidation | | Fee | 100 bps of collateral | | Leverage | 10-1000X | | Cap | 0-200% collateral value | | Liquidator | decentralized | | Network | Ethereum Mainnet | --- Source: https://ipor.io/docs/ipor-derivatives/automated-market-maker/the-automated-market-maker.md # The Automated Market Maker > This page describes the automated market maker > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). The AMM (Milton) is a dynamic pricing mechanism that offers quotes to users of the protocol for pay fixed rates (receive floating) or receive fixed rates (pay floating). The AMM takes the current IPOR rate at the time of quote and adds a spread taking into account a trailing moving average, the size of the trade, the risk exposure of the pool, current volatility, and reversion to the mean. **How is the Spread Calculated?** The IPOR Protocol is tuned to replicate the industry-standard methods to price interest rate swaps and apply them to the blockchain environment. The following criteria are computed to come up with the fair market price for the swap: 1. Volatility 2. Recent trend 3. Demand 4. Maturity 5. Direction (long or short) --- --- Source: https://ipor.io/docs/ipor-derivatives/automated-market-maker/liquidity-provisioning.md # Liquidity Provisioning > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). ### Role of Liquidity Providers Liquidity Providers (LPs) play a central role in providing capital used to underwrite derivatives. You can think of the liquidity pool as a passive market maker who is always available to be a counterpart in a trade. The IPOR protocol reserves capital from liquidity providers (maker) as counterparty collateral for a derivative on the opposite side of the trader (or taker). When the derivative is profitable for the trader, the funds from the liquidity pool are used to cover the payoff to the taker of the swap. ### Collateral Factor At its inception, the IPOR protocol will be fully collateralized. In other words, the Liquidity Pools will match the collateral from traders at least 1:1. The ratio between the aggregate collateral posted by the traders and the liquidity in the liquidity pool we call the collateral factor. ```math collateralFactor = \frac{\sum_{i}^{n} derivativeCollateral}{\sum liquidity} ``` There are two thresholds when it comes to utilization: - 80% - up to 80% collateralisation, the protocol will be issuing derivatives. Beyond 80%, no new derivatives can be issued. - 100% - At 100% collateralisation, the protocol will not permit withdrawing of liquidity by LPs When the collateral factor is between 80 and 100%, no new derivatives can be opened, and liquidity can be withdrawn. This way, the protocol can ensure that liquidity providers can withdraw all their funds, including those used to underwrite derivatives, without interrupting already opened contracts. Many parts of the IPOR protocol are meant to be configurable by the future IPOR DAO, such as the risk parameters of the derivative instruments. As utilization represents a form of risk, the protocol will launch conservatively. In the future, DAO participants may choose to change the collateral requirements depending on the performance of the AMM over time. Collateral Factor is used to set limits on how many derivatives the IPOR protocol can underwrite. Current limits can be found in the [Parameters](https://ipor.io/docs/ipor-derivatives/developers-docs/decentralizing-ipor/configuration-parameters.md) section of this documentation. ### Liquidity Tokens When an LP supplies funds to the pool, they receive a liquidity token in exchange for their stablecoin. Each currency has its own specific liquidity token such as: - ipUSDC - ipUSDT - ipDAI - ipXYZ (Future Tokens) The number of liquidity tokens issued to the user depends on the exchange rate between stable and liquidity token. This exchange rate is calculated in the following way: ```math exchangeRate = \frac{liquidityPoolHoldings}{qtyOfTokensIssued} ``` As the holdings of the liquidity pool change over time, the exchange rate dynamically adjusts. Holdings may change for several reasons, such as:\ \ 1\. Deposits by LPs 2\. Withdrawals by LPs 3\. [Revenue streams](https://ipor.io/docs/ipor-derivatives/automated-market-maker/liquidity-provisioning.md) described in the section below The rate is constantly changing based on the market activity to reflect the proportional value of the liquidity tokens held by an LP. ### Revenue Streams Liquidity pools have a few different ways in which revenue is generated and therefore affects the exchange rate of the ipTokens: - Fees charged when opening derivatives - Fees charged when withdrawing liquidity - P&L from the trades (both realized and unrealized) - Delegation of cash to the money markets through [Asset Management](https://ipor.io/docs/ipor-derivatives/automated-market-maker/asset-management.md) ### Withdrawing Liquidity Liquidity tokens can be redeemed for the underlying stable at any point, given that the [utilization](https://ipor.io/docs/ipor-derivatives/automated-market-maker/liquidity-provisioning.md) allows that to happen. To prevent manipulation, a fee of 0.5% is charged on withdrawal. This fee is then redistributed to the remaining holders of ipTokens within the same pool. ### Risk As with any liquidity provision, supplying stables to IPOR is associated with certain degrees of risk. Outside of standard 3rd party risks related to potential exploits, there are also economic risks to consider. Because the funds from liquidity providers are used to underwrite derivatives contracts, the net payout would be covered by the pool's funds if the traders make profitable trades. Spread and utilization thresholds are the measures implemented by the AMM to control the risk of LPs. The AMMs are not tuned for LPs to always be profitable; instead, they are designed to price for risk neutrality as much as possible. Refer to our [spread](https://ipor.io/docs/ipor-derivatives/automated-market-maker/spread.md "mention") calculation for more information. --- Source: https://ipor.io/docs/ipor-derivatives/automated-market-maker/ipor-swaps.md # IPOR Swaps > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). Interest Rate Derivatives in IPOR as a whole refer to any derivative instrument that uses an IPOR Index value as a contract reference. In the future, there could be multiple types of derivative instruments and contracts that use the IPOR Index as a benchmark rate. ### **Interest Rate Swap** ![Image](https://ipor.io/docs/assets/ipor-derivatives/ipor-image-c2-1-904c80.jpg) The IPOR Interest Rate Swap (IRS) is the cornerstone derivative product of IPOR. The IRS allows a market participant to be a Payer or Receiver and take a contract against the liquidity pool. For more detailed information about participants and contracts, reference [here](https://ipor.io/docs/ipor-derivatives/who-uses-ipor-and-for-what.md). Once a Payer or Receiver agrees to a contract quoted by the AMM, they will pay the collateral amount (margin), the contract fee, and applicable network fees (i.e., in the case of Ethereum, some ETH must be used to pay for network gas fees) to enter into a derivative smart contract. The liquidity pool will reserve an equal collateral to cover all payoff obligations. Over time the contract will manage the positions and payoffs. Once closed, it will pay the respective sum(s) to the parties. **What is notional?** Notional is the total value of the position that the market participant takes. This should not be confused with collateral. The notional value of derivative contracts is higher than the market value depending on the amount of leverage. ### Swap Directions The IPOR Protocol currently allows the opening of so-called vanilla swaps. That means that traders and LPs are exchanging two streams of cash flow: - Interest calculated based on the fixed interest rate - Interest calculated based on the floating (sometimes termed variable) interest rate.\ (see [IBT](https://ipor.io/docs/ipor-derivatives/interest-rate-derivatives/ibt.md) to learn how the floating is tracked ) Let's consider two possible directions of the interest rate swap that you can open on the IPOR protocol: - Pay fixed, receive floating. - Receive fixed, pay floating. In Pay Fixed, you are responsible for paying the fixed interest on the notional of your trade, and the AMM will be paying you the floating interest rate determined by IPOR (every time where floating rate is concerned, the IPOR is used). The net difference between what you pay and receive is your P&L. In Receive Fixed, the flow is reversed. Let's use an example of a trader who wants to hedge their loan using the IPOR rate as a benchmark between different platforms. 1. The trader takes a loan of 1.000.000 USDC at a 3.00% floating rate (at the time of opening) and is liable to pay interest on this loan. 2. Trader opens swap Pay Fixed - Receive Floating at 3.12% (the fixed rate). 3. Scenario 1: At the maturity of the loan/swap, interest rates were, on average, 3.95% 1. The trader had to pay additional interest on their loan. 2. The trader accrued interest on the swap that should cover most of their loss in the form of extra borrowing costs on the loan. 4. Scenario 2: At the maturity of the loan/swap, interest rates were, on average, 2.55% 1. The trader paid a lower interest on their loan (compared to what they would have paid at 3.00% - the original rate) 2. The trader has accrued a loss on their derivative that should be covered by the savings he made on the loan. ### Calculating the Payoff A trader's payoff at the time of the derivative closing is determined by the difference between their fixed and floating legs. In both floating and fixed cases, the Notional Amount of the derivative is used to calculate the amount of interest. **Fixed leg interest** ```math \alpha_{fix} = N * e^{ \frac{R_{fix} \cdot \Delta T}{T}} ``` **Floating leg interest** ```math \alpha_{floating} = \frac {N}{IBT_{n-1}} * IBT_{n} ``` The net payout depends on the leg. **Pay fixed - Receive Floating.** ```math \alpha_{net} = \alpha_{floating} - \alpha_{fix} ``` **Receive fixed - Pay Floating** ```math \alpha_{net} = \alpha_{fix}-\alpha_{floating} ``` Note that IBT_{n-1} is the value of IBT at the time when the swap was opened, and IBT_{n} is the IBT's price at the time of swap closing. N is the notional amount, and IR is the fixed interest rate at which the swap was opened. ### Spread Spread is one way for the AMM to control the risk and essentially price it to the traders. By exchanging one rate for another with the pool, traders effectively transfer risk to the liquidity pool. That service provided by the AMM and Liquidity pool is priced in the form of a spread. For more details, refer to the [spread section of this documentation](https://ipor.io/docs/ipor-derivatives/automated-market-maker/ipor-swaps.md). ### Fees The AMM charges a couple of fees that are summed up at the time the swap is opened: - **The opening fee** is calculated based on the notional of the swap. The DAO sets the fee's rate. Part of the opening fee is paid to the LP pool as compensation for underwriting the derivative's risk and part is set aside in the protocol's treasury. Forumula for calculating the opening fee ```math Notional * feeRate * (TimeToMaturityInDays/365) ``` - **Base flat fee** - the rate is set by the DAO. Proceeds from the flat base fee are used predominantly to subsidize the oracle. Once the oracle starts generating more ways to be supported, this fee will be phased out. - **Refundable** [**Liquidation deposit**](https://ipor.io/docs/ipor-derivatives/automated-market-maker/liquidations.md) ### Maturity IPOR Protocol offers swaps with a 28-day (or four weeks), 60 or 90 day tenors. This means that the swap will be up for liquidation once 28, 60 or 90 days have elapsed since the derivative has been opened. The contract is open for liquidation 6 hours before reaching maturity. It will continue to accrue interest until it is either closed by the trader or liquidated by a third party. ### Closing and Liquidations In V2 of IPOR swaps, new mechanism is introduced. Before reaching maturity swaps can be closed by the owner by opening an offsetting swap in the opposite direction. This process is called unwinding. The two swaps, originally opened and the offsetting one, as pair have a fixed known up-font payoff which, can be calculated immediately when the offsetting position is opened. This is why, offseting position is purely virtual. AMM opens and immediately closes it after the total payoff is calculated. ![At the point when the trader decides to unwind the swap, the hedging structure is set up.](https://ipor.io/docs/assets/ipor-derivatives/screenshot-2023-05-23-at-09-18-07-36d67f.png) _At the point when the trader decides to unwind the swap, the hedging structure is set up._ The whole process is wrapped into one action, and from the perspective of the user, the process is a one-click unwind of the swap. The cost of unwinding depends on the spread on the opposite leg. If the demand is high, then the cost of unwinding would be higher; if there is little demand cost of unwinding would be marginal. Formula to calculate the paoff when unwinding reads as follows: **Pay fixed Receive Floating** ```math PnL_{toDate} =IBT_{qty} \cdot IBT_{price}- N \cdot e^{\frac{R \cdot \Delta T }{T_{year}}} ``` ```math payoff_{receiveFixed} = Collateral + PnL_{toDate} + N \cdot (e ^ {\frac{(R_{UrFix} * T_{m}}{T_{year}}} - e ^ {\frac{(R_{pFix} * T_{m}}{T_{year}}}) - openingFee ``` **Receive fixed Pay floating** ```math PnL_{toDate} = N \cdot e^{\frac{R \cdot \Delta T }{T_{year}}} - IBT_{qty} \cdot IBT_{price} ``` ```math payoff_{receiveFixed} = Collateral + PnL_{toDate} + N \cdot (e ^ {\frac{(R_{rFix} * T_{m}}{T_{year}}} - e ^ {\frac{(R_{UpFix} * T_{m}}{T_{year}}}) - openingFee ``` **Where:** N- notional Tm- Time to maturity Tyear - time in the year R_pFix - currently offered payFixed rate\ R_rFix - currently offered receiveFixed rate\ R_UpFix -fixed rate of the pay fixed receive floating swap at the time of unwinding\ R_UrFix -fixed rate of the receive fixed pay floating swap at the time of unwinding At maturity, the swap can be closed without the offsetting position. When a trader decides to close the position, they will be reimbursed the liquidation deposit charged when the derivative is opened. Besides being closed by the owner, the IPOR Protocol allows the closing of the derivatives by the community given certain conditions: - The derivative is within 1 hour of reaching its maturity until full maturity (allowing small bandwidth described in the [Configuration Parameters](https://ipor.io/docs/ipor-derivatives/developers-docs/decentralizing-ipor/configuration-parameters.md)) - The derivative has lost all its collateral - The derivative has made 100% profit on collateral After the swap has reached its maturity, it can only be closed by the owner or an appointed in-house liquidation engine. The winnings and losings are capped at 2X or 0 as there is currently no simple way to enforce a margin top-up by the trader on the blockchain, resulting in an asymmetrical payoff risk against the pool if the contracts were allowed to exceed these limits. --- Source: https://ipor.io/docs/ipor-derivatives/automated-market-maker/ipor-swaps/hedging-example-with-morpho-protocol.md # Hedging example with Morpho protocol > Below is an illustrative example of how to create a simple fixed rate borrow using the Morpho and IPOR protocols > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). [Morpho](https://www.morpho.xyz/) is a lending protocol that allows borrowers and lenders to optimize their rates on AAVE and Compound. In other words, when matched, borrowers and lenders can meet halfway between the borrow and lend rates on the base protocol and match at a de-facto mid-market rate. Therefore IPOR Interest Rate Swaps, will tend to be a close hedge when using Morpho to deposit or borrow money from either AAVE or Compound.\ \ For this example we will use a borrow on Morpho, and a Pay Fixed swap on IPOR. The effective result will be a borrow rate which is fixed (or stable). In the case that the rate rises on Morpho, and therefore the cost, the derivative will be profitable and the winnings from the derivative would be able to pay the extra cost of credit. In the case the rate falls, the debt cost would be less but the derivative would be losing. In the end by using this strategy a user would be able to maintain an approximation of a fixed rate borrow with minimal basis risk. In order to borrow stablecoins from AAVE or Compound via Morpho and hedge the interest rate with IPOR effectively fixing the rate, you would need to: ### On Morpho 1. Go to Morpho's app and select the platform from which you want to borrow 1. Morpho-compound 2. Morpho-aave 2. Provide collateral (you will be able to borrow against it) 1. select supported collateral 2. make a transfer via Morpho ![Image](https://ipor.io/docs/assets/ipor-derivatives/morpho-provide-liquidity-efca4d.png) __ 3. Head to "Borrow market" and borrow one of the supported IPOR stablecoins: USDT, USDC, or DAI. The amount you have borrowed should match "**notional**" amount on IPOR. ![Image](https://ipor.io/docs/assets/ipor-derivatives/morpho-borrow-c7cdda.png) __ ### On IPOR 1. Head to IPOR swaps and select the same stable coin you have borrowed on Morpho 2. Click on "Open swap" for currency you have borrowed 3. Choose Pay Fixed - Receive Floating (this type of swap is used to hedge borrow positions) 4. Set your preferred leverage 5. Set **notional** to be the same as the amount you have borrowed 6. Open swap. Remember that the Maturity of a swap is 28 days. Your hedge is good for this long. If you close your borrow position before the 28 days maturity of your swap, you can also close the swap on the IPOR Protocol. ![Image](https://ipor.io/docs/assets/ipor-derivatives/ipor-open-swap-4fc56a.png) __ --- Source: https://ipor.io/docs/ipor-derivatives/automated-market-maker/spread.md # Spread > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). ### The goal of the Spread Spread is essentially a tool to control the risk exposure of the liquidity pool. The IPOR Protocol's spread configuration for the Interest Rate Swap is set in such a way to keep the spread as narrow as possible to incentivize market activity while minimizing the risk to which the liquidity pool is exposed. Having a low spread creates an ideal situation for traders as they can get exposure to the rates with a minimum premium. However, this could also limit the availability of capital to underwrite such risk as the pool could be fully utilized without creating any return incentive for the pool, disincentivizing LPs to lock capital. Therefore such situations would limit the utility of interest rate swaps. Having a high spread would be great for liquidity providers since they would always be very profitable, and their exposure to the risk would be minimal. Unfortunately, such swaps would provide little utility to the traders. The sweet spot lies somewhere in between: - Having a low enough spread so that derivatives instruments are useful for hedging and speculating for traders - Having a high enough spread so that LPs are not exposed to an unreasonable level of risk To achieve such spread levels, we run a large number of simulations using historical rates data and a series of market tests popular in quantitative finance. The future IPOR DAO will be responsible for further improving the spread models to maximize utility and efficiently manage risk. ### Spread Components Several factors contribute to the risk that the liquidity pool has to underwrite. - volatility - current levels over a given time horizon - volatility historical - reversion to the mean level Each of these components is used to calculate the fair and effective spread. --- Source: https://ipor.io/docs/ipor-derivatives/automated-market-maker/spread/math-behind-the-demand-spread.md # Math behind the demand spread > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). Demand-driven component to spread as input takes several variables: - Liquidity depth in the liquidity pools - amount of collateral deposited by the swap takers - amount of notional exposure on each leg (pay-fixed or receive-fixed) As well as configuration params from the[ risk oracle](https://ipor.io/docs/ipor-derivatives/automated-market-maker/risk-oracle.md): - Max Collateral Factor - Max Leverage The demand part is calculated in a couple of steps: 1. first, the depth of the pools is assessed by adding the liquidity available in the pools and the absolute value of the difference between collateral on both legs. ```math lpDepth = LPCollateral - |Collateral_{payFix} - Collatereal_{recFix}| ``` 2. Next, with help from the risk oracle the notional depth can be calculated. It is necessary later on to compile. MaxLeverage and MaxLPCollateralFactorPerLeg are fetched from the risk oracle ```math notionalDepth = lpDepth \cdot MaxLeverage \cdot MaxLPCollateralFactorPerLeg ``` 3. As the swaps get open their notional value is added and forms Time Weighted Notional (TWN) per leg. This value is kept separately per each asset and tenor. ```math TWN_{t,tenor,leg} = TWN_{t, tenor,leg} + N_{swap} ``` 4. As the time passes the effect of a swap on the TWN is decaying to 0 at maturity. This value is calculated on the fly and used to measure the dynamic exposure of the pool to a given leg. ```math TWN_{t, tenor,leg} = \frac{TWN_{t-1, tenor, leg} \cdot (tenor[s] - \Delta T)}{tenor[s]} ``` 5. In the next step the values of each tenor-specific TWN are added ```math TWN_{t, leg} = \sum_{tenor}TWN_{t,leg} ``` 6. Next it has to be determined, which leg is overweight and which one is underweight. This can be done by subtracting the TWN on each leg ```math overweight_{payFixed} = TWN_{payFixed} - TWN_{receiveFixed} ``` ```math overweight_{receiveFixed} = TWN_{receiveFixed} - TWN_{payFixed} ``` 7. Once it can be determined which leg is overweight, the spread can be applied to IT depending on the size of the difference. Formula for both legs is identical. ```math ratio_{payFixed} = \begin{cases} \frac{overweight_{payFixed}}{notionalDepth} & overweight_payFixed > 0 \\ 0 & overweight_{payFixced} \le 0 \end{cases} ``` 8. Finaly the demand spread can be calculated with help of simple step function. Linear step function presented below is subject to configuration and the final values of slope and base are to be set by the DAO. ```math demandSpread_{leg} = \begin{cases} 0.005 \cdot ratio & ratio < 0.1 \\ 0.01 \cdot ratio + 0.005 & ratio < 0.2 \\ 0.015 \cdot ratio + 0.005 & ratio < 0.3 \\ 0.02 \cdot ratio + 0.015 & ratio < 0.4 \\ 0.05 \cdot ratio + 0.03 & ratio < 0.5 \\ 0.33(3) \cdot ratio + 0.15 & ratio < 0.8 \\ 0.5 \cdot ratio + 0.2 & ratio < 1 \\ \end{cases} ``` 9. Now that the demand spread for leg is calculated same operations is repeated only this time notional of the new position that is to be opened is added to the "overweight" value. Afterwards simple average is calculated and final spread is returned. The last step is necessary in order to account for the slippage caused by the position and it removes the incentive of splitting position into multiple smaller swaps to potentially get a better rate --- Source: https://ipor.io/docs/ipor-derivatives/automated-market-maker/risk-oracle.md # Risk oracle > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). To remain gas and capital-efficient, IPOR Protocol relies on several externally modeled constants: - leverage cap - collateral factor - a dynamic offered rate cap - base spread params Those params are not saved to the chain, instead, they are compiled by the off-chain oracle service, signed, and provided via an S3 API. This solution allows to have the params always ready compiled regardless of the computational effort required to prepare them. The most recent risk params can be found under this URL: \------------------------ They are valid for 5 minutes from the moment they are published, and publication is done every 60 seconds. Methods that require risk params to be passed are: - opening swap - unwinding swap - getting offered rate --- Source: https://ipor.io/docs/ipor-derivatives/automated-market-maker/soap.md # SOAP > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). ### What is SOAP? SOAP, or Sum of All Payoffs, is essentially a snapshot view of the unrealized P&L of all open positions against the pool. It is the amount that the Liquidity Pool would be liable to payout should all the swaps be closed immediately. ### How is SOAP calculated? #### Fixed Interest Rate Tracking multiple portfolio positions using traditional computation is pretty straightforward. However, doing it on the blockchain requires a different approach due to computational cost. The IPOR AMM keeps track of each derivative by bundling all derivatives from a given leg into one virtual derivative. Every time the swap is opened or closed, its fixed interest rate is added to the "virtual" swap interest rate. Its notional value is used to calculate the weight of the interest rate. ```math I_{n} = \frac{I_{n-1} * N_{n-1} + I_{s} * N_{s}}{N_{n-1} + N_{s}} ``` Where I - is the interest rate of the "virtual" swap at the time of "n" N - is notional of the "virtual" swap at the time of "n" Is - is the interest rate of the newly opened swap Ns - is the notional amount of freshly opened derivative Calculating a "virtual" swap after closing a swap is the same, only + changes to -. Once the attributes of the "virtual swap" are calculated, we can then move to the floating rate as each IPOR swap is a difference in the cash flow between fixed and floating interest rates. #### Floating Interest Rate Monitoring the floating interest rate is done through "IBT" or Interest Bearing Token. IBT is not a token that you can own; instead, it accounts for the floating interest rate over time. All interest rate swaps have their notional amount denominated in IBT to account for the floating interest rate. ```math IBT_{new} = IBT_{old} \cdot e ^{\frac{IPOR \cdot \Delta T}{T_{Year}}} ``` Where IPOR is the IPOR rate at the time of calculating the IBT value adjusted for delta time. Every time the swap is opened or closed, it gets assigned with the amount of IBT reflecting its notional size. ```math N_{IBT} = \frac{N}{IBT} ``` A swap's notional denominated in IBT will grow with the floating rate. Thanks to this mechanism, the floating rate part of each swap are straightforward to calculate. We multiply IBT token count specific to a given derivative. Because in SOAP, we want to calculate the "aggregate" swap to track the whole portfolio; we have to add all of the IBT tokens together for a given leg - this represents the floating leg. #### Putting it all together The net payout would be the difference between interest generated by the fixed and floating legs in the delta time. It is, however, a little problematic to efficiently calculate it. We would need to track somehow the "average" entry-level of IBT for all derivatives, similar to what is done with the fixed rate. Alternatively, we could follow the interest accrued between each rebalance triggered every time swap is opened or closed. It then becomes a lot easier: ```math SOAP_{payFixed_{n}} = SOAP_{n-1} + N_{IBT} \cdot IBT_{price} - N_{n-1} \cdot e^{\frac{R * \Delta T}{T_{year}}} ``` ```math SOAP_{receiveFixed_n} = SOAP_{n-1} + N \cdot e^{\frac{R * \Delta T}{T_{year}}} - N_{IBT} \cdot IBT_{price} ``` ```math SOAP = SOAP_{payFixed_{N}} + SOAP_{receiveFixed_{n}} ``` Where **N** is the amount of notional from the last rebalancing **R** is the average fixed rate at the time of the previous rebalancing This simple calculation allows us to count the liability of opened swaps at the time of rebalancing. The interest "accrued" on the floating rate is cached and updated at each rebalancing. The last step is to account for the interest generated in between each rebalancing, but at this point, it is pretty straightforward. Since the IBT calculation is done in the same way, the fixed interest rate can be easily calculated for any given moment; we can then recycle the same formula to know precisely the state of the liabilities at any given moment. ### Use of SOAP Currently, SOAP is used in two places: - when calculating the worth of liquidity tokens (seem more in the [liquidity section](https://ipor.io/docs/ipor-derivatives/automated-market-maker/liquidity-provisioning.md)) - when assessing the risk of the liquidity pool --- Source: https://ipor.io/docs/ipor-derivatives/automated-market-maker/liquidations.md # Liquidations > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). ### Liquidation Deposit Liquidations are one thing that the whole DeFi running on Ethereum has to face in one way or another. The closing of a position must be triggered outside the blockchain; that is to say, some party must take action to close or liquidate a position. As IPOR interest rate swaps have a set maturity, they must be exercised at some point. Swaps may also run into situations where the whole collateral is used up, and the derivative would enter negative equity. Efficient liquidations, therefore, are a must under those conditions. The question is: how to enable liquidations without putting a high burden on the trader? At the inception of the IPOR Protocol, DAO opted for a liquidation deposit as we see this as the fairest and most efficient way to handle the process. Money markets usually allow liquidation of position at a hefty discount to incentivize liquidators to move quickly when high volatility may push loans' collateral to be worth less than it secures in a couple of minutes. With IPOR Swaps, since they are similar to vanilla swaps used in traditional markets, even at very high volatility, the derivatives are not affected to nearly the same extent since they are an exchange of cash flows over time. Therefore the protocol can allow even higher cash efficiency and let the derivative use its collateral to the very last cent. A refundable liquidation deposit is charged at the time of opening the swap. The amount of the deposit is fixed and set by the governance. The reason for charging the deposit is to make sure that there is an incentive for the trader to liquidate their derivative or for a community liquidator to do it instead of the derivative owner. The IPOR AMM allows multiple derivatives to be liquidated simultaneously, which should further help with the gas efficiency of such a procedure. ### Closing Your Derivative An interest rate swap can be closed at any time by the trader who has opened it. If the interest accrued is positive, in other words, the trader has made money on the swap; they will receive more than they initially put in. Otherwise, the interest payoff would be deducted from the trader's collateral and transferred to the liquidity pool. In any case, the liquidation deposit would be paid back to the user's Ethereum address along with the calculated payoff. ### Community Liquidations A derivative becomes available for liquidation when: - It reaches maturity in 6 hours - It has generated a 99% profit or loss Any community member can call a function to close the swap that meets these criteria within a certain threshold. The liquidator will be rewarded with the stablecoin that has been set aside as a liquidation deposit. That stablecoin reward will be transferred directly to the liquidator's Ethereum address. The reason behind allowing liquidations slightly before the maturity and 100% profit or loss is to remove friction from liquidations and increase the possibility that there might be more than one liquidation to perform at a time. ### Liquidation of last resort If the derivative reaches maturity or 100% profit or loss, the community liquidation is handed over to the DAO-appointed last-resort liquidators. At this time, the owner of the derivative can also close it and collect their liquidation deposit. --- Source: https://ipor.io/docs/ipor-derivatives/automated-market-maker/asset-management.md # Asset Management > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). ### What is Asset Management in the IPOR Protocol? When liquidity providers and traders use the IPOR protocol, the AMM keeps stablecoins in custody. That includes both LP's stable and collateral put forward by the traders. Those funds are used to make payments between Liquidity Pools and the swap takers. The funds must be kept to ensure the solvency of contracts. However, this is only necessary when the funds are transferred between parties. However, most of the time, the funds would simply be sitting there idle while they could be earning interest. This is where Asset Management comes in. Its task is to ensure that available funds are put to work at the lowest possible risk yet earning interest. At conception, the Asset Management will be delegating stable to AAVE and Compound as they are regarded as the most secure, liquid, and reliable. **Stanley** - the name of the asset management suite of contracts [Milton](https://ipor.io/docs/ipor-derivatives/automated-market-maker/the-automated-market-maker.md) - the name of Automated Market Maker ### ivTokens Below chart shows the flow of funds through the asset management: ![Deposit to asset management](https://ipor.io/docs/assets/ipor-derivatives/deposit-to-stanley-73c94c.png) When Milton has excess free funds in custody, it will deposit them to Stanley. It will receive ivTokens which serve as accounting tokens in exchange for that. Further, Stanley will deposit stable to one of the supported money markets and receive accounting tokens in exchange. ![Withdraw from asset management](https://ipor.io/docs/assets/ipor-derivatives/withdraw-from-stanley-3f4745.png) The withdrawal process is a reverse of a deposit: When Milton requests to withdraw assets from Stanley, then Stanley calculates the number of accounting tokens to withdraw from the money market selected according to its logic. It then redeems the accounting tokens and transfers the proceeds to Milton while burning the corresponding liquidity tokens. ivTokens, being accounting tokens, are used to represent the share of Milton in the funds kept by Stanley. This construction would allow opening position on Stanley by an outside actor. ### Governance Tokens When the funds are delegated to the money markets, Stanley may potentially be entitled to some rewards denominated in platform tokens (i.e., Comp or AAVE tokens). Stanley can then claim the tokens and transfer them to the appointed address controlled by the [DAO](https://ipor.io/docs/ipor-derivatives/automated-market-maker/asset-management.md), which can be used at the DAO's discretion. ### Strategy At conception, the strategy employed by asset management starts simple and will be constantly refined to maximize return. However, risk mitigation is of utmost importance when it comes to asset management. #### Allocation of Funds At inception, the strategy of the asset management is relatively simple: - each time the deposit is made from Milton, Stanley checks which money market offers the higher APR and deposits the whole amount there - every time withdrawal is triggered by Milton, Stanley checks where the APR is the lowest and draws stable from there #### Transfer of funds between markets Stanley allows for the manual action by way of multi-sig of transferring funds between money markets should the manager of Stanley have a reason to transfer holdings, either to improve APY or for maintenance reasons (money markets can be added and subtracted, in which case they would need to be drained from all the stable). This authority will be transferred to DAO. ### Reserves Not all the funds can be delegated to the money markets. A certain amount of cash needs to be held on hand to fulfill potential payoff obligations resulting from closing derivatives and withdrawing liquidity. Milton has a configuration to set the desired level of reserves and a public function "rebalance" that, when invoked, either deposits or withdraws funds from money markets to bring the reserves to the configured level. ### Calculating the token value As specified in [Liquidity Provisioning](https://ipor.io/docs/ipor-derivatives/automated-market-maker/liquidity-provisioning.md), returns from money markets are profits of liquidity providers. Calculating it, therefore, must consider the worth of the interest-bearing tokens coming from the money markets. When Milton needs to calculate the utilization or the LP pool, it requests Stanley (asset management contract) to calculate the value of its holdings. However, since the holdings of Stanley are made of the balance from the trader's collateral and deposits of liquidity providers, but the interest should be counted only towards the LPs, it makes the calculation a little bit more complex. First - Stanley needs to keep track of interest separately from its balance. The "virtual balance" is updated every time deposit or withdrawal from Stanley is made. Interest is calculated as a difference between balance (as calculated by counting interest-bearing tokens from money markets) and "virtual balance" from the time of rebalancing. Second - Interest is dynamically added to the LP on top of the balance kept by the AMM. At each rebalancing, the balance of the liquidity pool is updated, and the count of accrued interest is reset. --- Source: https://ipor.io/docs/ipor-derivatives/developers-docs/deployed-contracts.md # Deployed Contracts [Ethereum](https://ipor.io/docs/ipor-derivatives/developers-docs/deployed-contracts/contracts-overview.md) [Arbitrum](https://ipor.io/docs/ipor-derivatives/developers-docs/deployed-contracts/arbitrum.md) --- Source: https://ipor.io/docs/ipor-derivatives/developers-docs/deployed-contracts/contracts-overview.md # Ethereum > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). The list below does not cover all the implementation contracts. If you want to see the full list of deployed contracts, check the[ IPOR Addresses File on GitHub](https://github.com/IPOR-Labs/ipor-abi/blob/main/mainnet/mainnet-ethereum/addresses.json). In the list below, contracts marked as "**upgradeable**" can be updated by the IPOR Protocol team. That means the logic of those contracts can be modified as they are running. The reason for upgradability is adding new functionality and, if necessary, bug fixing. Each modification is done via a timelock contract and multi-sig contract. For the detailed list of governing accounts and multisigs, refer to the [Governing Multisig Wallets](https://ipor.io/docs/dao-governance/dao-governance/governing-multisig-wallets.md). If the contract is not marked as "upgradable," it indicates that this contract is immutable and can not be changed. ### IPOR Protocol Router | Name | Address | Links | Upgradable | | -------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | IPOR Protocol Router | 0x16d104009964e694761C0bf09d7Be49B7E3C26fd | [Etherscan](https://etherscan.io/address/0x16d104009964e694761C0bf09d7Be49B7E3C26fd) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/router/IporProtocolRouter.sol) | true | ### IPOR Oracle | Name | Address | Links | Upgradable | | --------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | IPOR Oracle | 0x421C69EAa54646294Db30026aeE80D01988a6876 | [Etherscan](https://etherscan.io/address/0x421C69EAa54646294Db30026aeE80D01988a6876) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/oracles/IporOracle.sol) | true | | OraclePublisher | 0xA735b8993778A10dE2382F57A8282738497dD508 | [Etherscan](https://etherscan.io/address/0xA735b8993778A10dE2382F57A8282738497dD508) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/oracles/OraclePublisher.sol) | true | | IPOR Algorithm | 0x9D4BD8CB9DA419A9cA1343A5340eD4Ce07E85140 | [Etherscan](https://etherscan.io/address/0x9D4BD8CB9DA419A9cA1343A5340eD4Ce07E85140) \| [Github](https://github.com/IPOR-Labs/ipor-algorithm-facade/blob/main/contracts/algorithm/IporWeighted.sol) | true | ### AMM | Name | Address | Links | Upgradable | | ---------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | AMM Swaps Lens | 0x41e34756a7772A4ca1115AFbE2e2aFbd1B0172CF | [Etherscan](https://etherscan.io/address/0x41e34756a7772A4ca1115AFbE2e2aFbd1B0172CF) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmSwapsLens.sol) | false | | AMM Open Swap Service | 0x78034b17f80c6209400B26AB7B217C31F87AE119 | [Etherscan](https://etherscan.io/address/0x78034b17f80c6209400B26AB7B217C31F87AE119) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmOpenSwapService.sol) | false | | AMM Close Swap Service | 0x6650DE6837839DFCb05D188C50b927b008825ee3 | [Etherscan](https://etherscan.io/address/0x6650DE6837839DFCb05D188C50b927b008825ee3) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmCloseSwapService.sol) | false | | AMM Pools Lens | 0xb653ED2bBd28DF9dde734FBe85f9312151940D01 | [Etherscan](https://etherscan.io/address/0xb653ED2bBd28DF9dde734FBe85f9312151940D01) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmPoolsLens.sol) | false | | AMM Pools Lens ETH | 0x8bEa65298C3E1A6CBB961a44b720D0216028bE1e | [Etherscan](https://etherscan.io/address/0x8bEa65298C3E1A6CBB961a44b720D0216028bE1e) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm-eth/AmmPoolsLensEth.sol) | false | | AMM Pools Lens WeEth | 0xB0d64c0375201911E09B0f8c4D38c5A286E165a6 | [Etherscan](https://etherscan.io/address/0xB0d64c0375201911E09B0f8c4D38c5A286E165a6) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm-weEth/AmmPoolsLensWeEth.sol) | false | | AMM Pools Service | 0x9bcde34F504A1a9BC3496Ba9f1AEA4c5FC400517 | [Etherscan](https://etherscan.io/address/0x9bcde34F504A1a9BC3496Ba9f1AEA4c5FC400517) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmPoolsService.sol) | false | | AMM Pools ServiceWeEth | 0x7b071c5A3b43B2D6624df1A649Fe78EAD2E475AC | [Etherscan \| ](https://etherscan.io/address/0x7b071c5A3b43B2D6624df1A649Fe78EAD2E475AC)[Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm-weEth/AmmPoolsServiceWeEth.sol) | false | | AMM Pools Service ETH | 0xA30845738443Aa2dd6bd0783A47B0AF8C01A9BED | [Etherscan](https://etherscan.io/address/0xA30845738443Aa2dd6bd0783A47B0AF8C01A9BED) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm-eth/AmmPoolsServiceEth.sol) | false | | AMM Storage DAI | 0xb99f2a02c0851efdD417bd6935d2eFcd23c56e61 | [Etherscan](https://etherscan.io/address/0xb99f2a02c0851efdD417bd6935d2eFcd23c56e61) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmStorage.sol) | true | | AMM Storage USDC | 0xB3d1c1aB4D30800162da40eb18B3024154924ba5 | [Etherscan](https://etherscan.io/address/0xB3d1c1aB4D30800162da40eb18B3024154924ba5) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmStorage.sol) | true | | AMM Storage USDT | 0x364f116352EB95033D73822bA81257B8c1f5B1CE | [Etherscan](https://etherscan.io/address/0x364f116352EB95033D73822bA81257B8c1f5B1CE) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmStorage.sol) | true | | AMM Storage ETH | 0x08a8Ec037DF2e54194B397cd7c761631440197c6 | [Etherscan](https://etherscan.io/address/0x08a8Ec037DF2e54194B397cd7c761631440197c6) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmStorage.sol) | true | | AMM Storage WeEth | 0x77Fe3a8E8d1d73Df54Ca07674Bf1bD6C5841e3b5 | [Etherscan](https://etherscan.io/address/0x77Fe3a8E8d1d73Df54Ca07674Bf1bD6C5841e3b5) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmStorage.sol) | true | | AMM Treasury DAI | 0xEd7d74AA7eB1f12F83dA36DFaC1de2257b4e7523 | [Etherscan](https://etherscan.io/address/0xEd7d74AA7eB1f12F83dA36DFaC1de2257b4e7523) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmTreasury.sol) | true | | AMM Treasury ETH | 0x63395EDAF74a80aa1155dB7Cd9BBA976a88DeE4E | [Etherscan](https://etherscan.io/address/0x63395EDAF74a80aa1155dB7Cd9BBA976a88DeE4E) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm-eth/AmmTreasuryEth.sol) | true | | AMM Treasury USDC | 0x137000352B4ed784e8fa8815d225c713AB2e7Dc9 | [Etherscan](https://etherscan.io/address/0x137000352B4ed784e8fa8815d225c713AB2e7Dc9) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmTreasury.sol) | true | | AMM Treasury USDT | 0x28BC58e600eF718B9E97d294098abecb8c96b687 | [Etherscan](https://etherscan.io/address/0x28BC58e600eF718B9E97d294098abecb8c96b687) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmTreasury.sol) | true | | AMM Treasury WeETH | 0xcC2fF2D38666723ea56c122097F6215B90d74196 | [Etherscan](https://etherscan.io/address/0xcC2fF2D38666723ea56c122097F6215B90d74196) \| [ub](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmTreasury.sol) | true | | AMM Governance Service | 0x8Ec9AEF0241A19Ffb278b3963d0EaaE7De52158d | [Etherscan](https://etherscan.io/address/0x8Ec9AEF0241A19Ffb278b3963d0EaaE7De52158d) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AmmGovernanceService.sol) | false | ### Spread | Name | Address | Links | Upgradable | | ------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | | Spread Router | 0xAc1C86CEacf03d5AFC8b08A22fc38Ec7c72338ed | [Etherscan](https://etherscan.io/address/0xAc1C86CEacf03d5AFC8b08A22fc38Ec7c72338ed) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/spread/SpreadRouter.sol) | true | | Spread 28 Days | 0xb8d531ea16CAF1CF7B7cBC333E8963dB59E8dAD5 | [Etherscan](https://etherscan.io/address/0xb8d531ea16CAF1CF7B7cBC333E8963dB59E8dAD5) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/spread/Spread28Days.sol) | false | | Spread 60 Days | 0x36618cE1615305f3b99eeB9dF8d4272E729A81aB | [Etherscan](https://etherscan.io/address/0x36618cE1615305f3b99eeB9dF8d4272E729A81aB) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/spread/Spread60Days.sol) | false | | Spread 90 Days | 0x22C1CF8FCDE74A373791863953B8C9aB417795D5 | [Etherscan](https://etherscan.io/address/0x22C1CF8FCDE74A373791863953B8C9aB417795D5) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/spread/Spread90Days.sol) | false | | Spread Close Swap Service | 0x948548414A364C7D6f379ED73aeDDb3C795Dcacd | [Etherscan](https://etherscan.io/address/0x948548414A364C7D6f379ED73aeDDb3C795Dcacd) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/spread/SpreadCloseSwapService.sol) | false | | Spread Storage Lens | 0xB50c618d63806Ec1594547ECDB3E97737d6C12C6 | [Etherscan](https://etherscan.io/address/0xB50c618d63806Ec1594547ECDB3E97737d6C12C6) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/spread/SpreadStorageLens.sol) | false | ### Liquidity mining | Name | Address | Links | Upgradable | | --------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | Liquidity Mining | 0xCC3Fc4C9Ba7f8b8aA433Bc586D390A70560FF366 | [Etherscan](https://etherscan.io/address/0xCC3Fc4C9Ba7f8b8aA433Bc586D390A70560FF366) \| [Github](https://github.com/IPOR-Labs/ipor-power-tokens/blob/main/contracts/mining/LiquidityMining.sol) | true | | Liquidity Mining Lens | 0x769d54D25DD9da2159Fa690e67B27484eeB39e98 | [Etherscan](https://etherscan.io/address/0x769d54D25DD9da2159Fa690e67B27484eeB39e98) \| [Github](https://github.com/IPOR-Labs/ipor-power-tokens/blob/main/contracts/lens/LiquidityMiningLens.sol) | false | | Power Token | 0xD72915B95c37ae1B16B926f85ad61ccA6395409F | [Etherscan](https://etherscan.io/address/0xD72915B95c37ae1B16B926f85ad61ccA6395409F) \| [Github](https://github.com/IPOR-Labs/ipor-power-tokens/blob/main/contracts/tokens/PowerToken.sol) | true | | Power Token Lens | 0x5a4fc8F98CA356B7E957d18c155bc62E32D21EC3 | [Etherscan](https://etherscan.io/address/0x5a4fc8F98CA356B7E957d18c155bc62E32D21EC3) \| [Github](https://github.com/IPOR-Labs/ipor-power-tokens/blob/main/contracts/lens/PowerTokenLens.sol) | false | | Stake Service | 0xf8302787582Fb769FD30107E4d877695f0DEaFEa | [Etherscan](https://etherscan.io/address/0xf8302787582Fb769FD30107E4d877695f0DEaFEa) \| [Github](https://github.com/IPOR-Labs/ipor-power-tokens/blob/main/contracts/services/StakeService.sol) | true | | FlowsService | 0xD3486D81D52B52125B9fb1AE9d674645ECe665Ac | [Etherscan](https://etherscan.io/address/0xD3486D81D52B52125B9fb1AE9d674645ECe665Ac) \| [Github](https://github.com/IPOR-Labs/ipor-power-tokens/blob/main/contracts/services/FlowsService.sol) | false | ### Asset management | Name | Address | Links | Upgradable | | ---------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | | Asset Management Lens | 0xB8dbDecBaF552e765619B2677f724a8415192389 | [Etherscan](https://etherscan.io/address/0xB8dbDecBaF552e765619B2677f724a8415192389) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/amm/AssetManagementLens.sol) | false | | Asset Management DAI | 0xA6aC8B6AF789319A1Db994E25760Eb86F796e2B0 | [Etherscan](https://etherscan.io/address/0xA6aC8B6AF789319A1Db994E25760Eb86F796e2B0) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/vault/AssetManagementDai.sol) | true | | Asset Management USDC | 0x7aa7b0B738C2570C2f9F892cB7cA5bB89b9BF260 | [Etherscan](https://etherscan.io/address/0x7aa7b0B738C2570C2f9F892cB7cA5bB89b9BF260) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/vault/AssetManagementUsdc.sol) | true | | Asset Management USDT | 0x8e679C1d67Af0CD4b314896856f09ece9E64D6B5 | [Etherscan](https://etherscan.io/address/0x8e679C1d67Af0CD4b314896856f09ece9E64D6B5) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/vault/AssetManagementUsdt.sol) | true | | Strategy AAVE DAI | 0x526d0047725D48BBc6e24C7B82A3e47C1AF1f62f | [Etherscan](https://etherscan.io/address/0x526d0047725D48BBc6e24C7B82A3e47C1AF1f62f) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/vault/strategies/StrategyAave.sol) | true | | Strategy AAVE USDC | 0x77fCaE921e3df22810c5a1aC1D33f2586BbA028f | [Etherscan](https://etherscan.io/address/0x77fCaE921e3df22810c5a1aC1D33f2586BbA028f) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/vault/strategies/StrategyAave.sol) | true | | Strategy AAVE USDT | 0x58703DA5295794ed4E82323fcce7371272c5127D | [Etherscan](https://etherscan.io/address/0x58703DA5295794ed4E82323fcce7371272c5127D) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/vault/strategies/StrategyAave.sol) | true | | Strategy Compound DAI | 0x87CEF19aCa214d12082E201e6130432Df39fc774 | [Etherscan](https://etherscan.io/address/0x87CEF19aCa214d12082E201e6130432Df39fc774) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/vault/strategies/StrategyCompound.sol) | true | | Strategy Compound USDC | 0xe5257cf3Bd0eFD397227981fe7bbd55c7582f526 | [Etherscan](https://etherscan.io/address/0xe5257cf3Bd0eFD397227981fe7bbd55c7582f526) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/vault/strategies/StrategyCompound.sol) | true | | Strategy Compound USDT | 0xE4cD9AA68Be5b5276573E24FA7A0007da29aB5B1 | [Etherscan](https://etherscan.io/address/0xE4cD9AA68Be5b5276573E24FA7A0007da29aB5B1) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/vault/strategies/StrategyCompound.sol) | true | | Strategy DSR DAI | 0xc26be51E50a358eC6d366147d78Ab94E9597239C | [Etherscan](https://etherscan.io/address/0xc26be51E50a358eC6d366147d78Ab94E9597239C) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/vault/strategies/StrategyDsrDai.sol) | true | ### Tokens | Name | Address | Links | Upgradable | | ---------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | IPOR Token | 0x1e4746dC744503b53b4A082cB3607B169a289090 | [Etherscan](https://etherscan.io/address/0x1e4746dC744503b53b4A082cB3607B169a289090) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/tokens/IporToken.sol) | false | | ipDAI | 0x8537b194BFf354c4738E9F3C81d67E3371DaDAf8 | [Etherscan](https://etherscan.io/address/0x8537b194BFf354c4738E9F3C81d67E3371DaDAf8) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/tokens/IpToken.sol) | false | | ipUSDC | 0x7c0e72f431FD69560D951e4C04A4de3657621a88 | [Etherscan](https://etherscan.io/address/0x7c0e72f431FD69560D951e4C04A4de3657621a88) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/tokens/IpToken.sol) | false | | ipUSDT | 0x9Bd2177027edEE300DC9F1fb88F24DB6e5e1edC6 | [Etherscan](https://etherscan.io/address/0x9Bd2177027edEE300DC9F1fb88F24DB6e5e1edC6) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/tokens/IpToken.sol) | false | | ipstETH | 0xc40431b6C510AeB45Fbb5e21E40D49F12b0c1F0c | [Etherscan](https://etherscan.io/address/0xc40431b6C510AeB45Fbb5e21E40D49F12b0c1F0c) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/tokens/IpToken.sol) | false | | ipweETH | 0xaC5B04988BC71bEE96f8D93040777Db3ef166125 | [Etherscan](https://etherscan.io/address/0xaC5B04988BC71bEE96f8D93040777Db3ef166125) \| [Github](https://github.com/IPOR-Labs/ipor-protocol/blob/main/contracts/tokens/IpToken.sol) | false | ### --- Source: https://ipor.io/docs/ipor-derivatives/developers-docs/deployed-contracts/arbitrum.md # Arbitrum > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). The list below does not cover all the implementation contracts. If you want to see the full list of deployed contracts, check the[ IPOR Addresses File on GitHub](https://github.com/IPOR-Labs/ipor-abi/tree/main/mainnet/mainnet-arbitrum). In the list below, contracts marked as "**upgradeable**" can be updated by the IPOR Protocol team. That means the logic of those contracts can be modified as they are running. The reason for upgradability is adding new functionality and, if necessary, bug fixing. Each modification is done via a timelock contract and multi-sig contract. For the detailed list of governing accounts and multisigs, refer to the [Governing Multisig Wallets](https://ipor.io/docs/dao-governance/dao-governance/governing-multisig-wallets.md). If the contract is not marked as "upgradable," it indicates that this contract is immutable and can not be changed. ### IPOR Protocol Router | Name | Address | Links | Upgradable | | -------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------- | ---------- | | IPOR Protocol Router | 0x760Fa0aB719c4067D3A8d4727Cf07E8f3Bf118db | [Arbiscan](https://arbiscan.io/address/0x760fa0ab719c4067d3a8d4727cf07e8f3bf118db) | true | ### IPOR Oracle | Name | Address | Links | Upgradable | | ----------- | ------------------------------------------ | ---------------------------------------------------------------------------------- | ---------- | | IPOR Oracle | 0x70DdDE503edf4816B5991Ca5E2f9DE79e295F2D0 | [Arbiscan](https://arbiscan.io/address/0x70ddde503edf4816b5991ca5e2f9de79e295f2d0) | true | ### AMM | Name | Address | Links | Upgradable | | ----------------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------- | ---------- | | AMM Swaps Lens | 0x8F98636d8c70Fc8aeBfA46c7E62d63A90Fea65DD | [Arbiscan](https://arbiscan.io/address/0x8f98636d8c70fc8aebfa46c7e62d63a90fea65dd) | false | | AMM Open Swap Service wstETH | 0x221A9A6A40A932816a56ABFEF1a8384dFF98d856 | [Arbiscan](https://arbiscan.io/address/0x221a9a6a40a932816a56abfef1a8384dff98d856) | false | | AMM Open Swap Service USDC | 0x168376391DB04F43e3924260E5aCe9BEC48a1372 | [Arbiscan](https://arbiscan.io/address/0x168376391DB04F43e3924260E5aCe9BEC48a1372) | false | | AMM Close Swap Service wstETH | 0x32365802690Ebc1E1db767f1e16974358ec3f5eC | [Arbiscan](https://arbiscan.io/address/0x32365802690Ebc1E1db767f1e16974358ec3f5eC) | false | | AMM Close Swap Service USDC | 0x8cc274CCEd430Ff6DCe4e95089b9307122803c18 | [Arbiscan](https://arbiscan.io/address/0x8cc274CCEd430Ff6DCe4e95089b9307122803c18) | false | | AMM Pools Lens wstETH | 0x7Bb6CbD3C2Ffb7ef31a55f98B7b3D11416AB9954 | [Arbiscan](https://arbiscan.io/address/0x7bb6cbd3c2ffb7ef31a55f98b7b3d11416ab9954) | false | | AMM Pools Service wstETH | 0x8cD6db83D972Da3289efFb2D02a866584a719A7f | [Arbiscan](https://arbiscan.io/address/0x8cD6db83D972Da3289efFb2D02a866584a719A7f) | false | | AMM Pools Service USDC | 0x0dfdE348bDd8E74369713C033A31a5FbB6a50F86 | [Arbiscan](https://arbiscan.io/address/0x0dfdE348bDd8E74369713C033A31a5FbB6a50F86) | false | | AMM Pools Service USDM | 0x9568A0970e5619f215F1Ba06623cBAc1eF06301d | [Arbiscan](https://arbiscan.io/address/0x9568A0970e5619f215F1Ba06623cBAc1eF06301d) | false | | AMM Treasury wstETH | 0xBd013Ea2E01C2Ab3462dd67e9C83aa3834882A5D | [Arbiscan](https://arbiscan.io/address/0xBd013Ea2E01C2Ab3462dd67e9C83aa3834882A5D) | true | | AMM Treasury USDC | 0x9324d39B29c85440cadd2202E4703E6f5d1e98F9 | [Arbiscan](https://arbiscan.io/address/0x9324d39B29c85440cadd2202E4703E6f5d1e98F9) | true | | AMM Treasury USDM | 0x88a4052FABa59AD82908D7064C8EF1778C6ea867 | [Arbiscan](https://arbiscan.io/address/0x88a4052FABa59AD82908D7064C8EF1778C6ea867) | true | | AMM Storage USDC | 0x52395372f2355491bC823d752bdb347807864308 | [Arbiscan](https://arbiscan.io/address/0x52395372f2355491bC823d752bdb347807864308) | true | | AMM Storage USDM | 0xb264E232d5Cd6120A016e419a3Ab3ED2dB86F14C | [Arbiscan](https://arbiscan.io/address/0xb264E232d5Cd6120A016e419a3Ab3ED2dB86F14C) | true | | AMM Storage wstETH | 0x326804339eC2a210e5f9246F4959aE50961c5C28 | [Arbiscan](https://arbiscan.io/address/0x326804339eC2a210e5f9246F4959aE50961c5C28) | true | | AMM Governance Service | 0xD07bcA51Eb945eC2652Ad149a0046835C692cDBc | [Arbiscan](https://arbiscan.io/address/0xD07bcA51Eb945eC2652Ad149a0046835C692cDBc) | false | ### Spread | Name | Address | Links | Upgradable | | ------------- | ------------------------------------------ | ---------------------------------------------------------------------------------- | ---------- | | Spread WstEth | 0x42444C388BEAC2D1685eBfaFaED1e86B9e7A1b3d | [Arbiscan](https://arbiscan.io/address/0x42444c388beac2d1685ebfafaed1e86b9e7a1b3d) | false | ### Liquidity mining | Name | Address | Links | Upgradable | | --------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------- | ---------- | | Liquidity Mining | 0xdE645aB0560E5A413820234d9DDED5f4a55Ff6dd | [Arbiscan](https://arbiscan.io/address/0xde645ab0560e5a413820234d9dded5f4a55ff6dd) | true | | Liquidity Mining Lens | 0xaD2a3CbFa2Bd5DFe1382491414e8A28c13ff4fc7 | [Arbiscan](https://arbiscan.io/address/0xad2a3cbfa2bd5dfe1382491414e8a28c13ff4fc7) | false | | Power Token | 0x21f1209692eD441664183413F2fdd675adb3223b | [Arbiscan](https://arbiscan.io/address/0x21f1209692eD441664183413F2fdd675adb3223b) | true | | Power Token Lens | 0x8C8a41f7c02D6828941ae7E8B689FC16e9630517 | [Arbiscan](https://arbiscan.io/address/0x8C8a41f7c02D6828941ae7E8B689FC16e9630517) | false | | Stake Service | 0x4cBAcB8F649483506a697e6C8ACD184cbFD5aE3F | [Arbiscan](https://arbiscan.io/address/0x4cBAcB8F649483506a697e6C8ACD184cbFD5aE3F) | true | | FlowsService | 0xE56DC533EC51662DF5F96BD1e0e4dE8d8AC95FFC | [Arbiscan](https://arbiscan.io/address/0xE56DC533EC51662DF5F96BD1e0e4dE8d8AC95FFC) | false | ### Tokens | Name | Address | Links | Upgradable | | ---------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | | IPOR Token | 0x34229B3f16fBCDfA8d8d9d17C0852F9496f4C7BB | [Arbiscan](https://arbiscan.io/address/0x34229B3f16fBCDfA8d8d9d17C0852F9496f4C7BB) | false | | ipwstETH | 0xbDa4b3e17a9B0ecb811E68c6f08907156CBa503C | [Arbiscan](https://arbiscan.io/address/0xbDa4b3e17a9B0ecb811E68c6f08907156CBa503C) | false | | ipUSDM | 0x4A319901c17748A637C2E0C4902f071Fa1Fd79bc | [Arbiscan](https://arbiscan.io/address/0x4a319901c17748a637c2e0c4902f071fa1fd79bc) | false | | ipUSDC | 0x485cAC13E6492CcF4d47764b0E4e07b5272B0167 | [Arbisca](https://arbiscan.io/address/0x485cAC13E6492CcF4d47764b0E4e07b5272B0167)[n](https://arbiscan.io/address/0x485cAC13E6492CcF4d47764b0E4e07b5272B0167) | false | ### Incentives | Name | Address | Links | Upgradable | | ------ | ------------------------------------------ | ---------------------------------------------------------------------------------- | ---------- | | ARB | 0x486230B2D9ACd4f10254595d5d5B9522FDe9b73a | [Arbiscan](https://arbiscan.io/address/0x486230B2D9ACd4f10254595d5d5B9522FDe9b73a) | false | | wstETH | 0x056bBD8e00e6314B811D3B904e2D788b75A7A23A | [Arbiscan](https://arbiscan.io/address/0x056bBD8e00e6314B811D3B904e2D788b75A7A23A) | false | --- Source: https://ipor.io/docs/ipor-derivatives/developers-docs/deployed-contracts/arbitrum-1.md # Base > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). The list below does not cover all the implementation contracts. If you want to see the full list of deployed contracts, check the[ IPOR Addresses File on GitHub](https://github.com/IPOR-Labs/ipor-abi/tree/main/mainnet/mainnet-arbitrum). In the list below, contracts marked as "**upgradeable**" can be updated by the IPOR Protocol team. That means the logic of those contracts can be modified as they are running. The reason for upgradability is adding new functionality and, if necessary, bug fixing. Each modification is done via a timelock contract and multi-sig contract. For the detailed list of governing accounts and multisigs, refer to the [Governing Multisig Wallets](https://ipor.io/docs/dao-governance/dao-governance/governing-multisig-wallets.md). If the contract is not marked as "upgradable," it indicates that this contract is immutable and can not be changed. ### IPOR Protocol Router | Name | Address | Links | Upgradable | | -------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------- | ---------- | | IPOR Protocol Router | 0x21d337eBF86E584e614ecC18A2B1144D3C375918 | [BaseScan](https://basescan.org/address/0x21d337eBF86E584e614ecC18A2B1144D3C375918) | true | ### IPOR Oracle | Name | Address | Links | Upgradable | | ----------- | ------------------------------------------ | ----------------------------------------------------------------------------------- | ---------- | | IPOR Oracle | 0x85564fb392e18A84A64343A3FB65839206936C0f | [BaseScan](https://basescan.org/address/0x85564fb392e18A84A64343A3FB65839206936C0f) | true | ### AMM | Name | Address | Links | Upgradable | | ----------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------- | ---------- | | AMM Swaps Lens | 0x6834BdFe5864c6B1703B999D04B092229A322943 | [BaseScan](https://basescan.org/address/0x6834BdFe5864c6B1703B999D04B092229A322943) | false | | AMM Open Swap Service wstETH | 0xFbE094Bcc8731fa45Eb88850592248e5D6aC9472 | [BaseScan](https://basescan.org/address/0xFbE094Bcc8731fa45Eb88850592248e5D6aC9472) | false | | AMM Open Swap Service USDC | 0xdF884ccEf3F18b107e0B9423aaE3b605461bB54d | [BaseScan](https://basescan.org/address/0xdF884ccEf3F18b107e0B9423aaE3b605461bB54d) | false | | AMM Close Swap Service wstETH | 0xD3626cf9DC33bB6bdEcc6CC1E2b6a6A69B561FAF | [BaseScan](https://basescan.org/address/0xD3626cf9DC33bB6bdEcc6CC1E2b6a6A69B561FAF) | false | | AMM Close Swap Service USDC | 0x8572Eb57F92F50913d9dA78E5C6a8065b0449A3D | [BaseScan](https://basescan.org/address/0x8572Eb57F92F50913d9dA78E5C6a8065b0449A3D) | false | | AMM Pools Lens | 0xa4989A9225f6DD130e8Ce4a4b5ef7902c8c389dc | [BaseScan](https://basescan.org/address/0xa4989A9225f6DD130e8Ce4a4b5ef7902c8c389dc) | false | | AMM Pools Service wstETH | 0x2bb871aC1823c7A7daeF9c00198E3f996C65401C | [BaseScan](https://basescan.org/address/0x2bb871aC1823c7A7daeF9c00198E3f996C65401C) | false | | AMM Pools Service USDC | 0x12bDfdBF97D68fc3CCC45Ef6E9c3Ca2c1F3F7522 | [BaseScan](https://basescan.org/address/0x12bDfdBF97D68fc3CCC45Ef6E9c3Ca2c1F3F7522) | false | | AMM Treasury wstETH | 0x09388e18d5C331449C6eF636726dD1fd007b8DDf | [BaseScan](https://basescan.org/address/0x09388e18d5C331449C6eF636726dD1fd007b8DDf) | true | | AMM Treasury USDC | 0x1AbA7a3C3bec8139B10a4807087084064A454a24 | [BaseScan](https://basescan.org/address/0x1AbA7a3C3bec8139B10a4807087084064A454a24) | true | | AMM Storage USDC | 0x86d94f5BACb94DaC2088a0096e88b06b1944AB1d | [BaseScan](https://basescan.org/address/0x86d94f5BACb94DaC2088a0096e88b06b1944AB1d) | true | | AMM Storage wstETH | 0x29399D76921e23314Ae259Cf5E17116f48AE65b7 | [BaseScan](https://basescan.org/address/0x29399D76921e23314Ae259Cf5E17116f48AE65b7) | true | | AMM Governance Service | 0x498eB532c9D3b4Cf20351b8767Dceb4B5D28FE4c | [BaseScan](https://basescan.org/address/0x498eB532c9D3b4Cf20351b8767Dceb4B5D28FE4c) | false | ### Spread | Name | Address | Links | Upgradable | | ------------- | ------------------------------------------ | ----------------------------------------------------------------------------------- | ---------- | | Spread WstEth | 0x3D21ADf3b0Ff5B3fDfFC8D5FFa6634Bd65949924 | [BaseScan](https://basescan.org/address/0x3D21ADf3b0Ff5B3fDfFC8D5FFa6634Bd65949924) | false | ### Liquidity mining | Name | Address | Links | Upgradable | | --------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------- | ---------- | | Liquidity Mining | 0xE9331948766593EE9CeBBB426faE317b44DaF0f2 | [BaseScan](https://basescan.org/address/0xE9331948766593EE9CeBBB426faE317b44DaF0f2) | true | | Liquidity Mining Lens | 0xF9f7FFd661F4C8De141732EEE07CEE7447C013d4 | [BaseScan](https://basescan.org/address/0xF9f7FFd661F4C8De141732EEE07CEE7447C013d4) | false | | Power Token | 0xA8799d46a00AD19B2EbD0D0D18792B4BAF26C0CC | [BaseScan](https://basescan.org/address/0xA8799d46a00AD19B2EbD0D0D18792B4BAF26C0CC) | true | | Power Token Lens | 0x4084e842E232d8b4460DEB0Bf792e94d513caa33 | [BaseScan](https://basescan.org/address/0x4084e842E232d8b4460DEB0Bf792e94d513caa33) | false | | Stake Service | 0x15AA5cd0ED90C77B8D5a6F6b163Cf8D374Eff55b | [BaseScan](https://basescan.org/address/0x15AA5cd0ED90C77B8D5a6F6b163Cf8D374Eff55b) | true | | FlowsService | 0xDB6b7c05e2ce7A1F0F0ee8eed788E5d52c909def | [BaseScan](https://basescan.org/address/0xDB6b7c05e2ce7A1F0F0ee8eed788E5d52c909def) | false | ### Tokens | Name | Address | Links | Upgradable | | ---------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------- | ---------- | | IPOR Token | 0xbd4e5C2f8dE5065993d29A9794E2B7cEfc41437A | [BaseScan](https://basescan.org/address/0xbd4e5c2f8de5065993d29a9794e2b7cefc41437a#readContract%23F9) | false | | ipwstETH | 0xff7907CDCA84DB03f09702A4A49C262908AF48Af | [BaseScan](https://basescan.org/address/0xff7907CDCA84DB03f09702A4A49C262908AF48Af) | false | | ipUSDC | 0x4AEE7072AC1a49A3F84D0A95e32F3B7D1C97fB30 | [BaseScan](https://basescan.org/address/0x4AEE7072AC1a49A3F84D0A95e32F3B7D1C97fB30) | false | --- Source: https://ipor.io/docs/ipor-derivatives/developers-docs/audits.md # Audits #### Ackee Blockchain Date: August 8, 2023 **Covers the currently live contracts** Report (Google Docs PDF): **Scope** - Asset Management DAI - EDSR Strategy #### Ackee Blockchain Date: January 28, 2023 **Covers the previous version of contracts** Report (Google Docs PDF):​[https://drive.google.com/file/d/1sM2YLOIyHO5_5YBENIPV10kwu20dso01/view](https://drive.google.com/file/d/1sM2YLOIyHO5_5YBENIPV10kwu20dso01/view?usp=share_link)​ **Scope** - Power Token (naming convention changes) - Liquidity Mining (naming convention changes) #### Ackee Blockchain Date: December 23, 2022 **Covers the previous version of contracts** Report (Google Docs PDF): [https://drive.google.com/file/d/1ZSoaibafHYfiDEVqxqRz--kuEnmBsh-J/view](https://drive.google.com/file/d/1ZSoaibafHYfiDEVqxqRz--kuEnmBsh-J/view?usp=share_link) **Scope** - Power Token - Liquidity Mining #### Zokyo Date: January 11, 2023 **Covers the previous version of contracts** Report (Google Docs PDF): [https://drive.google.com/file/d/1YzvSsyae0uf85RX7yGkIyiDnDXacenpk/view](https://drive.google.com/file/d/1YzvSsyae0uf85RX7yGkIyiDnDXacenpk/view?usp=share_link) **Scope** - Power Token - Liquidity Mining #### Ackee Blockchain Date: November 21, 2022 **Covers the previous version of contracts** Report (Google Docs PDF): [https://drive.google.com/file/d/1fXMK_pWAtmd_6FVl2h9HsZYDk8o-Q4uI](https://drive.google.com/file/d/1fXMK_pWAtmd_6FVl2h9HsZYDk8o-Q4uI/view?usp=share_link)​ **Scope** - IPOR Token #### Zokyo Date: November 29, 2022 **Covers the previous version of contracts** Report (Google Docs PDF): [https://drive.google.com/file/d/1tGTQ5j5N66Yu1kmR7mmHR67CaCViDbnd](https://drive.google.com/file/d/1tGTQ5j5N66Yu1kmR7mmHR67CaCViDbnd/view?usp=share_link)​ **Scope** - IPOR Token #### Zokyo Date: October 24, 2022 **Covers the previous version of contracts** Report (Google Docs PDF): [https://drive.google.com/file/d/1yX1_Cwpx-P0lrQj6nzgB8IcMEJGLDc0U](https://drive.google.com/file/d/1yX1_Cwpx-P0lrQj6nzgB8IcMEJGLDc0U/view)​ **Scope** - Asset management (Stanley) #### Zokyo Date: August 15, 2022 **Covers the previous version of contracts** Report (Google Docs PDF): [https://drive.google.com/file/d/1t5oRH8Cxux19Trl75qTEF3kxIpX717H7](https://drive.google.com/file/d/1t5oRH8Cxux19Trl75qTEF3kxIpX717H7/view?usp=sharing)​ **Scope** - IPOR Oracle, - Liquidity pools (Joseph), - IPOR AMM (Milton), - Spread Model, - Asset management (Stanley) --- Source: https://ipor.io/docs/ipor-derivatives/developers-docs/working-with-ipor-router.md # Working with IPOR Router > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). IPOR Protocol utilizes a diamond proxy pattern to interact with every contract in the suite. The IPOR Router is an entry point to the entire IPOR Protocol. To interact with IPOR, you should call the methods directly on the router. The calls will be delegated to the relevant contract. Router ABI and address can be found here: [#ipor-protocol-router](https://ipor.io/docs/ipor-derivatives/developers-docs/deployed-contracts/contracts-overview.md "mention") ## Calling functions on the router from Etherscan Etherscan does not allow importing ABI for the contract that uses the structure of Diamond Proxy. The "one proxy - many implementations" pattern is not yet supported at the time of writing this documentation. If you still want to use Etherscan to interact with the IPOR Router, you can do it by using custom ABI: 1. Given **you are logged** in to Etherscan, go to 2. Click "Add." 3. Fill the form with the following: 1. Title: **IPOR Protocol** 2. Address: **0x16d104009964e694761C0bf09d7Be49B7E3C26fd** 3. Custom ABI: Use the contents of the file from this repository\ After adding this custom setup, you can call the functions directly on the IPOR Router. Etherscan, as long as you're logged in, will show more methods when you open the router page: ![Custom methods on IPOR Router](https://ipor.io/docs/assets/ipor-derivatives/routercustomabi-7fcd8f.png) _Custom methods on IPOR Router_ --- Source: https://ipor.io/docs/ipor-derivatives/developers-docs/abi.md # ABI The below repository is updated every time the migration is run on IPOR smart contracts to reflect the latest state of ABIs. It contains the files of both Mainnet and Goerli Testnet.\ \ --- Source: https://ipor.io/docs/ipor-derivatives/developers-docs/v2-changes.md # V2 changes > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). ## ABI V1 to V2 update change log The below file contains a detailed log of the ABI changes that took place when upgrading from V1 to V2 ## Introduction of the router One of the most fundamental changes in V2 compared to V1 is the introduction of a new smart contract architecture - Diamond Proxy. This structure changes the way communication is done between smart contracts, both internally and externally. In V1, each component was a somewhat independent agent with its interface and administration. ![Image](https://ipor.io/docs/assets/ipor-derivatives/wookash-sketchpad-v1-a2d004.jpg) __ V2 introduces a router: a contract that acts as an abstraction layer between IPOR smart contracts and 3rd party, either a front-end application or another smart contract. ![Image](https://ipor.io/docs/assets/ipor-derivatives/wookash-sketchpad-v2-d4ef55.jpg) __ Each external method within the IPOR protocol must be called on the router to be delegated via a delegateCall to the corresponding smart contract. This helps remove complexity from the interface, save gas, and enable functionalities such as gas-efficient batching. The state that the router keeps is limited to the administration: - ownership - pausing method -> see more information under the [#risk-management-additional-information-necessary](https://ipor.io/docs/ipor-derivatives/developers-docs/v2-changes.md "mention") ### Fever Approvals V2, thanks to overhauled architecture, requires approval only on the router level. Whereas before, each proxy contract required its approval, now only one approval suffices. ### Batch executor - Method to chain the functions of the IPOR protocol. ### Executing on behalf of the "beneficiary" V2 introduces a way to execute many functions on behalf of another address. The following methods can be executed with `beneficiary` param: - Opening swap: ex. `openSwapPayFixed28daysUsdt`. The beneficiary will be an owner of the swap - Closing swap: ex. `closeSwapUsdc`. The beneficiary will receive the liquidation deposit. - Provide liquidity: ex. `provideLiquidityUsdt`. Liquidity will be deposited with the beneficiary as an owner. - Staking ipTokens: ex: `stakeLpTokensToLiquidityMining`. Each user can stake their own tokens to an account of the beneficiary. The beneficiary becomes the owner of staked tokens. - Stake IPOR token: `stakeGovernanceTokenToPowerToken`.The beneficiary will become the owner of pwIPOR staked. - Delegating pwIPOR to a pool can only be done on behalf of another user when combined with staking in one method: `stakeGovernanceTokenToPowerTokenAndDelegate`. ## Introduction of Services and Lenses #### Services Services are the contracts that change the state. #### Lenses In the chart depicting the V2 overview, the above lenses are marked in green serve. They are similar to views in MVC. ## Milton -> AMM AMM contract, formerly known as "Milton," has been divided into more manageable parts: - Treasury (state; pause, unpause, admin) that holds balances of ERC20 - services with business logic ## Multiple tenors V2 introduces multiple tenors of swaps that can be opened. Each tenor has its own individual function to open, i.e.: ``` openSwapPayFixed28daysUsdt openSwapPayFixed60daysUsdt openSwapPayFixed90daysUsdt ``` Tenor is the maximum time for which the derivative can stay open. The reason for splitting methods this way is to be able to pause them individually. Refer to [#risk-management](https://ipor.io/docs/ipor-derivatives/developers-docs/v2-changes.md "mention") ## Unwinding V2 changes the logic for closing swaps. Instead of allowing exit at any moment, V2 requires the user to open a swap on the opposite leg for a matching duration. That action is completed via the internal logic of the smart contract. Unless the swap is within 6 hours of maturity or its PLN is close to +/- 100%, the user can unwind. Otherwise, the swap can be closed as in V1. Unwinding PNL is calculated until the swap's maturity and immediately settled. ![Image](https://ipor.io/docs/assets/ipor-derivatives/unwinding-desicion-tree-c1a742.jpg) __ Read more: [/blog/unwinding-swaps-540abbe974a](https://ipor.io/news/unwinding-swaps-540abbe974a) ## Removed income fee V1 had a functionality to charge fees on profits of closed swaps. This has been removed in V2. ## Liquidity mining #### Claiming rewards from all pools at the same time V2 Introduces a function to claim from all the pools simultaneously. Thanks to the router-based architecture of diamond proxy, the claiming can be easily combined with re-delegation ## Risk oracle - new A new addition to the IPOR smart contracts is the risk oracle. It's dedicated to keeping track of parameters necessary to offer a fair rate when opening swaps. Service monitoring activity on the blockchain has a right to print to this oracle. - maxNotionalPayFixed - the maximum amount of notional that AMM should be willing to underwrite on the pay-fixed leg. This param is stored per asset. Used in calculating maximum leverage - maxNotionalReceiveFixed - the maximum amount of notional that AMM should be willing to underwrite on the receive-fixed leg. This param is stored per asset. Used in calculating maximum leverage - maxCollateralRatioPayFixed - the maximum ratio between collateral put against pay-fixed swaps and the liquidity pool depth - maxCollateralRatioReceiveFixed - the maximum ratio between collateral put against receive-fixed swaps and the liquidity pool depth - maxCollateralRatio - max collateral on both legs combined - demandSpreadFactor - parameter used to regulate the level of risk when calculating demand spread ## IPOR Oracle - simplified The following changes have been made to the IPOR oracle along with the V2 release of the IPOR protocol. 1. Removed EMA 2. Removed EMVar 3. Removed auto-update 4. **Introduction of continuously compounded interest** ## New spread model V2 introduces a new method to calculate the spread using multiple components: 1. Base spread - the component of the spread that is calculated using risk analysis 2. Demand spread AMM will price the notional as it moves away from the balance (a situation in which PayFixed and RexeiveFixed takers are in equilibrium across multiple tenors). Spread-related contracts share the same diamond proxy architecture as the rest of the protocol. One notable change in V2 is that the spread contract keeps the state related to the notional underwritten across multiple tenors. ## The Frontend data provider is removed. The frontend data provider was the middle layer contract, making it easier for the frontend to query main contracts. Since V2 is more straightforward to query data, no additional smart contracts are unnecessary. ## Risk Management - pausing. Pausing contracts, as a last line of defense, was reworked in V2. Instead of pausing separate contracts, V2 introduces "method pausing" via the router. In the new approach, Each pausable method can be paused individually or together with other methods by passing its signature to the pause function. Guardian address can execute the pause function without the need for the timelock, effectively restricting a pre-defined collection of functions. Unpausing requires the function to be called by the timelock controller. Pausing contracts with the list of method signatures ## ABDKMathQuad V2 uses ABDKMathQuad in the following places: - Calculating continuously compounding interest rate - user power-up in liquidity mining (logarithmic function) ## ERRORS Errors in V2 are revised. For the latest version of error codes, refer to the github repositories: Error Codes In IPOR Core Protocol Error Codes In Power IPOR --- Source: https://ipor.io/docs/ipor-derivatives/developers-docs/ipor-oracle.md # IPOR Oracle > **Warning:** **IPOR Derivatives has been phased out** (new swaps paused since 2 April 2026). This page is kept for reference only. See the [Fusion documentation](https://ipor.io/docs.md). > ### “Someone’s sitting in the shade today because someone planted a tree a long time ago.” > > Warren Buffet ### Oracle structure Oracle structure consists of 2 contracts and an off-chain component. 1. Rate calculation contract: This stateless contract fetches the data from all the protocols supported by IPOR Index and runs all the calculations to compute IPOR Rate. 2. Oracle contract\ This contract keeps the state of the IPOR rate and IBT. Oracle contract allows for permissionless update of the IPOR rate (as long as requested is willing to cover the gas costs associated with the rate calculation) by invoking updateIndex(asset Address) function. 3. Rate publication off-chain oracle service.\ This service reads the value calculated in the rate calculation contract are publishes it to the IPOR Oracle contract. This is mainly done due to gas optimization reasons. #### Public Functions | Function | Notes | | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [getIndex](https://etherscan.io/address/0x421C69EAa54646294Db30026aeE80D01988a6876#readProxyContract#F3) (address asset) | It returns the most recently published IPOR value for a given asset. | | [getAccruedIndex](https://etherscan.io/address/0x421C69EAa54646294Db30026aeE80D01988a6876#readProxyContract#F2)(uint256 calcTimestamp, address asset) | It returns the structure with: - the most recent IPOR Index - IBT as calculated to the current timestamp. See calculateAccruedIbtPrice | | [calculateAccruedIbtPrice](https://etherscan.io/address/0x421C69EAa54646294Db30026aeE80D01988a6876#readProxyContract#F1) (address asset, uint256 calcTimestamp) | For a given asset it calculates the current value of IBT considering the time passed from the last IPOR publication. Change in IBT is made based on the recently published IPOR. | | [updateIndex](https://etherscan.io/address/0x421C69EAa54646294Db30026aeE80D01988a6876#writeProxyContract#F12) (address asset, uint256 value) | Function available only to whitelisted addresses. It allows for IPOR publication. This function will also trigger a recalculation of IBT. | | [updateIndex](https://etherscan.io/address/0x421C69EAa54646294Db30026aeE80D01988a6876#writeProxyContract#F13) (address asset) | Function available only to whitelisted addresses. When invoked, it will make a request to [index-calculating smart contract](https://etherscan.io/address/0x9D4BD8CB9DA419A9cA1343A5340eD4Ce07E85140) (also used by the off-chain oracle) publish the index, and return value (same sa getIndex) | | [updateIndexes](https://etherscan.io/address/0x421C69EAa54646294Db30026aeE80D01988a6876#writeProxyContract#F14) (address\[] assets, uint256\[] values) | Allows IPOR updating for multiple assets simultaneously. | | [addUpdater](https://etherscan.io/address/0x421C69EAa54646294Db30026aeE80D01988a6876#writeProxyContract#F2) (address updater) | Available for Owner only. Adds address to whitelist of IPOR index updaters | | [removeUpdater](https://etherscan.io/address/0x421C69EAa54646294Db30026aeE80D01988a6876#writeProxyContract#F7) (address updater) | Available for Owner only. Removes address from the whitelist of IPOR index updaters | | [addAsset](https://etherscan.io/address/0x421C69EAa54646294Db30026aeE80D01988a6876#writeProxyContract#F1) (address asset, uint256 updateTimestamp | Available for Owner only. Adds asset for which IPOR can be compiled. | | [removeAsset](https://etherscan.io/address/0x421C69EAa54646294Db30026aeE80D01988a6876#writeProxyContract#F6) (address asset) | Available for Owner only. It removes asset. | --- Source: https://ipor.io/docs/ipor-derivatives/developers-docs/decentralizing-ipor.md # Decentralizing IPOR **Progressive Decentralization**\ The IPOR Protocol aims to be fully on-chain and decentralized. This is done via a clear road map for progressive decentralization.\ \ There are natural limitations of having complete decentralization at the beginning. Thus from the outset IPOR Labs as the first protocol developer sets itself out to build and iterate on the IPOR index initially with the community's help in a transparent manner to allow for feedback and time before the changes take effect. The project's ethos is outlined in the [IPOR Manifesto](https://www.ipor.io/manifesto), which acts as a guideline for protocol development.\ \ During the first step IPOR Labs will lead core development decisions in order to maintain a stable protocol launch. In the second step, 3-6 months later, IPOR Labs will create a snapshot voting page to allow the community to vote on modifying IPOR and developing new products. Finally, the IPOR Protocol then plans to mature to a fully community-driven DAO. The smart contracts which have been governed by multisignature by IPOR Labs will be cycled out and distributed to include other DAO members, and complete ownership and control of the IPOR protocol will be decided by governance voting by IPOR token holders. IPOR Labs will continue to participate and make proposals DAO willing; however, **the ultimate approval will be in a decentralized manner via the DAO**.\ \ Over time, IPOR will slowly move towards full DAO governance and ownership over the protocol so that it may be completely community-driven. This includes the DAO treasury and updates to the protocol. ### Initial phase governance structure In the initial period, IPOR smart contracts are managed by the IPOR Core Team via the structure consisting of Gnosis Safe, Timelock, and Open Zeppelin Defender. ### Timelocks Each contract allowing for state change by admin (such as pause) or upgrades is owned by a timelock. #### IPOR Protocol Owner with Timelock 0xD92E9F039E4189c342b4067CC61f5d063960D248 - Proposers: 0xF6a9bd8F6DC537675D499Ac1CA14f2c55d8b5569 (DAO Multisig Gnosis) - Executors: - 0xA21603c271C6f41CdC83E70a0691171eBB7db40A - 0xaf7ccC20aC512780b6245ff16aB60174dDEdf306 - 0x4C849F14fE8F7f880cEAcBd09A4f133c3bFa4b40 - 0xcd6f959660eEF9873c14f84d4b6893beB0Ab8Ef5 At the inception, the minimum time set on this timelock is 10 minutes. In the initial months from the launch highest priority is set on quick response. As protocol continues to operate and transition to the DAO-run governance model, this timelock will be adjusted to increase the minimum timelock. Each change to either configuration or implementation of contracts using a proxy is done with the help of OpenZeppelin Defender. Process of making a configuration change: - Transaction changing contract param is prepared and scheduled using Defender - Multisig collects signatures until a quorum is reached. At this point, the Timelock period is set. - After the timelock has passed, the transaction can be executed by one of the above-listed executors. Process of update (IPOR contracts often use constants as configuration params and require contract updates to change settings. Those optimizations are due to significant gas optimizations): - The new implementation is deployed - The transaction with changing of the contract implementation behind the proxy is prepared and scheduled using Defender. - Multisig collects signatures until a quorum is reached. At this point, the Timelock period is set. - After the timelock has passed, the transaction can be executed by one of the above-listed executors. ### DAO Multisig - Gnosis Safe 0xF6a9bd8F6DC537675D499Ac1CA14f2c55d8b5569 Signing addresses: - 0xA21603c271C6f41CdC83E70a0691171eBB7db40A - 0xaf7ccC20aC512780b6245ff16aB60174dDEdf306 - 0x1d682c7eDC203B8A17dC9b8B96cbf1e2ef5B5645 - 0xcd6f959660eEF9873c14f84d4b6893beB0Ab8Ef5 - 0x7E8d6204022F77a75Fe49498E5Dc083D5F22Ad2F - 0x684EBbf43FbbD29DaB271b9442D15dF34286D861 Consensus: **4 out of 6** - IPOR Core Team - Engineering, Business --- Source: https://ipor.io/docs/ipor-derivatives/developers-docs/decentralizing-ipor/configuration-parameters.md # Configuration Parameters The parameters listed below have been decided upon for the launch of the IPOR network. These parameters will go to governance and may be changed, updated, added to, or eliminated by the IPOR DAO.**AMM** - Max swap collateral amount: **100.000 stable (2000stETH)** - Maximum allowed utilization for issuing derivatives: **80%** - Maximum allowed utilization for a given leg: up to 48% (actual value determined by the risk engine ) - Maximum allowed utilization to withdraw liquidity: **100%** - Minimum leverage: **10x** - Maximum leverage: **1000x** (actual leverage is determined by the risk engine) - Max liquidity provided by one address: **10.000.000** stable **Liquidations** - time before the maturity when the position is put up for community liquidation: **1** **hour** - time before the maturity when the position can be closed by the owner without offsetting: **6 hours.** - profit or loss of the derivative - makes it available for community liquidation: **99%** **Asset Management** - level of cash reserves not delegated to money markets: - USDT, DAI, USDC: 5% - stETH: N/A **Spread**Spread params are constants that reflect the current spread model based on recent market conditions. It is intended to update those parameters periodically as the market conditions change.​​ **Fees** - opening fee rate: **0.0005** - Withdrawal from the liquidity pool: **0.5%** ([more info](https://app.gitbook.com/o/-Mb-rool_7klO2TEFlki/s/-Mb-rXRSKhSEzwSROdm-/automated-market-maker/liquidity-provisioning#withdrawing-liquidity)) - IPOR publication fee rate: **10** **stable** (USDC, USDT, DAI) or 0.005stETH - Part of the opening fee set aside for DAO: **50%** - Liquidation deposit amount: **20 stable** (USDC, USDT, DAI). or 0.01stETH - Address to which the publication fee can be transferred: **TBD** - Address to which the income fee can be transferred: **TBD** ​​ --- Source: https://ipor.io/docs/dao-governance.md # Overview The DAO is currently in a transition phase from IPOR DAO to Fusion DAO. IPOR DAO was governed by the $IPOR token. Fusion DAO will be governed by the $FUSN token in the future, which has not yet been launched. More details can be found in the [FAQ](https://ipor.io/docs/dao-governance/tokenomics/usdfusn-snapshot-faq.md). Until the new tokenomics are released, the [legacy $IPOR tokenomics docs](https://ipor.io/docs/dao-governance/tokenomics/usdipor-token-legacy.md) will still be available. --- Source: https://ipor.io/docs/dao-governance/tokenomics/usdfusn-snapshot-faq.md # $FUSN Snapshot FAQ ### 1: What is the purpose of IIP-35? [IIP-35](https://snapshot.box/#/s:ipordao.eth/proposal/0xb4a9a4f8fea0bd0351bfb46713ecf7bb10e7ef2fde596160b3aa4302415ac242) proposes a token migration from IPOR to a new token, FUSN, to support the growth of the Fusion protocol. It includes rebranding the protocol to Fusion, raising additional capital via a SAFT agreement, and transitioning the IPOR DAO to the Fusion DAO. ### 2: Why is the token migration necessary? The migration is needed to focus on Fusion as the core product, secure additional funding for technical development, operations, business development, and marketing, and position the protocol for long-term success in expanding markets like onchain asset management and structured products. ### 3: How will the DAO be rebranded? A: The IPOR DAO will transition to Fusion DAO to reflect its core focus, inheriting all existing assets, liabilities, and protocols. ### 4: What happens to existing IPOR token holders? IPOR token holders will receive FUSN tokens at a 1:1 ratio based on a snapshot of their holdings, taken on May 9, 2025, at 02:14:59 PM UTC at Ethereum block height 22446433. ### 5: What will the snapshot cover? The snapshot will cover both IPOR and pwIPOR balances on Ethereum, Arbitrum, and Base. Earned but unclaimed pwIPOR will also be included along with any $IPOR held in vesting contracts by the IPOR Labs team and investors. ### 6: What is the maximum supply of the FUSN token? The maximum supply of FUSN tokens will be 100 million, equivalent to the IPOR token supply. ### 7: What changes will occur to protocol-owned liquidity (POL) and pwlPOR liquidity mining? After the snapshot, POL will be withdrawn from decentralized and centralized exchanges (DEXs and CEXs). pwlPOR liquidity mining will be suspended, but pwlPOR holders will receive FUSN tokens without needing to unstake. When the liquidity is withdrawn, the IPOR token price will trend towards zero since it is effectively discontinued. ### 8: How will governance function during the transition phase? When IPOR token-based governance is temporarily unavailable during the transition, IPOR Labs and the IPOR DAO workgroups (economic, governance, and marketing) will act as guardians. A new snapshot space for governance will be set up after the FUSN token launch. ### 9: What is the plan for fundraising? A legal entity will be established to sign an SAFT agreement with investors. Proceeds from the token sale will go to the DAO treasury for protocol and business development by [IPOR Labs](https://snapshot.box/#/s:ipordao.eth/proposal/0x47a38a6361d06e2f62a1f03bd413c43a465ca776db1303afe4a780bf749fb8a0). ### 10: What are the vesting terms for FUSN tokens? FUSN tokens for new investors will be locked and subject to vesting. A significant portion of IPOR Labs team members’ liquid tokens will also have vesting aligned with new investors. Other token holders’ FUSN tokens may have vesting, but it will be shorter than or equal to that of new investors. ### 11: What is the FUSN token utility? The FUSN token will provide: 1. Governance voting power for protocol decisions, budget, and incentives. 2. Fee rebates for asset managers and power users who lock FUSN to reduce Fusion protocol fees. 3. Buybacks using protocol revenue to burn tokens or add DEX liquidity. 4. Liquidity mining power-up for derivative pool distribution and buyside demand. ### 12: What will be the approximate distribution of FUSN tokens after token migration? Please have a look at this chart: ![March 2025 estimation.](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfujFWsAdJviTK_OF0MzJNY_XfYS-3jT5T4tOehA-XKJ1xE1jPkIHYhnHaZb1p99mn0XmytywolMyWnUlp0qudqNdS7-l4uPyl3c2jVoBNiCdoOS_hhzSzLTuDfAEMTRBaUpAy4ag?key=KyhCehrST99cepR-Ax5tQYC0) _March 2025 estimation._ ### 13: How will protocol revenue be used with FUSN tokens? Up to 100% of protocol revenue can be used to buy back FUSN tokens for the DAO treasury. The use of these tokens (e.g., improving DEX liquidity) will be decided through snapshot- and workgroup-based governance initially, with a gauge system planned for long-term revenue distribution decisions by FUSN holders. ### 14: Will interest rate swaps and indices remain part of the protocol? Yes, interest rate swaps and indices (the IPOR protocol) will remain core components and will be expanded. New products combining interest rate swaps and Fusion vaults, like fixed-rate earn or borrow products, are also planned. ### 15: What is the timeline for the FUSN token launch? The FUSN token will launch once the protocol achieves significant traction, considering market conditions. The rebrand aims to build TVL, brand recognition around Fusion, and launch in proper market conditions. No specific timeline is provided. ### 16: Are $FUSN-related incentives campaigns planned? A [points program](https://ipor.io/news/introducing-ipor-fusion-points-6666d85abe8a) is live. ### 17: What happens to existing smart contracts and multisigs? Existing smart contracts and multisigs will remain unchanged during the transition. ### 18: What should I do if I have a question about the migration that’s not answered here? Please [join IPOR Labs’ Discord](https://discord.gg/MQhWx7KHuZ) and share your questions with the team and community. --- Source: https://ipor.io/docs/dao-governance/tokenomics/usdipor-token-legacy.md # $IPOR Token (Legacy) --- Source: https://ipor.io/docs/dao-governance/tokenomics/usdipor-token-legacy/usdipor-token.md # $IPOR Token The IPOR token is the protocol's native token issued to the parties involved with the project: builders, investors, liquidity providers, and the like. It's an ERC20 token issued on L1 Ethereum. ### Total supply At the inception, 100.000.000 tokens were minted and transferred to all appointed addresses: [0x1e4746dC744503b53b4A082cB3607B169a289090](https://etherscan.io/token/0x1e4746dc744503b53b4a082cb3607b169a289090) _Bridged IPOR:_ - Arbitrum [0x34229B3f16fBCDfA8d8d9d17C0852F9496f4C7BB](https://arbiscan.io/address/0x34229B3f16fBCDfA8d8d9d17C0852F9496f4C7BB) - Base [0xbd4e5C2f8dE5065993d29A9794E2B7cEfc41437A](https://basescan.org/address/0xbd4e5C2f8dE5065993d29A9794E2B7cEfc41437A) The minting function has been removed from the contract; hence no additional token will ever be minted. ### Philosophy The intention behind the IPOR token is to enable the protocol users to take ownership of the IPOR Protocol as it transitions to a fully decentralized DAO. Everything is geared towards achieving that goal: from the number of tokens, emission strategy, and allocations to how the liquidity mining is designed. The IPOR Protocol will be DAO governed and the IPOR token is a way to hand over ownership to its users. --- Source: https://ipor.io/docs/dao-governance/tokenomics/usdipor-token-legacy/token-distribution-model.md # Token distribution model ## Minting and burning One hundred million (100,000,000) IPOR tokens were minted at inception. The mint function is not available beyond the initial mint. Likewise, there is no burning method. The IPOR token is a simple non-upgradeable ERC20 contract. ## Token allocation All vesting mentioned below starts at TGE. | Share | Who | Vesting details | Wallet Address | | ------ | ------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | | 30% | DAO Treasury | Governed by IPOR DAO | [0x558c8eb91F6fd83FC5C995572c3515E2DAF7b7e0](https://etherscan.io/address/0x558c8eb91F6fd83FC5C995572c3515E2DAF7b7e0) | | 25% | Liquidity mining | Emission of 1.05 tokens per block. Can be adjusted by the DAO. | [0x0b65625f905168EF24829fb625B177f83f1BFe6B](https://etherscan.io/address/0x0b65625f905168EF24829fb625B177f83f1BFe6B) | | 12.76% | Operations | No vesting. To be used by the DAO | [0xB7bE82790d40258Fd028BEeF2f2007DC044F3459](https://etherscan.io/address/0xB7bE82790d40258Fd028BEeF2f2007DC044F3459) | | 20% | Core Team | Linear vesting over 3 years. No cliff. | [0x6f8c6Ae4e765a5d1fe07763B41c43453132C5D3d](https://etherscan.io/address/0x41a3176aed445af3307be0f44f88c568c665e6f8#tokentxns) | | 11.85% | Investors | Linear vesting over 3 years. No cliff. | Multiple vesting walllets | | 0.39% | Retroactive Rewards | 85,200 unlocked from 18.01.2023. 305,000 vesting 6 months from the same date. | [Multiple wallets](https://docs.google.com/spreadsheets/d/1v-UanyPFiNUPF-mYwwuvdb0mVQbjwI3874Rhlnqpctg/edit#gid=0). | ![Image](https://ipor.io/docs/assets/dao-governance/airdrop-blogpost-designs-c3-282d89.png) __ ### Inflation rate The IPOR Token emission starts with _retroactive rewards for early protocol users, followed by IPOR's Liquidity Mining model (_[_Power Tokens_](https://ipor.io/news/power-tokens-incentives-done-better-e9e88e38208b)_)_. The initial liquidity mining emission rate started at 10,800 pwIPOR tokens per day for the first 3 months. Issuance details are displayed in the chart below. ![Image](https://ipor.io/docs/assets/dao-governance/ipor-inflation-a3f44e.jpg) __ ### Further Liquidity Mining Adjustments After a successful [vote in IPOR's Economic Working Group](https://ipor.io/news/liquidity-mining-changes-approved-ipor-emission-reduction-and-boosting-curve-update-e593673a68fb) on April 25, 2023, the inflation rate was adjusted to 7,560 pwIPOR per day (0.35 tokens per block, per pool). With the [launch of the stETH pool](https://ipor.io/news/ipor-v2-multiple-protocol-upgrades-new-eth-rate-markets-and-yield-opportunities-d4afa7b2967a) on October 12, 2023, emissions were increased again to 10,800 per day. Through [IIP-13](https://snapshot.org/#/ipordao.eth/proposal/0xc0ced36e47dffd563f83af2fb1df5bde16b4c8f89b6bdedb9ab8b95176d9c481), the Economics Workgroup was authorized to make regular adjustments to the amount of total Liquidity Mining pwIPOR emissions and the allocation to individual liquidity pools. The changes were announced in the Discord channel [#the-pool](https://discord.com/channels/832532271734587423/968055239058010112). Liquidity Mining was discontinued in 2025 according to [IIP-35](https://snapshot.box/#/s:ipordao.eth/proposal/0xb4a9a4f8fea0bd0351bfb46713ecf7bb10e7ef2fde596160b3aa4302415ac242). --- Source: https://ipor.io/docs/dao-governance/dao-governance/fusion-dao-governance.md # Fusion DAO Governance The Fusion DAO is, by virtue of [IIP-35](https://snapshot.box/#/s:ipordao.eth/proposal/0xb4a9a4f8fea0bd0351bfb46713ecf7bb10e7ef2fde596160b3aa4302415ac242), the successor to the IPOR DAO, an was created to decentralize decision-making around the Fusion Protocol and the IPOR Protocol. It aims to become a fully community-governed public good. The following platforms are used to organize collaborative decision-making processes: - [**Discord** ](https://discord.com/invite/bSKzq6UMJ3)- used to inform the community and enable discussions. - [**Snapshot** ](https://snapshot.box/#/s:ipordao.eth)- used for token-based voting on formal proposals. --- Source: https://ipor.io/docs/dao-governance/dao-governance/discord-all-channels.md # Discord - All Channels The IPOR Fusion Discord is a great place for community members to interact with each other, learn about the protocol, and suggest improvements to different aspects of the products. The barrier to entry is low since Discord can be accessed on multiple devices and through free browser or desktop applications. > **Note:** The initial Discord conversations (in all channels) are used to gauge sentiment and gather information about community members' wishes, ideas, and needs. These conversations can kickstart proposals for work or changes to the protocol, which then move to the specialized #open-governance forum channel. --- Source: https://ipor.io/docs/dao-governance/dao-governance/discord-open-governance-forum.md # Discord - Open Governance Forum ![Open Governance forum](https://ipor.io/docs/assets/dao-governance/image-489cae.jpg) ## Open Governance forum (Discord) The Open Governance forum in Discord is where DAO Members post proposals following the relevant template, brainstorm, propose work, and like (❤️) proposals. > **Warning:** The Open Governance forum is where essential information about a proposal is presented and where other DAO Members can provide their initial opinions. --- Source: https://ipor.io/docs/dao-governance/dao-governance/discord-formal-governance.md # Discord - Formal Governance > **Warning:** Only pwIPOR token holders can vote on formal governance proposals. ![Governance process flow charts](https://ipor.io/docs/assets/dao-governance/image-90bd68.jpg) Major decisions regarding the workings of the app, business development, marketing collaborations, strategy, and protocol have to pass a formal vote. Initial proposal ideas should be discussed less formally in the Discord channel #the-senate and the [open governance Discord forum](https://ipor.io/docs/dao-governance/dao-governance/discord-open-governance-forum.md). After formalization with the corresponding proposal structure (template below), the proposal moves to the formal governance forum in Discord where the discussion is finalized. Any governance proposal posted in the formal governance forum should follow this template: - Summary: Provide a brief overview of the proposal and its potential impact. For extensive proposals, please add an abstract. - Problem/issue: Describe the problem or perceived issue that needs to be addressed. - Solution: Present the proposed solution and how it helps achieve the desired goal. - KPIs: What are the Key Performance Indicators to track successful completion? Any milestones? - Timeline & reporting: Deadline and timeline for the milestones and completion, as well as how it will be reported. - Discussion: - Pros and Cons: Highlight the advantages and disadvantages of the proposal. - Open Questions: Identify open questions and areas for feedback. - Resources: Identify skills required and necessary budget. - How you can help: Indicate if and how you can help implement this proposal. - Further information: Provide relevant links, resources, and additional information for participant education. You can find and copy/paste the template directly in Discord under Post Guidelines: ![Post guidelines template](https://ipor.io/docs/assets/dao-governance/image-ef379b.jpg) --- Source: https://ipor.io/docs/dao-governance/dao-governance/snapshot-formal-governance.md # Snapshot - Formal Governance On August 15, 2023, IIP-11 proposed the creation of a Snapshot space with specific parameters to the community. After receiving approval in the #open-governance IPOR Discord channel, the Snapshot space was set up on September 6, 2023 at: To participate in Snapshot-based voting, community members must own pwIPOR tokens or have pwIPOR delegated to them. > **Note:** pwIPOR-based voting DOES NOT require token holders to undelegate from a liquidity mining position first. The modularity of the Power Token liquidity mining mechanism enables boosting and voting to happen in parallel. Voting ### Cast your vote Go to the [IPOR DAO Snapshot space](https://snapshot.org/#/ipordao.eth) and connect a wallet with a pwIPOR token balance. ### Select proposal Select the proposal that you want to vote on. ### Vote Cast your vote by selecting your preferred option and clicking "Vote." > **Note:** You will be required to sign a message that is gas-free. > > You can change your vote before the voting period ends by selecting a different option and signing a new message. Learn more about the voting process in [Snapshot's Docs](https://docs.snapshot.box/user-guides/voting/vote). Delegating your voting power If you prefer to delegate your voting power to another community member, use the "Delegate" Snapshot function: [Delegate](https://snapshot.org/#/ipordao.eth/delegate) ![Delegate screenshot](https://ipor.io/docs/assets/dao-governance/image-1eb892.jpg) Select the wallet to which you want to delegate your voting power and click "Confirm." You will have to sign a transaction that requires gas. > **Note:** Delegating your votes DOES NOT grant access to your wallet/tokens. In addition, pwIPOR tokens are non-transferable by default. ![Delegate confirm screenshot](https://ipor.io/docs/assets/dao-governance/image-dde00c.jpg) Several IPORIANs have publicly announced their wallets in the [#meet-the-iporians](https://discord.gg/bYSnnh86xC) Discord channel and are open to receiving voting power. If you require further help with delegation, refer to the official [Snapshot Docs](https://docs.snapshot.box/user-guides/delegation). How is a Snapshot proposal created? **Details** Anyone can create a Snapshot proposal in the IPOR DAO space if they own a minimum of 25,000 own and/or delegated pwIPOR tokens. This threshold may gradually increase as the number of pwIPOR tokens grows. Voting begins 24 hours after the proposal is created and lasts three days. Please refer to the [guidelines](https://snapshot.org/#/ipordao.eth) for proposal creation. Is there a quorum requirement? **Details** Yes, at least 500,000 pwIPOR tokens must vote for a proposal to be accepted or rejected. If there are more “Yes” votes than “No” votes at the end of the voting period, and the quorum is reached, the proposal is accepted (or vice versa). --- Source: https://ipor.io/docs/dao-governance/dao-governance/governing-multisig-wallets.md # Governing Multisig wallets ## Fusion Each of the addresses marked "IPOR Labs" is held by one separate individual on the IPOR Labs core team. #### DAO Multisig Allowed to create proposals to modify the live contracts of IPOR Protocol. Address: 0xF6a9bd8F6DC537675D499Ac1CA14f2c55d8b5569\ (exceptions: RobinhoodChain: 0x0498D04036AC29A8eFD2f9610bf067e78CC7DA87) Consensus: **4 out of 6** Signing addresses: - IPOR Labs 0x5FFB51b6A68E2efc90A29e6bfB3bf317c2bB0d0c - IPOR Labs 0x9A3aD8E323CB4c7E351224077342a414fDeCfB58 - IPOR Labs 0x1d682c7eDC203B8A17dC9b8B96cbf1e2ef5B5645 - IPOR Labs 0xDd3a692864E8A1cb1549Df32A3e5D09ddf21a51b - IPOR Labs 0x7E8d6204022F77a75Fe49498E5Dc083D5F22Ad2F - IPOR Labs 0xd01911A1a0EFDdE736aF90B199Def918749c8A92 --- #### Operations wallet Address: 0xB7bE82790d40258Fd028BEeF2f2007DC044F3459 Address to hold the tokens budgeted for operations: DEXes, Airdrops, covering development and administrative costs\ (exceptions: RobinhoodChain: 0x5590604cf7f735786aae10a0F4B42B28E312eE34) Consensus: **4 out of 6** Signing addresses: - IPOR Labs 0x5FFB51b6A68E2efc90A29e6bfB3bf317c2bB0d0c - IPOR Labs 0x9A3aD8E323CB4c7E351224077342a414fDeCfB58 - IPOR Labs 0x1d682c7eDC203B8A17dC9b8B96cbf1e2ef5B5645 - IPOR Labs 0xDd3a692864E8A1cb1549Df32A3e5D09ddf21a51b - IPOR Labs 0x7E8d6204022F77a75Fe49498E5Dc083D5F22Ad2F - IPOR Labs 0xd01911A1a0EFDdE736aF90B199Def918749c8A92 --- ## IPOR Protocol #### IPOR Protocol Timelock Address: 0xD92E9F039E4189c342b4067CC61f5d063960D248 The smart contract has the owner rights over the IPOR Protocol. It can schedule proposals for execution. - Proposers: - 0xF6a9bd8F6DC537675D499Ac1CA14f2c55d8b5569 (DAO Multisig) - Executors: - IPOR Labs 0xA21603c271C6f41CdC83E70a0691171eBB7db40A - IPOR Labs 0xaf7ccC20aC512780b6245ff16aB60174dDEdf306 - IPOR Labs 0x4C849F14fE8F7f880cEAcBd09A4f133c3bFa4b40 - IPOR Labs 0xcd6f959660eEF9873c14f84d4b6893beB0Ab8Ef5 --- #### IPOR Oracle Address: 0x75DC10597861B687ea1c6F955cDDA0c913E2299f The wallet can collect the publication fee from the AMM's balance. Consensus: **3 out of 5** Signing addresses: - IPOR Labs 0x4E343Bb445a037cF217AfBBE0Ef51F83dfdc0Fff - IPOR Labs 0xaf7ccC20aC512780b6245ff16aB60174dDEdf306 - IPOR Labs 0x1d682c7eDC203B8A17dC9b8B96cbf1e2ef5B5645 - IPOR Labs 0xcd6f959660eEF9873c14f84d4b6893beB0Ab8Ef5 - IPOR Labs 0x7E8d6204022F77a75Fe49498E5Dc083D5F22Ad2F --- #### IPOR DAO Snapshot Address: 0x1619C8b25C12b12D652d9f0eaa2412830E77291C Address to administer the IPOR DAO snapshot. Consensus: **3 out of 5** Signing addresses: - IPOR Labs 0xA21603c271C6f41CdC83E70a0691171eBB7db40A - IPOR Labs 0x1d682c7eDC203B8A17dC9b8B96cbf1e2ef5B5645 - IPOR Labs 0xcd6f959660eEF9873c14f84d4b6893beB0Ab8Ef5 - IPOR Labs 0x7E8d6204022F77a75Fe49498E5Dc083D5F22Ad2F - IPOR Labs 0xd01911A1a0EFDdE736aF90B199Def918749c8A92 --- --- Source: https://ipor.io/docs/resources.md # Glossary of Terms | Term | Description | | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | AMM (Automated Market Maker) | A dynamic pricing mechanism that acts as the counterparty for all trades. It uses the IPOR Index and market demand to price interest rate derivatives while managing risk for liquidity providers. | | Liquidity Pool (LP) | A collective pool of assets provided by depositors. These assets serve as the counterparty for swaps. LPs earn yield from contract fees, net payouts, and leveraged returns from underlying money markets. | | IPOR Index | The benchmark reference interest rate for DeFi. It is sourced from various credit protocols and published on-chain. It serves as the "heartbeat" of DeFi, providing a risk-free rate for assets like USDT, USDC, DAI, and ETH | | SOAP (Sum of All Payoffs) | A valuation metric used by the AMM to represent the net value of all outstanding derivative contracts in the pool. | | IRS (Interest Rate Swap) | The primary derivative of the IPOR protocol. It allows users to exchange a fixed interest rate for a floating interest rate (or vice versa) without exchanging the underlying principal. | | Payer (Pay Fixed, Receive Floating) | A swap position where the user pays a fixed rate and receives the floating IPOR Index rate. This is typically used to hedge against rising interest rates. | | Receiver (Receive Fixed, Pay Floating) | A swap position where the user receives a fixed rate and pays the floating IPOR Index rate. This is typically used to hedge against falling interest rates. | | IBT (Interest Bearing Token) | A tokenized representation of a position that accumulates interest over time based on the underlying protocol rates. | | Spread | The difference between the fixed rate offered by the AMM and the current IPOR Index rate, used to compensate the pool for taking on risk. | | Liquidation | The process of closing out a position when the collateral no longer meets the required maintenance margin, ensuring the protocol remains solvent. | | IPOR Oracle | The system that delivers the IPOR Index data to the smart contracts on-chain. | | Snapshot | A tool used by the IPOR DAO for off-chain voting and community sentiment tracking. | | Atomist | A strategy designer or curator who designs the vault's investment logic. They define the "investment universe" by selecting specific assets, markets, and actions via Fuses. Typical Atomists include risk curators, asset managers, DAO treasuries, and protocols. See also [here](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-atomist.md). | | Alpha | An off-chain agent (often an automated bot or specialized strategist) responsible for executing a vault's strategy. Alphas monitor market conditions and trigger the rebalancing or movement of assets by calling specific Fuses. They act as the "brain" of the vault but are constrained by the security parameters set in the smart contracts. See also [here](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-an-alpha.md). | | Fuse | Modular, single-purpose smart contracts that allow a Plasma Vault to interact with external DeFi protocols (e.g., Aave or Curve). Each Fuse is designed to perform one atomic action— such as "deposit," "withdraw," or "claim rewards" — making the system highly composable and easy to extend without upgrading the core vault. See also [here](https://ipor.io/docs/build-on-fusion/architecture-overview/what-is-a-fuse.md). | | Substrate | The underlying target market or liquidity venue where capital is actually deployed. While a Fuse is the "connector" (the logic that executes the transaction), the Substrate is the "destination" (the specific financial environment)._Example:_ If a Vault wants to earn yield on Morpho, the Fuse is the smart contract code that knows how to talk to Morpho's functions, while the Substrate is the specific Morpho Market (e.g., the USDC/wETH market) where the funds reside. | --- Source: https://ipor.io/docs/resources/resources/research-and-whitepapers.md # Research and Whitepapers ​[Overview of all IPOR Labs research papers](https://ipor-labs.notion.site/e592feae2660418a90c35434849f0c0b?v=d35d84b479204c26bc1bb30d2b8ace4a) on Notion. > **Tip:** [**Pricing Liquidity on Real World Assets in DeFi**](https://ipor-labs.notion.site/Pricing-Liquidity-on-Real-World-Assets-in-DeFi-33d68a3d76da8019aa34cc3fe9990762) > > _Authors: Mau Hernandes, Ph. D._ > > **Date: April 2026** > **Tip:** [**IPOR Fusion vs Merkle-Proof Gated Vaults: Imperative–Declarative Execution, Polymorphic Vault Runtimes, and Why Rigidity Matters**](https://www.notion.so/ipor-labs/IPOR-Fusion-vs-Merkle-Proof-Gated-Vaults-Imperative-Declarative-Execution-Polymorphic-Vault-Runtim-2e768a3d76da802cb7b2f4cce9473ae8?v=d35d84b479204c26bc1bb30d2b8ace4a&source=copy_link) > > _Authors: Mariusz Szpiler_ > > **Date: January 2026** > **Tip:** **​**[**xUSD Contagion: Second-Order Risks and the PT Yield Curve as a Risk Management Tool**](https://www.notion.so/ipor-labs/xUSD-Contagion-Second-Order-Risks-and-the-PT-Yield-Curve-as-a-Risk-Management-Tool-2a868a3d76da80c2b1b2f6915c429779) > > _Authors: Mau Hernandes, Ph. D._ > > **Date: November 2025​** > **Tip:** **​**[**The IPOR Automated Market Maker (AMM) V2**](https://ipor-labs.notion.site/e592feae2660418a90c35434849f0c0b?v=d35d84b479204c26bc1bb30d2b8ace4a&p=2e15029e3d2d4731991f7fcd1d0ffee6&pm=c)**​** > > _Authors: Mau Hernandes, Ph. D._ > > **Date: December 2023​** > **Tip:** **​**[**The IPOR Automated Market Maker (AMM)**](https://ipor-labs.notion.site/The-IPOR-Automated-Market-Maker-AMM-2d1e187f699d4ce7a5d00dfc1b52b194)**​** > > _Authors: Mau Hernandes, Ph. D._ > > **Date: August 2022​** > **Tip:** **​**[**Estimating Fair Value of IPOR SWAPs**](https://ipor-labs.notion.site/Estimating-Fair-Value-of-IPOR-SWAPs-a3f27ff952564934913c59119564a6d8)**​** > > _Authors: Iain Clark, Ph.D.; Mau Hernandes, Ph. D._ > > **Date: August 2022​** > **Tip:** **​**[**The Fair Price of IPOR SWAPs via Longstaff-Shwartz**](https://ipor-labs.notion.site/The-Fair-Price-of-IPOR-SWAPs-via-Longstaff-Schwartz-b319eb6bbb9d4dbd834a2018704438ca)**​** > > _Authors: Iain Clark, Ph.D.; Mau Hernandes, Ph. D._ > > **Date: July 2022​** > **Tip:** **​**[**Simulating DeFi Interest Rate Swap trades with Hawkes Process and Synthetic data**](https://ipor-labs.notion.site/Simulating-DeFi-Interest-Rate-Swap-trades-with-Hawkes-Process-and-Synthetic-data-ebffce62f7fe4e19961604b10ea94391)**​** > > _Author: Mau Hernandes, Ph.D._ > > **Date: July 2022​** > **Tip:** **​**[**IPOR Index - The Heartbeat of DeFi** ](https://ipor-labs.notion.site/IPOR-Index-The-Heartbeat-of-DeFi-955bac03e3b147c09789cb0920b90b54)**​** > > _Author: Mau Hernandes, Ph.D._ > > **Date: April 2022​** > **Tip:** **​**[**IPOR: An Inter-protocol Offered Rate for Decentralized Finance**](https://ipor.io/docs/resources/resources/research-and-whitepapers.md)**​** > > Authors: _Darren Camas, Mauricio Hernandes, Ph.D., Dimitar Dinev_ > > **Date: March 2021** --- Source: https://ipor.io/docs/resources/resources/research-and-whitepapers/ipor-conceptual-whitepaper.md # IPOR Conceptual Whitepaper ## IPOR: an Inter-protocol Offered Rate for Decentralized Finance _Darren Camas, Mauricio Hernandes, Ph.D, Dimitar Dinev_ [www.ipor.io](http://www.ipor.io/) **March 12, 2021** ### Abstract An inter-protocol offered rate (IPOR) for blockchain based decentralized finance (DeFi) protocols would provide a robust foundation on which to build interest rate derivatives (IRDs). Current DeFi credit markets rely on crude mechanisms such as overcollateralized lending to mitigate default risk which is effective, but capital inefficient. The market is also immature, lacking a proper yield curve with interest rates by maturity, which is adamant for the valuation of fixed income instruments and pricing of its derivatives. IRDs could be used by investors to hedge or speculate on the interest rate risk, which would make markets more efficient by increasing the breadth of instruments while reducing the costs of financing. We borrow from the popularity and market function of decentralized liquidity pools to allow passive actors to contribute capital and earn yield as a reward for participation in market stabilization. While traditional IRDs require multiple parties IPOR will leverage liquidity pools (pool) to build a liquid market requiring only one contract participant where the pool of decentralized liquidity providers (LP) acts as a collective counterpart. Assuming stablecoin issuance growth, a stable, predictable, and high-yielding DeFi credit market could allow traditional players access to this market, growing it by orders of magnitude from the current tens of billions to challenge traditional credit markets in the trillions. ### **1. Introduction** With more than a decade of development on blockchain protocols, consumer usage has increased significantly in recent years. In 2020 the Ethereum network surpassed Bitcoin in terms of on-chain fees earned by miners, a proxy for user adoption of smart contract technologies. The primary driver for on-chain transactions was DeFi which broadly describes financial applications built on a decentralized blockchain infrastructure. Often described as “money legos,” it consists of independent software modules that can be pieced together to form financial products such as asset exchange, lending, and other fintech applications. DeFi lending and exchange applications in particular exploded in 2020 in both transaction volume and Total Value Locked (TVL) which refers to liquidity available across different platforms. TVL grew from approximately $660 million USD at the start of 2020 and grew over 2,300% to $15.39 billion by the start of 2021 and at time of writing sits at $42.39 billion. TVL growth was primarily due to two factors: 1.) the appreciating price of the underlying tokens used for debt and exchange transactions, and 2.) the maturity and usability of consumer ready applications. The usability of browser based wallets as well as gamified UI and UX likely contributed to the onboarding of non-technical users who could easily interact with blockchain applications for the first time with little technical know-how. The explosion of popularity of DEXes such as Uniswap and Sushiswap challenged centralized crypto exchanges for trading volume. The industry also grew due to new concepts such as yield farming, which has a broad range of applications from crude money market funds, to simple speculation on the price of the farmed asset. For the purpose of this paper, however, we will focus specifically on credit markets as they form the base of the financial system enabling economic growth by providing sources of liquidity for the borrower and income generation for the lender. ### **2. DeFi Credit Markets Overview** #### **2.1 Market Immaturity: Interest Rate Volatility and Unpredictable Liquidity** While current DeFi markets have proved functional, they are still immature. At time of writing credit applications accounted for 44.7% of TVL of all DeFi ($18.96 of $42.39 billion), with the top three lending applications Maker, AAVE, and Compound comprising 94.7% of total lending TVL. Despite the market size, DeFi loans have much room for improvement as they currently have a very short floating rate, which is quite volatile, and lacks a traditional risk-free yield curve (a cornerstone of traditional finance) which is broadly used to discount future cash flows. Essentially lenders must guess what the effective rate for the loan would be. _In a single day APR can range unpredictably, leading to inability to calculate the true cost of borrowing in the short term, and infeasibility of predicting long term borrowing costs. The market currently lacks a credit yield curve to predict short term rates (less than one year), and most DeFi loans are extremely short term compared to their traditional counterparts._ Future liquidity can also be difficult to predict, with utilization rates (the main factor in algorithmic interest rates) rising or falling with major market activities. Current DeFi lending markets rely on overcollateralization of loans where lenders typically post a crypto asset such as Ethereum (ETH) as collateral to borrow other assets such as USD stablecoins. When the market value of the collateral instrument increases, so does the borrowing liquidity which can in turn be used to speculate on rising asset prices. However, borrowers may not always have access to their desired liquidity. The free flow nature of blockchain systems enables lenders to move assets seamlessly between protocols seeking highest yield at the expense of borrowers who may not have guaranteed access to future liquidity on a specific platform or asset. _In order to establish a robust credit market, borrowers and lenders must be able to accurately calculate interest rates over the maturity of their desired loan. As the market matures and a yield curve can be established the industry could see longer loan duration, greater available liquidity, and reduced volatility._ #### **2.2 Lack of Reference Market Interest Rate** DeFi also lacks a reference interest rate. Borrowing rates are primarily determined algorithmically, where interest rates are calculated based on available liquidity and utilization rates within smart contracts and lending protocols. While algorithmic interest rates have been effective to bootstrap liquidity and provide base functionality to mimic market condition changes, the algorithms are limited by their own design parameters. Centralized crypto lenders match borrower and lender demand using a two sided market, however no such free market mechanism currently exists in DeFi lending. #### **2.3 IPOR: an Inter-protocol Offered Rate for Decentralized Finance** We propose the creation of an Inter-protocol Offered Rate (IPOR) that reflects the true cost of borrowing across predominant DeFi lending protocols. The IPOR would be calculated in real-time from the smart contracts of prevailing credit protocols as a weighted average (with capped weights) as its own index to establish a transparent reference market rate. The IPOR will also be used to structure Interest Rate Derivatives (IRDs) which can be used by market participants to stabilize the cost of borrowing for debtors and fixed future income for creditors.\\ We believe the IPOR would serve as a reference risk-free rate (Rf), reduce interest rate volatility, and increase market efficiency. With lower volatility, the cost of a loan or the return on a deposit could be predictable, able to meet expectations, making DeFi markets safer and attracting more participants. The possibility of locking rates using IRDs is another step towards market maturity, attracting institutional investors who need to be able to forecast yearly expected returns. In a world where banks no longer pay for depositors due to the negative rates policy established by Central Banks, a large amount of assets could migrate to DeFi once it could offer a more predictable rate backdrop and much higher returns than conventional bank deposits. #### **2.4 IPOR and the Stabilization of DeFi Credit Markets** #### **2.4.1 Market Transparency for all Actors** The IPOR could act as a stabilizing factor for DeFi credit markets. Through rate transparency borrowers and lenders would be able to make informed assessments of credit terms between lending protocols. If borrowers were to converge on platforms with the most competitive rates it could align liquidity provision with credit demand providing better predictable liquidity on these platforms. #### **2.4.2 Fixed Income, Fixed Borrowing Cost** A transparent reference rate should lower volatility for all protocols, and we believe fixed-rate instruments with a defined maturity would naturally emerge from the fact that investors are more confident of the path and volatility of interest rates. We believe that initially terms no longer than a week would be used, and as investors embrace the concept maturities would naturally stretch into a proper yield curve. This process would also enable the valuation of IRDs, enable market participants to switch between floating and fixed rates when desired, lock a range of interest rates using a collar, and multiple other uses. #### **2.4.3 Interest Rate Derivatives** The IPOR will be a driver for the decrease in interest rate volatility, which will naturally unfold into a yield curve that will become longer as it becomes more broadly accepted. The existence of the short-term IPOR with a fixed maturity (will develop further on the incentives to fulfill the contract term) will allow the existence of properly valued IRDs. The counterpart to the contract would be a decentralized liquidity pool which will be the counterparty for derivatives instruments such as interest rate swaps. ### **3. Interest Rates in Traditional Credit Markets** #### **3.1 History of Debt Markets and Interest Rates** Debt is the oldest form of financing, and is still the most important one today. Historical evidence shows that collateralized loans in pawn shops existed in China in the year 650 B.C., while the earliest evidence of joint stock companies dates almost two thousand years after that in France and Sweden. Fast forward to present times and global debt across all sectors (households, corporates, government and financial institutions) summed to $255 trillion at the end of 2019, over 3x the Global GDP in constant USD. Interest rates quantify the counterparty credit risk, i.e. the ability that the borrower has to fulfill their commitment and pay back the money to the lender plus the agreed upon interest. The riskier the borrower, the higher the rates, as the odds are also higher that the borrower wouldn’t be able to pay and will try to restructure the agreement in less convenient terms for the lender. By defining the terms of the contract and by assessing the creditworthiness of the counterpart (the role of rating agencies), generally the lender can expect fixed income during the term of the contract in the form of coupons and the repayment of the principal at maturity. This predictability of debt and coupons makes credit one of the most important instruments in global financial markets, as stocks don’t have such characteristics (you don’t sign an agreement to fix the price of the share and the dividends you will receive 2 years from now, for instance). Hence, financial institutions such as pension funds, insurance companies, and financial institutions rely on fixed income instruments for Asset-Liability Management, i.e., to match their future inflows against the expected outflows. E.g., if the actuarial calculations of a pension fund estimates that it will need $10m to pay to pensioners in a given month, they will manage their credit asset book in order to receive that same amount in that same period. IRDs are used to fine tune credit markets and are the bulk of the Global Derivatives Markets. A Portfolio Manager can use IRDs to swap interest rates from floating to fixed, which could adapt the characteristics of the credit to their needs. The portfolio manager, or anyone willing to bet that rates will go down, could enter an agreement to pay floating rates and receive fixed rates, making a profit out of it. IRDs are $11.7trn out of the $15.5trn global derivatives gross market value, and Interest Rate Swaps (IRS) are almost 90% of the IRDs. IRS sums up 2/3 of the global derivatives market value. #### **3.2 Benchmark Rates Overview** Benchmark interest rates take different forms, but the most popular are Interbank Offered Rates (IBORs) and Overnight Financing Rates (OFRs). These benchmark rates are designed to reflect the fair market cost of borrowing capital over certain durations between a set of banks for specific assets (normally currency) and durations. Where a central bank may increase or decrease its interest rates to stimulate or slow economic growth, interbank rates are considered to be a fair market gauge of actual borrowing rates between financial institutions. Risk-free rate (Rf) for a specific currency is the rate offered by its respective government for lenders, so for USD it would be the Treasury rates offered to investors. Rf is everywhere in finance; it is the reference rate over which counterparty credit risk is priced on top of (credit spread), derivative payoffs are calculated, and an integral part of the cost of equity via the Capital Asset Pricing Model. The Rf is needed to discount future cash flows for valuation purposes and to gauge the time value of money and opportunity cost. For practical purposes, LIBOR is usually used as an approximation of that Rf, and it represents the interest rate a bank is willing to make a short-term deposit with other banks. These banks usually have the highest credit ratings possible for financial institutions, but it is an approximation, as there is a very small chance that for instance a bank with an “AA+” rating defaults, but nonetheless they represent the best creditworthiness. #### **3.3 LIBOR Calculation** The LIBOR is a self reported rate calculated and published in a four step process conducted by the Intercontinental Exchange (ICE). 1.) The LIBOR is constructed from the survey of member banks self reporting lending rates across multiple short term durations from one day to one year for USD, EUR, GBP, JPY, CHF. 2.) The survey’s high and low figures are discarded, and 3.) the remainders are used to calculate the index using a volume weighted average price (VWAP), transaction based data, and expert judgement. 4.) The result is published at 11am BST during working days and is used as a benchmark to set interest rates for credit products ranging from retail mortgages and student loans to corporate fundraising and IRDs. While LIBOR is used for short term durations less than 1 year, the products which reference it such as mortgage rates can span significantly longer durations. #### **3.4 LIBOR scandal and fallout** The LIBOR is currently being phased out and will cease to be published on December 31, 2021. The rate was found to be manipulated from inside the reporting institutions, and is regarded as the largest rate fixing scandal in history by several orders of magnitude. The LIBOR came under fire in 2012 when the Financial Times reported that the rate had been manipulated likely since as early as 1991 by traders within the very reporting banks who understated the cost of borrowing and profit from taking a derivatives position which could net the trader millions of dollars for each basis point. However, its importance can be seen as the transition away from the benchmark has lasted nearly a decade and has strong complications and negative consequences. There are many replacements being discussed, and it is likely that a multitude of IPORs or OFRs will be used rather than a single rate. The current leading candidates vary by market, but the result of losing a central benchmark will have strong impacts. The hundreds of trillions of structured products that relied on the LIBOR must be unwound. New derivatives instruments are being structured across the likes of SOFR, SONIA, or STR, however, the multiple benchmarks will lead to fragmentation of rates will be launched resulting in fragmentation of rates and fractured liquidity. ### **4. IPOR Construction** #### **4.1 Differences Between Traditional Benchmarks and IPOR** _DeFi has many structural advantages which benefit the construction of the IPOR free from the collusion that was present in LIBOR. As interest rates are defined in the logic of the smart contracts for lending protocols the interbank lending market is replaced with protocol to protocol interactions. The interest rates can be sourced in real-time to periodically update the IPOR and would need to be constantly recalculated to reflect the changing market conditions._ Drawing a parallel to traditional finance, we look for the best proxy for Rf in DeFi, although this time it will not be defined by monetary policy or a weighted average of the best financial institutions. We see the existing overcollateralized loans as adequate proxies for Rf, as the probability of the lender not being made whole are small (e.g. lending stablecoin to a borrower who is 150% ETH-collateralized, the risk of not being paid 100% of your stablecoins is only if ETH drops in an eye blink by more than 33% and the smart contract gets terminated at such levels). We find this to be currently the most adequate Rf proxy in DeFi, and the IPOR would use supply and demand dynamics (available liquidity and utilization) across protocols to approximate the fair value of the Rf. This should reduce interest rate volatility and arbitrage opportunities across protocols as market participants would have a reference rate to look at before they make a decision. #### **4.2 Constant Liquidity** _DeFi markets are not restricted by geography or time. Rather than publishing the IPOR during business days using British Standard Time, the IPOR will be persistently available. The concept of overnight financing rates with off-market hours is replaced with uninterrupted transparent data, facilitating round the clock trading for greater risk management and new economic opportunities._ #### **4.3 Modularity and Adaptability** Where traditional finance functions around well established institutions and is slow to incorporate new players into a benchmark rate, the DeFi market is constantly changing and evolving with new protocols gaining in popularity and TVL. The underlying rate calculation could also be updated on the smart contracts of the different lending platforms which comprise the IPOR index. This constant flux requires the IPOR mechanism itself to be modular, able to account for market changes such as new protocols to be considered for inclusion or removal, changes in weighting due to market dominance, changes to third party code base, or other potential significant changes. As such, this modularity of IPOR allows the protocol to be easily expandable to other lending markets. While we will focus first on USD stablecoin lending markets as they are currently the most utilized and liquid credit markets, one could imagine the protocol accounting for lending markets in ETH, BTC, or other assets. Similarly, in the same way as EURO LIBOR is the average interest rate between banks willing to lend and borrow against EURO, ETH IPOR would be the average interest rate between protocols willing to lend in ETH. This process could be used to create a lending market for subsets of assets for new structured products. #### **4.4 IPOR Parameters and Weighting** #### **4.4.1 Calculation of the IPOR Index** The IPOR is constructed as a weighted average of the floating interest rates from multiple protocols. See formula below: ![Image](https://ipor.io/docs/assets/resources/image-52fe6b.png) __ ![Image](https://ipor.io/docs/assets/resources/image-4-a1ed5e.png) __ The number of protocols under consideration (N) will be re-evaluated from time to time allowing protocols to be added or removed from the calculation as they gain or lose relevance. The capping factors (and their sum C) are designed to limit the impact of any particular protocol in the calculation of IPOR. This feature allows IPOR designers to smooth the effect from less liquid protocols without completely ignoring their relevance, at the same time softening the effect of any single particular protocol, preventing manipulation of IPOR due to any particular misbehaving protocol. The calculation of each capping factor (ci) takes into consideration each protocol’s balance sheet, utilization rate and relevance. These values are also recalculated from time to time to closely follow the dynamic market. #### **4.4.2 Averaging Multiple Protocols Yields Lower Volatility** In the figures below you can see the impact of adding multiple interest rate protocols has in decreasing the volatility of IPOR: ![Image](https://ipor.io/docs/content-images/35f6092ce016.png) __ ![Image](https://ipor.io/docs/content-images/2c81bc62ba31.png) __ ![Image](https://ipor.io/docs/content-images/f68c7efe494f.png) __ In the figures above, one can see that the changes in the interest rates of IPOR over time when it has only 3 components is much more dynamic than when adding 10 or even 50 components. In plot form, this is the key value that IPOR wants to bring as a benchmark of inter-protocol interest rate. #### **4.5 IPOR-Based Derivatives: Automated Market Maker and Other Components** IPOR products are traded using its rate published on-chain and a series of components that come together in what we call Market which secures the matching, trading, and settlement between the parties. We will use the example of an IRS described further in the following section to introduce the Market. The Market is composed entirely of smart contracts. The main components of the Market are as follows: ![Image](https://ipor.io/docs/content-images/50efdde64d21.png) __ **IPOR Index:** The IPOR is published on-chain between each settlement period. This component is the cornerstone of the market, but it suffers no impact from the events in the IPOR market as it is a ‘read only’ component from the point of the view of the market. **Settlement Layer:** This component holds all contracts entered into by the payers and receivers of IPOR interest rates derivatives. Each settlement period this layer enforces contract closing/roll over and margin calls, making funds available to the relevant party. **Contract:** This component is the contract entered into by payers and receivers. Each contract has terms and parameters agreed by both parties that are enforced by the settlement layer at settlement (maturity or other market events). **Market Participant:** A user that chooses to enter the contract as a payer or receiver. In the case of an interest rate a market participant may be a payer or a receiver where a payer is the party that _pays_ a fixed interest rate, while the receiver is the party that _receives_ the fixed interest rate. Effectively the receiver is paying floating interest rate (paying IPOR) while the payer is receiving floating interest rate (receiving IPOR). **Liquidity Pool:** The liquidity pool is split into two components, the Automated Market Maker and the Liquidity Providers. The main role of the liquidity pool in the market is to serve as a counterparty to contracts at quotes offered in a system similar to a request for quote (RFQ) system. The Liquidity Pool charges a fee for its service, offering quotes based on the current interest on its contracts. **Automated Market Maker (AMM):** The AMM, like an RFQ system, offers quotes for contracts of fixed and floating interest rates (IPOR) for payers and receivers at competitive premiums from the current IPOR value. The rates are calculated at a premium from the IPOR value. **Liquidity Providers (LPs):** LPs are decentralized service providers that allocate funds to power the liquidity pool’s AMM in order to turn the wheels of the market. LPs receive the fees and the sum of the payoffs for all the contracts entered into by the AMM in proportion to their allocation and time of service. #### **4.6 IPOR Interest Rate Swap** Interest Rate Swaps are the most used instrument in global derivatives due to the fact that they allow market participants to manage interest rate risk in credit markets. As shown in section 3, IRSs make up 2/3 of the global derivatives market value and 88% of the total IRD market value. By entering an IRS a borrower who is exposed to floating interest rates on their loan can pay fixed rates to a counterparty, receiving floating rates in exchange, hence minimizing or eliminating their exposure to where floating rates will go. We elaborate an example below of how an IRS would work with the liquidity pool as counterparty. #### **4.6.1 Example: How to Fix Borrowing Rates Using an Interest Rate Swap with the Liquidity Pool as Contract Counterparty** ![Image](https://ipor.io/docs/content-images/0fe3aaa2b6f3.png) __ **Fixed Rate Payer Example** \*\*\*\*a) Judy borrows $100k. She doesn’t know how much she will pay for it and wants to minimize the interest rate risk, so she decides to enter an interest rate swap to do so. b) Judy enters an interest rate swap with the liquidity pool as a counterpart. The notional amount of the contract is $100k. In this example we assume she will be paying 5% to the pool and receiving the floating rate from it, which is the compounded IPOR rate from the contract inception until its termination. c) After 30 days the compounded floating rate (compounded IPOR) for the period is 20%, which is the rate Judy needs to pay to the Lessor on (c). Judy pays: ![Image](https://ipor.io/docs/assets/resources/image-1-985da3.png) __ The flipside is that now she made a profit with the IRS contract, as she decided to pay rates at 5% to the Liquidity Pool while receiving the floating rate at 20% from it. The contract payoff is: ![Image](https://ipor.io/docs/assets/resources/image-2-72e485.png) __ At the end of the day Judy profits $1,123 from the IRS contract, so if we deduct this from the amount she has to pay, she will effectively pay $101,531 - $1,123 = $100,407, which is what she decided to pay when fixing the rate at 5%. What would happen if the floating rate for the period goes down? If the case that the rate dropped to 3%, the payoff of the contract is negative as the value of the floating leg she receives is lower than the value of the fixed leg she pays. The important aspect of this is that the IRS enabled her to fix the rates and properly plan her cash flows. **Fixed Rate Receiver Example** If instead of borrowing she deposited money, she would like to receive fixed rates from the liquidity pool instead of paying. In this case she receives fixed, pays the floating rate, and the terms of the Payoff invert, i.e. ![Image](https://ipor.io/docs/assets/resources/image-3-d7c9f4.png) __ The opposite happens here. If the IPOR goes up significantly, she is receiving lower rates from the contract with the Liquidity Pool, as she is receiving fixed and paying floating, so the Payoff is negative. Not every market participant needs to be a borrower or lender, and an IRS can be used as a directional bet on which direction rates will go. A Margin Deposit is needed upon the inception of the contract, and is the maximum loss a counterparty can assume. In the case that the Payoff value is equal to the Margin Deposit, the smart contract will be settled (unless we decide to add a Margin Call mechanism to top it up) and the winner will receive the pot. #### **4.6.2 Liquidity Pool Optimization** The function of the Liquidity Pool is crucial for the AMM to have a constant community counterpart with whom market participants can open derivative contracts. In sub-optimized conditions where the pool is not currently being adequately utilized in open contracts, the protocol will allocate reserves to third party lending protocols in order to maximize return to the Liquidity Providers. Given that IPOR has comprehensive interest rate data, the protocol would algorithmically allocate reserves to the highest yielding strategy, which would in turn have a market effect by lowering the destination protocol’s utilization rate and in turn the interest rate. The basic function reserves allocation would maximize return to liquidity providers, allocate funds to the highest yielding (and greatest demand) pools, lowering interest rate and volatility in the market. ### **5. The IPOR DAO** #### **5.1 The Spirit of Decentralization** DeFi markets are entire financial systems built on open-source software run by decentralized parties. In the spirit of openness, innovation, and transparency the IPOR embraces the ethos of blockchain systems. Over time the protocol will be governed by a community rather than a corporation. #### **5.2 IPOR Token** The IPOR Token (Token) will be an ERC-20 token that acts as the protocol’s governance token. Token holders will be responsible for governing the IPOR protocol, which could include making changes to the parameters and weights in IPOR, as well as adding and removing protocols from the index via IPOR Improvement Proposals (IIPs) submitted to the Decentralized Autonomous Organization (DAO) for voting. Some tokens will also be held within the DAO Treasury (Treasury) and distributed to the community via different incentive programs aimed at bootstrapping liquidity for IPOR derivatives instruments and for promoting participation in the DAO. The distribution of tokens allows the protocol to progressively decentralize and underpins the credibility and transparency of the IPOR index and other products. #### **5.3 IPOR DAO** The IPOR DAO will utilize the Compound governance module, which is the gold standard in the DeFi industry as one of the most battle-tested and well-documented governance frameworks to date. Any token holder could initiate an IIP as long as they hold at least 1% of the IPOR tokens or have acquired more than 1% of voting power via delegation. In order for a proposal to be accepted by the DAO and make changes to the IPOR, an IIP would need to meet a sufficient quorum (a minimum threshold of all tokens in existence must vote YES) and more than 50% of all votes must vote “YES” on a specific proposal to pass. The decentralized nature of the IPOR DAO increases the resilience of the IPOR protocol and allows it to evolve into a fully on-chain decentralized financial infrastructure with no identifiable weak points and no reliance on any single team in order to function in perpetuity. In this way, the protocol can continue to scale with the growth of the entire DeFi ecosystem. #### **5.4 IPOR DAO Launch and Progressive Decentralization** The path from launch towards a fully on-chain decentralized governance involves 3 steps of progressive decentralization. **Step 1: \~3 months** At launch, the parameters and weights of IPOR will be set by IPOR Labs which is the team building the core protocol. During this phase IPOR Labs will have signing power of the smart contracts and custody over the tokens allocated to the DAO treasury via a multi-signature (multisig) wallet configuration. IPOR Labs will also retain control over decisions regarding product, token distribution, and various community incentives. Construction of the index and all changes to IPOR products will be presented to the community in a public and transparent manner with appropriate time for feedback and reviews of the changes before they take effect. **Step 2: \~3-6 months** During the second phase IPOR Labs will create a snapshot voting page and a governance forum where the community can actively participate and make proposals regarding modifications to IPOR and development of new products. The community can also vote to modify IPOR token emission and grants from the treasury to reward active community participants. Once a proposal gathers sufficient community support it will move to a snapshot vote. If successful, IPOR Labs will undertake the implementation of the proposal in a timely manner depending on the current development backlog and priority. **Step 3:** As IPOR matures towards a fully community-driven DAO, IPOR Labs will transfer ownership of the smart contracts as well as the community treasury to the IPOR DAO. At this point governance decisions regarding changes and updates to the IPOR protocol and the usage of the treasury will be in full control of the IPOR token holders. IPOR Labs will continue to actively participate in community discussions and make proposals for development and funding of new products from the treasury. However, the ultimate approval and implementation of such proposals will be handled in a fully decentralized manner via the DAO. ### **6. Conclusion** The growth of DeFi as a viable alternative to centralized financial institutions creates exciting opportunities for innovation and brings new challenges. Among those opportunities and challenges in the growth of crude yet effective credit markets whose loan books currently count in the tens of billions. For this market to further mature new instruments will need to be introduced which will help attract new market participants who could grow the market by orders of magnitude. We borrow from new concepts in decentralized finance such as DAOs, Liquidity Pools, and Automated Market Makers, and combine these with well established mechanisms such as reference rates and interest rate derivatives to create a stable base on which to build the fixed income and credit markets of the future. Through IPOR-enabled tools, the market should see reduced volatility, greater available liquidity, longer loan durations, and the establishment of a yield curve for DeFi. We welcome any feedback, comments, or suggestions in our pursuit to reimagine smart contract based financial market infrastructure one block at a time. --- Source: https://ipor.io/docs/resources/resources/brand-assets.md # Brand Assets ➡️ [Access IPOR Protocol's Media Kit](https://drive.google.com/drive/u/0/folders/1b7HWUDKVdt4stOPoFcZS7t3HHclRDxOA)