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

Add Alchemix Integration #192

Merged
merged 21 commits into from
Jul 13, 2021
Merged
Show file tree
Hide file tree
Changes from 18 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
5 changes: 0 additions & 5 deletions contracts/interfaces/IPlatformIntegration.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,4 @@ interface IPlatformIntegration {
* @dev Returns the current balance of the given bAsset
*/
function checkBalance(address _bAsset) external returns (uint256 balance);

/**
* @dev Returns the pToken
*/
function bAssetToPToken(address _bAsset) external returns (address pToken);
}
59 changes: 39 additions & 20 deletions contracts/masset/liquidator/Liquidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ contract Liquidator is ILiquidator, Initializable, ModuleKeysStorage, ImmutableM
IUniswapV3Quoter public immutable uniswapQuoter;
/// @notice Compound Token (COMP) address
address public immutable compToken;
/// @notice Alchemix (ALCX) address
address public immutable alchemixToken;

// No longer used
struct DeprecatedLiquidation {
Expand Down Expand Up @@ -91,7 +93,8 @@ contract Liquidator is ILiquidator, Initializable, ModuleKeysStorage, ImmutableM
address _aaveToken,
address _uniswapRouter,
address _uniswapQuoter,
address _compToken
address _compToken,
address _alchemixToken
) ImmutableModule(_nexus) {
require(_stkAave != address(0), "Invalid stkAAVE address");
stkAave = _stkAave;
Expand All @@ -107,15 +110,19 @@ contract Liquidator is ILiquidator, Initializable, ModuleKeysStorage, ImmutableM

require(_compToken != address(0), "Invalid COMP address");
compToken = _compToken;

require(_alchemixToken != address(0), "Invalid ALCX address");
alchemixToken = _alchemixToken;
}

/**
* @notice Liquidator approves Uniswap to transfer Aave and COMP tokens
* @notice Liquidator approves Uniswap to transfer Aave, COMP and ALCX tokens
* @dev to be called via the proxy proposeUpgrade function, not the constructor.
*/
function upgrade() external {
IERC20(aaveToken).safeApprove(address(uniswapRouter), type(uint256).max);
IERC20(compToken).safeApprove(address(uniswapRouter), type(uint256).max);
IERC20(alchemixToken).safeApprove(address(uniswapRouter), type(uint256).max);
}

/***************************************
Expand All @@ -125,8 +132,8 @@ contract Liquidator is ILiquidator, Initializable, ModuleKeysStorage, ImmutableM
/**
* @notice Create a liquidation
* @param _integration The integration contract address from which to receive sellToken
* @param _sellToken Token harvested from the integration contract. eg COMP or stkAave.
* @param _bAsset The asset to buy on Uniswap. eg USDC or WBTC
* @param _sellToken Token harvested from the integration contract. eg COMP, stkAave or ALCX.
* @param _bAsset The asset to buy on Uniswap. eg USDC, WBTC, GUSD or alUSD
* @param _uniswapPath The Uniswap V3 bytes encoded path.
* @param _trancheAmount The max amount of bAsset units to buy in each weekly tranche.
* @param _minReturn Minimum exact amount of bAsset to get for each (whole) sellToken unit
Expand Down Expand Up @@ -272,15 +279,18 @@ contract Liquidator is ILiquidator, Initializable, ModuleKeysStorage, ImmutableM

/**
* @notice Triggers a liquidation, flow (once per week):
* - Sells $COMP for $USDC (or other) on Uniswap (up to trancheAmount)
* - Mint mUSD using USDC
* - Send to SavingsManager
* - transfer sell token from integration to liquidator. eg COMP or ALCX
* - Swap sell token for bAsset on Uniswap (up to trancheAmount). eg
* - COMP for USDC
* - ALCX for alUSD
* - If bAsset in mAsset. eg USDC in mUSD
* - Mint mAsset using bAsset. eg mint mUSD using USDC.
* - Deposit mAsset to Savings Manager. eg deposit mUSD
* - else bAsset in Feeder Pool. eg alUSD in fPmUSD/alUSD.
* - Transfer bAsset to integration contract. eg transfer alUSD
* @param _integration Integration for which to trigger liquidation
*/
function triggerLiquidation(address _integration) external override {
// solium-disable-next-line security/no-tx-origin
require(tx.origin == msg.sender, "Must be EOA");

Liquidation memory liquidation = liquidations[_integration];

address bAsset = liquidation.bAsset;
Expand Down Expand Up @@ -333,15 +343,27 @@ contract Liquidator is ILiquidator, Initializable, ModuleKeysStorage, ImmutableM
);
uniswapRouter.exactInput(param);

// 4. Mint mAsset using purchased bAsset
address mAsset = liquidation.mAsset;
uint256 minted = _mint(bAsset, mAsset);

// 5. Send to SavingsManager
address savings = _savingsManager();
ISavingsManager(savings).depositLiquidation(mAsset, minted);
// If the integration contract is connected to a mAsset like mUSD or mBTC
if (mAsset != address(0)) {
// 4a. Mint mAsset using purchased bAsset
uint256 minted = _mint(bAsset, mAsset);

emit Liquidated(sellToken, mAsset, minted, bAsset);
// 5a. Send to SavingsManager
address savings = _savingsManager();
ISavingsManager(savings).depositLiquidation(mAsset, minted);

emit Liquidated(sellToken, mAsset, minted, bAsset);
} else {
// If a feeder pool like alUSD
// 4b. transfer bAsset directly to the integration contract.
// this will then increase the boosted savings vault price.
IERC20 bAssetToken = IERC20(bAsset);
uint256 bAssetBal = bAssetToken.balanceOf(address(this));
bAssetToken.transfer(_integration, bAssetBal);

emit Liquidated(aaveToken, mAsset, bAssetBal, bAsset);
}
}

/**
Expand All @@ -350,9 +372,6 @@ contract Liquidator is ILiquidator, Initializable, ModuleKeysStorage, ImmutableM
* Can only claim more stkAave if the last claim's unstake window has ended.
*/
function claimStakedAave() external override {
// solium-disable-next-line security/no-tx-origin
require(tx.origin == msg.sender, "Must be EOA");

// If the last claim has not yet been liquidated
uint256 totalAaveBalanceMemory = totalAaveBalance;
if (totalAaveBalanceMemory > 0) {
Expand Down
10 changes: 4 additions & 6 deletions contracts/masset/peripheral/AbstractIntegration.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.2;

// Internal
import { IPlatformIntegration } from "../../interfaces/IPlatformIntegration.sol";
import { Initializable } from "@openzeppelin/contracts/utils/Initializable.sol";

// Libs
import { ImmutableModule } from "../../shared/ImmutableModule.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import { Initializable } from "@openzeppelin/contracts/utils/Initializable.sol";

/**
* @title AbstractIntegration
Expand All @@ -34,11 +31,12 @@ abstract contract AbstractIntegration is
uint256 userAmount
);

// LP has write access
/// @notice mAsset or Feeder Pool using the integration. eg fPmUSD/alUSD
/// @dev LP has write access
address public immutable lpAddress;

// bAsset => pToken (Platform Specific Token Address)
mapping(address => address) public override bAssetToPToken;
mapping(address => address) public bAssetToPToken;
// Full list of all bAssets supported here
address[] internal bAssetsMapped;

Expand Down
Loading