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 (opens in new tab) 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.

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), and you know the compiler settings of each deployment (see the Coding Standard).

The market id pull request

The pull request changes one file, contracts/libraries/IporFusionMarkets.sol (opens in new tab), 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 (opens in new tab), 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:

/// @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 (<link to the venue documentation>):
///      - 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 <link to the fuse README>.
/// @dev Documentation: <link to the fuse repository>
uint256 public constant EXAMPLE_VENUE_SUPPLY = <next free number>;

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.

## Market

- Market id constant: `<NAME>` = `<number>`
- Venue: <name, link to the venue documentation>
- Fuse repository (where the code is maintained): <link>
- Fuse documentation, if kept outside that repository: <link>
- Fuse source commit: <link to the commit in your repository>

## Deployments (one block per chain)

- Chain: <name and chain id>
- [ ] `<FuseName>`: <address> - <block explorer link to the verified source>
- [ ] `<FuseName>`: <address> - <block explorer link to the verified source>
- Deployment date of each fuse: <date>

## Fuse types

- [ ] Action fuse(s): <names>
- [ ] Balance fuse: <name, or ZeroBalanceFuse with the reason>
- [ ] Claim fuse(s), if any: <names>
- [ ] Price feed(s), if any: <names>

## Build

- [ ] Compiler: solc <version>, EVM version <version>, optimizer <on/off>, runs <number>, per-chain profile <if any>
- [ ] Constructor arguments per fuse: <values>
- [ ] Differences between chains beyond VERSION, MARKET_ID and venue addresses: <none, or list>

## Substrates

- [ ] Substrate type and encoding: <address / encoded struct>
- [ ] Values to grant: <list>

## Vault configuration

- [ ] Price feeds required for every valued token: <tokens and sources>
- [ ] Dependency graph: <markets, or none>
- [ ] Instant withdraw: <fuses and params, or not supported>

## Venue risks

- [ ] Upgradeability, admin keys, pauses, withdrawal delays, caps: <summary and link to the README section>

## Optional

- [ ] Tests and fork-test results: <link>

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 (opens in new tab) 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 (opens in new tab) 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 (opens in new tab) (the link opens the Ethereum list). The registry contract, FuseWhitelist (opens in new tab), can be read by market id (getFusesByMarketId), by type (getFusesByType) and by address (getFuseByAddress).

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 for how these pieces fit together, and the Fuse Whitelist Registry 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 and the Coding Standard.

Last updated