diff --git a/.forge-snapshots/allowanceHolder_empty_Orvex-WETH-NVDA.snap b/.forge-snapshots/allowanceHolder_empty_Orvex-WETH-NVDA.snap new file mode 100644 index 000000000..e147f61e1 --- /dev/null +++ b/.forge-snapshots/allowanceHolder_empty_Orvex-WETH-NVDA.snap @@ -0,0 +1 @@ +8987 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_pancakeInfinityVIP_Orvex-WETH-NVDA.snap b/.forge-snapshots/allowanceHolder_pancakeInfinityVIP_Orvex-WETH-NVDA.snap new file mode 100644 index 000000000..852f8843f --- /dev/null +++ b/.forge-snapshots/allowanceHolder_pancakeInfinityVIP_Orvex-WETH-NVDA.snap @@ -0,0 +1 @@ +240788 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_Orvex-WETH-NVDA.snap b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_Orvex-WETH-NVDA.snap new file mode 100644 index 000000000..fd9576987 --- /dev/null +++ b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_Orvex-WETH-NVDA.snap @@ -0,0 +1 @@ +164248 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_pancakeInfinity_Orvex-WETH-NVDA.snap b/.forge-snapshots/settler_metaTxn_pancakeInfinity_Orvex-WETH-NVDA.snap new file mode 100644 index 000000000..c3d8cd6ac --- /dev/null +++ b/.forge-snapshots/settler_metaTxn_pancakeInfinity_Orvex-WETH-NVDA.snap @@ -0,0 +1 @@ +254306 \ No newline at end of file diff --git a/.forge-snapshots/settler_pancakeInfinityVIP_Orvex-WETH-NVDA.snap b/.forge-snapshots/settler_pancakeInfinityVIP_Orvex-WETH-NVDA.snap new file mode 100644 index 000000000..2329e9f72 --- /dev/null +++ b/.forge-snapshots/settler_pancakeInfinityVIP_Orvex-WETH-NVDA.snap @@ -0,0 +1 @@ +249295 \ No newline at end of file diff --git a/.forge-snapshots/settler_pancakeInfinity_Orvex-WETH-NVDA.snap b/.forge-snapshots/settler_pancakeInfinity_Orvex-WETH-NVDA.snap new file mode 100644 index 000000000..2e84b2dce --- /dev/null +++ b/.forge-snapshots/settler_pancakeInfinity_Orvex-WETH-NVDA.snap @@ -0,0 +1 @@ +276941 \ No newline at end of file diff --git a/.forge-snapshots/settler_rfq_fee_full_custody_Orvex-WETH-NVDA.snap b/.forge-snapshots/settler_rfq_fee_full_custody_Orvex-WETH-NVDA.snap new file mode 100644 index 000000000..d3f82f341 --- /dev/null +++ b/.forge-snapshots/settler_rfq_fee_full_custody_Orvex-WETH-NVDA.snap @@ -0,0 +1 @@ +214851 \ No newline at end of file diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index f8f989c4f..f880cdac9 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -52,6 +52,7 @@ jobs: ARBITRUM_MAINNET_RPC_URL: ${{ secrets.ARBITRUM_MAINNET_RPC_URL }} BASE_MAINNET_RPC_URL: ${{ secrets.BASE_MAINNET_RPC_URL }} MONAD_MAINNET_RPC_URL: ${{ secrets.MONAD_MAINNET_RPC_URL }} + ROBINHOOD_MAINNET_RPC_URL: ${{ secrets.ROBINHOOD_MAINNET_RPC_URL }} - name: Install ArbOS foundry fork run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 024409a44..122482e37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ * Fix a `metaTx` malleability bug in `CrossChainReceiverFactory` (contract is not deployed; no funds at risk) after a report in Immunefi bug 78645 +* Add Orvex CL PancakeInfinity fork to RobinHood chain + * Add `PANCAKE_INFINITY`, `PANCAKE_INFINITY_VIP`, and `METATXN_PANCAKE_INFINITY_VIP` ## 2026-07-27 diff --git a/foundry.toml b/foundry.toml index 95176be1b..4d2ff5c3f 100644 --- a/foundry.toml +++ b/foundry.toml @@ -62,6 +62,7 @@ plasma = "${PLASMA_MAINNET_RPC_URL}" arbitrum = "${ARBITRUM_MAINNET_RPC_URL}" base = "${BASE_MAINNET_RPC_URL}" monad = "${MONAD_MAINNET_RPC_URL}" +robinhood = "${ROBINHOOD_MAINNET_RPC_URL}" [lint] lint_on_build = false diff --git a/src/chains/Base/Common.sol b/src/chains/Base/Common.sol index b9a755b2a..cea079828 100644 --- a/src/chains/Base/Common.sol +++ b/src/chains/Base/Common.sol @@ -11,6 +11,11 @@ import {IPoolManager} from "../../core/UniswapV4Types.sol"; import {EulerSwap, IEVC, IEulerSwap} from "../../core/EulerSwap.sol"; import {BalancerV3} from "../../core/BalancerV3.sol"; import {PancakeInfinity} from "../../core/PancakeInfinity.sol"; +import { + pancakeInfinityVault, + pancakeInfinityClManager, + pancakeInfinityBinManager +} from "../../core/pancakeInfinityForks/PancakeInfinity.sol"; import {Renegade} from "../../core/Renegade.sol"; import {Bebop} from "../../core/Bebop.sol"; import {Hanji} from "../../core/Hanji.sol"; @@ -248,6 +253,18 @@ abstract contract BaseMixin is return BASE_POOL_MANAGER; } + function _PANCAKE_INFINITY_VAULT() internal pure override returns (address) { + return pancakeInfinityVault; + } + + function _PANCAKE_INFINITY_CL_MANAGER() internal pure override returns (address) { + return pancakeInfinityClManager; + } + + function _PANCAKE_INFINITY_BIN_MANAGER() internal pure override returns (address) { + return pancakeInfinityBinManager; + } + /* function _EVC() internal pure override returns (IEVC) { return IEVC(0x5301c7dD20bD945D2013b48ed0DEE3A284ca8989); diff --git a/src/chains/Bnb/Common.sol b/src/chains/Bnb/Common.sol index f997b8c3f..0ef99d975 100644 --- a/src/chains/Bnb/Common.sol +++ b/src/chains/Bnb/Common.sol @@ -10,6 +10,11 @@ import {DodoV2, IDodoV2} from "../../core/DodoV2.sol"; import {UniswapV4} from "../../core/UniswapV4.sol"; import {IPoolManager} from "../../core/UniswapV4Types.sol"; import {PancakeInfinity} from "../../core/PancakeInfinity.sol"; +import { + pancakeInfinityVault, + pancakeInfinityClManager, + pancakeInfinityBinManager +} from "../../core/pancakeInfinityForks/PancakeInfinity.sol"; import {EulerSwap, IEVC, IEulerSwap} from "../../core/EulerSwap.sol"; import {Bebop} from "../../core/Bebop.sol"; @@ -177,6 +182,18 @@ abstract contract BnbMixin is return BNB_POOL_MANAGER; } + function _PANCAKE_INFINITY_VAULT() internal pure override returns (address) { + return pancakeInfinityVault; + } + + function _PANCAKE_INFINITY_CL_MANAGER() internal pure override returns (address) { + return pancakeInfinityClManager; + } + + function _PANCAKE_INFINITY_BIN_MANAGER() internal pure override returns (address) { + return pancakeInfinityBinManager; + } + function _EVC() internal pure override returns (IEVC) { return IEVC(0xb2E5a73CeE08593d1a076a2AE7A6e02925a640ea); } diff --git a/src/chains/RobinHood/Common.sol b/src/chains/RobinHood/Common.sol index b1dc71459..856d02584 100644 --- a/src/chains/RobinHood/Common.sol +++ b/src/chains/RobinHood/Common.sol @@ -12,7 +12,7 @@ import {Hanji} from "../../core/Hanji.sol"; import {ISettlerActions} from "../../ISettlerActions.sol"; import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; -import {revertUnknownForkId} from "../../core/SettlerErrors.sol"; +import {revertUnknownForkId, revertUnknownPoolManagerId} from "../../core/SettlerErrors.sol"; import { uniswapV3RobinhoodFactory, @@ -35,6 +35,8 @@ import {swapHoodV3Factory, swapHoodV3InitHash, swapHoodV3ForkId} from "../../cor import {gigaDexV3Factory, gigaDexV3InitHash, gigaDexV3ForkId} from "../../core/univ3forks/GigaDexV3.sol"; import {IAlgebraCallback} from "../../core/univ3forks/Algebra.sol"; import {ROBINHOOD_POOL_MANAGER} from "../../core/UniswapV4Addresses.sol"; +import {PancakeInfinity} from "../../core/PancakeInfinity.sol"; +import {orvexVault, orvexClManager} from "../../core/pancakeInfinityForks/OrvexCL.sol"; import {FastLogic} from "../../utils/FastLogic.sol"; @@ -42,7 +44,7 @@ import {FastLogic} from "../../utils/FastLogic.sol"; import {SettlerSwapAbstract} from "../../SettlerAbstract.sol"; import {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol"; -abstract contract RobinHoodMixin is FreeMemory, SettlerBase, UniswapV4, EkuboV3, Hanji { +abstract contract RobinHoodMixin is FreeMemory, SettlerBase, UniswapV4, EkuboV3, Hanji, PancakeInfinity { using FastLogic for bool; constructor() { @@ -59,7 +61,8 @@ abstract contract RobinHoodMixin is FreeMemory, SettlerBase, UniswapV4, EkuboV3, if (super._dispatch(i, action, data, slippage)) { return true; } else if ((action == uint32(ISettlerActions.UNISWAPV4.selector)) - .or(action == uint32(ISettlerActions.EKUBOV3.selector))) { + .or(action == uint32(ISettlerActions.EKUBOV3.selector)) + .or(action == uint32(ISettlerActions.PANCAKE_INFINITY.selector))) { ( address recipient, IERC20 sellToken, @@ -73,8 +76,10 @@ abstract contract RobinHoodMixin is FreeMemory, SettlerBase, UniswapV4, EkuboV3, if (action == uint32(ISettlerActions.UNISWAPV4.selector)) { sellToUniswapV4(recipient, sellToken, bps, feeOnTransfer, hashMul, hashMod, fills, amountOutMin); - } else { // if (action == uint32(ISettlerActions.EKUBOV3.selector)) + } else if (action == uint32(ISettlerActions.EKUBOV3.selector)) { sellToEkuboV3(recipient, sellToken, bps, feeOnTransfer, hashMul, hashMod, fills, amountOutMin); + } else { // if (action == uint32(ISettlerActions.PANCAKE_INFINITY.selector)) + sellToPancakeInfinity(recipient, sellToken, bps, feeOnTransfer, hashMul, hashMod, fills, amountOutMin); } } else if (action == uint32(ISettlerActions.HANJI.selector)) { ( @@ -142,6 +147,19 @@ abstract contract RobinHoodMixin is FreeMemory, SettlerBase, UniswapV4, EkuboV3, return ROBINHOOD_POOL_MANAGER; } + function _PANCAKE_INFINITY_VAULT() internal pure override returns (address) { + return orvexVault; + } + + function _PANCAKE_INFINITY_CL_MANAGER() internal pure override returns (address) { + return orvexClManager; + } + + // Orvex does not have a Bin pool manager + function _PANCAKE_INFINITY_BIN_MANAGER() internal pure override returns (address) { + revertUnknownPoolManagerId(1); + } + // I hate Solidity inheritance function _fallback(bytes calldata data) internal diff --git a/src/chains/RobinHood/MetaTxn.sol b/src/chains/RobinHood/MetaTxn.sol index 26ee0e61f..56a6d478d 100644 --- a/src/chains/RobinHood/MetaTxn.sol +++ b/src/chains/RobinHood/MetaTxn.sol @@ -32,7 +32,8 @@ contract RobinHoodSettlerMetaTxn is SettlerMetaTxn, RobinHoodMixin { if (super._dispatchVIP(action, data, sig)) { return true; } else if ((action == uint32(ISettlerActions.METATXN_UNISWAPV4_VIP.selector)) - .or(action == uint32(ISettlerActions.METATXN_EKUBOV3_VIP.selector))) { + .or(action == uint32(ISettlerActions.METATXN_EKUBOV3_VIP.selector)) + .or(action == uint32(ISettlerActions.METATXN_PANCAKE_INFINITY_VIP.selector))) { ( address recipient, ISignatureTransfer.PermitTransferFrom memory permit, @@ -47,8 +48,10 @@ contract RobinHoodSettlerMetaTxn is SettlerMetaTxn, RobinHoodMixin { if (action == uint32(ISettlerActions.METATXN_UNISWAPV4_VIP.selector)) { sellToUniswapV4VIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); - } else { // if (action == uint32(ISettlerActions.METATXN_EKUBOV3_VIP.selector)) + } else if (action == uint32(ISettlerActions.METATXN_EKUBOV3_VIP.selector)) { sellToEkuboV3VIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); + } else { // if (action == uint32(ISettlerActions.METATXN_PANCAKE_INFINITY_VIP.selector)) + sellToPancakeInfinityVIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); } } else { return false; diff --git a/src/chains/RobinHood/TakerSubmitted.sol b/src/chains/RobinHood/TakerSubmitted.sol index 04de48c4c..6c6158272 100644 --- a/src/chains/RobinHood/TakerSubmitted.sol +++ b/src/chains/RobinHood/TakerSubmitted.sol @@ -25,7 +25,8 @@ contract RobinHoodSettler is Settler, RobinHoodMixin { if (super._dispatchVIP(action, data)) { return true; } else if ((action == uint32(ISettlerActions.UNISWAPV4_VIP.selector)) - .or(action == uint32(ISettlerActions.EKUBOV3_VIP.selector))) { + .or(action == uint32(ISettlerActions.EKUBOV3_VIP.selector)) + .or(action == uint32(ISettlerActions.PANCAKE_INFINITY_VIP.selector))) { ( address recipient, ISignatureTransfer.PermitTransferFrom memory permit, @@ -41,8 +42,10 @@ contract RobinHoodSettler is Settler, RobinHoodMixin { if (action == uint32(ISettlerActions.UNISWAPV4_VIP.selector)) { sellToUniswapV4VIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); - } else { // if (action == uint32(ISettlerActions.EKUBOV3_VIP.selector)) + } else if (action == uint32(ISettlerActions.EKUBOV3_VIP.selector)) { sellToEkuboV3VIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); + } else { // if (action == uint32(ISettlerActions.PANCAKE_INFINITY_VIP.selector)) + sellToPancakeInfinityVIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); } } else { return false; diff --git a/src/core/PancakeInfinity.sol b/src/core/PancakeInfinity.sol index 0483e0aee..42175885c 100644 --- a/src/core/PancakeInfinity.sol +++ b/src/core/PancakeInfinity.sol @@ -9,7 +9,7 @@ import {SettlerSwapAbstract} from "../SettlerAbstract.sol"; import {UnsafeMath} from "../utils/UnsafeMath.sol"; import {Panic} from "../utils/Panic.sol"; import {Ternary} from "../utils/Ternary.sol"; -import {ZeroSellAmount, UnknownPoolManagerId} from "./SettlerErrors.sol"; +import {ZeroSellAmount, UnknownPoolManagerId, revertUnknownPoolManagerId} from "./SettlerErrors.sol"; import {CreditDebt, Encoder, NotePtr, NotesLib, State, Decoder, Take} from "./FlashAccountingCommon.sol"; import {BalanceDelta} from "./UniswapV4Types.sol"; @@ -37,8 +37,6 @@ interface IPancakeInfinityVault { function lock(bytes calldata data) external returns (bytes memory); } -IPancakeInfinityVault constant VAULT = IPancakeInfinityVault(0x238a358808379702088667322f80aC48bAd5e6c4); - /// @notice Interface for the callback executed when an address locks the vault interface IPancakeInfinityLockCallback { /// @notice Called by the pool manager on `msg.sender` when a lock is acquired @@ -92,9 +90,6 @@ interface IPancakeInfinityCLPoolManager is IPancakeInfinityPoolManager { returns (BalanceDelta delta); } -IPancakeInfinityCLPoolManager constant CL_MANAGER = - IPancakeInfinityCLPoolManager(0xa0FfB9c1CE1Fe56963B0321B32E7A0302114058b); - interface IPancakeInfinityBinPoolManager is IPancakeInfinityPoolManager { /// @notice Peform a swap to a pool /// @param key The pool key @@ -194,9 +189,6 @@ library UnsafePancakeInfinityBinPoolManager { } } -IPancakeInfinityBinPoolManager constant BIN_MANAGER = - IPancakeInfinityBinPoolManager(0xC697d2898e0D09264376196696c51D7aBbbAA4a9); - abstract contract PancakeInfinity is SettlerSwapAbstract { using UnsafeMath for uint256; using UnsafeMath for int256; @@ -214,6 +206,14 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { assert(address(ETH_ADDRESS) == NotesLib.ETH_ADDRESS); } + function _PANCAKE_INFINITY_VAULT() internal pure virtual returns (address); + + // A chain hosting a fork that lacks CL_MANAGER must unconditionally call `revertUnknownPoolManagerId(0)` + function _PANCAKE_INFINITY_CL_MANAGER() internal pure virtual returns (address); + + // A chain hosting a fork that lacks BIN_MANAGER must unconditionally call `revertUnknownPoolManagerId(1)` + function _PANCAKE_INFINITY_BIN_MANAGER() internal pure virtual returns (address); + //// How to generate `fills` for Pancake Infinity: //// //// Linearize your DAG of fills by doing a topological sort on the tokens involved. In the @@ -279,7 +279,10 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { amountOutMin ); bytes memory encodedBuyAmount = _setOperatorAndCall( - address(VAULT), data, uint32(IPancakeInfinityLockCallback.lockAcquired.selector), _pancakeInfinityCallback + _PANCAKE_INFINITY_VAULT(), + data, + uint32(IPancakeInfinityLockCallback.lockAcquired.selector), + _pancakeInfinityCallback ); // buyAmount = abi.decode(abi.decode(encodedBuyAmount, (bytes)), (uint256)); assembly ("memory-safe") { @@ -313,7 +316,10 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { amountOutMin ); bytes memory encodedBuyAmount = _setOperatorAndCall( - address(VAULT), data, uint32(IPancakeInfinityLockCallback.lockAcquired.selector), _pancakeInfinityCallback + _PANCAKE_INFINITY_VAULT(), + data, + uint32(IPancakeInfinityLockCallback.lockAcquired.selector), + _pancakeInfinityCallback ); // buyAmount = abi.decode(abi.decode(encodedBuyAmount, (bytes)), (uint256)); assembly ("memory-safe") { @@ -475,7 +481,7 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { } { - uint8 poolManagerId; + uint256 poolManagerId; assembly ("memory-safe") { poolManagerId := shr(0xf8, calldataload(data.offset)) data.offset := add(0x01, data.offset) @@ -506,8 +512,8 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { Decoder.overflowCheck(data); - if (uint256(poolManagerId) == 0) { - poolKey.poolManager = CL_MANAGER; + if (poolManagerId == 0) { + poolKey.poolManager = IPancakeInfinityPoolManager(_PANCAKE_INFINITY_CL_MANAGER()); _pancakeInfinitySettleDelta( state, @@ -515,8 +521,8 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { .unsafeSwap(poolKey, zeroForOne, amountSpecified, sqrtPriceLimitX96, hookData), zeroForOne ); - } else if (uint256(poolManagerId) == 1) { - poolKey.poolManager = BIN_MANAGER; + } else if (poolManagerId == 1) { + poolKey.poolManager = IPancakeInfinityPoolManager(_PANCAKE_INFINITY_BIN_MANAGER()); if (amountSpecified >> 127 != amountSpecified >> 128) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); } @@ -527,11 +533,7 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { zeroForOne ); } else { - assembly ("memory-safe") { - mstore(0x00, 0x0a9a7da6) // selector for `UnknownPoolManagerId(uint8)` - mstore(0x20, and(0xff, poolManagerId)) - revert(0x1c, 0x24) - } + revertUnknownPoolManagerId(poolManagerId); } } } diff --git a/src/core/SettlerErrors.sol b/src/core/SettlerErrors.sol index 2029d2fb0..4ae56de38 100644 --- a/src/core/SettlerErrors.sol +++ b/src/core/SettlerErrors.sol @@ -126,6 +126,14 @@ error NotConverged(); /// the list of recognized pool managers. error UnknownPoolManagerId(uint8 poolManagerId); +function revertUnknownPoolManagerId(uint256 poolManagerId) pure { + assembly ("memory-safe") { + mstore(0x00, 0x0a9a7da6) // selector for `UnknownPoolManagerId(uint8)` + mstore(0x20, and(0xff, poolManagerId)) + revert(0x1c, 0x24) + } +} + /// @notice Thrown when the `msg.value` is less than the minimum expected value. error Underpayment(uint256 msgValueMin, uint256 msgValueActual); diff --git a/src/core/pancakeInfinityForks/OrvexCL.sol b/src/core/pancakeInfinityForks/OrvexCL.sol new file mode 100644 index 000000000..613e0667a --- /dev/null +++ b/src/core/pancakeInfinityForks/OrvexCL.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +// Orvex is a fork of PancakeSwap Infinity without the Bin pool manager +address constant orvexVault = 0xFe7E25dE55e5cBbEcCcb661F3679F873f72B9b0D; +address constant orvexClManager = 0xd01C774d4A66408326Bc65728Ac5Ae5aAf004032; diff --git a/src/core/pancakeInfinityForks/PancakeInfinity.sol b/src/core/pancakeInfinityForks/PancakeInfinity.sol new file mode 100644 index 000000000..ce00ba59c --- /dev/null +++ b/src/core/pancakeInfinityForks/PancakeInfinity.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +address constant pancakeInfinityVault = 0x238a358808379702088667322f80aC48bAd5e6c4; +address constant pancakeInfinityClManager = 0xa0FfB9c1CE1Fe56963B0321B32E7A0302114058b; +address constant pancakeInfinityBinManager = 0xC697d2898e0D09264376196696c51D7aBbbAA4a9; diff --git a/test/integration/OrvexCL.t.sol b/test/integration/OrvexCL.t.sol new file mode 100644 index 000000000..80602d1db --- /dev/null +++ b/test/integration/OrvexCL.t.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import {IERC20} from "@forge-std/interfaces/IERC20.sol"; + +import {RobinHoodSettler} from "src/chains/RobinHood/TakerSubmitted.sol"; +import {RobinHoodSettlerMetaTxn} from "src/chains/RobinHood/MetaTxn.sol"; +import {orvexVault, orvexClManager} from "src/core/pancakeInfinityForks/OrvexCL.sol"; + +import {PancakeInfinityTest} from "./PancakeInfinity.t.sol"; + +abstract contract OrvexCLTest is PancakeInfinityTest { + function _testBlockNumber() internal pure override returns (uint256) { + return 30443000; + } + + function _testChainId() internal pure override returns (string memory) { + return "robinhood"; + } + + function settlerInitCode() internal override returns (bytes memory) { + return bytes.concat(type(RobinHoodSettler).creationCode, abi.encode(bytes20(0))); + } + + function settlerMetaTxnInitCode() internal override returns (bytes memory) { + return bytes.concat(type(RobinHoodSettlerMetaTxn).creationCode, abi.encode(bytes20(0))); + } + + function vault() internal pure override returns (address) { + return orvexVault; + } + + function clPoolManager() internal pure override returns (address) { + return orvexClManager; + } + + // Orvex does not have a Bin pool manager + function binPoolManager() internal pure override returns (address) { + return address(0); + } +} + +contract OrvexWETHNVDATest is OrvexCLTest { + function _testName() internal pure override returns (string memory) { + return "Orvex-WETH-NVDA"; + } + + function fromToken() internal pure override returns (IERC20) { + return IERC20(0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73); // WETH + } + + function toToken() internal pure override returns (IERC20) { + return IERC20(0xd0601CE157Db5bdC3162BbaC2a2C8aF5320D9EEC); // NVDA + } + + function poolId() internal view virtual override returns (bytes32) { + return bytes32(0x257df135116403937e4b04b22b796e6746d965090fef574b684c9c294c542490); + } + + function amount() internal view virtual override returns (uint256) { + return 0.1 ether; + } +} diff --git a/test/integration/PancakeInfinity.t.sol b/test/integration/PancakeInfinity.t.sol index 656e9a5fc..02e11418f 100644 --- a/test/integration/PancakeInfinity.t.sol +++ b/test/integration/PancakeInfinity.t.sol @@ -20,15 +20,12 @@ import {tmp} from "src/utils/512Math.sol"; import {SettlerMetaTxnPairTest} from "./SettlerMetaTxnPairTest.t.sol"; import {AllowanceHolderPairTest} from "./AllowanceHolderPairTest.t.sol"; +import {PoolKey, PoolId, IPancakeInfinityPoolManager} from "src/core/PancakeInfinity.sol"; import { - PancakeInfinity, - PoolKey, - VAULT, - CL_MANAGER, - BIN_MANAGER, - PoolId, - IPancakeInfinityPoolManager -} from "src/core/PancakeInfinity.sol"; + pancakeInfinityVault, + pancakeInfinityClManager, + pancakeInfinityBinManager +} from "src/core/pancakeInfinityForks/PancakeInfinity.sol"; interface IPancakeInfinityCLPoolManagerSlot0 { function getSlot0(bytes32 poolId) external view returns (uint160 sqrtPriceX96); @@ -89,10 +86,22 @@ abstract contract PancakeInfinityTest is AllowanceHolderPairTest, SettlerMetaTxn } } + function vault() internal pure virtual returns (address) { + return pancakeInfinityVault; + } + + function clPoolManager() internal pure virtual returns (address) { + return pancakeInfinityClManager; + } + + function binPoolManager() internal pure virtual returns (address) { + return pancakeInfinityBinManager; + } + function _setPancakeInfinityLabels() private { - vm.label(address(VAULT), "Vault"); - vm.label(address(CL_MANAGER), "CLPoolManager"); - vm.label(address(BIN_MANAGER), "BINPoolManager"); + vm.label(vault(), "Vault"); + vm.label(clPoolManager(), "CLPoolManager"); + vm.label(binPoolManager(), "BINPoolManager"); } function _readSlot0Cold(bytes32 poolId_) private view returns (uint160 sqrtPriceX96) { @@ -105,7 +114,7 @@ abstract contract PancakeInfinityTest is AllowanceHolderPairTest, SettlerMetaTxn } function _readSlot0AndRevert(bytes32 poolId_) external view { - uint160 sqrtPriceX96 = IPancakeInfinityCLPoolManagerSlot0(address(CL_MANAGER)).getSlot0(poolId_); + uint160 sqrtPriceX96 = IPancakeInfinityCLPoolManagerSlot0(clPoolManager()).getSlot0(poolId_); assembly ("memory-safe") { mstore(0x00, sqrtPriceX96) revert(0x00, 0x20) @@ -138,10 +147,8 @@ abstract contract PancakeInfinityTest is AllowanceHolderPairTest, SettlerMetaTxn function pancakeInfinityFills(IERC20 fromToken, IERC20 toToken) internal view virtual returns (bytes memory) { bytes32 poolId_ = poolId(); uint8 managerId = poolManagerId(); - PoolKey memory poolKey = (managerId == 0 - ? IPancakeInfinityPoolManager(CL_MANAGER) - : IPancakeInfinityPoolManager(BIN_MANAGER)) - .poolIdToPoolKey(PoolId.wrap(poolId_)); + PoolKey memory poolKey = IPancakeInfinityPoolManager(managerId == 0 ? clPoolManager() : binPoolManager()) + .poolIdToPoolKey(PoolId.wrap(poolId_)); return abi.encodePacked( uint16(10_000),