Skip to content

Dev - #116

Merged
matteoettam09 merged 29 commits into
mainfrom
dev
Dec 15, 2025
Merged

Dev#116
matteoettam09 merged 29 commits into
mainfrom
dev

Conversation

@matteoettam09

@matteoettam09 matteoettam09 commented Dec 15, 2025

Copy link
Copy Markdown
Member

Summary by Sourcery

Refactor orchestrators, vaults, and adapters to introduce slippage‑aware execution and explicit vault portfolio/state handling, simplify curator and access control configuration, and align tests and configuration with the new epoch and orchestration model.

New Features:

  • Introduce slippage‑aware execution in the liquidity orchestrator and ERC4626 execution adapter using configurable slippage tolerance tied to the target buffer ratio.
  • Expose comprehensive vault state accessors in the internal state orchestrator, including combined total‑assets views and per‑vault portfolio snapshots for use by the liquidity orchestrator.

Bug Fixes:

  • Prevent dust‑level deposit and redeem requests by enforcing minimum remaining amounts on partial cancellation to avoid potential DoS and accounting edge cases.
  • Tighten adapter validation and decommissioning guards to ensure token decimals and decommissioning state are consistent before execution or vault removal.

Enhancements:

  • Move epoch accounting and completion events from the internal state orchestrator into the liquidity orchestrator and introduce a dedicated ProcessVaultOperations phase to decouple state estimation from vault operations.
  • Refine the vault state update pipeline so the internal state orchestrator computes per‑vault portfolios and the liquidity orchestrator applies both fulfill operations and portfolio/total‑assets updates in a single step, including stricter decommissioning completion checks.
  • Simplify curator management by removing curator whitelisting from configuration, factories, and vaults, placing responsibility for curator safety on vault owners.
  • Streamline vault fee accounting by removing epoch parameters from curator fee accrual and deposit/redeem events, and by batching request processing using snapshots to improve determinism.
  • Relax asset whitelisting so existing assets can be updated atomically while preserving token decimals, and adjust configuration events to include deposit access control metadata.
  • Remove ERC165 requirements from strategy contracts and related tests to simplify strategy interfaces.

Build:

  • Bump protocol package version to 0.7.0 and remove an unused verification script entry from package.json, while cleaning committed artifacts and updating .gitignore accordingly.

Documentation:

  • Clarify access‑control, adapter, and vault interface documentation, including new expectations for deposit access control, execution adapter validation, and transparent vault state updates.

Tests:

  • Update orchestrator, vault, adapter, and strategy tests to the new APIs, phases, and events; add coverage for execution adapter validation, epoch simulations, and slippage/error scenarios; and remove tests tied to curator whitelisting and ERC165‑based strategy detection.

Summary by CodeRabbit

  • New Features

    • Slippage tolerance enforced for buy/sell flows; basis-points factor added for precise checks.
  • Bug Fixes

    • Prevented dust deposits/redeems with minimum-amount validation.
    • Batch processing improved to avoid reordering and ensure consistent pricing.
  • Refactor

    • Curator whitelist flows removed/simplified.
    • Vault portfolio tracking consolidated to per-vault token/share mappings and a unified total-assets query.
    • Epoch processing renamed/streamlined (ProcessVaultOperations).

✏️ Tip: You can customize this high-level summary in your review settings.

matteoettam09 and others added 25 commits November 22, 2025 16:54
…based, and submitIntent enforces non-malicious intent validation
-  Atomic validation in buy/sell operations
-  Atomic validation in buy/sell operations
- ERC4626 interface validation
- Token decimals validation
- updateTokenDecimals admin function
- Zero totalAssets check
-  Slippage tolerance = 50% of targetBufferRatio
- buyApprovalMultiplier removed
-  MAX_BUY_APPROVAL_MULTIPLIER removed
- emergencyUpdateExecutionAdapter
- Slippage propagation to adapters

closes #99
… of LO; avoids splitting redeem/deposit into two updates due to minibatch-size constraints
@sourcery-ai

sourcery-ai Bot commented Dec 15, 2025

Copy link
Copy Markdown

Reviewer's Guide

Refactors epoch processing and slippage handling across InternalStatesOrchestrator, LiquidityOrchestrator, execution adapters, vaults and strategies, while removing curator whitelisting and updating tests to the new APIs and event semantics.

Sequence diagram for updated epoch lifecycle and vault operations

sequenceDiagram
    actor Keeper as ChainlinkAutomation
    participant ISO as InternalStatesOrchestrator
    participant LO as LiquidityOrchestrator
    participant Config as OrionConfig
    participant TV as OrionTransparentVault

    Keeper->>ISO: performUpkeep(performData)
    ISO->>ISO: decode performData -> processLP, excludedAssets
    ISO->>ISO: set processLP
    ISO->>ISO: if config.isSystemIdle() && _shouldTriggerUpkeep()
    ISO-->>ISO: _handleStart()
    ISO->>Config: getAllOrionVaults(Transparent)
    ISO->>ISO: build transparentVaultsEpoch
    ISO->>ISO: currentPhase = PreprocessingTransparentVaults

    loop Preprocessing minibatches
        ISO->>ISO: _preprocessTransparentMinibatch()
    end

    ISO->>ISO: currentPhase = Buffering
    ISO->>ISO: _buffer()

    ISO->>ISO: currentPhase = PostprocessingTransparentVaults
    loop Postprocessing minibatches
        ISO->>ISO: _postprocessTransparentMinibatch(excludedAssets)
        ISO->>ISO: update vaultsTotalAssets, vaultsTotalAssetsForFulfillRedeem, vaultsTotalAssetsForFulfillDeposit, vaultPortfolioTokens, vaultPortfolioShares
    end

    ISO->>ISO: currentPhase = BuildingOrders
    ISO->>ISO: _buildOrders()
    ISO->>LO: advanceIdlePhase()
    LO->>LO: if currentPhase == Idle
    LO->>LO: currentPhase = SellingLeg

    Note over LO,ISO: LiquidityOrchestrator trading phases

    loop SellingLeg
        Keeper->>LO: checkUpkeep/performUpkeep
        LO->>LO: _processSellLeg()
    end

    loop BuyingLeg
        Keeper->>LO: checkUpkeep/performUpkeep
        LO->>LO: _processBuyLeg()
    end

    LO->>ISO: getOrders(false)
    LO->>LO: currentPhase = ProcessVaultOperations

    loop ProcessVaultOperations minibatches
        Keeper->>LO: performUpkeep
        LO->>Config: getAllOrionVaults(Transparent)
        LO->>ISO: getVaultTotalAssetsAll(vault)
        LO->>ISO: getVaultPortfolio(vault)
        LO->>TV: _processSingleVaultOperations(vault, totalAssetsForDeposit, totalAssetsForRedeem, finalTotalAssets)
    end

    LO->>LO: currentPhase = Idle
    LO->>LO: currentMinibatchIndex = 0
    LO->>LO: emit EpochProcessed(epochCounter)
    LO->>LO: ++epochCounter
    ISO->>ISO: currentPhase = Idle
Loading

Sequence diagram for updated buy/sell execution with slippage checks

sequenceDiagram
    participant LO as LiquidityOrchestrator
    participant Exec as OrionAssetERC4626ExecutionAdapter
    participant VA as ERC4626VaultAsset
    participant UA as UnderlyingAssetToken

    rect rgb(230,230,250)
    Note over LO,Exec: Sell flow
    LO->>Exec: sell(asset, sharesAmount, estimatedUnderlying)
    Exec->>Exec: _validateExecutionAdapter(asset)
    Exec->>VA: redeem(sharesAmount, msg.sender, msg.sender)
    VA-->>Exec: receivedUnderlying
    Exec->>Exec: if receivedUnderlying < estimatedUnderlying
    Exec->>LO: read slippageTolerance()
    Exec->>Exec: maxUnderlying = estimatedUnderlying * (BASIS_POINTS_FACTOR - slippageTolerance) / BASIS_POINTS_FACTOR
    Exec->>Exec: if receivedUnderlying < maxUnderlying
    Exec-->>LO: revert SlippageExceeded
    Exec-->>LO: else return receivedUnderlying
    end

    rect rgb(230,250,230)
    Note over LO,Exec: Buy flow
    LO->>Exec: buy(asset, sharesAmount, estimatedUnderlying)
    Exec->>Exec: _validateExecutionAdapter(asset)
    Exec->>VA: previewMint(sharesAmount)
    VA-->>Exec: previewedUnderlying
    Exec->>Exec: if previewedUnderlying > estimatedUnderlying
    Exec->>LO: read slippageTolerance()
    Exec->>Exec: maxUnderlying = estimatedUnderlying * (BASIS_POINTS_FACTOR + slippageTolerance) / BASIS_POINTS_FACTOR
    Exec->>Exec: if previewedUnderlying > maxUnderlying
    Exec-->>LO: revert SlippageExceeded
    end

    Exec->>UA: safeTransferFrom(LO, Exec, previewedUnderlying)
    Exec->>UA: forceApprove(VA, previewedUnderlying)
    Exec->>VA: mint(sharesAmount, Exec)
    VA-->>Exec: spentUnderlying
    Exec->>UA: forceApprove(VA, 0)
    Exec->>VA: safeTransfer(LO, sharesAmount)
    Exec-->>LO: return spentUnderlying
Loading

Class diagram for updated orchestrators, vaults, adapters, and interfaces

