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

SiL #223

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

SiL #223

wants to merge 4 commits into from

Conversation

a17
Copy link
Member

@a17 a17 commented Feb 7, 2025

No description provided.

@a17 a17 linked an issue Feb 7, 2025 that may be closed by this pull request
Comment on lines 60 to 79
function initVariants(address platform_)
public
view
returns (string[] memory variants, address[] memory addresses, uint[] memory nums, int24[] memory ticks)
{
IFactory.StrategyAvailableInitParams memory params =
IFactory(IPlatform(platform_).factory()).strategyAvailableInitParams(keccak256(bytes(strategyLogicId())));
uint len = params.initNums[0];
variants = new string[](len);
addresses = new address[](len * 2);
nums = new uint[](0);
ticks = new int24[](0);
for (uint i; i < len; ++i) {
address collateralAsset = IERC4626(params.initAddresses[i * 2]).asset();
address borrowAsset = IERC4626(params.initAddresses[i * 2 + 1]).asset();
variants[i] = _generateDescription(collateralAsset, borrowAsset);
addresses[i * 2] = params.initAddresses[i * 2];
addresses[i * 2 + 1] = params.initAddresses[i * 2 + 1];
}
}

Check notice

Code scanning / Slither

Calls inside a loop Low

Comment on lines 60 to 79
function initVariants(address platform_)
public
view
returns (string[] memory variants, address[] memory addresses, uint[] memory nums, int24[] memory ticks)
{
IFactory.StrategyAvailableInitParams memory params =
IFactory(IPlatform(platform_).factory()).strategyAvailableInitParams(keccak256(bytes(strategyLogicId())));
uint len = params.initNums[0];
variants = new string[](len);
addresses = new address[](len * 2);
nums = new uint[](0);
ticks = new int24[](0);
for (uint i; i < len; ++i) {
address collateralAsset = IERC4626(params.initAddresses[i * 2]).asset();
address borrowAsset = IERC4626(params.initAddresses[i * 2 + 1]).asset();
variants[i] = _generateDescription(collateralAsset, borrowAsset);
addresses[i * 2] = params.initAddresses[i * 2];
addresses[i * 2 + 1] = params.initAddresses[i * 2 + 1];
}
}

Check notice

Code scanning / Slither

Calls inside a loop Low

Comment on lines +159 to +167
function _generateDescription(address collateralAsset, address borrowAsset) internal view returns (string memory) {
return string.concat(
"Supply ",
IERC20Metadata(collateralAsset).symbol(),
" and borrow ",
IERC20Metadata(borrowAsset).symbol(),
" on Silo V2 with leverage looping"
);
}
Copy link

codecov bot commented Feb 7, 2025

Codecov Report

Attention: Patch coverage is 98.79032% with 3 lines in your changes missing coverage. Please review.

Project coverage is 93.29%. Comparing base (9463c87) to head (07ebd26).

Files with missing lines Patch % Lines
src/strategies/SiloLeverageStrategy.sol 98.53% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #223      +/-   ##
==========================================
+ Coverage   93.12%   93.29%   +0.16%     
==========================================
  Files          91       93       +2     
  Lines        8296     8543     +247     
  Branches      708      721      +13     
==========================================
+ Hits         7726     7970     +244     
- Misses        534      537       +3     
  Partials       36       36              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

revert IControllable.IncorrectInitParams();
}

LeverageLendingStrategyBaseInitParams memory params;

Check warning

Code scanning / Slither

Uninitialized local variables Medium

