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

Support flashloans in Balancer adaptor API #225

Merged
merged 10 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from 5 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
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sommelier_steward"
version = "3.5.1"
version = "3.5.2"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Reference: https://www.lpalmieri.com/posts/fast-rust-docker-builds/

FROM rust:1.63 as cargo-chef-rust
FROM rust:1.65 as cargo-chef-rust
EricBolten marked this conversation as resolved.
Show resolved Hide resolved
RUN cargo install cargo-chef --version 0.1.51

FROM cargo-chef-rust as planner
Expand Down
5 changes: 3 additions & 2 deletions proto/adaptors/aave/aave_v3_debt_token.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ option go_package = "/steward_proto";
import "adaptors/aave/a_token.proto";
import "adaptors/aave/debt_token.proto";
import "adaptors/aave/aave_v3_a_token.proto";
import "adaptors/balancer/balancer_pool.proto";
import "adaptors/compound/c_token.proto";
import "adaptors/frax/f_token.proto";
import "adaptors/morpho/morpho_aave_v2_a_token.proto";
Expand Down Expand Up @@ -153,8 +152,10 @@ message AaveV3DebtTokenAdaptorV1 {
MorphoAaveV3ATokenP2PAdaptorV1Calls morpho_aave_v3_a_token_p2p_v1_calls = 22;
// Represents function calls to the MorphoAaveV3DebtToken V1
MorphoAaveV3DebtTokenAdaptorV1Calls morpho_aave_v3_debt_token_v1_calls = 23;
// TODO: Circular dep since balancer has adaptor calls with aave v3 debt token.
// Need a more permanent solution.
// Represents function calls to the BalancerPoolAdaptor V1
BalancerPoolAdaptorV1Calls balancer_pool_v1_calls = 24;
// BalancerPoolAdaptorV1Calls balancer_pool_v1_calls = 24;
EricBolten marked this conversation as resolved.
Show resolved Hide resolved
// Represents function calls to the LegacyCellarAdaptor V1
LegacyCellarAdaptorV1Calls legacy_cellar_v1_calls = 25;
// Represents function calls to the DebtFTokenAdaptor V1
Expand Down
101 changes: 100 additions & 1 deletion proto/adaptors/balancer/balancer_pool.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,28 @@ package steward.v3;
option go_package = "/steward_proto";

import "adaptors/base.proto";
import "adaptors/aave/a_token.proto";
import "adaptors/aave/debt_token.proto";
import "adaptors/aave/aave_v3_a_token.proto";
import "adaptors/aave/aave_v3_debt_token.proto";
import "adaptors/compound/c_token.proto";
import "adaptors/frax/f_token.proto";
import "adaptors/morpho/morpho_aave_v2_a_token.proto";
import "adaptors/morpho/morpho_aave_v2_debt_token.proto";
import "adaptors/morpho/morpho_aave_v3_a_token_collateral.proto";
import "adaptors/morpho/morpho_aave_v3_a_token_p2p.proto";
import "adaptors/morpho/morpho_aave_v3_debt_token.proto";
import "adaptors/uniswap/uniswap_v3.proto";
import "adaptors/uniswap/swap_with_uniswap.proto";
import "adaptors/fees_and_reserves.proto";
import "adaptors/zero_x/zero_x.proto";
import "adaptors/oneinch/oneinch.proto";
import "adaptors/vesting_simple.proto";
import "adaptors/sommelier/cellar_adaptor.proto";
import "adaptors/aave/aave_v2_enable_asset_as_collateral_adaptor.proto";
import "adaptors/sommelier/legacy_cellar_adaptor.proto";
import "adaptors/frax/debt_f_token.proto";
import "adaptors/frax/collateral_f_token.proto";

// Represents call data for the Balancer Pool adaptor V1, for managing pool positions on Balancer.
message BalancerPoolAdaptorV1 {
Expand All @@ -29,7 +51,8 @@ message BalancerPoolAdaptorV1 {
UnstakeBPT unstake_bpt = 5;
// Represents function `claimRewards(address gauge)`
ClaimRewards claim_rewards = 6;

// Represents function `makeFlashLoan(IERC20[] tokens, uint256[] amounts, bytes memory data)`
MakeFlashLoan make_flash_loan = 7;
}

// Represents the SwapKind enum defined here:
Expand Down Expand Up @@ -158,6 +181,82 @@ message BalancerPoolAdaptorV1 {
// The gauge to claim rewards from
string gauge = 1;
}

/*
* Make a flash loan
*
* Represents `function makeFlashLoan(IERC20[] tokens, uint256[] amounts, bytes memory data)`
*/
message MakeFlashLoan {
// The tokens to flash loan
repeated string tokens = 1;

// The amounts to flash loan
repeated string amounts = 2;

// The data to flash loan
repeated AdaptorCallForBalancerFlashloan data = 3;
}

message AdaptorCallForBalancerFlashloan {
// Address of the adaptor
string adaptor = 1;
// The function call data for the adaptor
oneof call_data {
// Represents function calls to the UniswapV3Adaptor V1
UniswapV3AdaptorV1Calls uniswap_v3_v1_calls = 2;
// Represents function calls to the AaveATokenAdaptor V1
AaveATokenAdaptorV1Calls aave_a_token_v1_calls = 3;
// Represents function calls to the AavaDebtTokenAdaptor V1
AaveDebtTokenAdaptorV1Calls aave_debt_token_v1_calls = 4;
// Represents function calls to the CompoundCTokenAdaptor V2
CompoundCTokenAdaptorV2Calls compound_c_token_v2_calls = 5;
// Represents function calls to the AaveATokenV2Adaptor
AaveATokenAdaptorV2Calls aave_a_token_v2_calls = 6;
// Represents function calls to the AavaDebtTokenV2Adaptor
AaveDebtTokenAdaptorV2Calls aave_debt_token_v2_calls = 7;
// Represents function calls to the AaveATokenV1Adaptor
AaveV3ATokenAdaptorV1Calls aave_v3_a_token_v1_calls = 8;
// Represents function calls to the AavaDebtTokenV1Adaptor
AaveV3DebtTokenAdaptorV1Calls aave_v3_debt_token_v1_calls = 9;
// Represents function calls to the OneInchAdaptorV1
OneInchAdaptorV1Calls one_inch_v1_calls = 10;
// Represents function calls to the FeesAndReservesAdaptorV1
FeesAndReservesAdaptorV1Calls fees_and_reserves_v1_calls = 11;
// Represents functionc alls to the ZeroXAdaptorV1
ZeroXAdaptorV1Calls zero_x_v1_calls = 12;
// Represents function calls to the SwapWithUniswapAdaptorV1
SwapWithUniswapAdaptorV1Calls swap_with_uniswap_v1_calls = 13;
// Represents function calls to VestingSimpleAdaptor
VestingSimpleAdaptorV2Calls vesting_simple_v2_calls = 14;
// Represents function calls to the CellarAdaptor
CellarAdaptorV1Calls cellar_v1_calls = 15;
// Represents function calls to the UniswapV3Adaptor V2
UniswapV3AdaptorV2Calls uniswap_v3_v2_calls = 16;
// Represents function calls to the AaveV2EnableAssetAsCollatorAdaptor V1
AaveV2EnableAssetAsCollateralAdaptorV1Calls aave_v2_enable_asset_as_collateral_v1_calls = 17;
// Represents function calls to the FTokenAdaptor V1
FTokenAdaptorV1Calls f_token_v1_calls = 18;
// Represents function calls to the MorphoAaveV2AToken V1
MorphoAaveV2ATokenAdaptorV1Calls morpho_aave_v2_a_token_v1_calls = 19;
// Represents function calls to the MorphoAaveV2DebtToken V1
MorphoAaveV2DebtTokenAdaptorV1Calls morpho_aave_v2_debt_token_v1_calls = 20;
// Represents function calls to the MorphoAaveV3ATokenCollateral V1
MorphoAaveV3ATokenCollateralAdaptorV1Calls morpho_aave_v3_a_token_collateral_v1_calls = 21;
// Represents function calls to the MorphoAaveV3ATokenP2P V1
MorphoAaveV3ATokenP2PAdaptorV1Calls morpho_aave_v3_a_token_p2p_v1_calls = 22;
// Represents function calls to the MorphoAaveV3DebtToken V1
MorphoAaveV3DebtTokenAdaptorV1Calls morpho_aave_v3_debt_token_v1_calls = 23;
// Represents function calls to the BalancerPoolAdaptor V1
BalancerPoolAdaptorV1Calls balancer_pool_v1_calls = 24;
EricBolten marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BalancerPoolAdaptorV1Calls can be removed as we are not allowed to call it in the Flashloan due to reentrancy

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would be true for aave v3's flash loan adaptor calls too right? remove its own calls from the set?

// Represents function calls to the LegacyCellarAdaptor V1
LegacyCellarAdaptorV1Calls legacy_cellar_v1_calls = 25;
// Represents function calls to the DebtFTokenAdaptor V1
DebtFTokenAdaptorV1Calls debt_f_token_v1_calls = 26;
// Represents function calls to the CollateralFTokenAdaptor V1
CollateralFTokenAdaptorV1Calls collateral_f_token_v1_calls = 27;
}
}
}

message BalancerPoolAdaptorV1Calls {
Expand Down
2 changes: 1 addition & 1 deletion steward/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "steward"
authors = []
version = "3.5.1"
version = "3.5.2"
edition = "2018"

[dependencies]
Expand Down
2 changes: 2 additions & 0 deletions steward/src/cellars/adaptors/aave_v3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,11 @@ fn get_encoded_adaptor_calls(
MorphoAaveV3DebtTokenV1Calls(params) => {
calls.extend(adaptors::morpho::morpho_aave_v3_debt_token_adaptor_v1_calls(params)?)
}
/*
EricBolten marked this conversation as resolved.
Show resolved Hide resolved
BalancerPoolV1Calls(params) => calls.extend(
adaptors::balancer_pool::balancer_pool_adaptor_v1_calls(params)?,
),
*/
LegacyCellarV1Calls(params) => {
calls.extend(adaptors::sommelier::legacy_cellar_adaptor_v1_calls(params)?)
}
Expand Down
138 changes: 134 additions & 4 deletions steward/src/cellars/adaptors/balancer_pool.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
use std::convert::TryInto;

use abscissa_core::prelude::debug;
use ethers::{abi::AbiEncode, types::Bytes};
use steward_abi::balancer_pool_adaptor_v1::{
BalancerPoolAdaptorV1Calls, ExitPoolRequest, SingleSwap as AbiSingleSwap,
SwapData as AbiSwapData,
use steward_abi::{
balancer_pool_adaptor_v1::{
BalancerPoolAdaptorV1Calls, ExitPoolRequest, SingleSwap as AbiSingleSwap,
SwapData as AbiSwapData,
},
cellar_v2_2::AdaptorCall as AbiAdaptorCall,
};
use steward_proto::steward::balancer_pool_adaptor_v1::{
self, adaptor_call_for_balancer_flashloan::CallData::*, AdaptorCallForBalancerFlashloan,
SingleSwap, SwapData,
};
use steward_proto::steward::balancer_pool_adaptor_v1::{self, SingleSwap, SwapData};

use crate::{
cellars::adaptors,
error::{Error, ErrorKind},
utils::{sp_call_error, sp_call_parse_address, string_to_u256},
};
Expand Down Expand Up @@ -124,6 +132,26 @@ pub(crate) fn balancer_pool_adaptor_v1_calls(
.into(),
)
}
balancer_pool_adaptor_v1::Function::MakeFlashLoan(p) => {
let call = steward_abi::balancer_pool_adaptor_v1::MakeFlashLoanCall {
tokens: p
.tokens
.iter()
.map(|t| sp_call_parse_address(t.clone()))
.collect::<Result<Vec<_>, _>>()?,
amounts: p
.amounts
.iter()
.map(|a| string_to_u256(a.clone()))
.collect::<Result<Vec<_>, _>>()?,
data: get_encoded_adaptor_calls(p.data)?.encode().into(),
};
calls.push(
BalancerPoolAdaptorV1Calls::MakeFlashLoan(call)
.encode()
.into(),
)
}
}
}

Expand Down Expand Up @@ -169,3 +197,105 @@ fn convert_swap_data(data: SwapData) -> Result<AbiSwapData, Error> {
.collect::<Result<Vec<_>, Error>>()?,
})
}