classDiagram
    class IInternalStateOrchestrator {
        <<interface>>
        +InternalUpkeepPhase currentPhase()
        +void updateAutomationRegistry(address newAutomationRegistry)
        +void updateProtocolFees(uint16 vFeeCoefficient, uint16 rsFeeCoefficient)
        +void resetPhase(InternalUpkeepPhase targetPhase)
        +uint256 pendingProtocolFees()
        +uint256 bufferAmount()
        +bool processLP()
        +void subtractPendingProtocolFees(uint256 amount)
        +void updateBufferAmount(int256 deltaAmount)
        +tuple getVaultTotalAssetsAll(address vault)
        +address[] getTokens()
        +address[] getTransparentVaultsEpoch()
        +tuple getVaultPortfolio(address vault)
        +void pause()
        +void unpause()
    }

    class InternalStatesOrchestrator {
        +uint32 MAX_EPOCH_DURATION
        +uint8 transparentMinibatchSize
        +uint32 epochDuration
        +uint256 bufferAmount
        +bool processLP
        +void performUpkeep(bytes performData)
        +void resetPhase(InternalUpkeepPhase targetPhase)
        +tuple getVaultTotalAssetsAll(address vault)
        +address[] getTransparentVaultsEpoch()
        +tuple getVaultPortfolio(address vault)
        +bool processLP()
        -EpochState _currentEpoch
        -void _handleStart()
        -void _preprocessTransparentMinibatch()
        -void _buffer()
        -void _postprocessTransparentMinibatch(address[] excludedAssets)
        -void _buildOrders()
    }

    class EpochState {
        +address[] tokens
        +mapping(address => bool) tokenExists
        +mapping(address => uint256) priceArray
        +mapping(address => uint256) vaultsTotalAssets
        +mapping(address => uint256) vaultsTotalAssetsForFulfillRedeem
        +mapping(address => uint256) vaultsTotalAssetsForFulfillDeposit
        +mapping(address => address[]) vaultPortfolioTokens
        +mapping(address => uint256[]) vaultPortfolioShares
        +mapping(address => uint256) initialBatchPortfolio
        +mapping(address => uint256) finalBatchPortfolio
        +mapping(address => uint256) sellingOrders
        +mapping(address => uint256) buyingOrders
    }

    IInternalStateOrchestrator <|.. InternalStatesOrchestrator
    InternalStatesOrchestrator o-- EpochState

    class ILiquidityOrchestrator {
        <<interface>>
        +uint16 epochCounter()
        +LiquidityUpkeepPhase currentPhase()
        +uint256 targetBufferRatio()
        +uint256 slippageTolerance()
        +void updateMinibatchSize(uint8 minibatchSize)
        +void setTargetBufferRatio(uint256 targetBufferRatio)
        +void advanceIdlePhase()
        +void transferRedemptionFunds(address to, uint256 amount)
    }

    class LiquidityOrchestrator {
        +uint16 BASIS_POINTS_FACTOR
        +uint16 epochCounter
        +uint8 minibatchSize
        +uint256 targetBufferRatio
        +uint256 slippageTolerance
        +void advanceIdlePhase()
        +bool checkUpkeep(bytes checkData) returns (bool, bytes)
        +void performUpkeep(bytes performData)
        +void setTargetBufferRatio(uint256 targetBufferRatio)
        -LiquidityUpkeepPhase currentPhase
        -uint16 currentMinibatchIndex
        -void _processSellLeg()
        -void _processBuyLeg()
        -void _processVaultOperations()
        -void _processSingleVaultOperations(address vault, uint256 totalAssetsForDeposit, uint256 totalAssetsForRedeem, uint256 finalTotalAssets)
    }

    ILiquidityOrchestrator <|.. LiquidityOrchestrator
    InternalStatesOrchestrator --> ILiquidityOrchestrator : liquidityOrchestrator

    class IExecutionAdapter {
        <<interface>>
        +void validateExecutionAdapter(address asset)
        +uint256 sell(address asset, uint256 sharesAmount, uint256 estimatedUnderlyingAmount)
        +uint256 buy(address asset, uint256 sharesAmount, uint256 estimatedUnderlyingAmount)
    }

    class OrionAssetERC4626ExecutionAdapter {
        +uint16 BASIS_POINTS_FACTOR
        +IOrionConfig config
        +IERC20 underlyingAssetToken
        +ILiquidityOrchestrator liquidityOrchestrator
        +constructor(address configAddress)
        +void validateExecutionAdapter(address asset)
        +uint256 sell(address vaultAsset, uint256 sharesAmount, uint256 estimatedUnderlyingAmount)
        +uint256 buy(address vaultAsset, uint256 sharesAmount, uint256 estimatedUnderlyingAmount)
        -void _validateExecutionAdapter(address asset)
    }

    class MockExecutionAdapter {
        +uint256 buy(address asset, uint256 sharesAmount, uint256 estimatedUnderlyingAmount)
        +uint256 sell(address asset, uint256 sharesAmount, uint256 estimatedUnderlyingAmount)
    }

    IExecutionAdapter <|.. OrionAssetERC4626ExecutionAdapter
    IExecutionAdapter <|.. MockExecutionAdapter
    OrionAssetERC4626ExecutionAdapter --> ILiquidityOrchestrator

    class IOrionVault {
        <<interface>>
        +event Redeem(address vault, address user, uint256 redeemAmount, uint256 sharesBurned)
        +event CuratorFeesAccrued(uint256 feeAmount, uint256 pendingCuratorFees)
        +void updateCurator(address newCurator)
        +void fulfillDeposit(uint256 depositTotalAssets)
        +void fulfillRedeem(uint256 redeemTotalAssets)
        +void accrueCuratorFees(uint256 feeAmount)
    }

    class OrionVault {
        +IInternalStateOrchestrator internalStatesOrchestrator
        +IOrionConfig config
        +ILiquidityOrchestrator liquidityOrchestrator
        +void cancelDeposit(uint256 amount)
        +void cancelRedeem(uint256 shares)
        +void fulfillDeposit(uint256 depositTotalAssets)
        +void fulfillRedeem(uint256 redeemTotalAssets)
        +void accrueCuratorFees(uint256 feeAmount)
        -mapping(address => uint256) _depositRequests
        -mapping(address => uint256) _redeemRequests
    }

    IOrionVault <|.. OrionVault

    class IOrionTransparentVault {
        <<interface>>
        +void updateVaultState(address[] tokens, uint256[] shares, uint256 newTotalAssets)
    }

    class OrionTransparentVault {
        -mapping(address => uint256) _portfolio
        -uint256 _totalAssets
        +void updateVaultState(address[] tokens, uint256[] shares, uint256 newTotalAssets)
        +void updateCurator(address newCurator)
    }

    IOrionTransparentVault <|.. OrionTransparentVault
    OrionTransparentVault --|> OrionVault

    class OrionConfig {
        +mapping(address => uint8) tokenDecimals
        +void addWhitelistedAsset(address asset, address priceAdapter, address executionAdapter)
        +bool isWhitelistedVaultOwner(address vaultOwner) returns bool
        +bool isDecommissioningVault(address vault) returns bool
        +void completeVaultDecommissioning(address vault)
    }

    class TransparentVaultFactory {
        +void createTransparentVault(
            address asset,
            string name,
            string symbol,
            address curator,
            address strategy,
            uint8 feeType,
            uint16 performanceFee,
            uint16 managementFee,
            address depositAccessControl
        )
    }

    OrionConfig <.. TransparentVaultFactory
    OrionConfig <.. InternalStatesOrchestrator
    OrionConfig <.. LiquidityOrchestrator
    OrionConfig <.. OrionAssetERC4626ExecutionAdapter

    LiquidityOrchestrator --> OrionTransparentVault : process vault ops
    LiquidityOrchestrator --> IExecutionAdapter : buy/sell
    InternalStatesOrchestrator --> OrionTransparentVault : read intents
    TransparentVaultFactory --> OrionTransparentVault : creates

    class EventsLib {
        <<library>>
        +event EpochProcessed(uint16 epochCounter)
        +event OrionVaultCreated(address vault, address asset, address vaultOwner, address curator, address strategy, uint8 feeType, uint16 performanceFee, uint16 managementFee, address depositAccessControl, VaultType vaultType)
    }

    class ErrorsLib {
        <<library>>
        +error SlippageExceeded(address asset, uint256 actual, uint256 expected)
    }

    class LiquidityUpkeepPhase {
        <<enumeration>>
        Idle
        SellingLeg
        BuyingLeg
        ProcessVaultOperations
    }
Loading

File-Level Changes

Change Details Files
Refined epoch state management and vault accounting in InternalStatesOrchestrator and LiquidityOrchestrator, and updated how vault total assets and portfolios are propagated.
  • Extended EpochState to track per‑vault portfolios and token sets, and added processLP flag to optionally skip LP processing during preprocessing/postprocessing.
  • Reworked performUpkeep in InternalStatesOrchestrator to accept encoded parameters (processLP and excludedAssets), removed action constants and epochCounter, and added resetPhase to allow controlled phase resets based on LiquidityOrchestrator state.
  • Changed buffering and postprocessing logic: curator fees are accrued without epoch number, optional LP processing is guarded by processLP, vault total assets are stored, and portfolio tokens/shares are accumulated for later use.
  • Introduced getVaultTotalAssetsAll and getVaultPortfolio view functions, replaced older per‑field getters, and wired LiquidityOrchestrator to consume these when processing vault operations.
  • Renamed FulfillDepositAndRedeem phase to ProcessVaultOperations, added epochCounter and EpochProcessed event emission in LiquidityOrchestrator, and centralized vault operations in _processSingleVaultOperations that calls fulfillDeposit/fulfillRedeem conditionally and then updateVaultState with final portfolio data.
  • Adjusted InternalStatesOrchestrator start/reset logic to properly clear epoch mappings, rebuild vault lists, and reset minibatch index, and removed InternalStateProcessed event and epochCounter usage.
