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

feat: add an AMO minter and an Aave AMO #956

Merged
merged 43 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
3cc89d0
feat: add safe transfer library
zugdev Sep 7, 2024
01de15a
feat: wip ubiquity AMO minter
zugdev Sep 7, 2024
f7c9d4b
feat: generalize tickers
zugdev Sep 9, 2024
ba66a5f
feat: add dollar and governance minting/burning
zugdev Sep 9, 2024
73bb161
chore: format
zugdev Sep 10, 2024
701a83b
feat: set constants and immutables
zugdev Sep 10, 2024
f15daba
feat: add Aave AMO
zugdev Sep 10, 2024
96e72d7
feat: clean AMO minter addAMO function
zugdev Sep 10, 2024
e98f977
chore: delete aave interfaces
zugdev Sep 11, 2024
ee2528b
chore: install aave submodules
zugdev Sep 11, 2024
53b8e1a
feat: refac AMO minter to handle only collateral
zugdev Sep 11, 2024
61530d0
feat: refac aave AMO to V3 and use submodules
zugdev Sep 11, 2024
29c2ea5
feat: add events
zugdev Sep 11, 2024
42f592e
chore: fix slither warning
zugdev Sep 11, 2024
746c6f5
feat: test AMO minter constructor
zugdev Sep 16, 2024
5a6fb7f
feat: change AMO minter borrow cap
zugdev Sep 16, 2024
a521729
feat: remove timelock and add fine AMO control to owner
zugdev Sep 16, 2024
624a9ea
chore: code order
zugdev Sep 17, 2024
32284d6
feat: adhere to LibUbiquityPool AMO minter standard
zugdev Sep 17, 2024
2dbd2da
feat: full test suite for AMO minter
zugdev Sep 17, 2024
e03c3eb
chore: comments
zugdev Sep 17, 2024
e24e164
feat: receive Aave parameters in AaveAMO
zugdev Sep 17, 2024
9092bec
feat: wip AaveAMO tests
zugdev Sep 17, 2024
10136da
feat: missing immutable
zugdev Sep 17, 2024
1e7c794
feat: working AaveAMO test suite
zugdev Sep 17, 2024
aafc79b
feat: test constructor
zugdev Sep 18, 2024
c3e21c2
chore: match comment style
zugdev Sep 18, 2024
861de4f
chore: change MockERC20 import path
zugdev Sep 18, 2024
5d5cb86
feat: remove unused modifier
zugdev Sep 18, 2024
397d1fd
feat: add claim Aave rewards mechanism
zugdev Sep 18, 2024
375e8d1
feat: test AMO minter constructor
zugdev Sep 18, 2024
dc2eb43
feat: rename error msg
zugdev Sep 18, 2024
30c9512
feat: fix rewards controller test
zugdev Sep 18, 2024
a79de73
chore: delete unused lib
zugdev Sep 19, 2024
e8d1d6f
feat: style changes
zugdev Sep 19, 2024
3a66f18
chore: comments
zugdev Sep 19, 2024
94f9c4f
feat: interface natspec
zugdev Sep 19, 2024
02bbe8f
feat: implemente amo interface in Aave AMO to ensure amo standard
zugdev Sep 19, 2024
4bdd75c
chore: fix AMO contracts version
zugdev Sep 21, 2024
ee11e95
chore: specify branch in git submodules
zugdev Sep 21, 2024
5e6a5fc
feat: remove borrowing from AaveAmo
zugdev Sep 22, 2024
d133e8a
feat: adapt tests
zugdev Sep 22, 2024
c8a9b02
Merge branch 'development' of https://github.com/zugdev/ubiquity-doll…
zugdev Sep 22, 2024
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
8 changes: 7 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,10 @@
[submodule "packages/contracts/lib/chainlink-brownie-contracts"]
path = packages/contracts/lib/chainlink-brownie-contracts
url = https://github.com/smartcontractkit/chainlink-brownie-contracts
branch= main
branch= main
[submodule "packages/contracts/lib/aave-v3-core"]
path = packages/contracts/lib/aave-v3-core
url = https://github.com/aave/aave-v3-core
[submodule "packages/contracts/lib/aave-v3-periphery"]
path = packages/contracts/lib/aave-v3-periphery
zugdev marked this conversation as resolved.
Show resolved Hide resolved
url = https://github.com/aave/aave-v3-periphery
8 changes: 7 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,13 @@
"blockhash",
"Merkle",
"UUPS",
"Initializable"
"Initializable",
"IAMO",
"timelock",
"AAve",
"AAveV3",
"IAAve",
"Cust"
],
"flagWords": ["creditNFT", "CreditNFT"],
"language": "en-US"
Expand Down
1 change: 1 addition & 0 deletions packages/contracts/LICENSE_GPL
0x4007 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Sections of this software is licensed under the GNU GPL-2.0-or-later. You can find the source code at: https://github.com/FraxFinance.
1 change: 1 addition & 0 deletions packages/contracts/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ force = false

