From ab527411e9c7f8ff7750794bfcc726659a589d18 Mon Sep 17 00:00:00 2001 From: YBM Date: Fri, 30 Aug 2024 18:20:12 -0500 Subject: [PATCH] feat: skeleton for GsmConverter buyAsset --- .../facilitators/gsm/GsmConverter.sol | 86 +++++++++++++++++++ .../circle/interfaces/IRedemption.sol | 42 +++++++++ 2 files changed, 128 insertions(+) create mode 100644 src/contracts/facilitators/gsm/GsmConverter.sol create mode 100644 src/contracts/facilitators/gsm/dependencies/circle/interfaces/IRedemption.sol diff --git a/src/contracts/facilitators/gsm/GsmConverter.sol b/src/contracts/facilitators/gsm/GsmConverter.sol new file mode 100644 index 00000000..fb6a76f0 --- /dev/null +++ b/src/contracts/facilitators/gsm/GsmConverter.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.10; + +// import {VersionedInitializable} from '@aave/core-v3/contracts/protocol/libraries/aave-upgradeability/VersionedInitializable.sol'; +// import {IERC20} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20.sol'; +import {GPv2SafeERC20} from '@aave/core-v3/contracts/dependencies/gnosis/contracts/GPv2SafeERC20.sol'; +// import {EIP712} from '@openzeppelin/contracts/utils/cryptography/EIP712.sol'; +// import {SignatureChecker} from '@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol'; +// import {SafeCast} from '@openzeppelin/contracts/utils/math/SafeCast.sol'; +// import {AccessControl} from '@openzeppelin/contracts/access/AccessControl.sol'; +// import {IGhoFacilitator} from '../../gho/interfaces/IGhoFacilitator.sol'; +// import {IGhoToken} from '../../gho/interfaces/IGhoToken.sol'; +// import {IGsmPriceStrategy} from './priceStrategy/interfaces/IGsmPriceStrategy.sol'; +// import {IGsmFeeStrategy} from './feeStrategy/interfaces/IGsmFeeStrategy.sol'; +import {IGsm} from './interfaces/IGsm.sol'; +import {IRedemption} from './dependencies/circle/interfaces/IRedemption.sol'; + +/** + * @title GsmConverter + * @author Aave + * @notice GHO Stability Module. It provides buy/sell facilities to go to/from an underlying asset to/from GHO. + * @dev To be covered by a proxy contract. + */ +contract GsmConverter { + using GPv2SafeERC20 for IERC20; + + address public immutable GSM; + address public immutable GHO_TOKEN; + address public immutable REDEEMABLE_ASSET; // BUIDL token + address public immutable REDEEMED_ASSET; // USDC token + address public immutable REDEMPTION; // redeem BUIDL to USDC + + event BuyAssetThroughRedemption( + address indexed originator, + address indexed receiver, + uint256 redemptionAssetAmount, + uint256 ghoSold + ); + + /** + * @dev Constructor + * @param ghoToken The address of the GHO token contract + * @param underlyingAsset The address of the collateral asset + * @param priceStrategy The address of the price strategy + */ + constructor(address gsm, address redemption, address redeemableAsset, address redeemedAsset) { + require(gsm != address(0), 'ZERO_ADDRESS_NOT_VALID'); + require(redemption != address(0), 'ZERO_ADDRESS_NOT_VALID'); + require(redeemableAsset != address(0), 'ZERO_ADDRESS_NOT_VALID'); + require(redeemedAsset != address(0), 'ZERO_ADDRESS_NOT_VALID'); + + GSM = gsm; + REDEMPTION = redemption; + REDEEMABLE_ASSET = redeemableAsset; + REDEEMED_ASSET = redeemedAsset; + } + + // TODO: + // 1) implement buyAsset (sell GHO -> get USDC) + // - GHO transferFrom user to converter + // - call buyAsset on GSM, get the BUIDL + // - offramp BUIDL to USDC, send USDC to user + // - call redeem on offramp to get BUIDL + // - send USDC to user, safeTransfer + + /** + * @dev + */ + function buyAssetThroughRedemption( + uint256 minAmount, + address receiver + ) external returns (uint256, uint256) { + IGhoToken(IGSM(GSM).GHO_TOKEN()).transferFrom(msg.sender, address(this), minAmount); + (uint256 redemptionAssetAmount, uint256 ghoSold) = IGSM(GSM).buyAsset(minAmount, receiver); + IRedemption(REDEMPTION).redeem(redemptionAssetAmount); + IERC20(REDEEMED_ASSET).safeTransfer(receiver, redemptionAssetAmount); + + emit BuyAssetThroughRedemption(msg.sender, receiver, redemptionAssetAmount, ghoSold); + } + + // TODO: + // 2) implement sellAsset (sell USDC -> get GHO) + // - onramp USDC to BUIDL, get BUIDL - unknown how to onramp USDC to BUIDL currently + // - send BUIDL to GSM, get GHO from GSM + // - send GHO to user, safeTransfer +} diff --git a/src/contracts/facilitators/gsm/dependencies/circle/interfaces/IRedemption.sol b/src/contracts/facilitators/gsm/dependencies/circle/interfaces/IRedemption.sol new file mode 100644 index 00000000..e79e388e --- /dev/null +++ b/src/contracts/facilitators/gsm/dependencies/circle/interfaces/IRedemption.sol @@ -0,0 +1,42 @@ +/** + * Copyright 2024 Circle Internet Financial, LTD. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.16; + +/** + * @title IRedemption + */ +interface IRedemption { + /** + * @notice The asset being redeemed. + * @return The address of the asset token. + */ + function asset() external view returns (address); + + /** + * @notice The liquidity token that the asset is being redeemed for. + * @return The address of the liquidity token. + */ + function liquidity() external view returns (address); + + /** + * @notice Redeems an amount of asset for liquidity + * @param amount The amount of the asset token to redeem + */ + function redeem(uint256 amount) external; +}