contracts/orchestrators/InternalStatesOrchestrator.sol
contracts/orchestrators/LiquidityOrchestrator.sol
contracts/interfaces/IInternalStateOrchestrator.sol
contracts/interfaces/ILiquidityOrchestrator.sol
contracts/libraries/EventsLib.sol
test/orchestrator/Orchestrators.test.ts
test/orchestrator/OrchestratorsZeroState.test.ts
test/orchestrator/OrchestratorConfiguration.test.ts
test/orchestrator/OrchestratorSecurity.test.ts
test/orchestrator/RedeemBeforeDepositOrder.test.ts
Hardened execution adapter logic with ERC4626 validation and explicit slippage checks, and updated adapter interfaces and tests accordingly.
  • Extended IExecutionAdapter buy/sell signatures to include estimatedUnderlyingAmount and added validateExecutionAdapter; updated MockExecutionAdapter to match the new interface.
  • In OrionAssetERC4626ExecutionAdapter, wired config and liquidityOrchestrator as typed contracts, factored validation into _validateExecutionAdapter that checks ERC4626.asset() and tokenDecimals vs config, and reused it across operations.
  • Implemented slippage enforcement in buy/sell using BASIS_POINTS_FACTOR and LiquidityOrchestrator.slippageTolerance; buy now uses previewMint and rejects orders exceeding tolerance, while sell checks that redeemed underlying is within tolerance relative to estimate.
  • Adjusted LiquidityOrchestrator’s _executeBuy/_executeSell to pass estimatedUnderlyingAmount, replaced buyApprovalMultiplier with slippageTolerance derived from targetBufferRatio, and ensured approvals are sized to estimated amount plus tolerance.
  • Updated ERC4626 price adapter to validate underlying via IERC4626.asset() and clarified rounding behavior in getPriceData.
  • Added dedicated tests verifying ERC4626 execution adapter share accounting, slippage‑safe mint/redeem behavior, and adapter validation with a mock price adapter and whitelisted ERC4626 vault.
contracts/execution/OrionAssetERC4626ExecutionAdapter.sol
contracts/interfaces/IExecutionAdapter.sol
contracts/orchestrators/LiquidityOrchestrator.sol
contracts/price/OrionAssetERC4626PriceAdapter.sol
contracts/mocks/MockExecutionAdapter.sol
contracts/libraries/ErrorsLib.sol
test/Adapters.test.ts
test/ExecutionAdapterValidation.test.ts
Simplified vault/curator model by removing curator whitelisting from OrionConfig and factories, loosening curator interface constraints, and updating events and APIs.
  • Removed whitelistedCurators set and associated add/remove/isWhitelistedCurator functions and tests from OrionConfig, and simplified addWhitelistedAsset to be idempotent for already whitelisted assets while still updating decimals and adapters.
  • Stopped enforcing curator whitelisting in TransparentVaultFactory.createVault and OrionTransparentVault.updateCurator; updated IOrionVault/IOrionConfig/IOrionTransparentVault documentation to make curator and access‑control safety the vault owner’s responsibility.
  • Removed ERC165 inheritance and supportsInterface checks from KBestTvlWeightedAverage and its invalid variant, and deleted strategy interface detection tests.
  • Deleted all usages and tests related to curator whitelisting across protocol, orchestrator, access‑control, removal, fee cooldown, DOS, mainnet‑fork, and other vault tests.
  • Updated EventsLib.OrionVaultCreated to include depositAccessControl address and wired TransparentVaultFactory to emit it, and simplified Deposit/Redeem/CuratorFeesAccrued events to no longer carry epoch or vault address fields where not needed.
contracts/OrionConfig.sol
contracts/factories/TransparentVaultFactory.sol
contracts/vaults/OrionTransparentVault.sol
contracts/interfaces/IOrionConfig.sol
contracts/interfaces/IOrionVault.sol
contracts/interfaces/IOrionTransparentVault.sol
contracts/strategies/KBestTvlWeightedAverage.sol
contracts/test/KBestTvlWeightedAverageInvalid.sol
contracts/libraries/EventsLib.sol
test/PassiveCuratorStrategy.test.ts
test/AccessControl.test.ts
test/TransparentVault.test.ts
test/OrionConfigVault.test.ts
test/Removal.test.ts
test/VaultOwnerRemoval.test.ts
test/BatchLimitAccounting.test.ts
test/FeeCooldown.test.ts
test/MinimumAmountDOS.test.ts
test/ProtocolPause.test.ts
test/mainnet-fork/multiAssetRobustness.test.ts
Adjusted OrionVault request and batch‑fulfillment mechanics to avoid dust requests and rely purely on snapshot‑based accounting without epoch coupling.
  • In cancelDepositRequest/cancelRedeemRequest, enforced minimum remaining deposit/redeem amounts based on config.minDepositAmount/minRedeemAmount to prevent creation of dust requests that could DoS batching.
  • Refactored accrueCuratorFees to drop epoch parameter and updated event signature; OrionVault now accumulates pendingCuratorFees and emits CuratorFeesAccrued(feeAmount,pendingCuratorFees).
  • Rewrote fulfillDeposit and fulfillRedeem to snapshot totalSupply once, pre‑collect batch users/amounts from EnumerableMap to avoid index‑shifting issues, and emit Deposit/Redeem events without epoch dependency, while pulling redemption funds from LiquidityOrchestrator via transferRedemptionFunds.
  • Updated OrionVaultExchangeRate and related tests to impersonate only the LiquidityOrchestrator when calling fulfillDeposit/updateVaultState and to use the new updateVaultState(tokens,shares,totalAssets) signature.
  • Adjusted event expectations and math‑property tests to align with the new batch accounting behavior and event shapes.
contracts/vaults/OrionVault.sol
contracts/vaults/OrionTransparentVault.sol
contracts/interfaces/IOrionVault.sol
contracts/interfaces/IOrionTransparentVault.sol
test/OrionVaultExchangeRate.test.ts
test/MinimumAmountDOS.test.ts
Refined orchestrator tests and simulations to cover new slippage behavior, multi‑epoch flows, and ProcessVaultOperations semantics.
  • Updated orchestrator integration tests to use getVaultTotalAssetsAll instead of separate fulfillDeposit/redeem getters, and to assert vault totalAssets after LiquidityOrchestrator completes ProcessVaultOperations, not earlier.
  • Introduced a richer epoch simulation in Orchestrators tests that runs two epochs, injects gains/losses into mock assets, intentionally triggers slippage reverts in buying/selling legs, tests liquidity injection recovery, and validates metaportfolio vs order amounts.
  • Adjusted expectations around LiquidityOrchestrator.currentPhase from FulfillDepositAndRedeem to ProcessVaultOperations throughout tests and comments, and updated security tests accordingly.
  • Removed direct epochCounter assertions from tests in favor of LiquidityOrchestrator’s EpochProcessed event/epochCounter, and added TODOs for future ISO retry and LP‑ignore paths for failing legs.
  • Dropped outdated artifacts from version control and bumped package version from 0.6.0 to 0.7.0 to reflect the protocol upgrade.
  • Ensured new helper views like getTransparentVaultsEpoch and getVaultPortfolio are used where appropriate in tests for introspection and debugging.