Comment on lines +72 to +139
function receiveFlashLoan(
address[] memory tokens,
uint[] memory amounts,
uint[] memory feeAmounts,
bytes memory /*userData*/
) external {
// Flash loan is performed upon deposit and withdrawal

LeverageLendingBaseStorage storage $ = _getLeverageLendingBaseStorage();
address flashLoanVault = $.flashLoanVault;
if (msg.sender != flashLoanVault) {
revert IControllable.IncorrectMsgSender();
}

if ($.tempAction == CurrentAction.Deposit) {
// tokens[0] is collateral asset
uint tempBorrowAmount = $.tempBorrowAmount;

// supply
ISilo($.lendingVault).deposit(amounts[0], address(this), ISilo.CollateralType.Collateral);

// borrow
ISilo($.borrowingVault).borrow(tempBorrowAmount, address(this), address(this));

// swap
_swap($.borrowAsset, tokens[0], tempBorrowAmount);

// pay flash loan
IERC20(tokens[0]).safeTransfer(flashLoanVault, amounts[0] + feeAmounts[0]);

// reset temp vars
$.tempBorrowAmount = 0;
}

if ($.tempAction == CurrentAction.Withdraw) {
// tokens[0] is borrow asset
address lendingVault = $.lendingVault;
address collateralAsset = $.collateralAsset;
uint tempCollateralAmount = $.tempCollateralAmount;

// repay debt
ISilo($.borrowingVault).repay(amounts[0], address(this));

// withdraw
uint collateralAmountTotal = IERC4626(lendingVault).convertToAssets(StrategyLib.balance(lendingVault));
collateralAmountTotal -= collateralAmountTotal / 1000;
ISilo(lendingVault).withdraw(
Math.min(tempCollateralAmount, collateralAmountTotal),
address(this),
address(this),
ISilo.CollateralType.Collateral
);

// swap
_swap(collateralAsset, tokens[0], Math.min(tempCollateralAmount, StrategyLib.balance(collateralAsset)));

// pay flash loan
IERC20(tokens[0]).safeTransfer(flashLoanVault, amounts[0] + feeAmounts[0]);

// swap unnecessary borrow asset
_swap(tokens[0], collateralAsset, StrategyLib.balance(tokens[0]));

// reset temp vars
$.tempCollateralAmount = 0;
}

$.tempAction = CurrentAction.None;
}

Check warning

Code scanning / Slither

Unused return Medium

