Skip to content
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

EulerSwap - a la uni-v2 integration - aborted #1

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
Prev Previous commit
Next Next commit
init tests
  • Loading branch information
haythemsellami committed Feb 14, 2025
commit 0db4463f273565b78dcd57b0d32da25f0cc0674e
118 changes: 80 additions & 38 deletions evm/src/euler-swap/EulerSwapAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ contract EulerSwapAdapter is ISwapAdapter {
uint256[] memory specifiedAmounts
) external view override returns (Fraction[] memory prices) {
prices = new Fraction[](specifiedAmounts.length);

IMaglevEulerSwap pool = IMaglevEulerSwap(address(bytes20(poolId)));
for (uint256 i = 0; i < specifiedAmounts.length; i++) {
prices[i] = quoteExactInput(pool, sellToken, buyToken, specifiedAmounts[i]);
prices[i] =
quoteExactInput(pool, sellToken, buyToken, specifiedAmounts[i]);
}
}

Expand All @@ -45,24 +46,30 @@ contract EulerSwapAdapter is ISwapAdapter {
uint256 amountIn;
uint256 amountOut;
if (side == OrderSide.Buy) {
amountIn = (quoteExactOutput(pool, sellToken, buyToken, specifiedAmount).denominator);
amountIn = (
quoteExactOutput(pool, sellToken, buyToken, specifiedAmount)
.denominator
);
trade.calculatedAmount = amountOut = specifiedAmount;
} else {
trade.calculatedAmount = amountIn = specifiedAmount;
amountOut =
(quoteExactInput(pool, sellToken, buyToken, specifiedAmount).numerator);
amountOut = (
quoteExactInput(pool, sellToken, buyToken, specifiedAmount)
.numerator
);
}

IERC20(sellToken).safeTransferFrom(
msg.sender, address(pool), amountIn
);
IERC20(sellToken).safeTransferFrom(msg.sender, address(pool), amountIn);

uint256 gasBefore = gasleft();
(isAmountOutAsset0) ? pool.swap(amountOut, 0, msg.sender, "") : pool.swap(0, amountOut, msg.sender, "");
(isAmountOutAsset0)
? pool.swap(amountOut, 0, msg.sender, "")
: pool.swap(0, amountOut, msg.sender, "");
trade.gasUsed = gasBefore - gasleft();

if (side == OrderSide.Buy) {
trade.price = quoteExactOutput(pool, sellToken, buyToken, specifiedAmount);
trade.price =
quoteExactOutput(pool, sellToken, buyToken, specifiedAmount);
} else {
trade.price =
quoteExactInput(pool, sellToken, buyToken, specifiedAmount);
Expand All @@ -71,25 +78,30 @@ contract EulerSwapAdapter is ISwapAdapter {

/// @inheritdoc ISwapAdapter
function getLimits(bytes32 poolId, address sellToken, address buyToken)
external view override
returns (uint256[] memory limits) {
limits = new uint256[](2);
external
view
override
returns (uint256[] memory limits)
{
limits = new uint256[](2);

IMaglevEulerSwap pool = IMaglevEulerSwap(address(bytes20(poolId)));
address swapAccount = pool.myAccount();
(address token0, address token1) = (sellToken < buyToken) ? (sellToken, buyToken) : (buyToken, sellToken);
IMaglevEulerSwap pool = IMaglevEulerSwap(address(bytes20(poolId)));
address swapAccount = pool.myAccount();
(address token0, address token1) = (sellToken < buyToken)
? (sellToken, buyToken)
: (buyToken, sellToken);

if(token0 == buyToken) {
// max amount for buyToken
uint256 maxWithdraw = vaultBalance(pool.vault0(), swapAccount);
if (token0 == buyToken) {
// max amount for buyToken
uint256 maxWithdraw = vaultBalance(pool.vault0(), swapAccount);

limits[1] = maxWithdraw;
} else {
// max amount for buyToken
uint256 maxWithdraw = vaultBalance(pool.vault1(), swapAccount);
limits[1] = maxWithdraw;
} else {
// max amount for buyToken
uint256 maxWithdraw = vaultBalance(pool.vault1(), swapAccount);

limits[1] = maxWithdraw;
}
limits[1] = maxWithdraw;
}
}

/// @inheritdoc ISwapAdapter
Expand Down Expand Up @@ -142,8 +154,9 @@ contract EulerSwapAdapter is ISwapAdapter {
address tokenOut,
uint256 amountIn
) internal view returns (Fraction memory calculatedPrice) {
calculatedPrice =
Fraction(pool.quoteExactInput(tokenIn, tokenOut, amountIn), amountIn);
calculatedPrice = Fraction(
pool.quoteExactInput(tokenIn, tokenOut, amountIn), amountIn
);
}

function quoteExactOutput(
Expand All @@ -152,11 +165,16 @@ contract EulerSwapAdapter is ISwapAdapter {
address tokenOut,
uint256 amountOut
) internal view returns (Fraction memory calculatedPrice) {
calculatedPrice =
Fraction(amountOut, pool.quoteExactOutput(tokenIn, tokenOut, amountOut));
calculatedPrice = Fraction(
amountOut, pool.quoteExactOutput(tokenIn, tokenOut, amountOut)
);
}

function vaultBalance(address vault, address swapAccount) internal view returns (uint256) {
function vaultBalance(address vault, address swapAccount)
internal
view
returns (uint256)
{
uint256 shares = IEVault(vault).balanceOf(swapAccount);

return shares == 0 ? 0 : IEVault(vault).convertToAssets(shares);
Expand All @@ -166,8 +184,13 @@ contract EulerSwapAdapter is ISwapAdapter {
}

interface IMaglevEulerSwapFactory {
event PoolDeployed(address indexed asset0, address indexed asset1, uint256 indexed feeMultiplier, address pool);

event PoolDeployed(
address indexed asset0,
address indexed asset1,
uint256 indexed feeMultiplier,
address pool
);

function deployPool(
address vault0,
address vault1,
Expand All @@ -183,17 +206,36 @@ interface IMaglevEulerSwapFactory {

function evc() external view returns (address);
function allPools(uint256 index) external view returns (address);
function getPool(address assetA, address assetB, uint256 fee) external view returns (address);
function getPool(address assetA, address assetB, uint256 fee)
external
view
returns (address);
function allPoolsLength() external view returns (uint256);
function getAllPoolsListSlice(uint256 start, uint256 end) external view returns (address[] memory);
function getAllPoolsListSlice(uint256 start, uint256 end)
external
view
returns (address[] memory);
}

interface IMaglevEulerSwap {
// IMaglevBase
function configure() external;
function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;
function quoteExactInput(address tokenIn, address tokenOut, uint256 amountIn) external view returns (uint256);
function quoteExactOutput(address tokenIn, address tokenOut, uint256 amountOut) external view returns (uint256);
function swap(
uint256 amount0Out,
uint256 amount1Out,
address to,
bytes calldata data
) external;
function quoteExactInput(
address tokenIn,
address tokenOut,
uint256 amountIn
) external view returns (uint256);
function quoteExactOutput(
address tokenIn,
address tokenOut,
uint256 amountOut
) external view returns (uint256);

function vault0() external view returns (address);
function vault1() external view returns (address);
Expand All @@ -218,4 +260,4 @@ interface IEVault {
function balanceOf(address account) external view returns (uint256);
function convertToAssets(uint256 shares) external view returns (uint256);
function maxWithdraw(address owner) external view returns (uint256);
}
}
42 changes: 42 additions & 0 deletions evm/test/EulerSwapAdapter.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.13;

import "./AdapterTest.sol";
import {EulerSwapAdapter, IERC20} from "src/euler-swap/EulerSwapAdapter.sol";
import {FractionMath} from "src/libraries/FractionMath.sol";

contract EulerSwapAdapterTest is AdapterTest {
using FractionMath for Fraction;

EulerSwapAdapter adapter;
address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;

function setUp() public {
uint256 forkBlock = 21845705;
vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock);
adapter =
new EulerSwapAdapter(0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f);

vm.label(address(adapter), "EulerSwapAdapter");
vm.label(WETH, "WETH");
vm.label(USDC, "USDC");
}

function testGetCapabilities(
bytes32 poolId,
address sellToken,
address buyToken
) public view {
Capability[] memory res =
adapter.getCapabilities(poolId, sellToken, buyToken);

assertEq(res.length, 3);
}

// function testGetLimits() public {
// bytes32 pair = bytes32(bytes20(USDC_WETH_POOL));
// uint256[] memory limits = adapter.getLimits(pair, USDC, WETH);
// assertEq(limits.length, 2);
// }
}