test/orchestrator/Orchestrators.test.ts
test/orchestrator/EpochSimulation.test.ts
test/orchestrator/OrchestratorSecurity.test.ts
test/orchestrator/OrchestratorConfiguration.test.ts
test/orchestrator/OrchestratorsZeroState.test.ts
test/OrionVaultExchangeRate.test.ts
test/RedeemBeforeDepositOrder.test.ts
test/PassiveCuratorStrategy.test.ts
test/OrionConfigVault.test.ts
test/orchestrator/OrchestratorPerformUpkeep.test.ts
artifacts/** (removed)
package.json
Improved access‑control and documentation for deposit access controllers and related interfaces.
  • Extended IOrionAccessControl documentation to clarify its role for KYC/AML and compliance, and documented WhitelistAccessControl events and constructor parameters.
  • Ensured WhitelistAccessControl inherits Ownable2Step consistently and uses public whitelist mapping with events for add/remove operations (implementation largely unchanged).
  • Clarified in IOrionVault and OrionTransparentVault comments that owner bears full responsibility for curator and deposit access control safety.
  • Updated tests that instantiate WhitelistAccessControl to match the new constructor and behavior signatures.
contracts/access_controllers/WhitelistAccessControl.sol
contracts/interfaces/IOrionAccessControl.sol
contracts/interfaces/IOrionVault.sol
contracts/vaults/OrionTransparentVault.sol
test/AccessControl.test.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Dec 15, 2025

Copy link
Copy Markdown

Walkthrough

Removed many generated artifact JSON files; removed curator-whitelist state and APIs; introduced slippage-tolerant buy/sell signatures and validation; replaced PortfolioPosition arrays with parallel tokens/shares arrays across orchestrators and vaults; renamed orchestrator phase and added epoch signaling; updated tests and bumped package version.

Changes

Cohort / File(s) Summary
Artifact deletions
artifacts/contracts/**/\*.json
Removed generated Hardhat artifact JSONs across contracts, interfaces, libraries, mocks, orchestrators, strategies and tests.
OrionConfig & curator whitelist
contracts/OrionConfig.sol
contracts/interfaces/IOrionConfig.sol
contracts/access_controllers/WhitelistAccessControl.sol
Removed whitelistedCurators storage and curator management functions; adjusted addWhitelistedAsset duplicate handling; removed curator-related tests/setup.
Execution adapter & interface
contracts/execution/OrionAssetERC4626ExecutionAdapter.sol
contracts/interfaces/IExecutionAdapter.sol
Added BASIS_POINTS_FACTOR constant; changed liquidityOrchestrator to ILiquidityOrchestrator type; added internal _validateExecutionAdapter; extended buy/sell signatures to accept estimatedUnderlyingAmount and added slippage checks.
Errors & Events libraries
contracts/libraries/ErrorsLib.sol
contracts/libraries/EventsLib.sol
Added SlippageExceeded error; replaced InternalStateProcessed with EpochProcessed; extended OrionVaultCreated event to include depositAccessControl.
InternalStatesOrchestrator interface & impl
contracts/interfaces/IInternalStateOrchestrator.sol
contracts/orchestrators/InternalStatesOrchestrator.sol
Replaced getVaultTotalAssetsForFulfillDeposit/Redeem with getVaultTotalAssetsAll returning multi-values; added getVaultPortfolio; removed epochCounter from ISO interface; internal epoch state now stores tokens array, tokenExists, and per-vault vaultPortfolioTokens/vaultPortfolioShares; replaced PortfolioPosition usage with parallel arrays.
LiquidityOrchestrator interface & impl
contracts/interfaces/ILiquidityOrchestrator.sol
contracts/orchestrators/LiquidityOrchestrator.sol
Renamed FulfillDepositAndRedeem → ProcessVaultOperations; added epochCounter and slippageTolerance getters/state; removed buyApprovalMultiplier; setTargetBufferRatio sets slippageTolerance; adjusted buy/sell flows to pass estimatedUnderlyingAmount and use BASIS_POINTS_FACTOR+slippageTolerance; emit EpochProcessed and increment epochCounter.
Vault interfaces & implementations
contracts/interfaces/IOrionTransparentVault.sol
contracts/interfaces/IOrionVault.sol
contracts/vaults/OrionTransparentVault.sol
contracts/vaults/OrionVault.sol
Removed PortfolioPosition struct; changed updateVaultState to accept address[] tokens, uint256[] shares, uint256 newTotalAssets and moved access control to onlyLiquidityOrchestrator; removed Deposit epoch param and simplified Redeem/CuratorFeesAccrued events and accrueCuratorFees signature; fulfillDeposit/fulfillRedeem changed to batch-processing and emit simplified events; added dust checks on cancellations; updateCurator no longer requires whitelist.
TransparentVaultFactory & access control
contracts/factories/TransparentVaultFactory.sol
Removed curator-whitelist check in createVault; propagated depositAccessControl to vault constructor and OrionVaultCreated event.
Strategy ERC165 removal
contracts/strategies/KBestTvlWeightedAverage.sol
contracts/test/KBestTvlWeightedAverageInvalid.sol
Removed ERC165 inheritance and supportsInterface override from strategy contracts/tests.
Price adapter minor
contracts/price/OrionAssetERC4626PriceAdapter.sol
Minor local variable rename and comments in validatePriceAdapter/getPriceData; behavior unchanged.
Package & misc docs
package.json
contracts/interfaces/IOrionAccessControl.sol
Bumped package version 0.6.0 → 0.7.0; removed verify script; updated compliance wording in IOrionAccessControl docs.
Mocks & tests
contracts/mocks/*
test/**/*.test.ts
Updated mock adapter function signatures to accept estimatedUnderlyingAmount; removed curator whitelist setup across many tests; updated tests to use getVaultTotalAssetsAll and new buy/sell signatures; added ExecutionAdapterValidation.test.ts and EpochSimulation.test.ts and other orchestrator test updates; adjusted fixtures to remove InternalStatesOrchestrator returns.

Sequence Diagram(s)

sequenceDiagram
    participant LO as LiquidityOrchestrator
    participant ISO as InternalStatesOrchestrator
    participant VAULT as OrionTransparentVault / ERC4626 Vault
    participant ADAPTER as ExecutionAdapter
    participant CONFIG as OrionConfig

    Note over LO,ISO: Epoch processing and per-vault portfolio flow

    LO->>ISO: checkUpkeep()
    ISO-->>LO: (upkeepNeeded, phase)
    LO->>ISO: performUpkeep(phase) / preprocess
    ISO-->>LO: vault list & store vaultPortfolioTokens/vaultPortfolioShares
    loop ProcessVaultOperations per vault
        LO->>ISO: getVaultTotalAssetsAll(vault)
        ISO-->>LO: (forRedeem, forDeposit, total)
        LO->>VAULT: updateVaultState(tokens[], shares[], finalTotalAssets)
        VAULT-->>LO: ack
    end
    LO->>LO: epochCounter++
    LO->>CONFIG: emit EpochProcessed(epochCounter)
Loading
sequenceDiagram
    participant LO as LiquidityOrchestrator
    participant ADAPTER as ExecutionAdapter
    participant VAULT as ERC4626 Vault
    participant CONFIG as OrionConfig

    Note over LO,ADAPTER: Slippage-aware buy flow

    LO->>CONFIG: slippageTolerance()
    CONFIG-->>LO: tolerance
    LO->>VAULT: approve(ADAPTER, approvalAmount) calculated with BASIS_POINTS_FACTOR + tolerance
    LO->>ADAPTER: buy(vaultAsset, shares, estimatedUnderlying)
    ADAPTER->>ADAPTER: _validateExecutionAdapter(vaultAsset)
    ADAPTER->>VAULT: transferFrom(underlying, estimatedUnderlying)
    ADAPTER->>VAULT: deposit(estimatedUnderlying, adapter)
    VAULT-->>ADAPTER: mintedShares (may include dust)
    ADAPTER-->>LO: actualUnderlyingUsed
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Review focus areas:
    • Portfolio refactor: ensure tokens/shares parallel arrays are handled consistently and safely across ISO, LO, and vaults.
    • Slippage math: verify BASIS_POINTS_FACTOR usage and tolerance arithmetic across orchestrator and adapters.
    • Access control changes: confirm onlyLiquidityOrchestrator is correct caller after updateVaultState access shift.
    • Event and signature changes: check downstream consumers/tests and off-chain tooling for compatibility.
    • Batch processing in vaults: validate correctness of pre-collection logic and dust-check behavior.

Possibly related PRs

  • Dev #70 — overlapping changes to IExecutionAdapter and OrionAssetERC4626ExecutionAdapter (buy/sell signature and slippage handling).
  • fix: epoch vaults selection internal state orchestrator #76 — related InternalStatesOrchestrator epoch and preprocessing refactors affecting _handleStart and vault portfolio building.
  • Access control #109 — related depositAccessControl propagation across TransparentVaultFactory, OrionTransparentVault, and events.

Poem

🐰
I hopped through arrays of tokens and shares,
Checked slippage with careful numeric cares,
Whitelists shrank, epochs now soundly processed,
Artifacts cleared, tests adjusted and dressed,
A rabbit cheers — the protocol’s hopped and blessed!

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Dev' is vague and non-descriptive, failing to convey any meaningful information about the substantial refactoring changes in this PR. Use a descriptive title that summarizes the main change, such as 'Refactor orchestrators with slippage-aware execution and simplified curator management' or 'Implement slippage tolerance and vault portfolio state handling'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@matteoettam09
matteoettam09 marked this pull request as ready for review December 15, 2025 19:34
@immunefi-magnus

Copy link
Copy Markdown

🛡️ Immunefi PR Reviews

We noticed that your project isn't set up for automatic code reviews. If you'd like this PR reviewed by the Immunefi team, you can request it manually using the link below:

🔗 Send this PR in for review

Once submitted, we'll take care of assigning a reviewer and follow up here.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
contracts/OrionConfig.sol (1)

238-251: Silent duplicate handling may mask configuration errors.

The function now silently skips adding duplicates to whitelistedAssets but still:

  1. Overwrites tokenDecimals[asset] (line 244)
  2. Re-registers adapters (lines 247-248)
  3. Emits WhitelistedAssetAdded event (line 250)

