Skip to content

Commit

Permalink
merged with upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
vminkov committed Oct 24, 2024
2 parents ce49e26 + 6e55000 commit ed86436
Show file tree
Hide file tree
Showing 189 changed files with 9,344 additions and 3,164 deletions.
6 changes: 3 additions & 3 deletions packages/chains/src/base/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,9 @@ export const assets: SupportedAsset[] = [
aggregator: "0x64c911996D3c6aC71f9b455B1E8E7266BcbD848F",
feedBaseCurrency: ChainlinkFeedBaseCurrency.USD
},
initialSupplyCap: parseUnits(String(1), 8).toString(),
initialBorrowCap: parseUnits(String(1), 8).toString(),
initialCf: "0.30",
initialSupplyCap: parseUnits(String(1200), 8).toString(),
initialBorrowCap: parseUnits(String(900), 8).toString(),
initialCf: "0.80",
extraDocs: defaultDocs("https://basescan.org", cbBTC)
},
{
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts/contracts/bridge/xERC20LayerZero.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.22;
import { OApp, Origin, MessagingFee, MessagingReceipt } from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
import { OptionsBuilder } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OptionsBuilder.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { IXERC20 } from "./interface/IXERC20.sol";

contract xERC20LayerZero is Ownable, OApp {
Expand Down
6 changes: 3 additions & 3 deletions packages/contracts/contracts/external/aerodrome/IRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.10;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
interface IERC20_Router {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
Expand Down Expand Up @@ -75,13 +75,13 @@ interface IERC20 {
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

interface IWETH is IERC20 {
interface IWETH is IERC20_Router {
function deposit() external payable;

function withdraw(uint256) external;
}

interface IRouter {
interface IRouter_Aerodrome {
struct Route {
address from;
address to;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity ^0.8.10;

/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via CL
interface ISwapRouter {
interface ISwapRouter_Aerodrome {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IRouter {
interface IRouter_Velodrome {
struct Route {
address from;
address to;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ interface ILeveredPositionFactoryFirstExtension {
function getBorrowableMarketsByCollateral(ICErc20 _collateralMarket) external view returns (address[] memory);

function getPositionsExtension(bytes4 msgSig) external view returns (address);

function _setPositionsExtension(bytes4 msgSig, address extension) external;
}

interface ILeveredPositionFactorySecondExtension {
Expand Down
13 changes: 13 additions & 0 deletions packages/contracts/contracts/ionic/levered/LeveredPosition.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import { LeveredPositionStorage } from "./LeveredPositionStorage.sol";
import "openzeppelin-contracts-upgradeable/contracts/token/ERC20/utils/SafeERC20Upgradeable.sol";
import "openzeppelin-contracts-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol";

interface IFlywheelLensRouter_LP {
function claimAllRewardTokens(address user) external returns (address[] memory, uint256[] memory);
}

contract LeveredPosition is LeveredPositionStorage, IFlashLoanReceiver {
using SafeERC20Upgradeable for IERC20Upgradeable;

Expand Down Expand Up @@ -172,6 +176,15 @@ contract LeveredPosition is LeveredPositionStorage, IFlashLoanReceiver {
asset.transfer(positionOwner, asset.balanceOf(address(this)));
}

function claimRewardsFromRouter(address _flr) external returns (address[] memory, uint256[] memory) {
IFlywheelLensRouter_LP flr = IFlywheelLensRouter_LP(_flr);
(address[] memory rewardTokens, uint256[] memory rewards) = flr.claimAllRewardTokens(address(this));
for (uint256 i = 0; i < rewardTokens.length; i++) {
IERC20Upgradeable(rewardTokens[i]).safeTransfer(positionOwner, rewards[i]);
}
return (rewardTokens, rewards);
}

fallback() external {
address extension = factory.getPositionsExtension(msg.sig);
if (extension == address(0)) revert ExtNotFound(msg.sig);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ contract LeveredPositionFactoryFirstExtension is
error PositionNotClosed();

function _getExtensionFunctions() external pure override returns (bytes4[] memory) {
uint8 fnsCount = 9;
uint8 fnsCount = 10;
bytes4[] memory functionSelectors = new bytes4[](fnsCount);
functionSelectors[--fnsCount] = this.removeClosedPosition.selector;
functionSelectors[--fnsCount] = this.closeAndRemoveUserPosition.selector;
Expand All @@ -40,6 +40,8 @@ contract LeveredPositionFactoryFirstExtension is
functionSelectors[--fnsCount] = this.getAccountsWithOpenPositions.selector;
functionSelectors[--fnsCount] = this.getPositionsByAccount.selector;
functionSelectors[--fnsCount] = this.getPositionsExtension.selector;
functionSelectors[--fnsCount] = this._setPositionsExtension.selector;

require(fnsCount == 0, "use the correct array length");
return functionSelectors;
}
Expand Down Expand Up @@ -68,6 +70,10 @@ contract LeveredPositionFactoryFirstExtension is
if (userPositions.length() == 0) accountsWithOpenPositions.remove(positionOwner);
}

function _setPositionsExtension(bytes4 msgSig, address extension) external onlyOwner {
_positionsExtensions[msgSig] = extension;
}

/*----------------------------------------------------------------
View Functions
----------------------------------------------------------------*/
Expand All @@ -76,19 +82,16 @@ contract LeveredPositionFactoryFirstExtension is
return feeDistributor.minBorrowEth();
}

function getRedemptionStrategies(IERC20Upgradeable inputToken, IERC20Upgradeable outputToken)
external
view
returns (IRedemptionStrategy[] memory strategies, bytes[] memory strategiesData)
{
function getRedemptionStrategies(
IERC20Upgradeable inputToken,
IERC20Upgradeable outputToken
) external view returns (IRedemptionStrategy[] memory strategies, bytes[] memory strategiesData) {
return liquidatorsRegistry.getRedemptionStrategies(inputToken, outputToken);
}

function getPositionsByAccount(address account)
external
view
returns (address[] memory positions, bool[] memory closed)
{
function getPositionsByAccount(
address account
) external view returns (address[] memory positions, bool[] memory closed) {
positions = positionsByAccount[account].values();
closed = new bool[](positions.length);
for (uint256 i = 0; i < positions.length; i++) {
Expand All @@ -109,7 +112,6 @@ contract LeveredPositionFactoryFirstExtension is
}

function getPositionsExtension(bytes4 msgSig) external view returns (address) {
// TODO return the address of some freshly created levered position
return address(0);
return _positionsExtensions[msgSig];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ abstract contract LeveredPositionFactoryStorage is SafeOwnable {
IFeeDistributor public feeDistributor;
ILiquidatorsRegistry public liquidatorsRegistry;
uint256 public blocksPerYear;

mapping(bytes4 => address) internal _positionsExtensions;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity >=0.8.0;

import { IRedemptionStrategy } from "./IRedemptionStrategy.sol";
import { ISwapRouter } from "../external/aerodrome/ISwapRouter.sol";
import { ISwapRouter_Aerodrome } from "../external/aerodrome/ISwapRouter.sol";

import { IERC20Upgradeable } from "openzeppelin-contracts-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol";
import { IERC4626 } from "../compound/IERC4626.sol";
Expand Down Expand Up @@ -31,11 +31,11 @@ contract AerodromeCLLiquidator is IRedemptionStrategy {
(
,
address _outputToken,
ISwapRouter swapRouter,
ISwapRouter_Aerodrome swapRouter,
address _unwrappedInput,
address _unwrappedOutput,
int24 _tickSpacing
) = abi.decode(strategyData, (address, address, ISwapRouter, address, address, int24));
) = abi.decode(strategyData, (address, address, ISwapRouter_Aerodrome, address, address, int24));
if (_unwrappedOutput != address(0)) {
outputToken = IERC20Upgradeable(_unwrappedOutput);
} else {
Expand All @@ -51,7 +51,7 @@ contract AerodromeCLLiquidator is IRedemptionStrategy {
inputToken.approve(address(swapRouter), inputAmount);

outputAmount = swapRouter.exactInputSingle(
ISwapRouter.ExactInputSingleParams(
ISwapRouter_Aerodrome.ExactInputSingleParams(
address(inputToken),
address(outputToken),
_tickSpacing,
Expand Down
14 changes: 10 additions & 4 deletions packages/contracts/contracts/liquidators/AerodromeV2Liquidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
pragma solidity >=0.8.0;
import "openzeppelin-contracts-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol";

import { IRouter } from "../external/aerodrome/IRouter.sol";
import { IRouter_Aerodrome } from "../external/aerodrome/IRouter.sol";

/**
* @title UniswapV2Liquidator
* @notice Exchanges seized token collateral for underlying tokens via a Uniswap V2 router for use as a step in a liquidation.
* @author David Lucid <[email protected]> (https://github.com/davidlucid)
*/
contract AerodromeV2Liquidator {
function _swap(IRouter router, uint256 inputAmount, IRouter.Route[] memory swapPath) internal {
function _swap(IRouter_Aerodrome router, uint256 inputAmount, IRouter_Aerodrome.Route[] memory swapPath) internal {
router.swapExactTokensForTokens(inputAmount, 0, swapPath, address(this), block.timestamp);
}

Expand Down Expand Up @@ -40,8 +40,14 @@ contract AerodromeV2Liquidator {
bytes memory strategyData
) internal returns (IERC20Upgradeable outputToken, uint256 outputAmount) {
// Get Uniswap router and path
(IRouter router, IRouter.Route[] memory swapPath) = abi.decode(strategyData, (IRouter, IRouter.Route[]));
require(swapPath.length >= 1 && swapPath[0].from == address(inputToken), "Invalid AerodromeV2Liquidator swap path.");
(IRouter_Aerodrome router, IRouter_Aerodrome.Route[] memory swapPath) = abi.decode(
strategyData,
(IRouter_Aerodrome, IRouter_Aerodrome.Route[])
);
require(
swapPath.length >= 1 && swapPath[0].from == address(inputToken),
"Invalid AerodromeV2Liquidator swap path."
);

// Swap underlying tokens
inputToken.approve(address(router), inputAmount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
pragma solidity >=0.8.0;
import "openzeppelin-contracts-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol";

import { IRouter } from "../external/velodrome/IRouter.sol";
import { IRouter_Velodrome } from "../external/velodrome/IRouter.sol";

/**
* @title VelodromeV2Liquidator
* @notice Exchanges seized token collateral for underlying tokens via a Velodrome V2 router for use as a step in a liquidation.
*/
contract VelodromeV2Liquidator {
function _swap(IRouter router, uint256 inputAmount, IRouter.Route[] memory swapPath) internal {
function _swap(IRouter_Velodrome router, uint256 inputAmount, IRouter_Velodrome.Route[] memory swapPath) internal {
router.swapExactTokensForTokens(inputAmount, 0, swapPath, address(this), block.timestamp);
}

Expand Down Expand Up @@ -39,7 +39,10 @@ contract VelodromeV2Liquidator {
bytes memory strategyData
) internal returns (IERC20Upgradeable outputToken, uint256 outputAmount) {
// Get Uniswap router and path
(IRouter router, IRouter.Route[] memory swapPath) = abi.decode(strategyData, (IRouter, IRouter.Route[]));
(IRouter_Velodrome router, IRouter_Velodrome.Route[] memory swapPath) = abi.decode(
strategyData,
(IRouter_Velodrome, IRouter_Velodrome.Route[])
);
require(swapPath.length >= 1 && swapPath[0].from == address(inputToken), "Invalid VelodromeV2Liquidator swap path.");

// Swap underlying tokens
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import "../IRedemptionStrategy.sol";
import "../../ionic/DiamondExtension.sol";
import { MasterPriceOracle } from "../../oracles/MasterPriceOracle.sol";

import { IRouter as IAerodromeV2Router } from "../../external/aerodrome/IRouter.sol";
import { IRouter as IVelodromeV2Router } from "../../external/velodrome/IRouter.sol";
import { IRouter_Aerodrome as IAerodromeV2Router } from "../../external/aerodrome/IRouter.sol";
import { IRouter_Velodrome as IVelodromeV2Router } from "../../external/velodrome/IRouter.sol";
import { IRouter } from "../../external/solidly/IRouter.sol";
import { IPair } from "../../external/solidly/IPair.sol";
import { IUniswapV2Pair } from "../../external/uniswap/IUniswapV2Pair.sol";
Expand Down
69 changes: 52 additions & 17 deletions packages/contracts/contracts/test/DevTesting.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { IonicComptroller } from "../compound/ComptrollerInterface.sol";
import { ComptrollerFirstExtension } from "../compound/ComptrollerFirstExtension.sol";
import { CErc20PluginRewardsDelegate } from "../compound/CErc20PluginRewardsDelegate.sol";
import { Unitroller } from "../compound/Unitroller.sol";
import { DiamondExtension } from "../ionic/DiamondExtension.sol";
import { DiamondExtension, DiamondBase } from "../ionic/DiamondExtension.sol";
import { ICErc20 } from "../compound/CTokenInterfaces.sol";
import { ISwapRouter } from "../external/uniswap/ISwapRouter.sol";
import { RedstoneAdapterPriceOracle } from "../oracles/default/RedstoneAdapterPriceOracle.sol";
Expand All @@ -23,16 +23,21 @@ import { JumpRateModel } from "../compound/JumpRateModel.sol";
import { LeveredPositionsLens } from "../ionic/levered/LeveredPositionsLens.sol";
import { ILiquidatorsRegistry } from "../liquidators/registry/ILiquidatorsRegistry.sol";
import { ILeveredPositionFactory } from "../ionic/levered/ILeveredPositionFactory.sol";
import { LeveredPositionFactoryFirstExtension } from "../ionic/levered/LeveredPositionFactoryFirstExtension.sol";
import { LeveredPositionFactorySecondExtension } from "../ionic/levered/LeveredPositionFactorySecondExtension.sol";
import { LeveredPositionFactory } from "../ionic/levered/LeveredPositionFactory.sol";
import { LeveredPositionStorage } from "../ionic/levered/LeveredPositionStorage.sol";
import { LeveredPosition } from "../ionic/levered/LeveredPosition.sol";
import { IonicFlywheelLensRouter, IonicComptroller, ICErc20, ERC20, IPriceOracle_IFLR } from "../ionic/strategies/flywheel/IonicFlywheelLensRouter.sol";
import { PoolDirectory } from "../PoolDirectory.sol";
import { AlgebraSwapLiquidator } from "../liquidators/AlgebraSwapLiquidator.sol";
import { AerodromeV2Liquidator } from "../liquidators/AerodromeV2Liquidator.sol";
import { AerodromeCLLiquidator } from "../liquidators/AerodromeCLLiquidator.sol";
import { CurveSwapLiquidator } from "../liquidators/CurveSwapLiquidator.sol";
import { CurveV2LpTokenPriceOracleNoRegistry } from "../oracles/default/CurveV2LpTokenPriceOracleNoRegistry.sol";
import { IRouter } from "../external/aerodrome/IRouter.sol";
import { IRouter_Aerodrome } from "../external/aerodrome/IRouter.sol";
import { VelodromeV2Liquidator } from "../liquidators/VelodromeV2Liquidator.sol";
import { IRouter as IVelodromeV2Router } from "../external/velodrome/IRouter.sol";
import { IRouter_Velodrome } from "../external/velodrome/IRouter.sol";
import "forge-std/console.sol";

struct HealthFactorVars {
Expand Down Expand Up @@ -688,8 +693,8 @@ contract DevTesting is BaseTest {

vm.startPrank(eusdWhale);
eUSD.transfer(address(liquidator), 1000 ether);
IRouter.Route[] memory path = new IRouter.Route[](1);
path[0] = IRouter.Route({
IRouter_Aerodrome.Route[] memory path = new IRouter_Aerodrome.Route[](1);
path[0] = IRouter_Aerodrome.Route({
from: address(eUSD),
to: address(usdc),
stable: true,
Expand Down Expand Up @@ -804,12 +809,8 @@ contract DevTesting is BaseTest {

vm.startPrank(usdcWhale);
usdc.transfer(address(liquidator), 1000 * 10e6);
IVelodromeV2Router.Route[] memory path = new IVelodromeV2Router.Route[](1);
path[0] = IVelodromeV2Router.Route({
from: address(usdc),
to: address(weth),
stable: false
});
IRouter_Velodrome.Route[] memory path = new IRouter_Velodrome.Route[](1);
path[0] = IRouter_Velodrome.Route({ from: address(usdc), to: address(weth), stable: false });
liquidator.redeem(usdc, 1000 * 10e6, abi.encode(veloRouter, path));
emit log_named_uint("weth received", weth.balanceOf(address(liquidator)));
vm.stopPrank();
Expand All @@ -825,18 +826,52 @@ contract DevTesting is BaseTest {

vm.startPrank(wethWhale);
weth.transfer(address(liquidator), 1 ether);
IVelodromeV2Router.Route[] memory path = new IVelodromeV2Router.Route[](1);
path[0] = IVelodromeV2Router.Route({
from: address(weth),
to: address(usdc),
stable: false
});
IRouter_Velodrome.Route[] memory path = new IRouter_Velodrome.Route[](1);
path[0] = IRouter_Velodrome.Route({ from: address(weth), to: address(usdc), stable: false });

liquidator.redeem(weth, 1 ether, abi.encode(veloRouter, path));
emit log_named_uint("usdc received", usdc.balanceOf(address(liquidator)));
vm.stopPrank();
}

function test_claimRewardFromLeveredPosition() public debuggingOnly fork(BASE_MAINNET) {
LeveredPosition position = LeveredPosition(
0x3a0eA2C577b0e0f2CAaEcC2b8fF8fF1850267ba2 // 20 days old
);
ILeveredPositionFactory factory = position.factory();

vm.prank(address(factory));
LeveredPosition dummy = new LeveredPosition(
msg.sender,
ICErc20(0x49420311B518f3d0c94e897592014de53831cfA3),
ICErc20(0xa900A17a49Bc4D442bA7F72c39FA2108865671f0)
);
emit log_named_address("dummy", address(dummy));

vm.startPrank(factory.owner());
DiamondBase(address(factory))._registerExtension(
new LeveredPositionFactoryFirstExtension(),
DiamondExtension(0x115455f15ef67e298F012F225B606D3c4Daa1d60)
);
factory._setPositionsExtension(LeveredPosition.claimRewardsFromRouter.selector, address(dummy));
vm.stopPrank();

{
// mock the usdz call
vm.mockCall(
0x04D5ddf5f3a8939889F11E97f8c4BB48317F1938,
abi.encodeWithSelector(IERC20Upgradeable.balanceOf.selector),
abi.encode(53307671999615298341926)
);
}

vm.startPrank(0xC13110d04f22ed464Cb72A620fF8163585358Ff9);
(address[] memory rewardTokens, uint256[] memory rewards) = position.claimRewardsFromRouter(0xB1402333b12fc066C3D7F55d37944D5e281a3e8B);
emit log_named_uint("reward tokens", rewardTokens.length);
emit log_named_uint("rewards", rewards.length);
vm.stopPrank();
}

function _functionCall(
address target,
bytes memory data,
Expand Down
Loading

0 comments on commit ed86436

Please sign in to comment.