-
Notifications
You must be signed in to change notification settings - Fork 70
Add OrvexCL PancakeInfinity fork to Robinhood #621
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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,10 +189,7 @@ library UnsafePancakeInfinityBinPoolManager { | |
| } | ||
| } | ||
|
|
||
| IPancakeInfinityBinPoolManager constant BIN_MANAGER = | ||
| IPancakeInfinityBinPoolManager(0xC697d2898e0D09264376196696c51D7aBbbAA4a9); | ||
|
|
||
| abstract contract PancakeInfinity is SettlerSwapAbstract { | ||
| abstract contract PancakeInfinityBase is SettlerSwapAbstract { | ||
| using UnsafeMath for uint256; | ||
| using UnsafeMath for int256; | ||
| using Ternary for bool; | ||
|
|
@@ -214,6 +206,8 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { | |
| assert(address(ETH_ADDRESS) == NotesLib.ETH_ADDRESS); | ||
| } | ||
|
|
||
| function _PANCAKE_INFINITY_VAULT() internal pure virtual returns (address vault); | ||
|
|
||
| //// 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 +273,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 +310,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") { | ||
|
|
@@ -506,33 +506,13 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { | |
|
|
||
| Decoder.overflowCheck(data); | ||
|
|
||
| if (uint256(poolManagerId) == 0) { | ||
| poolKey.poolManager = CL_MANAGER; | ||
|
|
||
| _pancakeInfinitySettleDelta( | ||
| state, | ||
| IPancakeInfinityCLPoolManager(address(poolKey.poolManager)) | ||
| .unsafeSwap(poolKey, zeroForOne, amountSpecified, sqrtPriceLimitX96, hookData), | ||
| zeroForOne | ||
| ); | ||
| } else if (uint256(poolManagerId) == 1) { | ||
| poolKey.poolManager = BIN_MANAGER; | ||
| if (amountSpecified >> 127 != amountSpecified >> 128) { | ||
| Panic.panic(Panic.ARITHMETIC_OVERFLOW); | ||
| } | ||
| _pancakeInfinitySettleDelta( | ||
| state, | ||
| IPancakeInfinityBinPoolManager(address(poolKey.poolManager)) | ||
| .unsafeSwap(poolKey, zeroForOne, int128(amountSpecified), hookData), | ||
| zeroForOne | ||
| ); | ||
| } else { | ||
| assembly ("memory-safe") { | ||
| mstore(0x00, 0x0a9a7da6) // selector for `UnknownPoolManagerId(uint8)` | ||
| mstore(0x20, and(0xff, poolManagerId)) | ||
| revert(0x1c, 0x24) | ||
| } | ||
| } | ||
| _pancakeInfinitySettleDelta( | ||
| state, | ||
| _dispatchPancakeInfinity( | ||
| poolManagerId, poolKey, zeroForOne, amountSpecified, sqrtPriceLimitX96, hookData | ||
| ), | ||
| zeroForOne | ||
| ); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -593,4 +573,48 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { | |
| return returndata; | ||
| } | ||
| } | ||
|
|
||
| // Each fork mixin in `pancakeInfinityForks/` defines its binding of pool manager IDs to pool | ||
| // managers by overriding this function with one that routes each recognized ID to | ||
| // `swapToClManager` or `swapToBinManager` with the appropriate pool manager's address, and | ||
| // calls `revertUnknownPoolManagerId` otherwise. A fork that lacks one of the pool manager | ||
| // types simply omits that route, which also omits the corresponding swap code from the | ||
| // compiled contract. | ||
| function _dispatchPancakeInfinity( | ||
| uint8 poolManagerId, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When possible, types should be widened to a full word to avoid |
||
| PoolKey memory poolKey, | ||
| bool zeroForOne, | ||
| int256 amountSpecified, | ||
| uint160 sqrtPriceLimitX96, | ||
| bytes calldata hookData | ||
| ) internal virtual returns (BalanceDelta); | ||
|
|
||
| function swapToClManager( | ||
| address clManager, | ||
| PoolKey memory poolKey, | ||
| bool zeroForOne, | ||
| int256 amountSpecified, | ||
| uint160 sqrtPriceLimitX96, | ||
| bytes calldata hookData | ||
| ) internal returns (BalanceDelta) { | ||
| poolKey.poolManager = IPancakeInfinityPoolManager(clManager); | ||
| return IPancakeInfinityCLPoolManager(clManager) | ||
| .unsafeSwap(poolKey, zeroForOne, amountSpecified, sqrtPriceLimitX96, hookData); | ||
| } | ||
|
|
||
| function swapToBinManager( | ||
| address binManager, | ||
| PoolKey memory poolKey, | ||
| bool zeroForOne, | ||
| int256 amountSpecified, | ||
| bytes calldata hookData | ||
| ) internal returns (BalanceDelta) { | ||
| poolKey.poolManager = IPancakeInfinityPoolManager(binManager); | ||
| if (amountSpecified >> 127 != amountSpecified >> 128) { | ||
| Panic.panic(Panic.ARITHMETIC_OVERFLOW); | ||
| } | ||
| return | ||
| IPancakeInfinityBinPoolManager(binManager) | ||
| .unsafeSwap(poolKey, zeroForOne, int128(amountSpecified), hookData); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.25; | ||
|
|
||
| import {PancakeInfinityBase, PoolKey} from "../PancakeInfinity.sol"; | ||
| import {BalanceDelta} from "../UniswapV4Types.sol"; | ||
| import {revertUnknownPoolManagerId} from "../SettlerErrors.sol"; | ||
|
|
||
| address constant orvexVault = 0xFe7E25dE55e5cBbEcCcb661F3679F873f72B9b0D; | ||
| address constant orvexClManager = 0xd01C774d4A66408326Bc65728Ac5Ae5aAf004032; | ||
|
|
||
| abstract contract OrvexCL is PancakeInfinityBase { | ||
| function _PANCAKE_INFINITY_VAULT() internal pure override returns (address) { | ||
| return orvexVault; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should check if |
||
| } | ||
|
|
||
| function _dispatchPancakeInfinity( | ||
| uint8 poolManagerId, | ||
| PoolKey memory poolKey, | ||
| bool zeroForOne, | ||
| int256 amountSpecified, | ||
| uint160 sqrtPriceLimitX96, | ||
| bytes calldata hookData | ||
| ) internal override returns (BalanceDelta) { | ||
| if (poolManagerId == 0) { | ||
| return swapToClManager(orvexClManager, poolKey, zeroForOne, amountSpecified, sqrtPriceLimitX96, hookData); | ||
| } else { | ||
| revertUnknownPoolManagerId(poolManagerId); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.25; | ||
|
|
||
| import {PancakeInfinityBase, PoolKey} from "../PancakeInfinity.sol"; | ||
| import {BalanceDelta} from "../UniswapV4Types.sol"; | ||
| import {revertUnknownPoolManagerId} from "../SettlerErrors.sol"; | ||
|
|
||
| address constant pancakeInfinityVault = 0x238a358808379702088667322f80aC48bAd5e6c4; | ||
| address constant pancakeInfinityClManager = 0xa0FfB9c1CE1Fe56963B0321B32E7A0302114058b; | ||
| address constant pancakeInfinityBinManager = 0xC697d2898e0D09264376196696c51D7aBbbAA4a9; | ||
|
|
||
| abstract contract PancakeInfinity is PancakeInfinityBase { | ||
| function _PANCAKE_INFINITY_VAULT() internal pure override returns (address) { | ||
| return pancakeInfinityVault; | ||
| } | ||
|
|
||
| function _dispatchPancakeInfinity( | ||
| uint8 poolManagerId, | ||
| PoolKey memory poolKey, | ||
| bool zeroForOne, | ||
| int256 amountSpecified, | ||
| uint160 sqrtPriceLimitX96, | ||
| bytes calldata hookData | ||
| ) internal override returns (BalanceDelta) { | ||
| if (poolManagerId == 0) { | ||
| return swapToClManager( | ||
| pancakeInfinityClManager, poolKey, zeroForOne, amountSpecified, sqrtPriceLimitX96, hookData | ||
| ); | ||
| } else if (poolManagerId == 1) { | ||
| return swapToBinManager(pancakeInfinityBinManager, poolKey, zeroForOne, amountSpecified, hookData); | ||
| } else { | ||
| revertUnknownPoolManagerId(poolManagerId); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The risk with this pattern is that it invites more flexibility in the mixin than in required to get this feature functional. Instead of allowing the mixin arbitrary flexibility in
_pancakeInfinitySettleDeltato call back into the base'sswapToClManagerandswapToBinManager(inversion of control) having avirtual purefunction that simply returns the address of the CL manager or Bin manager (or revert) removes the footgun and (potentially, should be measured) improvessolc's ability to optimize.I would expect that that change would also improve the amount of boilerplate required, potentially allowing us to move the vault/manager address selection into the chain-specific mixin. Of course, that totally breaks everything if there are 2 PancakeInfinity forks on the same chain