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 an AMO minter and an Aave AMO #956

Open
wants to merge 43 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 23 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
236 changes: 236 additions & 0 deletions packages/contracts/src/dollar/amo/AaveAMO.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.19;

import {UbiquityAMOMinter} from "../core/UbiquityAMOMinter.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";

contract AaveAMO is Ownable {
using SafeERC20 for ERC20;

/* ========== STATE VARIABLES ========== */

// Constants
UbiquityAMOMinter public amo_minter;

// Pools and vaults
IPool public immutable aave_pool;

// Reward Tokens
ERC20 public immutable AAVE;

// Rewards Controller
IRewardsController public AAVERewardsController;

// Aave data provider
IPoolDataProvider public immutable AAVEPoolDataProvider;

// Borrowed assets
address[] public aave_borrow_asset_list;
mapping(address => bool) public aave_borrow_asset_check; // Mapping is also used for faster verification

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

constructor(
address _owner_address,
address _amo_minter_address,
address _aave_pool,
address _aave,
address _aave_rewards_controller,
address _aave_pool_data_provider
) {
require(_owner_address != address(0), "Owner address cannot be zero");
require(
_amo_minter_address != address(0),
"AMO minter address cannot be zero"
);
require(_aave_pool != address(0), "Aave pool address cannot be zero");
require(_aave != address(0), "AAVE address cannot be zero");
require(
_aave_rewards_controller != address(0),
"AAVE rewards controller address cannot be zero"
);
require(
_aave_pool_data_provider != address(0),
"AAVE pool data provider address cannot be zero"
);

// Set owner
transferOwnership(_owner_address);

// Set AMO minter
amo_minter = UbiquityAMOMinter(_amo_minter_address);

// Set Aave pool
aave_pool = IPool(_aave_pool);

// Set AAVE
AAVE = ERC20(_aave);

// Set AAVE rewards controller
AAVERewardsController = IRewardsController(_aave_rewards_controller);

// Set AAVE pool data provider
AAVEPoolDataProvider = IPoolDataProvider(_aave_pool_data_provider);
}

/* ========== MODIFIERS ========== */

modifier onlyByMinter() {
require(msg.sender == address(amo_minter), "Not minter");
_;
}

/* ========== AAVE V3 + Rewards ========== */

/// @notice Function to deposit other assets as collateral to Aave pool
/// @param collateral_address collateral ERC20 address
/// @param amount Amount of asset to be deposited
function aaveDepositCollateral(
address collateral_address,
uint256 amount
) public onlyOwner {
ERC20 token = ERC20(collateral_address);
token.safeApprove(address(aave_pool), amount);
aave_pool.deposit(collateral_address, amount, address(this), 0);

emit CollateralDeposited(collateral_address, amount);
}

/// @notice Function to withdraw other assets as collateral from Aave pool
/// @param collateral_address collateral ERC20 address
/// @param aToken_amount Amount of asset to be withdrawn
function aaveWithdrawCollateral(
address collateral_address,
uint256 aToken_amount
) public onlyOwner {
aave_pool.withdraw(collateral_address, aToken_amount, address(this));

emit CollateralWithdrawn(collateral_address, aToken_amount);
}

/// @notice Function to borrow other assets from Aave pool
/// @param asset Borrowing asset ERC20 address
/// @param borrow_amount Amount of asset to be borrowed
/// @param interestRateMode The interest rate mode: 1 for Stable, 2 for Variable
function aaveBorrow(
address asset,
uint256 borrow_amount,
uint256 interestRateMode
) public onlyOwner {
aave_pool.borrow(
asset,
borrow_amount,
interestRateMode,
0,
address(this)
);
aave_borrow_asset_check[asset] = true;
aave_borrow_asset_list.push(asset);

emit Borrowed(asset, borrow_amount, interestRateMode);
}

/// @notice Function to repay other assets to Aave pool
/// @param asset Borrowing asset ERC20 address
/// @param repay_amount Amount of asset to be repaid
/// @param interestRateMode The interest rate mode: 1 for Stable, 2 for Variable
function aaveRepay(
address asset,
uint256 repay_amount,
uint256 interestRateMode
) public onlyOwner {
ERC20 token = ERC20(asset);
token.safeApprove(address(aave_pool), repay_amount);
aave_pool.repay(asset, repay_amount, interestRateMode, address(this));

emit Repaid(asset, repay_amount, interestRateMode);
}

/// @notice Function to claim all rewards
function claimAllRewards() external {
address[] memory allTokens = aave_pool.getReservesList();
AAVERewardsController.claimAllRewards(allTokens, address(this));

emit RewardsClaimed();
}

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

/// @notice Function to return collateral to the minter
/// @param collat_amount Amount of collateral to return to the minter
function returnCollateralToMinter(uint256 collat_amount) public onlyOwner {
ERC20 collateral_token = amo_minter.collateral_token();

if (collat_amount == 0) {
collat_amount = collateral_token.balanceOf(address(this));
}

// Approve collateral to UbiquityAMOMinter
collateral_token.approve(address(amo_minter), collat_amount);

// Call receiveCollatFromAMO from the UbiquityAMOMinter
amo_minter.receiveCollatFromAMO(collat_amount);

emit CollateralReturnedToMinter(collat_amount);
}

// Sets AMO minter
function setAMOMinter(address _amo_minter_address) external onlyOwner {
amo_minter = UbiquityAMOMinter(_amo_minter_address);

emit AMOMinterSet(_amo_minter_address);
}

// Emergency ERC20 recovery function
function recoverERC20(
address tokenAddress,
uint256 tokenAmount
) external onlyOwner {
ERC20(tokenAddress).safeTransfer(msg.sender, tokenAmount);

emit ERC20Recovered(tokenAddress, tokenAmount);
}

// Emergency generic proxy - allows owner to execute arbitrary calls on this contract
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 collateral_address,
uint256 amount
);
event CollateralWithdrawn(
address indexed collateral_address,
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 new_minter);
event ERC20Recovered(address tokenAddress, uint256 tokenAmount);
event ExecuteCalled(address indexed to, uint256 value, bytes data);
}
Loading
Loading