[rpc_endpoints]
mainnet = "https://rpc.ankr.com/eth"
sepolia = "https://1rpc.io/sepolia"

[profile.SMT.model_checker]
contracts = { }
Expand Down
1 change: 1 addition & 0 deletions packages/contracts/lib/aave-v3-core
Submodule aave-v3-core added at b74526
1 change: 1 addition & 0 deletions packages/contracts/lib/aave-v3-periphery
Submodule aave-v3-periphery added at 72fdcc
4 changes: 3 additions & 1 deletion packages/contracts/remappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ solidity-linked-list/=lib/solidity-linked-list
@uniswap/v3-periphery/contracts/=lib/Uniswap/v3-periphery/contracts
abdk/=lib/abdk-libraries-solidity/
operator-filter-registry/=lib/operator-filter-registry/src
@chainlink/=lib/chainlink-brownie-contracts/contracts/src/v0.8/
@chainlink/=lib/chainlink-brownie-contracts/contracts/src/v0.8/
@aavev3-core/contracts/=lib/aave-v3-core/contracts
@aavev3-periphery/contracts/=lib/aave-v3-periphery/contracts
272 changes: 272 additions & 0 deletions packages/contracts/src/dollar/amo/AaveAmo.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.19;
zugdev marked this conversation as resolved.
Show resolved Hide resolved

import {UbiquityAmoMinter} from "../core/UbiquityAmoMinter.sol";
import {IAmo} from "../interfaces/IAmo.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IPool} from "@aavev3-core/contracts/interfaces/IPool.sol";
import {IPoolDataProvider} from "@aavev3-core/contracts/interfaces/IPoolDataProvider.sol";
import {IRewardsController} from "@aavev3-periphery/contracts/rewards/interfaces/IRewardsController.sol";