Comment on lines +72 to +139
function receiveFlashLoan(
address[] memory tokens,
uint[] memory amounts,
uint[] memory feeAmounts,
bytes memory /*userData*/
) external {
// Flash loan is performed upon deposit and withdrawal

LeverageLendingBaseStorage storage $ = _getLeverageLendingBaseStorage();
address flashLoanVault = $.flashLoanVault;
if (msg.sender != flashLoanVault) {
revert IControllable.IncorrectMsgSender();
}

if ($.tempAction == CurrentAction.Deposit) {
// tokens[0] is collateral asset
uint tempBorrowAmount = $.tempBorrowAmount;

// supply
ISilo($.lendingVault).deposit(amounts[0], address(this), ISilo.CollateralType.Collateral);

// borrow
ISilo($.borrowingVault).borrow(tempBorrowAmount, address(this), address(this));

// swap
_swap($.borrowAsset, tokens[0], tempBorrowAmount);

// pay flash loan
IERC20(tokens[0]).safeTransfer(flashLoanVault, amounts[0] + feeAmounts[0]);

// reset temp vars
$.tempBorrowAmount = 0;
}

if ($.tempAction == CurrentAction.Withdraw) {
// tokens[0] is borrow asset
address lendingVault = $.lendingVault;
address collateralAsset = $.collateralAsset;
uint tempCollateralAmount = $.tempCollateralAmount;

// repay debt
ISilo($.borrowingVault).repay(amounts[0], address(this));

// withdraw
uint collateralAmountTotal = IERC4626(lendingVault).convertToAssets(StrategyLib.balance(lendingVault));
collateralAmountTotal -= collateralAmountTotal / 1000;
ISilo(lendingVault).withdraw(
Math.min(tempCollateralAmount, collateralAmountTotal),
address(this),
address(this),
ISilo.CollateralType.Collateral
);

// swap
_swap(collateralAsset, tokens[0], Math.min(tempCollateralAmount, StrategyLib.balance(collateralAsset)));

// pay flash loan
IERC20(tokens[0]).safeTransfer(flashLoanVault, amounts[0] + feeAmounts[0]);

// swap unnecessary borrow asset
_swap(tokens[0], collateralAsset, StrategyLib.balance(tokens[0]));

// reset temp vars
$.tempCollateralAmount = 0;
}

$.tempAction = CurrentAction.None;
}
Comment on lines +72 to +139
function receiveFlashLoan(
address[] memory tokens,
uint[] memory amounts,
uint[] memory feeAmounts,
bytes memory /*userData*/
) external {
// Flash loan is performed upon deposit and withdrawal

LeverageLendingBaseStorage storage $ = _getLeverageLendingBaseStorage();
address flashLoanVault = $.flashLoanVault;
if (msg.sender != flashLoanVault) {
revert IControllable.IncorrectMsgSender();
}

if ($.tempAction == CurrentAction.Deposit) {
// tokens[0] is collateral asset
uint tempBorrowAmount = $.tempBorrowAmount;

// supply
ISilo($.lendingVault).deposit(amounts[0], address(this), ISilo.CollateralType.Collateral);

// borrow
ISilo($.borrowingVault).borrow(tempBorrowAmount, address(this), address(this));

// swap
_swap($.borrowAsset, tokens[0], tempBorrowAmount);

// pay flash loan
IERC20(tokens[0]).safeTransfer(flashLoanVault, amounts[0] + feeAmounts[0]);

// reset temp vars
$.tempBorrowAmount = 0;
}

if ($.tempAction == CurrentAction.Withdraw) {
// tokens[0] is borrow asset
address lendingVault = $.lendingVault;
address collateralAsset = $.collateralAsset;
uint tempCollateralAmount = $.tempCollateralAmount;

// repay debt
ISilo($.borrowingVault).repay(amounts[0], address(this));

// withdraw
uint collateralAmountTotal = IERC4626(lendingVault).convertToAssets(StrategyLib.balance(lendingVault));
collateralAmountTotal -= collateralAmountTotal / 1000;
ISilo(lendingVault).withdraw(
Math.min(tempCollateralAmount, collateralAmountTotal),
address(this),
address(this),
ISilo.CollateralType.Collateral
);

// swap
_swap(collateralAsset, tokens[0], Math.min(tempCollateralAmount, StrategyLib.balance(collateralAsset)));

// pay flash loan
IERC20(tokens[0]).safeTransfer(flashLoanVault, amounts[0] + feeAmounts[0]);

// swap unnecessary borrow asset
_swap(tokens[0], collateralAsset, StrategyLib.balance(tokens[0]));

// reset temp vars
$.tempCollateralAmount = 0;
}

$.tempAction = CurrentAction.None;
}
Comment on lines +72 to +139
function receiveFlashLoan(
address[] memory tokens,
uint[] memory amounts,
uint[] memory feeAmounts,
bytes memory /*userData*/
) external {
// Flash loan is performed upon deposit and withdrawal

LeverageLendingBaseStorage storage $ = _getLeverageLendingBaseStorage();
address flashLoanVault = $.flashLoanVault;
if (msg.sender != flashLoanVault) {
revert IControllable.IncorrectMsgSender();
}

if ($.tempAction == CurrentAction.Deposit) {
// tokens[0] is collateral asset
uint tempBorrowAmount = $.tempBorrowAmount;

// supply
ISilo($.lendingVault).deposit(amounts[0], address(this), ISilo.CollateralType.Collateral);

// borrow
ISilo($.borrowingVault).borrow(tempBorrowAmount, address(this), address(this));

// swap
_swap($.borrowAsset, tokens[0], tempBorrowAmount);

// pay flash loan
IERC20(tokens[0]).safeTransfer(flashLoanVault, amounts[0] + feeAmounts[0]);

// reset temp vars
$.tempBorrowAmount = 0;
}

if ($.tempAction == CurrentAction.Withdraw) {
// tokens[0] is borrow asset
address lendingVault = $.lendingVault;
address collateralAsset = $.collateralAsset;
uint tempCollateralAmount = $.tempCollateralAmount;

// repay debt
ISilo($.borrowingVault).repay(amounts[0], address(this));

// withdraw
uint collateralAmountTotal = IERC4626(lendingVault).convertToAssets(StrategyLib.balance(lendingVault));
collateralAmountTotal -= collateralAmountTotal / 1000;
ISilo(lendingVault).withdraw(
Math.min(tempCollateralAmount, collateralAmountTotal),
address(this),
address(this),
ISilo.CollateralType.Collateral
);

// swap
_swap(collateralAsset, tokens[0], Math.min(tempCollateralAmount, StrategyLib.balance(collateralAsset)));

// pay flash loan
IERC20(tokens[0]).safeTransfer(flashLoanVault, amounts[0] + feeAmounts[0]);

// swap unnecessary borrow asset
_swap(tokens[0], collateralAsset, StrategyLib.balance(tokens[0]));

// reset temp vars
$.tempCollateralAmount = 0;
}

$.tempAction = CurrentAction.None;
}
Comment on lines +260 to +296
function _claimRevenue()
internal
override
returns (
address[] memory __assets,
uint[] memory __amounts,
address[] memory __rewardAssets,
uint[] memory __rewardAmounts
)
{
__assets = assets();
__rewardAssets = new address[](0);
__rewardAmounts = new uint[](0);
__amounts = new uint[](1);

LeverageLendingBaseStorage storage $ = _getLeverageLendingBaseStorage();
LeverageLendingAddresses memory v = LeverageLendingAddresses({
collateralAsset: $.collateralAsset,
borrowAsset: $.borrowAsset,
lendingVault: $.lendingVault,
borrowingVault: $.borrowingVault
});
StrategyBaseStorage storage $base = _getStrategyBaseStorage();

uint totalWas = $base.total;

ISilo(v.lendingVault).accrueInterest();
ISilo(v.borrowingVault).accrueInterest();

uint totalNow = StrategyLib.balance(v.collateralAsset) + _calcTotal(v);
if (totalNow > totalWas) {
__amounts[0] = totalNow - totalWas;
}
$base.total = totalNow;
//console.log('total was', totalWas);
//console.log('total now', totalNow);
}

