generated from ZeframLou/foundry-template
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* scUSDSv2, adapters & swapper added
- Loading branch information
Showing
8 changed files
with
560 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
optimizer_runs = 1000000 | ||
verbosity = 1 | ||
solc = "0.8.21" | ||
evm_version = "cancun" | ||
|
||
[fuzz] | ||
runs = 256 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.19; | ||
|
||
interface IRewardsController { | ||
function claimAllRewardsToSelf(address[] calldata assets) | ||
external | ||
returns (address[] memory rewardsList, uint256[] memory claimedAmounts); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
pragma solidity ^0.8.19; | ||
|
||
import {ERC20} from "solmate/tokens/ERC20.sol"; | ||
import {ERC4626} from "solmate/mixins/ERC4626.sol"; | ||
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol"; | ||
|
||
import {scCrossAssetYieldVault} from "./scCrossAssetYieldVault.sol"; | ||
import {Constants as C} from "../lib/Constants.sol"; | ||
import {ISinglePairPriceConverter} from "./priceConverter/ISinglePairPriceConverter.sol"; | ||
import {ISinglePairSwapper} from "./swapper/ISinglePairSwapper.sol"; | ||
|
||
/** | ||
* @title scUSDSv2 | ||
* @notice Sandclock USDS Vault implementation. | ||
* @dev Inherits from scCrossAssetYieldVault to manage and generate USDS yield. | ||
* @dev There is no USDS Chainlink Feed, but since USDS to DAI is always 1:1 so | ||
* we are using the DAI Price Converter here. | ||
* @dev This vault also receives aUSDS rewards which must be claimed periodically using claimRewards() | ||
*/ | ||
contract scUSDSv2 is scCrossAssetYieldVault { | ||
using SafeTransferLib for ERC20; | ||
|
||
constructor( | ||
address _admin, | ||
address _keeper, | ||
ERC4626 _targetVault, | ||
ISinglePairPriceConverter _priceConverter, | ||
ISinglePairSwapper _swapper | ||
) | ||
scCrossAssetYieldVault( | ||
_admin, | ||
_keeper, | ||
ERC20(C.USDS), | ||
_targetVault, | ||
_priceConverter, | ||
_swapper, | ||
"Sandclock USDS Real Yield Vault", | ||
"scUSDSv2" | ||
) | ||
{ | ||
ERC20(C.DAI).safeApprove(C.DAI_USDS_CONVERTER, type(uint256).max); | ||
ERC20(C.USDS).safeApprove(C.DAI_USDS_CONVERTER, type(uint256).max); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
pragma solidity ^0.8.19; | ||
|
||
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol"; | ||
import {ERC20} from "solmate/tokens/ERC20.sol"; | ||
import {WETH} from "solmate/tokens/WETH.sol"; | ||
import {IRewardsController} from "../../interfaces/aave-v3/IRewardsController.sol"; | ||
|
||
import {Constants as C} from "../../lib/Constants.sol"; | ||
import {IPool} from "aave-v3/interfaces/IPool.sol"; | ||
import {IPoolDataProvider} from "aave-v3/interfaces/IPoolDataProvider.sol"; | ||
import {IAdapter} from "../IAdapter.sol"; | ||
|
||
/** | ||
* @title Aave v3 Lending Protocol Adapter | ||
* @notice Facilitates lending and borrowing for the Aave v3 lending protocol | ||
*/ | ||
contract AaveV3ScUsdsAdapter is IAdapter { | ||
using SafeTransferLib for ERC20; | ||
using SafeTransferLib for WETH; | ||
|
||
ERC20 public constant usds = ERC20(C.USDS); | ||
WETH public constant weth = WETH(payable(C.WETH)); | ||
|
||
// Aave v3 pool contract | ||
IPool public constant pool = IPool(C.AAVE_V3_POOL); | ||
// Aave v3 pool data provider contract | ||
IPoolDataProvider public constant aaveV3PoolDataProvider = IPoolDataProvider(C.AAVE_V3_POOL_DATA_PROVIDER); | ||
// Aave v3 "aEthUSDS" token (supply token) | ||
ERC20 public constant aUsds = ERC20(C.AAVE_V3_AUSDS_TOKEN); | ||
// Aave v3 "variableDebtEthWETH" token (variable debt token) | ||
ERC20 public constant dWeth = ERC20(C.AAVE_V3_VAR_DEBT_WETH_TOKEN); | ||
|
||
/// @inheritdoc IAdapter | ||
uint256 public constant override id = 1; | ||
|
||
/// @inheritdoc IAdapter | ||
function setApprovals() external override { | ||
usds.safeApprove(address(pool), type(uint256).max); | ||
weth.safeApprove(address(pool), type(uint256).max); | ||
} | ||
|
||
/// @inheritdoc IAdapter | ||
function revokeApprovals() external override { | ||
usds.safeApprove(address(pool), 0); | ||
weth.safeApprove(address(pool), 0); | ||
} | ||
|
||
/// @inheritdoc IAdapter | ||
function supply(uint256 _amount) external override { | ||
pool.supply(address(usds), _amount, address(this), 0); | ||
} | ||
|
||
/// @inheritdoc IAdapter | ||
function borrow(uint256 _amount) external override { | ||
pool.borrow(address(weth), _amount, C.AAVE_VAR_INTEREST_RATE_MODE, 0, address(this)); | ||
} | ||
|
||
/// @inheritdoc IAdapter | ||
function repay(uint256 _amount) external override { | ||
pool.repay(address(weth), _amount, C.AAVE_VAR_INTEREST_RATE_MODE, address(this)); | ||
} | ||
|
||
/// @inheritdoc IAdapter | ||
function withdraw(uint256 _amount) external override { | ||
pool.withdraw(address(usds), _amount, address(this)); | ||
} | ||
|
||
/// @inheritdoc IAdapter | ||
function claimRewards(bytes calldata) external override { | ||
address[] memory assets = new address[](1); | ||
assets[0] = C.AAVE_V3_AUSDS_TOKEN; | ||
|
||
IRewardsController(C.AAVE_V3_REWARDS_CONTROLLER).claimAllRewardsToSelf(assets); | ||
} | ||
|
||
/// @inheritdoc IAdapter | ||
function getCollateral(address _account) external view override returns (uint256) { | ||
return aUsds.balanceOf(_account); | ||
} | ||
|
||
/// @inheritdoc IAdapter | ||
function getDebt(address _account) external view override returns (uint256) { | ||
return dWeth.balanceOf(_account); | ||
} | ||
|
||
/// @inheritdoc IAdapter | ||
function getMaxLtv() external view override returns (uint256) { | ||
(, uint256 ltv,,,,,,,,) = aaveV3PoolDataProvider.getReserveConfigurationData(address(usds)); | ||
|
||
// ltv is returned as a percentage with 2 decimals (e.g. 80% = 8000) so we need to multiply by 1e14 | ||
return ltv * 1e14; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
pragma solidity ^0.8.19; | ||
|
||
import {ERC20} from "solmate/tokens/ERC20.sol"; | ||
import {ERC4626} from "solmate/mixins/ERC4626.sol"; | ||
|
||
import {Constants as C} from "../../lib/Constants.sol"; | ||
import {ISinglePairSwapper} from "../swapper/ISinglePairSwapper.sol"; | ||
import {SwapperLib} from "./SwapperLib.sol"; | ||
import {UniversalSwapper} from "./UniversalSwapper.sol"; | ||
import {IDaiUsds} from "../../interfaces/sky/IDaiUsds.sol"; | ||
|
||
contract UsdsWethSwapper is ISinglePairSwapper, UniversalSwapper { | ||
/// @notice The address of the asset token (USDS). | ||
address public constant override asset = address(C.USDS); | ||
|
||
/// @notice The address of the target token (WETH). | ||
address public constant override targetToken = address(C.WETH); | ||
|
||
/// @notice DAI token used as an intermediate token for swaps. | ||
ERC20 public constant dai = ERC20(C.DAI); | ||
|
||
/// @notice The Dai - USDS converter contract from sky | ||
IDaiUsds public constant converter = IDaiUsds(C.DAI_USDS_CONVERTER); | ||
|
||
/// @notice Encoded swap path from WETH to DAI. | ||
bytes public constant swapPath = abi.encodePacked(targetToken, uint24(500), C.USDC, uint24(100), dai); | ||
|
||
/** | ||
* @notice Swap WETH for USDS. | ||
* @param _wethAmount The amount of WETH to swap. | ||
* @param _usdsAmountOutMin The minimum amount of USDS to receive. | ||
* @return usdsReceived The amount of USDS received from the swap. | ||
*/ | ||
function swapTargetTokenForAsset(uint256 _wethAmount, uint256 _usdsAmountOutMin) | ||
external | ||
override | ||
returns (uint256 usdsReceived) | ||
{ | ||
// swap weth to dai | ||
usdsReceived = SwapperLib._uniswapSwapExactInputMultihop(targetToken, _wethAmount, _usdsAmountOutMin, swapPath); | ||
|
||
// swap dai to usds | ||
converter.daiToUsds(address(this), usdsReceived); | ||
} | ||
|
||
/** | ||
* @notice Swap USDS for an exact amount of WETH. | ||
* @param _wethAmountOut The exact amount of WETH desired. | ||
* @return usdsSpent The amount of USDS spent to receive `_wethAmountOut` of WETH. | ||
*/ | ||
function swapAssetForExactTargetToken(uint256 _wethAmountOut) external override returns (uint256 usdsSpent) { | ||
// convert all USDS to DAI | ||
uint256 usdsBalance = ERC20(asset).balanceOf(address(this)); | ||
converter.usdsToDai(address(this), usdsBalance); | ||
|
||
// Swap DAI for exact amount of WETH | ||
usdsSpent = SwapperLib._uniswapSwapExactOutputMultihop(address(dai), _wethAmountOut, usdsBalance, swapPath); | ||
|
||
// convert remaining DAI back to USDS | ||
converter.daiToUsds(address(this), usdsBalance - usdsSpent); | ||
} | ||
} |
Oops, something went wrong.