This allows atomic adapter updates for existing assets, but the event emission for already-whitelisted assets could be misleading. Consider emitting a different event (e.g., WhitelistedAssetUpdated) when the asset was already present.

 function addWhitelistedAsset(address asset, address priceAdapter, address executionAdapter) external onlyOwner {
     if (!isSystemIdle()) revert ErrorsLib.SystemNotIdle();

+    bool isNew = !this.isWhitelisted(asset);
-    if (!this.isWhitelisted(asset)) {
+    if (isNew) {
         // slither-disable-next-line unused-return
         whitelistedAssets.add(asset);
     }

     // Store token decimals
     tokenDecimals[asset] = IERC20Metadata(asset).decimals();

     // Register the adapters
     IPriceAdapterRegistry(priceAdapterRegistry).setPriceAdapter(asset, IPriceAdapter(priceAdapter));
     ILiquidityOrchestrator(liquidityOrchestrator).setExecutionAdapter(asset, IExecutionAdapter(executionAdapter));

-    emit EventsLib.WhitelistedAssetAdded(asset);
+    if (isNew) {
+        emit EventsLib.WhitelistedAssetAdded(asset);
+    } else {
+        emit EventsLib.WhitelistedAssetUpdated(asset);
+    }
 }
contracts/interfaces/IOrionTransparentVault.sol (1)

18-24: Remove unused PortfolioPosition struct.

This struct is not referenced anywhere in the codebase and has been superseded by the parallel arrays approach in updateVaultState. Remove it to reduce interface clutter.

🧹 Nitpick comments (10)
test/orchestrator/EpochSimulation.test.ts (4)

46-51: Box-Muller implementation is correct.

The Gaussian random number generator using Box-Muller transform is mathematically sound. Note that Math.random() is not seedable, so test results are non-deterministic. For reproducible tests, consider using a seeded PRNG.


192-205: Potential weight rounding issue with equal distribution.

With NUM_ASSETS = 100 and intentFactor = 10^9, weightPerAsset = Math.floor(10^9 / 100) = 10000000. Total weight = 100 * 10000000 = 1000000000 = 10^9, so this case works perfectly.

However, if NUM_ASSETS doesn't evenly divide intentFactor, the total weights won't sum to intentScale, potentially causing InvalidTotalWeight revert. Consider adding remainder distribution logic similar to KBestTvlWeightedAverage._calculatePositions.


280-309: Consider using phase enum names instead of magic numbers.

Hardcoded phase numbers (1n, 2n, 3n, 4n) are brittle. If the phase enum ordering changes in InternalStatesOrchestrator, this test will silently misbehave. Consider importing or referencing the enum values directly.

Example approach:

// At the top of the file or in a helper
const InternalPhase = {
  Idle: 0n,
  PreprocessingTransparentVaults: 1n,
  Buffering: 2n,
  PostprocessingTransparentVaults: 3n,
  BuildingOrders: 4n,
};

// Then use:
while ((await internalStatesOrchestrator.currentPhase()) === InternalPhase.PreprocessingTransparentVaults) {
  // ...
}

351-365: Consider adding basic invariant assertions.

The test only logs state without validating invariants. While this works as a smoke/stress test, adding assertions would catch regressions:

// Example invariants to check each epoch
expect(sharePrice).to.be.gt(0, "Share price should be positive");
expect(totalAssets).to.be.gte(0, "Total assets should not be negative");
expect(pendingCuratorFees).to.be.gte(0, "Fees should not be negative");
test/ExecutionAdapterValidation.test.ts (1)

159-172: Consider using a more specific error assertion.

The assertion .to.be.reverted is generic and may pass for unexpected failure reasons. Consider asserting the specific error or at least the contract that reverts.

-        ).to.be.reverted;
+        ).to.be.revertedWithoutReason(); // or revertedWithCustomError if specific error expected
contracts/execution/OrionAssetERC4626ExecutionAdapter.sol (2)

91-99: Misleading variable name: maxUnderlyingAmount should be minUnderlyingAmount.