Check warning

Code scanning / Slither

Unused return Medium

Comment on lines +260 to +296
function _claimRevenue()
internal
override
returns (
address[] memory __assets,
uint[] memory __amounts,
address[] memory __rewardAssets,
uint[] memory __rewardAmounts
)
{
__assets = assets();
__rewardAssets = new address[](0);
__rewardAmounts = new uint[](0);
__amounts = new uint[](1);

LeverageLendingBaseStorage storage $ = _getLeverageLendingBaseStorage();
LeverageLendingAddresses memory v = LeverageLendingAddresses({
collateralAsset: $.collateralAsset,
borrowAsset: $.borrowAsset,
lendingVault: $.lendingVault,
borrowingVault: $.borrowingVault
});
StrategyBaseStorage storage $base = _getStrategyBaseStorage();

uint totalWas = $base.total;

ISilo(v.lendingVault).accrueInterest();
ISilo(v.borrowingVault).accrueInterest();

uint totalNow = StrategyLib.balance(v.collateralAsset) + _calcTotal(v);
if (totalNow > totalWas) {
__amounts[0] = totalNow - totalWas;
}
$base.total = totalNow;
//console.log('total was', totalWas);
//console.log('total now', totalNow);
}

Check warning

Code scanning / Slither

Unused return Medium

