diff --git a/.gitmodules b/.gitmodules index cc50581..6c9874d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,6 +4,3 @@ [submodule "lib/openzeppelin-contracts"] path = evm/lib/openzeppelin-contracts url = https://github.com/OpenZeppelin/openzeppelin-contracts -[submodule "evm/lib/balancer-v2-monorepo"] - path = evm/lib/balancer-v2-monorepo - url = https://github.com/balancer/balancer-v2-monorepo diff --git a/evm/lib/balancer-v2-monorepo b/evm/lib/balancer-v2-monorepo deleted file mode 160000 index c7d4abb..0000000 --- a/evm/lib/balancer-v2-monorepo +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c7d4abbea39834e7778f9ff7999aaceb4e8aa048 diff --git a/evm/remappings.txt b/evm/remappings.txt index 2c8eb8b..5df14d4 100644 --- a/evm/remappings.txt +++ b/evm/remappings.txt @@ -1,4 +1,4 @@ -interfaces/=src/interfaces/ forge-std/=lib/forge-std/src/ openzeppelin-contracts/=lib/openzeppelin-contracts/ -src/=src/ \ No newline at end of file +src/=src/ +balancer-v2/interfaces/=lib/balancer-v2-monorepo/pkg/interfaces/contracts diff --git a/evm/src/balancer-v2/BalancerV2SwapAdapter.sol b/evm/src/balancer-v2/BalancerV2SwapAdapter.sol index 3175f32..da182f6 100644 --- a/evm/src/balancer-v2/BalancerV2SwapAdapter.sol +++ b/evm/src/balancer-v2/BalancerV2SwapAdapter.sol @@ -1,19 +1,67 @@ // SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.13; -import {IERC20, ISwapAdapter} from "interfaces/ISwapAdapter.sol"; +import {IERC20, ISwapAdapter} from "src/interfaces/ISwapAdapter.sol"; -contract BalancerV2SwapAdapter is ISwapAdapter { +interface IVault { + function getPoolTokens(bytes32 poolId) + external + view + returns ( + IERC20[] memory tokens, + uint256[] memory balances, + uint256 lastChangeBlock + ); - constructor() { + function swap( + SingleSwap memory singleSwap, + FundManagement memory funds, + uint256 limit, + uint256 deadline + ) external payable returns (uint256); + + function queryBatchSwap( + SwapKind kind, + BatchSwapStep[] memory swaps, + IAsset[] memory assets, + FundManagement memory funds + ) external returns (int256[] memory assetDeltas); + + struct SingleSwap { + bytes32 poolId; + SwapKind kind; + IAsset assetIn; + IAsset assetOut; + uint256 amount; + bytes userData; } - function getPairReserves( - bytes32 pairId, - IERC20 sellToken, - IERC20 buyToken - ) internal view returns (uint112 r0, uint112 r1) { - revert NotImplemented("BalancerV2SwapAdapter.getPairReserves"); + struct BatchSwapStep { + bytes32 poolId; + uint256 assetInIndex; + uint256 assetOutIndex; + uint256 amount; + bytes userData; + } + + struct FundManagement { + address sender; + bool fromInternalBalance; + address payable recipient; + bool toInternalBalance; + } + + enum SwapKind { GIVEN_IN, GIVEN_OUT } +} + +interface IAsset is IERC20 { +} + +contract BalancerV2SwapAdapter is ISwapAdapter { + IVault immutable vault; + + constructor(address vault_) { + vault = IVault(vault_); } function price( @@ -49,7 +97,7 @@ contract BalancerV2SwapAdapter is ISwapAdapter { override returns (uint256[] memory limits) { - revert NotImplemented("BalancerV2SwapAdapter.getLimits"); + (, limits, ) = vault.getPoolTokens(pairId); } function getCapabilities(bytes32, IERC20, IERC20) @@ -73,6 +121,7 @@ contract BalancerV2SwapAdapter is ISwapAdapter { revert NotImplemented("BalancerV2SwapAdapter.getTokens"); } + /// @dev Balancer V2 does not support listing pools. function getPoolIds(uint256 offset, uint256 limit) external view diff --git a/evm/src/interfaces/ISwapAdapter.sol b/evm/src/interfaces/ISwapAdapter.sol index 1714bc7..bc7ebe4 100644 --- a/evm/src/interfaces/ISwapAdapter.sol +++ b/evm/src/interfaces/ISwapAdapter.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.13; import {IERC20} from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; -import {ISwapAdapterTypes} from "interfaces/ISwapAdapterTypes.sol"; +import {ISwapAdapterTypes} from "src/interfaces/ISwapAdapterTypes.sol"; /// @title ISwapAdapter /// @dev Implement this interface to support propeller routing through your diff --git a/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol b/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol index 3345bfc..9d4ef9e 100644 --- a/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol +++ b/evm/src/uniswap-v2/UniswapV2SwapAdapter.sol @@ -1,7 +1,9 @@ // SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.13; -import {IERC20, ISwapAdapter} from "interfaces/ISwapAdapter.sol"; +import {IERC20, ISwapAdapter} from "src/interfaces/ISwapAdapter.sol"; + +uint256 constant RESERVE_LIMIT_FACTOR = 10; contract UniswapV2SwapAdapter is ISwapAdapter { IUniswapV2Factory immutable factory; @@ -170,11 +172,11 @@ contract UniswapV2SwapAdapter is ISwapAdapter { limits = new uint256[](2); (uint256 r0, uint256 r1,) = pair.getReserves(); if (side == SwapSide.Sell) { - limits[0] = r0 * 10; - limits[1] = r1 * 10; + limits[0] = r0 * RESERVE_LIMIT_FACTOR; + limits[1] = r1 * RESERVE_LIMIT_FACTOR; } else { - limits[0] = r1 * 10; - limits[1] = r0 * 10; + limits[0] = r1 * RESERVE_LIMIT_FACTOR; + limits[1] = r0 * RESERVE_LIMIT_FACTOR; } } diff --git a/evm/test/BalancerV2SwapAdapter.t.sol b/evm/test/BalancerV2SwapAdapter.t.sol new file mode 100644 index 0000000..64b955a --- /dev/null +++ b/evm/test/BalancerV2SwapAdapter.t.sol @@ -0,0 +1 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/evm/test/UniswapV2SwapAdapter.t.sol b/evm/test/UniswapV2SwapAdapter.t.sol index d6951c9..f662972 100644 --- a/evm/test/UniswapV2SwapAdapter.t.sol +++ b/evm/test/UniswapV2SwapAdapter.t.sol @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.13; import "forge-std/Test.sol"; import "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import "src/uniswap-v2/UniswapV2SwapAdapter.sol"; -import "interfaces/ISwapAdapterTypes.sol"; +import "src/interfaces/ISwapAdapterTypes.sol"; contract UniswapV2PairFunctionTest is Test, ISwapAdapterTypes { UniswapV2SwapAdapter pairFunctions;