From a6f19a1f12701cd55940b4d39e0ec8c7d2e31a95 Mon Sep 17 00:00:00 2001 From: Jaskaran Singh Date: Sat, 8 Feb 2025 16:52:45 +0530 Subject: [PATCH] added arbitrage --- src/Vault.sol | 152 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 116 insertions(+), 36 deletions(-) diff --git a/src/Vault.sol b/src/Vault.sol index 68661fb..fd92aab 100644 --- a/src/Vault.sol +++ b/src/Vault.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.22; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "./LiquidityManager.sol"; +import {ArbitrageContract} from "./Arbitrage.sol"; /** * @title Vault @@ -13,7 +14,7 @@ import "./LiquidityManager.sol"; * @dev It allows users to deposit and withdraw ERC20 tokens. * @dev It also allows users to get their balance of a specific token. */ -contract Vault is Ownable, LiquidityManager { +contract Vault is Ownable, LiquidityManager, ArbitrageContract { /// @notice The agent address is the address that can call the liquidity functions. address public agent; @@ -35,14 +36,17 @@ contract Vault is Ownable, LiquidityManager { error AerodromeNotImplemented(); modifier onlyAgent() { - require(msg.sender == agent || msg.sender == owner(), "Only agent or owner"); + require( + msg.sender == agent || msg.sender == owner(), + "Only agent or owner" + ); _; } modifier validLendingProtocol(string memory protocol) { if ( - keccak256(bytes(protocol)) != keccak256(bytes("aave")) - && keccak256(bytes(protocol)) != keccak256(bytes("compound")) + keccak256(bytes(protocol)) != keccak256(bytes("aave")) && + keccak256(bytes(protocol)) != keccak256(bytes("compound")) ) { revert InvalidProtocol(protocol); } @@ -51,8 +55,8 @@ contract Vault is Ownable, LiquidityManager { modifier validLPProtocol(string memory protocol) { if ( - keccak256(bytes(protocol)) != keccak256(bytes("uniswap")) - && keccak256(bytes(protocol)) != keccak256(bytes("aerodrome")) + keccak256(bytes(protocol)) != keccak256(bytes("uniswap")) && + keccak256(bytes(protocol)) != keccak256(bytes("aerodrome")) ) { revert InvalidProtocol(protocol); } @@ -74,7 +78,15 @@ contract Vault is Ownable, LiquidityManager { address _compoundUsdc, address _uniswapRouter, address _uniswapFactory - ) Ownable(_owner) LiquidityManager(_aavePool, _compoundUsdc, _uniswapRouter, _uniswapFactory) { + ) + Ownable(_owner) + LiquidityManager( + _aavePool, + _compoundUsdc, + _uniswapRouter, + _uniswapFactory + ) + { agent = _agent; } @@ -84,8 +96,15 @@ contract Vault is Ownable, LiquidityManager { * @param _amount Amount of token to deposit. */ function depositERC20(address _token, uint256 _amount) external onlyOwner { - require(IERC20(_token).allowance(msg.sender, address(this)) >= _amount, "Insufficient allowance"); - bool success = IERC20(_token).transferFrom(msg.sender, address(this), _amount); + require( + IERC20(_token).allowance(msg.sender, address(this)) >= _amount, + "Insufficient allowance" + ); + bool success = IERC20(_token).transferFrom( + msg.sender, + address(this), + _amount + ); require(success, "Transfer failed"); tokenAddressToStruct[_token].balance += _amount; emit ERC20Deposited(_token, _amount); @@ -97,7 +116,10 @@ contract Vault is Ownable, LiquidityManager { * @param _amount Amount of token to withdraw. */ function withdrawERC20(address _token, uint256 _amount) external onlyOwner { - require(tokenAddressToStruct[_token].balance >= _amount, "Insufficient balance"); + require( + tokenAddressToStruct[_token].balance >= _amount, + "Insufficient balance" + ); IERC20(_token).approve(owner(), _amount); bool success = IERC20(_token).transfer(owner(), _amount); require(success, "Transfer failed"); @@ -119,12 +141,15 @@ contract Vault is Ownable, LiquidityManager { * @param token The token to lend. * @param amount The amount of token to lend. */ - function lendTokens(string memory protocol, address token, uint256 amount) - external - onlyAgent - validLendingProtocol(protocol) - { - require(tokenAddressToStruct[token].balance >= amount, "Insufficient balance"); + function lendTokens( + string memory protocol, + address token, + uint256 amount + ) external onlyAgent validLendingProtocol(protocol) { + require( + tokenAddressToStruct[token].balance >= amount, + "Insufficient balance" + ); if (keccak256(bytes(protocol)) == keccak256(bytes("aave"))) { supplyLiquidityOnAave(token, amount); @@ -143,18 +168,28 @@ contract Vault is Ownable, LiquidityManager { * @param token The token to withdraw. * @param amount The amount of token to withdraw. */ - function withdrawLentTokens(string memory protocol, address token, uint256 amount) + function withdrawLentTokens( + string memory protocol, + address token, + uint256 amount + ) external onlyAgent validLendingProtocol(protocol) returns (uint256 amountWithdrawn) { if (keccak256(bytes(protocol)) == keccak256(bytes("aave"))) { - require(tokenAddressToStruct[token].investedInAave >= amount, "Insufficient invested amount"); + require( + tokenAddressToStruct[token].investedInAave >= amount, + "Insufficient invested amount" + ); amountWithdrawn = withdrawLiquidityFromAave(token, amount); tokenAddressToStruct[token].investedInAave -= amount; } else if (keccak256(bytes(protocol)) == keccak256(bytes("compound"))) { - require(tokenAddressToStruct[token].investedInCompound >= amount, "Insufficient invested amount"); + require( + tokenAddressToStruct[token].investedInCompound >= amount, + "Insufficient invested amount" + ); amountWithdrawn = withdrawLiquidityFromCompound(token, amount); tokenAddressToStruct[token].investedInCompound -= amount; } @@ -184,14 +219,30 @@ contract Vault is Ownable, LiquidityManager { int24 tickLower, int24 tickUpper ) external onlyAgent validLPProtocol(protocol) { - require(tokenAddressToStruct[token0].balance >= amount0, "Insufficient balance token0"); - require(tokenAddressToStruct[token1].balance >= amount1, "Insufficient balance token1"); + require( + tokenAddressToStruct[token0].balance >= amount0, + "Insufficient balance token0" + ); + require( + tokenAddressToStruct[token1].balance >= amount1, + "Insufficient balance token1" + ); if (keccak256(bytes(protocol)) == keccak256(bytes("uniswap"))) { - supplyLiquidityOnUniswap(token0, token1, amount0, amount1, fee, tickLower, tickUpper); + supplyLiquidityOnUniswap( + token0, + token1, + amount0, + amount1, + fee, + tickLower, + tickUpper + ); tokenAddressToStruct[token0].investedInUniswap += amount0; tokenAddressToStruct[token1].investedInUniswap += amount1; - } else if (keccak256(bytes(protocol)) == keccak256(bytes("aerodrome"))) { + } else if ( + keccak256(bytes(protocol)) == keccak256(bytes("aerodrome")) + ) { revert AerodromeNotImplemented(); } @@ -206,11 +257,12 @@ contract Vault is Ownable, LiquidityManager { * @param token1 The second token to remove liquidity from. * @param liquidityAmount The amount of liquidity to remove. */ - function removeLiquidity(string memory protocol, address token0, address token1, uint256 liquidityAmount) - external - onlyAgent - validLPProtocol(protocol) - { + function removeLiquidity( + string memory protocol, + address token0, + address token1, + uint256 liquidityAmount + ) external onlyAgent validLPProtocol(protocol) { if (keccak256(bytes(protocol)) == keccak256(bytes("uniswap"))) { withdrawLiquidityFromUniswap( token0, @@ -219,7 +271,9 @@ contract Vault is Ownable, LiquidityManager { /// @param fee default fee uint128(liquidityAmount) ); - } else if (keccak256(bytes(protocol)) == keccak256(bytes("aerodrome"))) { + } else if ( + keccak256(bytes(protocol)) == keccak256(bytes("aerodrome")) + ) { revert AerodromeNotImplemented(); } } @@ -231,23 +285,49 @@ contract Vault is Ownable, LiquidityManager { * @param _amountIn The amount of tokenIn to swap. * @param _fee The fee to swap on. */ - function swapOnUniswap(address _tokenIn, address _tokenOut, uint256 _amountIn, uint24 _fee) - external - onlyAgent - returns (uint256 amountOut) - { - require(tokenAddressToStruct[_tokenIn].balance >= _amountIn, "Insufficient balance"); + function swapOnUniswap( + address _tokenIn, + address _tokenOut, + uint256 _amountIn, + uint24 _fee + ) external onlyAgent returns (uint256 amountOut) { + require( + tokenAddressToStruct[_tokenIn].balance >= _amountIn, + "Insufficient balance" + ); amountOut = swapOnUniswap(_tokenIn, _tokenOut, _amountIn, 1, _fee); tokenAddressToStruct[_tokenIn].balance -= _amountIn; tokenAddressToStruct[_tokenOut].balance += amountOut; } + /** + * @notice Do arbitrage on Uniswap. + * @param _routerPath The router path to do arbitrage on. + * @param _tokenPath The token path to do arbitrage on. + * @param _fee The fee to do arbitrage on. + * @param _amount The amount to do arbitrage on. + */ + function doArbitrage( + address[] memory _routerPath, + address[] memory _tokenPath, + uint24 _fee, + uint256 _amount + ) external onlyAgent { + require( + tokenAddressToStruct[_tokenPath[0]].balance >= _amount, + "Insufficient balance" + ); + ArbitrageWithoutFlashLoan(_routerPath, _tokenPath, _fee, _amount); + } + /** * @notice Get the struct details for a token.. * @param _token Token address to get the balance of. * @return balance Balance of the user for the token. */ - function getUserStruct(address _token) external view returns (UserBalance memory) { + function getUserStruct( + address _token + ) external view returns (UserBalance memory) { return tokenAddressToStruct[_token]; } }