Comment on lines +314 to +348
function _depositAssets(uint[] memory amounts, bool /*claimRevenue*/ ) internal override returns (uint value) {
LeverageLendingBaseStorage storage $ = _getLeverageLendingBaseStorage();
$.tempAction = CurrentAction.Deposit;
LeverageLendingAddresses memory v = LeverageLendingAddresses({
collateralAsset: $.collateralAsset,
borrowAsset: $.borrowAsset,
lendingVault: $.lendingVault,
borrowingVault: $.borrowingVault
});
address[] memory _assets = assets();
uint valueWas = StrategyLib.balance(_assets[0]) + _calcTotal(v);

(uint maxLtv,, uint targetLeverage) = _getLtvData(v.lendingVault, $.targetLeveragePercent);

uint[] memory flashAmounts = new uint[](1);
flashAmounts[0] = amounts[0] * targetLeverage / INTERNAL_PRECISION;

(uint priceCtoB,) = _getPrices(ISilo(v.lendingVault).config(), v.lendingVault, v.borrowingVault);
$.tempBorrowAmount = (flashAmounts[0] * maxLtv / 1e18) * priceCtoB / 1e18 - 2;

IBVault($.flashLoanVault).flashLoan(address(this), _assets, flashAmounts, "");

uint valueNow = StrategyLib.balance(_assets[0]) + _calcTotal(v);

if (valueNow > valueWas) {
// deposit profit
value = amounts[0] + (valueNow - valueWas);
} else {
// deposit loss
value = amounts[0] - (valueWas - valueNow);
}

StrategyBaseStorage storage $base = _getStrategyBaseStorage();
$base.total += value;
}

Check warning

Code scanning / Slither

Divide before multiply Medium

Comment on lines +351 to +393
function _withdrawAssets(uint value, address receiver) internal override returns (uint[] memory amountsOut) {
LeverageLendingBaseStorage storage $ = _getLeverageLendingBaseStorage();
$.tempAction = CurrentAction.Withdraw;
LeverageLendingAddresses memory v = LeverageLendingAddresses({
collateralAsset: $.collateralAsset,
borrowAsset: $.borrowAsset,
lendingVault: $.lendingVault,
borrowingVault: $.borrowingVault
});
amountsOut = new uint[](1);

uint valueWas = StrategyLib.balance(v.collateralAsset) + _calcTotal(v);

(uint maxLtv, uint maxLeverage,) = _getLtvData(v.lendingVault, $.targetLeveragePercent);

(uint priceCtoB,) = _getPrices(ISilo(v.lendingVault).config(), v.lendingVault, $.borrowingVault);

{
uint collateralAmountToWithdraw = value * maxLeverage / INTERNAL_PRECISION;
$.tempCollateralAmount = collateralAmountToWithdraw;
uint[] memory flashAmounts = new uint[](1);
flashAmounts[0] = (collateralAmountToWithdraw * maxLtv / 1e18) * priceCtoB / 1e18;
address[] memory flashAssets = new address[](1);
flashAssets[0] = $.borrowAsset;
IBVault($.flashLoanVault).flashLoan(address(this), flashAssets, flashAmounts, "");
}

uint valueNow = StrategyLib.balance(v.collateralAsset) + _calcTotal(v);

uint bal = StrategyLib.balance(v.collateralAsset);
if (valueWas > valueNow) {
//console.log('withdraw loss', valueWas - valueNow);
amountsOut[0] = Math.min(value - (valueWas - valueNow), bal);
} else {
//console.log('withdraw profit', valueNow - valueWas);
amountsOut[0] = Math.min(value + (valueNow - valueWas), bal);
}

IERC20(v.collateralAsset).safeTransfer(receiver, amountsOut[0]);

StrategyBaseStorage storage $base = _getStrategyBaseStorage();
$base.total -= value;
}

Check warning

Code scanning / Slither

Divide before multiply Medium

Comment on lines +421 to +430
function _getLtvData(
address lendingVault,
uint targetLeveragePercent
) internal view returns (uint maxLtv, uint maxLeverage, uint targetLeverage) {
address configContract = ISilo(lendingVault).config();
ISiloConfig.ConfigData memory config = ISiloConfig(configContract).getConfig(lendingVault);
maxLtv = config.maxLtv;
maxLeverage = 1e18 * INTERNAL_PRECISION / (1e18 - maxLtv);
targetLeverage = maxLeverage * targetLeveragePercent / INTERNAL_PRECISION;
}

Check warning

Code scanning / Slither

Divide before multiply Medium

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

📜 [DEVELOPMENT] Silo Leverage
1 participant