Skip to content

Commit

Permalink
feat - implement leverage function on the CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
Dvisacker committed Oct 13, 2024
1 parent 0da0f2b commit dd6562e
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ forge-clean:
# This command will generate an error (no cargo.toml) that can be ignored because we are generating the bindings in a subcrate of the src folder
forge-bind:
@echo "Generating Rust bindings for Solidity contracts..."
@cd $(CONTRACTS_DIR) && forge bind --alloy --bindings-path ../src/bindings --crate-name bindings --alloy-version 0.3.3 --module
@cd $(CONTRACTS_DIR) && forge bind --alloy --bindings-path ../src/bindings --alloy-version 0.3.3 --module

deploy:
@echo "Deploying AaveLooper..."
Expand Down
2 changes: 1 addition & 1 deletion contracts/script/Leverage.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ contract Leverage is Script {

vm.startBroadcast();
ERC20(supplyAsset).approve(aaveLooper, initialAmount);
uint256 liquidity = looper.enterPosition(supplyAsset, borrowAsset, initialAmount, iterations, 500);
uint256 liquidity = looper.leverage(supplyAsset, borrowAsset, initialAmount, iterations, 500);
vm.stopBroadcast();

console2.log("Entered position. Final liquidity:", liquidity);
Expand Down
16 changes: 7 additions & 9 deletions contracts/src/AaveLooper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,12 @@ contract AaveLooper is ImmutableOwnable {
* @param iterations - Loop count
* @return Liquidity at end of the loop
*/
function enterPositionFully(address supplyAsset, address borrowAsset, uint256 iterations, uint24 feeTier)
function leverageFully(address supplyAsset, address borrowAsset, uint256 iterations, uint24 feeTier)
external
onlyOwner
returns (uint256)
{
return enterPosition(supplyAsset, borrowAsset, ERC20(supplyAsset).balanceOf(msg.sender), iterations, feeTier);
return leverage(supplyAsset, borrowAsset, ERC20(supplyAsset).balanceOf(msg.sender), iterations, feeTier);
}

function getBestFeeTier(address factory, address tokenIn, address tokenOut, uint256 amountIn)
Expand Down Expand Up @@ -211,13 +211,11 @@ contract AaveLooper is ImmutableOwnable {
* @param feeTier - Fee tier for the swap
* @return Liquidity at end of the loop
*/
function enterPosition(
address supplyAsset,
address borrowAsset,
uint256 principal,
uint256 iterations,
uint24 feeTier
) public onlyOwner returns (uint256) {
function leverage(address supplyAsset, address borrowAsset, uint256 principal, uint256 iterations, uint24 feeTier)
public
onlyOwner
returns (uint256)
{
if (principal > 0) {
ERC20(supplyAsset).transferFrom(msg.sender, address(this), principal);
}
Expand Down
41 changes: 40 additions & 1 deletion src/bot.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use crate::provider::SignerProvider;
use alloy::sol;
use alloy::{providers::WalletProvider, transports::BoxTransport};
use alloy_primitives::aliases::U24;
use alloy_primitives::{Address, U256};
use std::error::Error;
use std::sync::Arc;
use std::time::Duration;
use tokio::time;
use AaveLooper::AaveLooperInstance;
use ILendingPool::ILendingPoolInstance;
use IERC20::IERC20Instance;

Expand All @@ -26,15 +28,24 @@ sol! {
}
}

sol!(
#[sol(rpc)]
#[derive(Debug, PartialEq, Eq)]
AaveLooper,
"./contracts/out/AaveLooper.sol/AaveLooper.json"
);

type Token = IERC20Instance<BoxTransport, Arc<SignerProvider>>;
type LendingPool = ILendingPoolInstance<BoxTransport, Arc<SignerProvider>>;
type Looper = AaveLooperInstance<BoxTransport, Arc<SignerProvider>>;

pub struct AaveBot {
provider: Arc<SignerProvider>,
signer_address: Address,
asset_address: Address,
lending_pool: LendingPool,
asset: Token,
looper: Looper,
max_amount: U256,
leverage: u8,
threshold: U256,
Expand All @@ -56,13 +67,18 @@ impl AaveBot {
let lending_pool = ILendingPool::new(aave_address, provider.clone());
let asset = IERC20::new(asset_address, provider.clone());
let signer_address = provider.default_signer_address();
// let telegram_bot = Bot::new(telegram_token);

// Initialize the AaveLooper contract
// Note: You'll need to deploy this contract and get its address
let looper_address = Address::from_str("YOUR_DEPLOYED_AAVELOOPER_ADDRESS_HERE")?;
let looper = AaveLooper::new(looper_address, provider.clone());

Ok(Arc::new(Self {
provider,
signer_address,
lending_pool,
asset,
looper,
asset_address,
max_amount,
leverage,
Expand Down Expand Up @@ -236,4 +252,27 @@ impl AaveBot {
// .await?;
Ok(())
}

pub async fn leverage(
&self,
asset_address: Address,
amount: U256,
) -> Result<(), Box<dyn Error>> {
// First, approve the AaveLooper contract to spend tokens on our behalf
self.approve_tokens(asset_address, amount).await?;

// Call the leverage function on the AaveLooper contract
let tx = self.looper.leverage(
asset_address, // supplyAsset
asset_address, // borrowAsset (same as supply in this case)
amount, // principal
U256::from(1), // iterations (you can adjust this as needed)
U24::from(500), // feeTier (0.3% fee tier for Uniswap V3, adjust if needed)
);

let receipt = tx.send().await?.get_receipt().await?;
println!("Increased leverage: {:?}", receipt);

Ok(())
}
}
34 changes: 34 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ enum Commands {
#[arg(short, long)]
token: String,
},
Leverage {
#[arg(short, long)]
amount: u64,
#[arg(short, long)]
token: String,
},
}

pub async fn run_cli(provider: Arc<SignerProvider>) -> Result<(), Box<dyn Error>> {
Expand Down Expand Up @@ -201,6 +207,34 @@ pub async fn run_cli(provider: Arc<SignerProvider>) -> Result<(), Box<dyn Error>
bot.repay_tokens(asset_address, amount_wei).await?;
println!("Repay successful!");
}
Commands::Leverage { amount, token } => {
let aave_address = get_aave_lending_pool_address(chain).ok_or_else(|| {
Box::<dyn Error>::from("Aave lending pool address not found for this chain")
})?;
let asset_address = get_token_address(chain, token).ok_or_else(|| {
Box::<dyn Error>::from(format!("{} address not found for this chain", token))
})?;
let amount_wei = U256::from(*amount) * U256::from(10).pow(U256::from(6)); // Assuming 6 decimals, adjust if needed

let bot = AaveBot::new(
provider.clone(),
aave_address,
asset_address,
amount_wei,
1, // Leverage not used for this operation
U256::from(0), // Threshold not used for this operation
String::new(),
0,
)
.await?;

println!(
"Increasing leverage by borrowing {} {} and supplying it back...",
amount, token
);
bot.leverage(asset_address, amount_wei).await?;
println!("Leverage increased successfully!");
}
}

Ok(())
Expand Down

0 comments on commit dd6562e

Please sign in to comment.