Skip to content

Commit

Permalink
Merge pull request #166 from Popcorn-Limited/feat/pendle-adapter
Browse files Browse the repository at this point in the history
Feat/pendle adapter
  • Loading branch information
RedVeil authored Jun 14, 2024
2 parents 8e9b443 + bb99404 commit 8d2b07d
Show file tree
Hide file tree
Showing 23 changed files with 1,663 additions and 77 deletions.
13 changes: 3 additions & 10 deletions script/deploy/lido/WstETHLooper.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,10 @@ contract DeployStrategy is Script {
IERC20 vdWETH;

function run() public {
string memory json = vm.readFile(
string.concat(
vm.projectRoot(),
"./srcript/deploy/lido/WstETHLooperDeployConfig.json"
)
);
string memory json =
vm.readFile(string.concat(vm.projectRoot(), "./srcript/deploy/lido/WstETHLooperDeployConfig.json"));

LooperInitValues memory looperValues = abi.decode(
json.parseRaw(".strategyInit"),
(LooperInitValues)
);
LooperInitValues memory looperValues = abi.decode(json.parseRaw(".strategyInit"), (LooperInitValues));

// Deploy Strategy
WstETHLooper strategy = new WstETHLooper();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.25

pragma solidity ^0.8.25;

import {IERC20} from "openzeppelin-contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol";
Expand All @@ -9,6 +12,15 @@ enum SwapKind {

interface IAsset {}

struct SingleSwap {
bytes32 poolId;
SwapKind kind;
address assetIn;
address assetOut;
uint256 amount;
bytes userData;
}

struct BatchSwapStep {
bytes32 poolId;
uint256 assetInIndex;
Expand Down Expand Up @@ -52,3 +64,37 @@ interface IBalancerVault {
external
payable;
}

interface IBalancerRouter {
function swap(SingleSwap memory singleSwap, FundManagement memory funds, uint256 limit, uint256 deadline)
external
returns (uint256 amountCalculated);
}

interface IGauge {
function lp_token() external view returns (address);

function bal_token() external view returns (address);

function is_killed() external view returns (bool);

function totalSupply() external view returns (uint256);

function balanceOf(address user) external view returns (uint256);

function withdraw(uint256 amount, bool _claim_rewards) external;

function deposit(uint256 amount) external;
}

interface IMinter {
function mint(address gauge) external;

function getBalancerToken() external view returns (address);

function getGaugeController() external view returns (address);
}

interface IController {
function gauge_exists(address _gauge) external view returns (bool);
}
2 changes: 1 addition & 1 deletion src/peripheral/BalancerTradeLibrary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
BatchSwapStep,
FundManagement,
JoinPoolRequest
} from "../interfaces/external/balancer/IBalancerVault.sol";
} from "../interfaces/external/balancer/IBalancer.sol";

library BalancerTradeLibrary {
function trade(
Expand Down
16 changes: 9 additions & 7 deletions src/peripheral/BaseBalancerCompounder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
pragma solidity ^0.8.25;

import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
import {BalancerTradeLibrary, IBalancerVault, IAsset, BatchSwapStep} from "./BalancerTradeLibrary.sol";

struct TradePath {
Expand All @@ -13,10 +14,11 @@ struct TradePath {
}

abstract contract BaseBalancerCompounder {
using SafeERC20 for IERC20;
IBalancerVault public balancerVault;

address[] public _balancerSellTokens;
TradePath[] public tradePaths;
address[] public _rewardTokens;

function sellRewardsViaBalancer() internal {
// Caching
Expand All @@ -43,15 +45,15 @@ abstract contract BaseBalancerCompounder {

function setBalancerTradeValues(address newBalancerVault, TradePath[] memory newTradePaths) internal {
// Remove old rewardToken allowance
uint256 rewardTokenLen = _rewardTokens.length;
uint256 rewardTokenLen = _balancerSellTokens.length;
if (rewardTokenLen > 0) {
// caching
address oldBalancerVault = address(balancerVault);
address[] memory oldRewardTokens = _rewardTokens;
address[] memory oldRewardTokens = _balancerSellTokens;

// void approvals
for (uint256 i = 0; i < rewardTokenLen;) {
IERC20(oldRewardTokens[i]).approve(oldBalancerVault, 0);
IERC20(oldRewardTokens[i]).forceApprove(oldBalancerVault, 0);

unchecked {
++i;
Expand All @@ -60,7 +62,7 @@ abstract contract BaseBalancerCompounder {
}

// delete old state
delete _rewardTokens;
delete _balancerSellTokens;
delete tradePaths;

// Add new allowance + state
Expand All @@ -69,9 +71,9 @@ abstract contract BaseBalancerCompounder {
for (uint256 i; i < rewardTokenLen;) {
newRewardToken = address(newTradePaths[i].assets[0]);

IERC20(newRewardToken).approve(newBalancerVault, type(uint256).max);
IERC20(newRewardToken).forceApprove(newBalancerVault, type(uint256).max);

_rewardTokens.push(newRewardToken);
_balancerSellTokens.push(newRewardToken);
tradePaths.push(newTradePaths[i]);

unchecked {
Expand Down
7 changes: 5 additions & 2 deletions src/peripheral/BaseBalancerLpCompounder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
pragma solidity ^0.8.25;

import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
import {BaseBalancerCompounder, BalancerTradeLibrary, TradePath} from "./BaseBalancerCompounder.sol";

struct HarvestValues {
Expand All @@ -16,6 +17,8 @@ struct HarvestValues {
}

abstract contract BaseBalancerLpCompounder is BaseBalancerCompounder {
using SafeERC20 for IERC20;

HarvestValues public harvestValues;

error CompoundFailed();
Expand Down Expand Up @@ -52,10 +55,10 @@ abstract contract BaseBalancerLpCompounder is BaseBalancerCompounder {

// Reset old base asset
if (harvestValues.depositAsset != address(0)) {
IERC20(harvestValues.depositAsset).approve(address(balancerVault), 0);
IERC20(harvestValues.depositAsset).forceApprove(address(balancerVault), 0);
}
// approve and set new base asset
IERC20(harvestValues_.depositAsset).approve(newBalancerVault, type(uint256).max);
IERC20(harvestValues_.depositAsset).forceApprove(newBalancerVault, type(uint256).max);

harvestValues = harvestValues_;
}
Expand Down
33 changes: 18 additions & 15 deletions src/peripheral/BaseCurveCompounder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,22 @@
pragma solidity ^0.8.25;

import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
import {ICurveRouter, CurveSwap, ICurveLp} from "../strategies/curve/ICurve.sol";
import {CurveTradeLibrary} from "./CurveTradeLibrary.sol";

abstract contract BaseCurveCompounder {
using SafeERC20 for IERC20;

ICurveRouter public curveRouter;

address[] public _rewardTokens;
CurveSwap[] internal swaps; // Must be ordered like `_rewardTokens`
address[] public _curveSellTokens;
CurveSwap[] internal curveSwaps; // Must be ordered like `_sellTokens`

function sellRewardsViaCurve() internal {
// caching
ICurveRouter router = curveRouter;
CurveSwap[] memory sellSwaps = swaps;
CurveSwap[] memory sellSwaps = curveSwaps;

uint256 amount;
uint256 rewLen = sellSwaps.length;
Expand All @@ -35,15 +38,15 @@ abstract contract BaseCurveCompounder {

function setCurveTradeValues(address newRouter, CurveSwap[] memory newSwaps) internal {
// Remove old rewardToken allowance
uint256 rewardTokenLen = _rewardTokens.length;
if (rewardTokenLen > 0) {
uint256 sellTokensLen = _curveSellTokens.length;
if (sellTokensLen > 0) {
// caching
address oldRouter = address(curveRouter);
address[] memory oldRewardTokens = _rewardTokens;
address[] memory oldSellTokens = _curveSellTokens;

// void approvals
for (uint256 i = 0; i < rewardTokenLen;) {
IERC20(oldRewardTokens[i]).approve(oldRouter, 0);
for (uint256 i = 0; i < sellTokensLen;) {
IERC20(oldSellTokens[i]).forceApprove(oldRouter, 0);

unchecked {
++i;
Expand All @@ -52,19 +55,19 @@ abstract contract BaseCurveCompounder {
}

// delete old state
delete _rewardTokens;
delete swaps;
delete _curveSellTokens;
delete curveSwaps;

// Add new allowance + state
address newRewardToken;
rewardTokenLen = newSwaps.length;
for (uint256 i = 0; i < rewardTokenLen;) {
sellTokensLen = newSwaps.length;
for (uint256 i = 0; i < sellTokensLen;) {
newRewardToken = newSwaps[i].route[0];

IERC20(newRewardToken).approve(newRouter, type(uint256).max);
IERC20(newRewardToken).forceApprove(newRouter, type(uint256).max);

_rewardTokens.push(newRewardToken);
swaps.push(newSwaps[i]);
_curveSellTokens.push(newRewardToken);
curveSwaps.push(newSwaps[i]);

unchecked {
++i;
Expand Down
7 changes: 5 additions & 2 deletions src/peripheral/BaseCurveLpCompounder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
pragma solidity ^0.8.25;

import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
import {BaseCurveCompounder, CurveTradeLibrary, CurveSwap, ICurveLp} from "./BaseCurveCompounder.sol";

abstract contract BaseCurveLpCompounder is BaseCurveCompounder {
using SafeERC20 for IERC20;

address public depositAsset;
int128 public indexIn;

Expand Down Expand Up @@ -36,9 +39,9 @@ abstract contract BaseCurveLpCompounder is BaseCurveCompounder {

address depositAsset_ = ICurveLp(poolAddress).coins(uint256(uint128(indexIn_)));
if (depositAsset != address(0)) {
IERC20(depositAsset).approve(poolAddress, 0);
IERC20(depositAsset).forceApprove(poolAddress, 0);
}
IERC20(depositAsset_).approve(poolAddress, type(uint256).max);
IERC20(depositAsset_).forceApprove(poolAddress, type(uint256).max);

depositAsset = depositAsset_;
indexIn = indexIn_;
Expand Down
2 changes: 1 addition & 1 deletion src/strategies/aura/AuraCompounder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ contract AuraCompounder is BaseStrategy, BaseBalancerLpCompounder {

/// @notice The token rewarded
function rewardTokens() external view override returns (address[] memory) {
return _rewardTokens;
return _balancerSellTokens;
}

/*//////////////////////////////////////////////////////////////
Expand Down
4 changes: 2 additions & 2 deletions src/strategies/balancer/BalancerCompounder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
pragma solidity ^0.8.25;

import {BaseStrategy, IERC20, IERC20Metadata, SafeERC20, ERC20, Math} from "../BaseStrategy.sol";
import {IMinter, IGauge} from "./IBalancer.sol";
import {IMinter, IGauge} from "../../interfaces/external/balancer/IBalancer.sol";
import {BaseBalancerLpCompounder, HarvestValues, TradePath} from "../../peripheral/BaseBalancerLpCompounder.sol";

/**
Expand Down Expand Up @@ -76,7 +76,7 @@ contract BalancerCompounder is BaseStrategy, BaseBalancerLpCompounder {

/// @notice The token rewarded
function rewardTokens() external view override returns (address[] memory) {
return _rewardTokens;
return _balancerSellTokens;
}

/*//////////////////////////////////////////////////////////////
Expand Down
32 changes: 0 additions & 32 deletions src/strategies/balancer/IBalancer.sol

This file was deleted.

2 changes: 1 addition & 1 deletion src/strategies/convex/ConvexCompounder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ contract ConvexCompounder is BaseStrategy, BaseCurveLpCompounder {

/// @notice The token rewarded from the convex reward contract
function rewardTokens() external view override returns (address[] memory) {
return _rewardTokens;
return _curveSellTokens;
}

/*//////////////////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion src/strategies/curve/CurveGaugeCompounder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ contract CurveGaugeCompounder is BaseStrategy, BaseCurveLpCompounder {

/// @notice The token rewarded from the convex reward contract
function rewardTokens() external view override returns (address[] memory) {
return _rewardTokens;
return _curveSellTokens;
}

/*//////////////////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion src/strategies/curve/CurveGaugeSingleAssetCompounder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ contract CurveGaugeSingleAssetCompounder is BaseStrategy, BaseCurveCompounder {

/// @notice The token rewarded from the convex reward contract
function rewardTokens() external view override returns (address[] memory) {
return _rewardTokens;
return _curveSellTokens;
}

function previewDeposit(uint256 assets) public view override returns (uint256) {
Expand Down
Loading

0 comments on commit 8d2b07d

Please sign in to comment.