In the sell context, you're computing the minimum acceptable amount (applying negative slippage tolerance), yet the variable is named maxUnderlyingAmount. This is semantically incorrect and confusing for maintainers.

         if (receivedUnderlyingAmount < estimatedUnderlyingAmount) {
-            uint256 maxUnderlyingAmount = estimatedUnderlyingAmount.mulDiv(
+            uint256 minUnderlyingAmount = estimatedUnderlyingAmount.mulDiv(
                 BASIS_POINTS_FACTOR - liquidityOrchestrator.slippageTolerance(),
                 BASIS_POINTS_FACTOR
             );
-            if (receivedUnderlyingAmount < maxUnderlyingAmount) {
+            if (receivedUnderlyingAmount < minUnderlyingAmount) {
                 revert ErrorsLib.SlippageExceeded(vaultAsset, receivedUnderlyingAmount, estimatedUnderlyingAmount);
             }
         }

136-137: Dust acceptance is reasonable but consider documenting threshold.

The comment notes that some ERC4626 implementations may leave dust. Consider whether a maximum acceptable dust threshold should be enforced to prevent unexpected accumulation over many operations.

contracts/orchestrators/LiquidityOrchestrator.sol (1)

170-172: Slippage tolerance is coupled to buffer ratio.

Setting slippageTolerance = targetBufferRatio / 2 creates an implicit relationship. While this may be intentional (higher buffer → can tolerate more slippage), consider whether these should be independently configurable for more fine-grained control.

test/orchestrator/Orchestrators.test.ts (2)

718-722: Redundant duplicate calls to getVaultTotalAssetsAll.

Two separate calls are made to retrieve the same tuple, destructuring different parts. This is inefficient and can be consolidated into a single call.

-        const [, totalAssetsForDeposit] = await internalStatesOrchestrator.getVaultTotalAssetsAll(await v.getAddress());
-        const [totalAssetsForRedeem, ,] = await internalStatesOrchestrator.getVaultTotalAssetsAll(await v.getAddress());
-        expect(totalAssetsForDeposit).to.equal(0);
-        expect(totalAssetsForRedeem).to.equal(0);
+        const [totalAssetsForRedeem, totalAssetsForDeposit] = await internalStatesOrchestrator.getVaultTotalAssetsAll(await v.getAddress());
+        expect(totalAssetsForRedeem).to.equal(0);
+        expect(totalAssetsForDeposit).to.equal(0);

762-795: Address TODO: Commented-out assertions should be implemented or removed.

These commented-out expected total assets calculations represent incomplete test coverage. Either implement the assertions or remove the dead code with an issue tracking the work.

Would you like me to open an issue to track implementing these assertions, or should they be removed if no longer relevant?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ad6ba22 and e2d9eff.

📒 Files selected for processing (72)
  • .gitignore (2 hunks)
  • artifacts/contracts/OrionConfig.sol/OrionConfig.json (0 hunks)
  • artifacts/contracts/access_controllers/WhitelistAccessControl.sol/WhitelistAccessControl.json (0 hunks)
  • artifacts/contracts/execution/OrionAssetERC4626ExecutionAdapter.sol/OrionAssetERC4626ExecutionAdapter.json (0 hunks)
  • artifacts/contracts/factories/TransparentVaultFactory.sol/TransparentVaultFactory.json (0 hunks)
  • artifacts/contracts/interfaces/IExecutionAdapter.sol/IExecutionAdapter.json (0 hunks)
  • artifacts/contracts/interfaces/IInternalStateOrchestrator.sol/IInternalStateOrchestrator.json (0 hunks)
  • artifacts/contracts/interfaces/ILiquidityOrchestrator.sol/ILiquidityOrchestrator.json (0 hunks)
  • artifacts/contracts/interfaces/IOrionAccessControl.sol/IOrionAccessControl.json (0 hunks)
  • artifacts/contracts/interfaces/IOrionConfig.sol/IOrionConfig.json (0 hunks)
  • artifacts/contracts/interfaces/IOrionStrategy.sol/IOrionStrategy.json (0 hunks)
  • artifacts/contracts/interfaces/IOrionTransparentVault.sol/IOrionTransparentVault.json (0 hunks)
  • artifacts/contracts/interfaces/IOrionVault.sol/IOrionVault.json (0 hunks)
  • artifacts/contracts/interfaces/IPriceAdapter.sol/IPriceAdapter.json (0 hunks)
  • artifacts/contracts/interfaces/IPriceAdapterRegistry.sol/IPriceAdapterRegistry.json (0 hunks)
  • artifacts/contracts/libraries/ErrorsLib.sol/ErrorsLib.json (0 hunks)
  • artifacts/contracts/libraries/EventsLib.sol/EventsLib.json (0 hunks)
  • artifacts/contracts/libraries/UtilitiesLib.sol/UtilitiesLib.json (0 hunks)
  • artifacts/contracts/mocks/MockERC4626Asset.sol/MockERC4626Asset.json (0 hunks)
  • artifacts/contracts/mocks/MockExecutionAdapter.sol/MockExecutionAdapter.json (0 hunks)
  • artifacts/contracts/mocks/MockPriceAdapter.sol/MockPriceAdapter.json (0 hunks)
  • artifacts/contracts/mocks/MockUnderlyingAsset.sol/MockUnderlyingAsset.json (0 hunks)
  • artifacts/contracts/orchestrators/InternalStatesOrchestrator.sol/InternalStatesOrchestrator.json (0 hunks)
  • artifacts/contracts/orchestrators/LiquidityOrchestrator.sol/LiquidityOrchestrator.json (0 hunks)
  • artifacts/contracts/price/OrionAssetERC4626PriceAdapter.sol/OrionAssetERC4626PriceAdapter.json (0 hunks)
  • artifacts/contracts/price/PriceAdapterRegistry.sol/PriceAdapterRegistry.json (0 hunks)
  • artifacts/contracts/strategies/KBestTvlWeightedAverage.sol/KBestTvlWeightedAverage.json (0 hunks)
  • artifacts/contracts/test/KBestTvlWeightedAverageInvalid.sol/KBestTvlWeightedAverageInvalid.json (0 hunks)
  • artifacts/contracts/test/UtilitiesLibTest.sol/UtilitiesLibTest.json (0 hunks)
  • artifacts/contracts/vaults/OrionVault.sol/OrionVault.json (0 hunks)
  • contracts/OrionConfig.sol (2 hunks)
  • contracts/access_controllers/WhitelistAccessControl.sol (1 hunks)
  • contracts/execution/OrionAssetERC4626ExecutionAdapter.sol (4 hunks)
  • contracts/factories/TransparentVaultFactory.sol (1 hunks)
  • contracts/interfaces/IExecutionAdapter.sol (1 hunks)
  • contracts/interfaces/IInternalStateOrchestrator.sol (2 hunks)
  • contracts/interfaces/ILiquidityOrchestrator.sol (3 hunks)
  • contracts/interfaces/IOrionAccessControl.sol (1 hunks)
  • contracts/interfaces/IOrionConfig.sol (0 hunks)
  • contracts/interfaces/IOrionTransparentVault.sol (1 hunks)
  • contracts/interfaces/IOrionVault.sol (4 hunks)
  • contracts/libraries/ErrorsLib.sol (1 hunks)
  • contracts/libraries/EventsLib.sol (3 hunks)
  • contracts/mocks/MockExecutionAdapter.sol (1 hunks)
  • contracts/orchestrators/InternalStatesOrchestrator.sol (7 hunks)
  • contracts/orchestrators/LiquidityOrchestrator.sol (12 hunks)
  • contracts/price/OrionAssetERC4626PriceAdapter.sol (2 hunks)
  • contracts/strategies/KBestTvlWeightedAverage.sol (1 hunks)
  • contracts/test/KBestTvlWeightedAverageInvalid.sol (1 hunks)
  • contracts/vaults/OrionTransparentVault.sol (1 hunks)
  • contracts/vaults/OrionVault.sol (6 hunks)
  • package.json (1 hunks)
  • test/AccessControl.test.ts (0 hunks)
  • test/Adapters.test.ts (8 hunks)
  • test/BatchLimitAccounting.test.ts (0 hunks)
  • test/ExecutionAdapterValidation.test.ts (1 hunks)
  • test/FeeCooldown.test.ts (0 hunks)
  • test/MinimumAmountDOS.test.ts (0 hunks)
  • test/OrionConfigVault.test.ts (0 hunks)
  • test/OrionVaultExchangeRate.test.ts (16 hunks)
  • test/PassiveCuratorStrategy.test.ts (0 hunks)
  • test/ProtocolPause.test.ts (0 hunks)
  • test/RedeemBeforeDepositOrder.test.ts (3 hunks)
  • test/Removal.test.ts (0 hunks)
  • test/TransparentVault.test.ts (0 hunks)
  • test/VaultOwnerRemoval.test.ts (0 hunks)
  • test/mainnet-fork/multiAssetRobustness.test.ts (1 hunks)
  • test/orchestrator/EpochSimulation.test.ts (1 hunks)
  • test/orchestrator/OrchestratorConfiguration.test.ts (0 hunks)
  • test/orchestrator/OrchestratorSecurity.test.ts (2 hunks)
  • test/orchestrator/Orchestrators.test.ts (10 hunks)
  • test/orchestrator/OrchestratorsZeroState.test.ts (0 hunks)
💤 Files with no reviewable changes (42)
  • test/VaultOwnerRemoval.test.ts
  • test/BatchLimitAccounting.test.ts
  • test/orchestrator/OrchestratorsZeroState.test.ts
  • artifacts/contracts/OrionConfig.sol/OrionConfig.json
  • artifacts/contracts/execution/OrionAssetERC4626ExecutionAdapter.sol/OrionAssetERC4626ExecutionAdapter.json
  • artifacts/contracts/test/UtilitiesLibTest.sol/UtilitiesLibTest.json
  • artifacts/contracts/libraries/EventsLib.sol/EventsLib.json
  • test/orchestrator/OrchestratorConfiguration.test.ts
  • test/MinimumAmountDOS.test.ts
  • artifacts/contracts/factories/TransparentVaultFactory.sol/TransparentVaultFactory.json
  • artifacts/contracts/orchestrators/LiquidityOrchestrator.sol/LiquidityOrchestrator.json
  • artifacts/contracts/interfaces/IPriceAdapterRegistry.sol/IPriceAdapterRegistry.json
  • artifacts/contracts/interfaces/IOrionVault.sol/IOrionVault.json
  • artifacts/contracts/test/KBestTvlWeightedAverageInvalid.sol/KBestTvlWeightedAverageInvalid.json
  • contracts/interfaces/IOrionConfig.sol
  • test/Removal.test.ts
  • test/ProtocolPause.test.ts
  • artifacts/contracts/price/OrionAssetERC4626PriceAdapter.sol/OrionAssetERC4626PriceAdapter.json
  • artifacts/contracts/strategies/KBestTvlWeightedAverage.sol/KBestTvlWeightedAverage.json
  • test/AccessControl.test.ts
  • artifacts/contracts/mocks/MockERC4626Asset.sol/MockERC4626Asset.json
  • artifacts/contracts/orchestrators/InternalStatesOrchestrator.sol/InternalStatesOrchestrator.json
  • artifacts/contracts/interfaces/IOrionAccessControl.sol/IOrionAccessControl.json
  • artifacts/contracts/price/PriceAdapterRegistry.sol/PriceAdapterRegistry.json
  • test/TransparentVault.test.ts
  • test/FeeCooldown.test.ts
  • artifacts/contracts/interfaces/IPriceAdapter.sol/IPriceAdapter.json
  • artifacts/contracts/libraries/ErrorsLib.sol/ErrorsLib.json
  • artifacts/contracts/libraries/UtilitiesLib.sol/UtilitiesLib.json
  • artifacts/contracts/mocks/MockPriceAdapter.sol/MockPriceAdapter.json
  • artifacts/contracts/mocks/MockExecutionAdapter.sol/MockExecutionAdapter.json
  • test/OrionConfigVault.test.ts
  • artifacts/contracts/interfaces/IExecutionAdapter.sol/IExecutionAdapter.json
  • artifacts/contracts/interfaces/IOrionConfig.sol/IOrionConfig.json
  • artifacts/contracts/interfaces/ILiquidityOrchestrator.sol/ILiquidityOrchestrator.json
  • artifacts/contracts/interfaces/IInternalStateOrchestrator.sol/IInternalStateOrchestrator.json
  • artifacts/contracts/mocks/MockUnderlyingAsset.sol/MockUnderlyingAsset.json
  • artifacts/contracts/access_controllers/WhitelistAccessControl.sol/WhitelistAccessControl.json
  • test/PassiveCuratorStrategy.test.ts
  • artifacts/contracts/vaults/OrionVault.sol/OrionVault.json
  • artifacts/contracts/interfaces/IOrionTransparentVault.sol/IOrionTransparentVault.json
  • artifacts/contracts/interfaces/IOrionStrategy.sol/IOrionStrategy.json
🧰 Additional context used
🧬 Code graph analysis (7)
test/orchestrator/OrchestratorSecurity.test.ts (1)
test/orchestrator/OrchestratorPerformUpkeep.test.ts (1)
  • it (748-2469)
test/RedeemBeforeDepositOrder.test.ts (1)
test/OrionConfigVault.test.ts (1)
  • describe (338-593)
test/ExecutionAdapterValidation.test.ts (1)
test/OrionConfigVault.test.ts (1)
  • describe (338-593)
contracts/test/KBestTvlWeightedAverageInvalid.sol (1)
test/PassiveCuratorStrategy.test.ts (2)
  • it (259-275)
  • KBestTvlWeightedAverageInvalidFactory (509-568)
contracts/libraries/EventsLib.sol (1)
test/AccessControl.test.ts (1)
  • vault (270-280)
contracts/interfaces/IOrionVault.sol (1)
test/AccessControl.test.ts (2)
  • vault (270-280)
  • vault (138-237)
contracts/strategies/KBestTvlWeightedAverage.sol (1)
test/PassiveCuratorStrategy.test.ts (1)
  • it (259-275)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Sourcery review
  • GitHub Check: Sourcery review
  • GitHub Check: Build, Lint and Test
🔇 Additional comments (58)
contracts/interfaces/IOrionAccessControl.sol (1)

8-8: Doc wording update is clear and accurate

The new dev comment better specifies compliance intent (KYC/AML/other requirements) without changing behavior. No further changes needed.

.gitignore (1)

25-25: Consolidation of artifact ignores aligns with PR cleanup goals.

The two changes—adding .cursor/ (Cursor IDE cache) and consolidating artifact patterns into a blanket artifacts/ ignore—are appropriate housekeeping. The shift from preserving artifacts/contracts/**/*.json to ignoring the entire artifacts/ directory aligns with the PR's artifact cleanup and regeneration-on-build model.

Please verify that the removal of the selective negation patterns (!artifacts/contracts/**/*.json) doesn't inadvertently exclude files that should be version-controlled. Given the PR's scope around artifact cleanup, this appears intentional, but confirming that generated ABIs/artifacts are no longer expected to be committed would be helpful.

Also applies to: 46-46

package.json (1)

4-4: Version bump aligns with architectural refactoring.

The protocol version bump to 0.7.0 is appropriate given the significant architectural changes throughout this PR (orchestrator refactors, slippage handling, epoch tracking, vault state management).

contracts/access_controllers/WhitelistAccessControl.sol (4)

4-6: Import cleanup and base class usage look good

Using Ownable2Step for ownership and removing the unused error library keeps this access controller lean; no functional concerns here.


7-11: Contract-level NatSpec/author tag is clear

The added @notice and @author metadata improve discoverability without altering behavior.


16-22: Event parameter documentation is now complete

Adding @param account descriptions for both whitelist events makes their semantics explicit and aligns with NatSpec best practices.


24-26: Constructor NatSpec matches the implementation

The constructor docs correctly describe initialOwner_ and the ownership pattern; no issues with the current wording or implementation.

test/RedeemBeforeDepositOrder.test.ts (3)

252-253: Correct migration to new getVaultTotalAssetsAll API.

The destructuring properly extracts both totalAssetsForRedeem and totalAssetsForDeposit from the tuple return value. The subsequent assertions correctly verify that redemptions use higher totalAssets (before deposit impact).


348-348: LGTM!

Correct use of destructuring to extract only totalAssetsForDeposit while ignoring the first element.


383-384: LGTM!

Edge case correctly verifies that without redemptions, both totalAssetsForRedeem and totalAssetsForDeposit are equal.

contracts/OrionConfig.sol (1)

397-398: LGTM!

Using this.isDecommissioningVault(vault) instead of direct set access improves consistency and maintainability, even with slight gas overhead. This is appropriate for an admin function called by the liquidity orchestrator.

contracts/strategies/KBestTvlWeightedAverage.sol (1)

17-17: ERC165 inheritance removed as intended.

The contract correctly removes ERC165 from the inheritance chain. The concern about failing tests related to supportsInterface is not applicable—no such tests exist in the test suite, and no ERC165 references are present in any test files. The code change is clean with no test impact.

Likely an incorrect or invalid review comment.

contracts/test/KBestTvlWeightedAverageInvalid.sol (1)

18-18: Contract signature change is correct; ERC165 tests do not exist and do not require updates.

The contract correctly inherits only from IOrionStrategy and Ownable. No supportsInterface tests exist for this contract or any strategy in the codebase. Strategy contracts do not inherit from ERC165.

Likely an incorrect or invalid review comment.

contracts/interfaces/IInternalStateOrchestrator.sol (2)

83-90: Consolidated getter improves gas efficiency for callers.

Replacing two separate getters (getVaultTotalAssetsForFulfillRedeem and getVaultTotalAssetsForFulfillDeposit) with a single getVaultTotalAssetsAll that returns all three values reduces external call overhead when callers need multiple values.


101-106: New per-vault portfolio getter aligns with parallel arrays pattern.

The getVaultPortfolio function correctly returns parallel arrays (tokens, shares) consistent with the updated updateVaultState signature in IOrionTransparentVault. Documentation is clear.

contracts/libraries/ErrorsLib.sol (1)

91-96: Well-structured slippage error with actionable parameters.

The SlippageExceeded error includes asset, actual, and expected values, enabling precise debugging and off-chain monitoring of slippage events. This follows the library's existing pattern for parameterized errors.

test/mainnet-fork/multiAssetRobustness.test.ts (1)

402-411: Test updated for new depositAccessControl parameter.

Passing ethers.ZeroAddress as the deposit access control parameter aligns with the factory interface change. This correctly configures the vault with no deposit restrictions for testing purposes.

contracts/price/OrionAssetERC4626PriceAdapter.sol (2)

37-43: LGTM!

Variable rename to underlying improves readability in the local scope. The validation logic remains correct.


52-54: Helpful rounding behavior documentation.

The comment clarifies the intentional use of floor rounding here versus ceiling rounding in previewMint during execution, with the buffer handling any rounding discrepancies. This aids future maintainers.

contracts/factories/TransparentVaultFactory.sol (1)

64-75: LGTM!

The depositAccessControl parameter is correctly propagated through the vault constructor and included in the OrionVaultCreated event emission, aligning with the updated event signature in EventsLib.sol.

test/orchestrator/OrchestratorSecurity.test.ts (2)

41-42: LGTM!

Phase sequence documentation correctly updated to reflect the renamed ProcessVaultOperations phase, consistent with the ILiquidityOrchestrator enum change.


56-58: LGTM!

Cross-phase test documentation accurately reflects the new phase naming, maintaining consistency with the orchestrator interface changes.

contracts/mocks/MockExecutionAdapter.sol (1)

12-20: LGTM!

The mock correctly implements the updated IExecutionAdapter interface with the new three-parameter signatures for buy() and sell(). The unused third parameter is appropriate for a test mock that doesn't need to implement actual slippage logic.

contracts/interfaces/ILiquidityOrchestrator.sol (3)

16-16: LGTM!

The phase rename from FulfillDepositAndRedeem to ProcessVaultOperations accurately reflects the broader scope of this phase, which now handles epoch accounting and completion events in addition to fulfill operations.


19-33: LGTM!

The new epochCounter() and slippageTolerance() getters are well-documented and provide the necessary state visibility for execution adapters and external consumers to implement slippage-aware operations.


48-52: LGTM!

The dev comment clearly explains the slippage tolerance calculation (50% of targetBufferRatio) and the rationale behind it—ensuring all trades pass even with maximum price impact during full NAV rebalancing.

contracts/vaults/OrionTransparentVault.sol (1)

163-166: Verify removal of curator whitelist check is intentional.

The updateCurator function no longer validates that the new curator is whitelisted. Per the PR objectives, this shifts responsibility to vault owners. However, this allows setting any address (including address(0)) as curator.

Consider whether a zero-address check should remain:

     function updateCurator(address newCurator) external onlyVaultOwner {
+        if (newCurator == address(0)) revert ErrorsLib.ZeroAddress();
         curator = newCurator;
         emit CuratorUpdated(newCurator);
     }
contracts/libraries/EventsLib.sol (2)

106-108: LGTM!

The event rename from InternalStateProcessed to EpochProcessed better reflects the epoch-based lifecycle signaling, aligning with the broader orchestration model changes.


125-138: LGTM!

The OrionVaultCreated event correctly includes the new depositAccessControl parameter with proper documentation. The parameter placement before VaultType maintains logical grouping of vault configuration parameters.

test/ExecutionAdapterValidation.test.ts (2)

31-113: LGTM!

The test setup is comprehensive and correctly wires up the full deployment environment including underlying assets, ERC4626 vault seeding, config, price/execution adapters, and orchestrators. The seeding of the vault with initial deposits ensures totalAssets > 0 for validation tests.


452-544: LGTM!

The integration tests provide excellent end-to-end coverage of the buy-sell cycle with validation and slippage checks. The tests properly verify share balances, underlying token returns, and slippage propagation across configuration changes.

contracts/interfaces/IExecutionAdapter.sol (1)

14-38: Interface updates for slippage-aware execution look good.

The addition of validateExecutionAdapter(address asset) and the new estimatedUnderlyingAmount parameter to buy() and sell() aligns with the PR objectives for slippage tolerance handling. The NatSpec documentation is clear and accurate.

test/Adapters.test.ts (2)

227-248: Proper test setup for the new execution adapter interface.

The beforeEach block correctly:

  1. Seeds the vault with initial assets to enable validation
  2. Deploys and whitelists the mock price adapter
  3. Sets slippage tolerance via setTargetBufferRatio(400)

This ensures tests exercise the new slippage-aware execution paths.


397-403: Correct use of previewRedeem for sell operations.

Using previewRedeem(sharesAmount) to compute the expected underlying amount before calling sell() follows ERC4626 best practices and ensures the slippage check in the adapter has accurate data.

test/OrionVaultExchangeRate.test.ts (2)

129-144: Tests correctly updated for new updateVaultState signature.

The tests now use updateVaultState([], [], depositAmount) via the liquidity orchestrator, aligning with the refactored vault state update pipeline where the liquidity orchestrator applies portfolio/total-assets updates.


81-97: Fixture structure is appropriate.

The fixture returns both orchestrator references, providing flexibility for tests while the actual state update calls correctly use the liquidity orchestrator path. This is a reasonable approach.

contracts/interfaces/IOrionVault.sol (3)

54-63: Simplified event signatures by removing epoch parameter.

The Redeem and CuratorFeesAccrued events no longer include epoch information, aligning with the PR's goal to decouple epoch accounting from vault operations. This simplification is appropriate.


139-143: Good documentation enhancement for curator responsibility.

The added clarification that "Curator can be a smart contract or an address. It is the FULL responsibility of the vault owner to ensure the curator is capable of performing its duties" is an important security reminder given the removal of curator whitelisting.


202-204: accrueCuratorFees signature correctly simplified.

Removing the epoch parameter aligns with the updated event signature and the decoupled epoch model.

contracts/vaults/OrionVault.sol (5)

375-386: Good dust prevention in deposit cancellation.

Enforcing minDeposit on the remaining amount after partial cancellation prevents dust-level deposits that would be inefficient to process. The logic correctly handles the zero case (full cancellation) separately.


431-436: Consistent dust prevention for redeem cancellation.

Mirrors the deposit cancellation pattern by enforcing minRedeem on remaining shares. This prevents dust redemption requests.


637-642: Simplified accrueCuratorFees implementation.

The epoch parameter removal is consistent with the interface change. The function correctly handles zero fee amounts with an early return.


657-682: Batch processing refactored to pre-collect request data.

Pre-collecting users and amounts into arrays before iterating and removing entries avoids the swap-and-pop reordering issues inherent to EnumerableMap.remove() during iteration. This is a correct and important fix.

The memory allocation is bounded by config.maxFulfillBatchSize(), ensuring gas costs remain predictable.


697-726: Redemption fulfillment also correctly pre-collects request data.

The same pre-collection pattern is applied consistently to fulfillRedeem, avoiding iteration issues with EnumerableMap. The comment on line 697 clearly documents the rationale.

contracts/execution/OrionAssetERC4626ExecutionAdapter.sol (2)

52-73: LGTM: Validation logic is well-structured.

The _validateExecutionAdapter function properly checks both the underlying asset compatibility and decimal consistency with the config. The fallback reverts on any failure are appropriate.


117-125: Slippage check for buy is correctly implemented.

The pre-execution slippage check using previewMint before pulling funds is the correct approach, preventing overspending within tolerance bounds.

contracts/orchestrators/LiquidityOrchestrator.sol (4)

456-465: Potential logic issue: comparing shares to finalTotalAssets for decommissioning check.

The condition shares[i] == finalTotalAssets compares the share amount of the underlying asset in the portfolio to finalTotalAssets. However, for the underlying asset (which is not an ERC4626 vault), the "shares" are actually the underlying asset amount itself (1:1), so this comparison should be valid.

However, this logic assumes the portfolio only contains the underlying asset when decommissioning is ready. If there are any residual non-underlying tokens with shares > 0, the vault won't be decommissioned even if the underlying portion equals finalTotalAssets.

Please verify that the decommissioning flow ensures all non-underlying assets are fully sold before this check runs. Consider adding a comment clarifying this expectation, or add an explicit check that verifies only the underlying asset remains in the portfolio.


132-132: Initial slippageTolerance of 0 may cause issues before setTargetBufferRatio is called.

With slippageTolerance = 0, any price movement between estimation and execution will cause slippage reverts. The owner must call setTargetBufferRatio before the first epoch can successfully execute trades.

Verify that the deployment/initialization sequence ensures setTargetBufferRatio is called before any epoch processing. Consider documenting this requirement or setting a sensible default.


385-389: Approval includes slippage buffer for buy operations.

Good approach - approving estimatedUnderlyingAmount * (1 + slippageTolerance/BASIS_POINTS_FACTOR) ensures the adapter has sufficient allowance even with adverse price movement, while the adapter's internal slippage check prevents overspending.


409-415: Epoch counter increment and event emission are correctly placed.

The EpochProcessed event is emitted and epochCounter incremented only after all vault operations in the final minibatch complete, ensuring consistent epoch signaling.

test/orchestrator/Orchestrators.test.ts (2)

1187-1191: Good pattern: Using getVaultTotalAssetsAll to validate vault state.

The test correctly validates that totalAssets() from the vault matches the expected value from the internal state orchestrator after LiquidityOrchestrator completes.


1788-1793: Consistent use of consolidated getter pattern.

The test properly destructures the tuple from getVaultTotalAssetsAll to access both redeem and deposit totals in a single call.

contracts/orchestrators/InternalStatesOrchestrator.sol (6)

84-109: Well-structured epoch state with proper token tracking.

The addition of tokens array and tokenExists mapping provides efficient O(1) duplicate checking while maintaining iteration order. The parallel arrays for vault portfolios (vaultPortfolioTokens and vaultPortfolioShares) are a reasonable pattern for Solidity.


310-348: Comprehensive epoch state cleanup in _handleStart.

The cleanup logic properly handles:

  1. Token-specific mappings (price, portfolio, orders)
  2. Vault-specific mappings (total assets, portfolio tokens/shares)
  3. The tokens array itself

This prevents stale data from affecting subsequent epochs.


676-684: Clean consolidation of asset getters into single function.

getVaultTotalAssetsAll returns all three values in one call, reducing gas costs for callers that need multiple values. This is a good refactoring pattern.


692-695: New getVaultPortfolio provides clean access to per-vault portfolio data.

This getter enables the LiquidityOrchestrator to retrieve computed portfolio data for each vault during _processSingleVaultOperations.


527-528: Portfolio population uses push to dynamic arrays in mapping.

Each call to _postprocessTransparentMinibatch pushes to vaultPortfolioTokens[vaultAddress] and vaultPortfolioShares[vaultAddress]. Since these are cleared in _handleStart, this is safe. However, ensure that postprocessing is only called once per vault per epoch to avoid duplicate entries.

The minibatch logic should guarantee each vault is processed exactly once. Verify this assumption holds with the minibatch index progression.


419-419: Interface and implementation signatures are already aligned.

The accrueCuratorFees method is consistently defined with a single uint256 feeAmount parameter across IOrionVault (interface), OrionVault (implementation), and all call sites. No action required.

Comment thread contracts/interfaces/IOrionTransparentVault.sol
Comment thread contracts/vaults/OrionTransparentVault.sol

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (6)
contracts/interfaces/IOrionTransparentVault.sol (1)

37-40: Signature and docs look good; consider minor naming alignment.

The updated updateVaultState signature and NatSpec for tokens / shares and newTotalAssets are consistent and match the new portfolio handling model. As a small clarity tweak, consider aligning the shares parameter name with the sharesPerAsset terminology used in getPortfolio (either rename the param or adjust one of the docs) to keep the API surface fully self-consistent.

test/orchestrator/EpochSimulation.test.ts (5)

45-51: Consider using a seeded random number generator for test determinism.

The current implementation uses Math.random(), which produces non-deterministic results. This makes test failures difficult to reproduce and debug, especially in a 10-epoch simulation with 100 assets (1000 random values).

Consider using a seeded PRNG library like seedrandom for reproducible test runs:

import seedrandom from 'seedrandom';

function generateGaussian(mean: number, stdDev: number, rng: () => number): number {
  const u1 = rng();
  const u2 = rng();
  const z0 = Math.sqrt(-2.0 * Math.log(u1)) * Math.cos(2.0 * Math.PI * u2);
  return z0 * stdDev + mean;
}

// In beforeEach:
const rng = seedrandom('test-seed');

// In test:
const gainFactor = generateGaussian(GAIN_MEAN, GAIN_STD_DEV, rng);

272-334: Consider extracting hardcoded phase constants.

The phase numbers (1n, 2n, 3n, 4n) are hardcoded throughout the test. If phase enumeration changes in the contracts, this test will break silently or behave unexpectedly.

Consider defining phase constants at the top of the test or querying them from the contracts if exposed:

// At the top of the test suite
const PHASE_IDLE = 0n;
const PHASE_PREPROCESSING = 1n;
const PHASE_BUFFERING = 2n;
const PHASE_POSTPROCESSING = 3n;
const PHASE_BUILDING_ORDERS = 4n;

const LIQUIDITY_PHASE_SELLING = 1n;
const LIQUIDITY_PHASE_BUYING = 2n;
const LIQUIDITY_PHASE_VAULT_OPERATIONS = 3n;

// Then use in conditions:
while ((await internalStatesOrchestrator.currentPhase()) === PHASE_PREPROCESSING) {
  // ...
}

This makes the test more maintainable and self-documenting.


235-248: Extract duplicate idle-wait logic into a helper function.

The idle-wait pattern is duplicated at lines 235-248 and 337-349, increasing maintenance burden and test length.

Extract the pattern into a reusable helper:

async function waitForSystemIdle() {
  while (!(await orionConfig.isSystemIdle())) {
    let [upkeepNeeded, performData] = await internalStatesOrchestrator.checkUpkeep("0x");
    if (upkeepNeeded) {
      await internalStatesOrchestrator.connect(automationRegistry).performUpkeep(performData);
      continue;
    }

    [upkeepNeeded, performData] = await liquidityOrchestrator.checkUpkeep("0x");
    if (upkeepNeeded) {
      await liquidityOrchestrator.connect(automationRegistry).performUpkeep(performData);
      continue;
    }
  }
}

// Usage:
await waitForSystemIdle();

Also applies to: 337-349


18-21: Consider test performance and organization.

This test deploys 100 mock assets and simulates 10 epochs with extensive phase processing. While comprehensive, it may be slow to execute (potentially several minutes), which could impact CI/CD pipeline performance.

Consider one of the following approaches:

  1. Reduce asset count for faster feedback:

    const NUM_ASSETS = 10; // Reduced for faster test execution
  2. Mark as integration test with longer timeout:

    it("should simulate 10 epochs with Gaussian-distributed gains/losses", async function () {
      this.timeout(300000); // 5 minutes
      // ...
    });
  3. Split into multiple focused tests:

    • One test for basic epoch progression with few assets
    • Separate stress test for 100-asset scenario (run less frequently)

This maintains test value while improving developer experience during local testing.

Also applies to: 53-212


192-205: Distributing weight remainder improves robustness for varying asset counts.

The vault enforces strict weight sum validation: if (totalWeight != 10 ** config.curatorIntentDecimals()) revert InvalidTotalWeight();. With NUM_ASSETS = 100 and curatorIntentDecimals = 9, the current calculation works correctly since 10^9 divides evenly by 100. However, if asset count changes to any non-divisor of 10^9, the test will fail.

Apply this refactor to handle remainders:

   const intentFactor = 10 ** curatorIntentDecimals;
   const weightPerAsset = Math.floor(intentFactor / NUM_ASSETS);
+  const remainder = intentFactor - (weightPerAsset * NUM_ASSETS);
   const intent = [];
 
   for (let i = 0; i < NUM_ASSETS; i++) {
     intent.push({
       token: await mockAssets[i].getAddress(),
-      weight: weightPerAsset,
+      weight: weightPerAsset + (i < remainder ? 1 : 0),
     });
   }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2d9eff and 06f67ea.

📒 Files selected for processing (2)
  • contracts/interfaces/IOrionTransparentVault.sol (1 hunks)
  • test/orchestrator/EpochSimulation.test.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Sourcery review
  • GitHub Check: Build, Lint and Test

Comment thread test/orchestrator/EpochSimulation.test.ts Outdated
Comment thread test/orchestrator/EpochSimulation.test.ts Outdated
Comment thread test/orchestrator/EpochSimulation.test.ts Outdated
@codecov

codecov Bot commented Dec 15, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.87500% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ts/execution/OrionAssetERC4626ExecutionAdapter.sol 85.71% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

@matteoettam09
matteoettam09 merged commit 6ff5a8d into main Dec 15, 2025
4 of 5 checks passed
@matteoettam09
matteoettam09 deleted the dev branch December 15, 2025 19:55
@coderabbitai coderabbitai Bot mentioned this pull request Jan 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants