-
Notifications
You must be signed in to change notification settings - Fork 3
Feat/aave and morpho vaults #185
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
Changes from 11 commits
43707c9
d05d40d
462e01e
e76018c
db24ac1
74b10e9
64618d2
d78beb8
cf6ae91
714194d
c50988f
675402c
8fc4cf5
23a59c1
8dbcbcd
8dfa398
e54995e
cb1033e
67c35b9
62d441b
840a2a0
4703429
478497f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity 0.8.9; | ||
|
|
||
| import {IERC20Upgradeable as IERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; | ||
| import {SafeERC20Upgradeable as SafeERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; | ||
|
|
||
| import "./DepositVault.sol"; | ||
| import "./interfaces/aave/IAaveV3Pool.sol"; | ||
|
|
||
| /** | ||
| * @title DepositVaultWithAave | ||
| * @notice Smart contract that handles mToken minting and invests | ||
| * proceeds into Aave V3 Pool | ||
| * @dev If `aaveDepositsEnabled` is false, regular deposit flow is used | ||
| * @author RedDuck Software | ||
| */ | ||
| contract DepositVaultWithAave is DepositVault { | ||
| using DecimalsCorrectionLibrary for uint256; | ||
| using SafeERC20 for IERC20; | ||
|
|
||
| /** | ||
| * @notice mapping payment token to Aave V3 Pool | ||
| */ | ||
| mapping(address => IAaveV3Pool) public aavePools; | ||
|
|
||
| /** | ||
| * @notice Whether Aave auto-invest deposits are enabled | ||
| * @dev if false, regular deposit flow will be used | ||
| */ | ||
| bool public aaveDepositsEnabled; | ||
|
|
||
| /** | ||
| * @dev leaving a storage gap for futures updates | ||
| */ | ||
| uint256[50] private __gap; | ||
|
|
||
| /** | ||
| * @notice Emitted when an Aave V3 Pool is configured for a payment token | ||
| * @param caller address of the caller | ||
| * @param token payment token address | ||
| * @param pool Aave V3 Pool address | ||
| */ | ||
| event SetAavePool( | ||
| address indexed caller, | ||
| address indexed token, | ||
| address indexed pool | ||
| ); | ||
|
|
||
| /** | ||
| * @notice Emitted when an Aave V3 Pool is removed for a payment token | ||
| * @param caller address of the caller | ||
| * @param token payment token address | ||
| */ | ||
| event RemoveAavePool(address indexed caller, address indexed token); | ||
|
|
||
| /** | ||
| * @notice Emitted when `aaveDepositsEnabled` flag is updated | ||
| * @param enabled Whether Aave deposits are enabled | ||
| */ | ||
| event SetAaveDepositsEnabled(bool indexed enabled); | ||
|
|
||
| /** | ||
| * @notice Sets the Aave V3 Pool for a specific payment token | ||
| * @param _token payment token address | ||
| * @param _aavePool Aave V3 Pool address for this token | ||
| */ | ||
| function setAavePool(address _token, address _aavePool) | ||
| external | ||
| onlyVaultAdmin | ||
| { | ||
| _validateAddress(_token, false); | ||
| _validateAddress(_aavePool, false); | ||
| require( | ||
| IAaveV3Pool(_aavePool).getReserveAToken(_token) != address(0), | ||
| "DVA: token not in pool" | ||
| ); | ||
| aavePools[_token] = IAaveV3Pool(_aavePool); | ||
| emit SetAavePool(msg.sender, _token, _aavePool); | ||
| } | ||
|
|
||
| /** | ||
| * @notice Removes the Aave V3 Pool for a specific payment token | ||
| * @param _token payment token address | ||
| */ | ||
| function removeAavePool(address _token) external onlyVaultAdmin { | ||
| require(address(aavePools[_token]) != address(0), "DVA: pool not set"); | ||
| delete aavePools[_token]; | ||
| emit RemoveAavePool(msg.sender, _token); | ||
| } | ||
|
|
||
| /** | ||
| * @notice Updates `aaveDepositsEnabled` value | ||
| * @param enabled whether Aave auto-invest deposits are enabled | ||
| */ | ||
| function setAaveDepositsEnabled(bool enabled) external onlyVaultAdmin { | ||
| aaveDepositsEnabled = enabled; | ||
| emit SetAaveDepositsEnabled(enabled); | ||
| } | ||
|
|
||
| /** | ||
| * @dev overrides original transfer to tokens receiver function | ||
| * in case of Aave deposits are disabled, it will act as the original transfer | ||
| * otherwise it will take payment tokens from user, supply them to Aave V3 Pool | ||
| * and aTokens will be minted to tokens receiver | ||
| * @param tokenIn token address | ||
| * @param amountToken amount of tokens to transfer in base18 | ||
| * @param tokensDecimals decimals of tokens | ||
| */ | ||
| function _instantTransferTokensToTokensReceiver( | ||
| address tokenIn, | ||
| uint256 amountToken, | ||
| uint256 tokensDecimals | ||
| ) internal override { | ||
| if (!aaveDepositsEnabled) { | ||
| return | ||
| super._instantTransferTokensToTokensReceiver( | ||
| tokenIn, | ||
| amountToken, | ||
| tokensDecimals | ||
| ); | ||
| } | ||
|
|
||
| IAaveV3Pool pool = aavePools[tokenIn]; | ||
| require(address(pool) != address(0), "DVA: no pool for token"); | ||
|
|
||
| uint256 transferredAmount = _tokenTransferFromUser( | ||
| tokenIn, | ||
| address(this), | ||
| amountToken, | ||
| tokensDecimals | ||
| ); | ||
|
|
||
| IERC20(tokenIn).safeIncreaseAllowance(address(pool), transferredAmount); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| pool.supply(tokenIn, transferredAmount, tokensReceiver, 0); | ||
| } | ||
dmytro-horbatenko marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,166 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity 0.8.9; | ||
|
|
||
| import {IERC20Upgradeable as IERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; | ||
| import {SafeERC20Upgradeable as SafeERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; | ||
|
|
||
| import "./DepositVault.sol"; | ||
| import "./interfaces/IDepositVault.sol"; | ||
|
|
||
| /** | ||
| * @title DepositVaultWithMToken | ||
| * @notice Smart contract that handles mToken minting and invests | ||
| * proceeds into another mToken's DepositVault | ||
| * @dev If `mTokenDepositsEnabled` is false, regular deposit flow is used | ||
| * @author RedDuck Software | ||
| */ | ||
| contract DepositVaultWithMToken is DepositVault { | ||
| using DecimalsCorrectionLibrary for uint256; | ||
| using SafeERC20 for IERC20; | ||
|
|
||
| /** | ||
| * @notice Target mToken DepositVault for auto-invest | ||
| */ | ||
| IDepositVault public mTokenDepositVault; | ||
|
|
||
| /** | ||
| * @notice Whether mToken auto-invest deposits are enabled | ||
| * @dev if false, regular deposit flow will be used | ||
| */ | ||
| bool public mTokenDepositsEnabled; | ||
|
|
||
| /** | ||
| * @dev leaving a storage gap for futures updates | ||
| */ | ||
| uint256[50] private __gap; | ||
|
|
||
| /** | ||
| * @notice Emitted when the mToken DepositVault address is updated | ||
| * @param caller address of the caller | ||
| * @param newVault new mToken DepositVault address | ||
| */ | ||
| event SetMTokenDepositVault( | ||
| address indexed caller, | ||
| address indexed newVault | ||
| ); | ||
|
|
||
| /** | ||
| * @notice Emitted when `mTokenDepositsEnabled` flag is updated | ||
| * @param enabled Whether mToken deposits are enabled | ||
| */ | ||
| event SetMTokenDepositsEnabled(bool indexed enabled); | ||
|
|
||
| /** | ||
| * @notice upgradeable pattern contract`s initializer | ||
| * @param _ac address of MidasAccessControll contract | ||
| * @param _mTokenInitParams init params for mToken | ||
| * @param _receiversInitParams init params for receivers | ||
| * @param _instantInitParams init params for instant operations | ||
| * @param _sanctionsList address of sanctionsList contract | ||
| * @param _variationTolerance percent of prices diviation 1% = 100 | ||
| * @param _minAmount basic min amount for operations in mToken | ||
| * @param _minMTokenAmountForFirstDeposit min amount for first deposit in mToken | ||
| * @param _maxSupplyCap max supply cap for mToken | ||
| * @param _mTokenDepositVault target mToken DepositVault address | ||
| */ | ||
| function initialize( | ||
| address _ac, | ||
| MTokenInitParams calldata _mTokenInitParams, | ||
| ReceiversInitParams calldata _receiversInitParams, | ||
| InstantInitParams calldata _instantInitParams, | ||
| address _sanctionsList, | ||
| uint256 _variationTolerance, | ||
| uint256 _minAmount, | ||
| uint256 _minMTokenAmountForFirstDeposit, | ||
| uint256 _maxSupplyCap, | ||
| address _mTokenDepositVault | ||
| ) external { | ||
dmytro-horbatenko marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| initialize( | ||
| _ac, | ||
| _mTokenInitParams, | ||
| _receiversInitParams, | ||
| _instantInitParams, | ||
| _sanctionsList, | ||
| _variationTolerance, | ||
| _minAmount, | ||
| _minMTokenAmountForFirstDeposit, | ||
| _maxSupplyCap | ||
| ); | ||
|
|
||
| _validateAddress(_mTokenDepositVault, false); | ||
| mTokenDepositVault = IDepositVault(_mTokenDepositVault); | ||
| } | ||
|
|
||
| /** | ||
| * @notice Sets the target mToken DepositVault address | ||
| * @param _mTokenDepositVault new mToken DepositVault address | ||
| */ | ||
| function setMTokenDepositVault(address _mTokenDepositVault) | ||
| external | ||
| onlyVaultAdmin | ||
| { | ||
| require( | ||
| _mTokenDepositVault != address(mTokenDepositVault), | ||
| "DVMT: already set" | ||
| ); | ||
| _validateAddress(_mTokenDepositVault, false); | ||
| mTokenDepositVault = IDepositVault(_mTokenDepositVault); | ||
| emit SetMTokenDepositVault(msg.sender, _mTokenDepositVault); | ||
| } | ||
|
|
||
| /** | ||
| * @notice Updates `mTokenDepositsEnabled` value | ||
| * @param enabled whether mToken auto-invest deposits are enabled | ||
| */ | ||
| function setMTokenDepositsEnabled(bool enabled) external onlyVaultAdmin { | ||
| mTokenDepositsEnabled = enabled; | ||
| emit SetMTokenDepositsEnabled(enabled); | ||
| } | ||
|
|
||
| /** | ||
| * @dev overrides original transfer to tokens receiver function | ||
| * in case of mToken deposits are disabled, it will act as the original transfer | ||
| * otherwise it will take payment tokens from user, deposit them into the target | ||
| * mToken DepositVault and forward received mTokens to tokens receiver | ||
| * @param tokenIn token address | ||
| * @param amountToken amount of tokens to transfer in base18 | ||
| * @param tokensDecimals decimals of tokens | ||
| */ | ||
| function _instantTransferTokensToTokensReceiver( | ||
| address tokenIn, | ||
| uint256 amountToken, | ||
| uint256 tokensDecimals | ||
| ) internal override { | ||
| if (!mTokenDepositsEnabled) { | ||
| return | ||
| super._instantTransferTokensToTokensReceiver( | ||
| tokenIn, | ||
| amountToken, | ||
| tokensDecimals | ||
| ); | ||
| } | ||
|
|
||
| uint256 transferredAmount = _tokenTransferFromUser( | ||
| tokenIn, | ||
| address(this), | ||
| amountToken, | ||
| tokensDecimals | ||
| ); | ||
|
|
||
| IERC20(tokenIn).safeIncreaseAllowance( | ||
| address(mTokenDepositVault), | ||
| transferredAmount | ||
| ); | ||
|
Comment on lines
+211
to
+214
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using |
||
|
|
||
| IERC20 targetMToken = IERC20(address(mTokenDepositVault.mToken())); | ||
| uint256 balanceBefore = targetMToken.balanceOf(address(this)); | ||
|
|
||
| mTokenDepositVault.depositInstant(tokenIn, amountToken, 0, bytes32(0)); | ||
|
|
||
| uint256 mTokenReceived = targetMToken.balanceOf(address(this)) - | ||
| balanceBefore; | ||
| require(mTokenReceived > 0, "DVMT: zero mToken received"); | ||
|
|
||
| targetMToken.safeTransfer(tokensReceiver, mTokenReceived); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.