/// Encodes calls to the Adaptor contracts
fn get_encoded_adaptor_calls(
data: Vec<AdaptorCallForBalancerFlashloan>,
) -> Result<Vec<AbiAdaptorCall>, Error> {
let mut result: Vec<AbiAdaptorCall> = Vec::new();
for d in data {
debug!("adaptor call to {}", d.adaptor);
let mut calls: Vec<Bytes> = Vec::new();
let call_data = d
.call_data
.ok_or_else(|| sp_call_error("call data is empty".to_string()))?;

match call_data {
UniswapV3V1Calls(params) => {
calls.extend(adaptors::uniswap_v3::uniswap_v3_adaptor_v1_calls(params)?)
}
AaveATokenV1Calls(params) => {
calls.extend(adaptors::aave_v2::aave_a_token_adaptor_v1_calls(params)?)
}
AaveDebtTokenV1Calls(params) => {
calls.extend(adaptors::aave_v2::aave_debt_token_adaptor_v1_calls(params)?)
}
AaveATokenV2Calls(params) => {
calls.extend(adaptors::aave_v2::aave_a_token_adaptor_v2_calls(params)?)
}
AaveDebtTokenV2Calls(params) => {
calls.extend(adaptors::aave_v2::aave_debt_token_adaptor_v2_calls(params)?)
}
AaveV3ATokenV1Calls(params) => {
calls.extend(adaptors::aave_v3::aave_v3_a_token_adaptor_v1_calls(params)?)
}
AaveV3DebtTokenV1Calls(params) => calls.extend(
adaptors::aave_v3::aave_v3_debt_token_adaptor_v1_calls(params)?,
),
OneInchV1Calls(params) => {
calls.extend(adaptors::oneinch::one_inch_adaptor_v1_calls(params)?)
}
FeesAndReservesV1Calls(params) => calls
.extend(adaptors::fees_and_reserves::fees_and_reserves_adaptor_v1_calls(params)?),
ZeroXV1Calls(params) => {
calls.extend(adaptors::zero_x::zero_x_adaptor_v1_calls(params)?)
}
SwapWithUniswapV1Calls(params) => calls
.extend(adaptors::swap_with_uniswap::swap_with_uniswap_adaptor_v1_calls(params)?),
CompoundCTokenV2Calls(params) => {
calls.extend(adaptors::compound::compound_c_token_v2_calls(params)?)
}
VestingSimpleV2Calls(params) => calls.extend(
adaptors::vesting_simple::vesting_simple_adaptor_v2_calls(params)?,
),
CellarV1Calls(params) => {
calls.extend(adaptors::sommelier::cellar_adaptor_v1_calls(params)?)
}
UniswapV3V2Calls(params) => {
calls.extend(adaptors::uniswap_v3::uniswap_v3_adaptor_v2_calls(params)?)
}
AaveV2EnableAssetAsCollateralV1Calls(params) => calls.extend(
adaptors::aave_v2_collateral::aave_v2_enable_asset_as_collateral_adaptor_v1_calls(
params,
)?,
),
FTokenV1Calls(params) => {
calls.extend(adaptors::frax::f_token_adaptor_v1_calls(params)?)
}
MorphoAaveV2ATokenV1Calls(params) => calls.extend(
adaptors::morpho::morpho_aave_v2_a_token_adaptor_v1_calls(params)?,
),
MorphoAaveV2DebtTokenV1Calls(params) => {
calls.extend(adaptors::morpho::morpho_aave_v2_debt_token_adaptor_v1_calls(params)?)
}
MorphoAaveV3ATokenCollateralV1Calls(params) => calls.extend(
adaptors::morpho::morpho_aave_v3_a_token_collateral_adaptor_v1_calls(params)?,
),
MorphoAaveV3ATokenP2pV1Calls(params) => {
calls.extend(adaptors::morpho::morpho_aave_v3_a_token_p2p_adaptor_v1_calls(params)?)
}
MorphoAaveV3DebtTokenV1Calls(params) => {
calls.extend(adaptors::morpho::morpho_aave_v3_debt_token_adaptor_v1_calls(params)?)
}
BalancerPoolV1Calls(params) => calls.extend(
adaptors::balancer_pool::balancer_pool_adaptor_v1_calls(params)?,
),
LegacyCellarV1Calls(params) => {
calls.extend(adaptors::sommelier::legacy_cellar_adaptor_v1_calls(params)?)
}
DebtFTokenV1Calls(params) => {
calls.extend(adaptors::frax::debt_f_token_adaptor_v1_calls(params)?)
}
CollateralFTokenV1Calls(params) => {
calls.extend(adaptors::frax::collateral_f_token_adaptor_v1_calls(params)?)
}
};

result.push(AbiAdaptorCall {
adaptor: sp_call_parse_address(d.adaptor)?,
call_data: calls,
})
}

Ok(result)
}
2 changes: 1 addition & 1 deletion steward_abi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "steward_abi"
version = "3.5.1"
version = "3.5.2"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
Loading
Loading