/**
* @title AaveAmo
* @notice AMO to interact with Aave V3 and manage rewards and borrowing mechanisms.
* @notice Can receive collateral from UbiquityAmoMinter and interact with Aave's V3 pool.
*/
contract AaveAmo is IAmo, Ownable {
using SafeERC20 for ERC20;

/// @notice UbiquityAmoMinter instance
UbiquityAmoMinter public amoMinter;

/// @notice Aave V3 pool instance
IPool public immutable aavePool;

/// @notice Aave token address
ERC20 public immutable aaveToken;

/// @notice Aave rewards controller
IRewardsController public immutable aaveRewardsController;

/// @notice Aave data provider
IPoolDataProvider public immutable aavePoolDataProvider;

/// @notice List of borrowed assets from Aave
address[] public aaveBorrowedAssets;

/// @notice Mapping for tracking borrowed assets
mapping(address => bool) public aaveIsAssetBorrowed;

/* ========== CONSTRUCTOR ========== */

/**
* @notice Initializes the contract with necessary parameters
* @param _ownerAddress Address of the contract owner
* @param _amoMinterAddress Address of the Ubiquity Amo minter
* @param _aavePool Address of the Aave pool
* @param _aaveToken Address of the Aave token
* @param _aaveRewardsController Address of the Aave rewards controller
* @param _aavePoolDataProvider Address of the Aave data provider
*/
constructor(
address _ownerAddress,
address _amoMinterAddress,
address _aavePool,
address _aaveToken,
address _aaveRewardsController,
address _aavePoolDataProvider
) {
require(_ownerAddress != address(0), "Owner address cannot be zero");
require(
_amoMinterAddress != address(0),
"Amo minter address cannot be zero"
);
require(_aavePool != address(0), "Aave pool address cannot be zero");
require(_aaveToken != address(0), "Aave address cannot be zero");
require(
_aaveRewardsController != address(0),
"Aave rewards controller address cannot be zero"
);
require(
_aavePoolDataProvider != address(0),
"Aave pool data provider address cannot be zero"
);

// Set contract owner
transferOwnership(_ownerAddress);

// Set the Amo minter
amoMinter = UbiquityAmoMinter(_amoMinterAddress);

// Set the Aave pool
aavePool = IPool(_aavePool);

// Set the Aave token
aaveToken = ERC20(_aaveToken);

// Set the Aave rewards controller
aaveRewardsController = IRewardsController(_aaveRewardsController);

// Set the Aave pool data provider
aavePoolDataProvider = IPoolDataProvider(_aavePoolDataProvider);
}

/* ========== Aave V3 + REWARDS ========== */

/**
* @notice Deposits collateral to Aave pool
* @param collateralAddress Address of the collateral ERC20
* @param amount Amount of collateral to deposit
*/
function aaveDepositCollateral(
address collateralAddress,
uint256 amount
) public onlyOwner {
ERC20 token = ERC20(collateralAddress);
token.safeApprove(address(aavePool), amount);
aavePool.deposit(collateralAddress, amount, address(this), 0);

emit CollateralDeposited(collateralAddress, amount);
}

/**
* @notice Withdraws collateral from Aave pool
* @param collateralAddress Address of the collateral ERC20
* @param aTokenAmount Amount of collateral to withdraw
*/
function aaveWithdrawCollateral(
address collateralAddress,
uint256 aTokenAmount
) public onlyOwner {
aavePool.withdraw(collateralAddress, aTokenAmount, address(this));

emit CollateralWithdrawn(collateralAddress, aTokenAmount);
}

/**
* @notice Borrows an asset from Aave pool
* @param asset Address of the asset to borrow
* @param borrowAmount Amount of asset to borrow
* @param interestRateMode Interest rate mode: 1 for Stable, 2 for Variable
*/
function aaveBorrow(
address asset,
uint256 borrowAmount,
uint256 interestRateMode
) public onlyOwner {
aavePool.borrow(
asset,
borrowAmount,
interestRateMode,
0,
address(this)
);
aaveIsAssetBorrowed[asset] = true;
aaveBorrowedAssets.push(asset);

emit Borrowed(asset, borrowAmount, interestRateMode);
}

/**
* @notice Repays a borrowed asset to Aave pool
* @param asset Address of the asset to repay
* @param repayAmount Amount of asset to repay
* @param interestRateMode Interest rate mode: 1 for Stable, 2 for Variable
*/
function aaveRepay(
zugdev marked this conversation as resolved.
Show resolved Hide resolved
address asset,
uint256 repayAmount,
uint256 interestRateMode
) public onlyOwner {
ERC20 token = ERC20(asset);
token.safeApprove(address(aavePool), repayAmount);
aavePool.repay(asset, repayAmount, interestRateMode, address(this));

emit Repaid(asset, repayAmount, interestRateMode);
}

/**
* @notice Claims all rewards available from the list of assets provided, will fail if balance on asset is zero
* @param assets Array of aTokens/sTokens/vTokens addresses to claim rewards from
*/
function claimAllRewards(address[] memory assets) external {
// Claim all rewards for the collected tokens
aaveRewardsController.claimAllRewards(assets, address(this));

emit RewardsClaimed();
}

/* ========== RESTRICTED GOVERNANCE FUNCTIONS ========== */

/**
* @notice Returns collateral back to the AMO minter
* @param collateralAmount Amount of collateral to return
*/
function returnCollateralToMinter(
uint256 collateralAmount
) public override onlyOwner {
ERC20 collateralToken = amoMinter.collateralToken();

if (collateralAmount == 0) {
collateralAmount = collateralToken.balanceOf(address(this));
}

// Approve and return collateral
collateralToken.approve(address(amoMinter), collateralAmount);
amoMinter.receiveCollateralFromAmo(collateralAmount);

emit CollateralReturnedToMinter(collateralAmount);
}

/**
* @notice Sets the AMO minter address
* @param _amoMinterAddress New address of the AMO minter
*/
function setAmoMinter(
address _amoMinterAddress
) external override onlyOwner {
amoMinter = UbiquityAmoMinter(_amoMinterAddress);

emit AmoMinterSet(_amoMinterAddress);
}

/**
* @notice Recovers any ERC20 tokens held by the contract
* @param tokenAddress Address of the token to recover
* @param tokenAmount Amount of tokens to recover
*/
function recoverERC20(
address tokenAddress,
uint256 tokenAmount
) external onlyOwner {
ERC20(tokenAddress).safeTransfer(msg.sender, tokenAmount);

emit ERC20Recovered(tokenAddress, tokenAmount);
}

/**
* @notice Executes arbitrary calls from this contract
* @param _to Address to call
* @param _value Value to send
* @param _data Data to execute
* @return success, result Returns whether the call succeeded and the returned data
*/
function execute(
address _to,
uint256 _value,
bytes calldata _data
) external onlyOwner returns (bool, bytes memory) {
(bool success, bytes memory result) = _to.call{value: _value}(_data);

emit ExecuteCalled(_to, _value, _data);
return (success, result);
}

/* ========== EVENTS ========== */

event CollateralDeposited(
address indexed collateralAddress,
uint256 amount
);
event CollateralWithdrawn(
address indexed collateralAddress,
uint256 amount
);
event Borrowed(
address indexed asset,
uint256 amount,
uint256 interestRateMode
);
event Repaid(
address indexed asset,
uint256 amount,
uint256 interestRateMode
);
event CollateralReturnedToMinter(uint256 amount);
event RewardsClaimed();
event AmoMinterSet(address indexed newMinter);
event ERC20Recovered(address tokenAddress, uint256 tokenAmount);
event ExecuteCalled(address indexed to, uint256 value, bytes data);
}
Loading
Loading