Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 116 additions & 36 deletions src/Vault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;

Expand All @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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;
}

Expand All @@ -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);
Expand All @@ -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");
Expand All @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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();
}

Expand All @@ -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,
Expand All @@ -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();
}
}
Expand All @@ -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];
}
}
Loading