-
Notifications
You must be signed in to change notification settings - Fork 1
feat: v4 direct minter #3
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
base: main
Are you sure you want to change the base?
Changes from all commits
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,75 @@ | ||
| // SPDX-License-Identifier: BUSL-1.1 | ||
| pragma solidity ^0.8.0; | ||
|
|
||
| import { | ||
| UpgradeableOwnableWithGuardian | ||
| } from "solidity-utils/contracts/access-control/UpgradeableOwnableWithGuardian.sol"; | ||
| import {Initializable} from "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; | ||
| import {SafeERC20, IERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; | ||
| import {IHub} from "aave-v4/hub/interfaces/IHub.sol"; | ||
| import {IGhoDirectMinterV4} from "src/interfaces/IGhoDirectMinterV4.sol"; | ||
| import {IGhoToken} from "src/interfaces/IGhoToken.sol"; | ||
|
|
||
| /// @title GhoDirectMinterV4 | ||
| /// @author Aave Labs | ||
| /// @notice A GHO facilitator that injects (mints) and removes (burns) GHO from an Aave V4 Hub. | ||
| /// @dev The GhoDirectMinterV4 is expected to be registered as a spoke on the Hub with infinite addCap. | ||
| contract GhoDirectMinterV4 is Initializable, UpgradeableOwnableWithGuardian, IGhoDirectMinterV4 { | ||
| IGhoToken internal immutable GHO; | ||
| IHub internal immutable HUB; | ||
| uint256 internal immutable ASSET_ID; | ||
|
|
||
| /// @dev Constructor. | ||
| /// @param hub_ The address of the Aave v4 Hub. | ||
| /// @param gho_ The address of the GHO token. | ||
| constructor(address hub_, address gho_) { | ||
|
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. What do we think about having this more flexible so it can mint GHO to multiple hubs if needed? Is that unnecessary?
Collaborator
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. while that's possible, I think we'd need to do like AIP to grant access to each, rather than allowing the same owner/guardian to supply into multiple hubs, so would need to add more granular access controls on a per-hub basis perhaps
Member
Author
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. no i dont think we should mix facilitator capacities also |
||
| _disableInitializers(); | ||
| HUB = IHub(hub_); | ||
| ASSET_ID = HUB.getAssetId(gho_); // reverts on invalid `underlying` | ||
| GHO = IGhoToken(gho_); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoDirectMinterV4 | ||
| function initialize(address owner, address council) external virtual initializer { | ||
| __Ownable_With_Guardian_init(owner, council); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoDirectMinterV4 | ||
| function mintAndSupply(uint256 amount) external onlyOwnerOrGuardian { | ||
| GHO.mint(address(HUB), amount); | ||
| HUB.add(ASSET_ID, amount); // this spoke is given infinite cap | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoDirectMinterV4 | ||
| function withdrawAndBurn(uint256 amount) external onlyOwnerOrGuardian { | ||
| HUB.remove(ASSET_ID, amount, address(this)); | ||
| GHO.burn(amount); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoDirectMinterV4 | ||
| function transferExcessToTreasury() external { | ||
| (, uint256 level) = GHO.getFacilitatorBucket(address(this)); | ||
| uint256 balance = HUB.getSpokeAddedAssets(ASSET_ID, address(this)); | ||
| uint256 excess = balance - level; | ||
| // underestimate excess shares to ensure the facilitator remains at or above bucket level | ||
| uint256 excessShares = HUB.previewAddByAssets(ASSET_ID, excess); | ||
| if (excessShares > 0) { | ||
| HUB.payFeeShares(ASSET_ID, excessShares); | ||
| } | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoDirectMinterV4 | ||
| function hub() external view returns (address) { | ||
| return address(HUB); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoDirectMinterV4 | ||
| function assetId() external view returns (uint256) { | ||
| return ASSET_ID; | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoDirectMinterV4 | ||
| function gho() external view returns (address) { | ||
| return address(GHO); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| // SPDX-License-Identifier: BUSL-1.1 | ||
| pragma solidity ^0.8.0; | ||
|
|
||
| /// @title IGhoDirectMinterV4 | ||
| /// @author Aave Labs | ||
| /// @notice Interface for the GhoDirectMinter, a GHO facilitator that injects (mints) and removes (burns) GHO from an Aave V4 Hub. | ||
| /// @dev The GhoDirectMinter is expected to be registered as a spoke on the Hub with infinite addCap. | ||
| interface IGhoDirectMinterV4 { | ||
| /// @notice Initializes the contract. | ||
| /// @param owner The address of the owner. | ||
| /// @param council The address of the guardian council. | ||
| function initialize(address owner, address council) external; | ||
|
|
||
| /// @notice Mints GHO and adds it as liquidity to the Hub. | ||
| /// @dev Only callable by the owner or guardian. | ||
| /// @param amount The amount of GHO to mint and supply. | ||
| function mintAndSupply(uint256 amount) external; | ||
|
|
||
| /// @notice Removes GHO liquidity from the Hub and burns it. | ||
| /// @dev Only callable by the owner or guardian. | ||
| /// @param amount The amount of GHO to withdraw and burn. | ||
| function withdrawAndBurn(uint256 amount) external; | ||
|
|
||
| /// @notice Transfers excess GHO interest (added shares above facilitator bucket level) to the fee receiver. | ||
| /// @dev Callable by anyone. | ||
| /// @dev Due to rounding in the share conversion, the amount transferred may be slightly less than the true excess. | ||
| function transferExcessToTreasury() external; | ||
|
|
||
| /// @notice Returns the address of the Aave v4 Hub. | ||
| /// @return The Hub contract address. | ||
| function hub() external view returns (address); | ||
|
|
||
| /// @notice Returns the asset identifier for GHO in the Hub. | ||
| /// @return The asset identifier. | ||
| function assetId() external view returns (uint256); | ||
|
|
||
| /// @notice Returns the address of the GHO token. | ||
| /// @return The GHO token address. | ||
| function gho() external view returns (address); | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.