-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds integration for Savings USDS on L2 chains + tests on Base (#1230)
* add SavingsUSDSBase deployer coordinator and instance * refactor savings-usds-base integration into savings-usds-l2. Add tests. * linting fixes * remove console imports * linting fixes * precision fixes * benchmark test * benchmark test * remove commented code, address review comments * remove unnecessary functions from IPSM interface * testing for GH action: benchmark * pin foundry build to nightly-75fc63b * revert benchmark script to original version
- Loading branch information
Showing
22 changed files
with
1,283 additions
and
1 deletion.
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
66 changes: 66 additions & 0 deletions
66
contracts/src/deployers/savings-usds-l2/SavingsUSDSL2HyperdriveCoreDeployer.sol
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,66 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity 0.8.24; | ||
|
||
import { IHyperdrive } from "../../interfaces/IHyperdrive.sol"; | ||
import { IHyperdriveAdminController } from "../../interfaces/IHyperdriveAdminController.sol"; | ||
import { IHyperdriveCoreDeployer } from "../../interfaces/IHyperdriveCoreDeployer.sol"; | ||
import { IPSM } from "../../interfaces/IPSM.sol"; | ||
import { SavingsUSDSL2Hyperdrive } from "../../instances/savings-usds-l2/SavingsUSDSL2Hyperdrive.sol"; | ||
|
||
/// @author DELV | ||
/// @title SavingsUSDSL2HyperdriveCoreDeployer | ||
/// @notice The core deployer for the SavingsUSDSL2Hyperdrive implementation. | ||
/// @custom:disclaimer The language used in this code is for coding convenience | ||
/// only, and is not intended to, and does not, have any | ||
/// particular legal or regulatory significance. | ||
contract SavingsUSDSL2HyperdriveCoreDeployer is IHyperdriveCoreDeployer { | ||
/// @notice Deploys a Hyperdrive instance with the given parameters. | ||
/// @param __name The name of the Hyperdrive pool. | ||
/// @param _config The configuration of the Hyperdrive pool. | ||
/// @param _adminController The admin controller that will specify the | ||
/// admin parameters for this instance. | ||
/// @param _target0 The target0 address. | ||
/// @param _target1 The target1 address. | ||
/// @param _target2 The target2 address. | ||
/// @param _target3 The target3 address. | ||
/// @param _target4 The target4 address. | ||
/// @param _salt The create2 salt used in the deployment. | ||
/// @return The address of the newly deployed SavingsUSDSL2Hyperdrive instance. | ||
function deployHyperdrive( | ||
string memory __name, | ||
IHyperdrive.PoolConfig memory _config, | ||
IHyperdriveAdminController _adminController, | ||
bytes memory _extraData, | ||
address _target0, | ||
address _target1, | ||
address _target2, | ||
address _target3, | ||
address _target4, | ||
bytes32 _salt | ||
) external returns (address) { | ||
// The PSM contract. This is where the base token will be swapped | ||
// for shares. | ||
require(_extraData.length >= 20, "Invalid _extraData length"); | ||
IPSM PSM = abi.decode(_extraData, (IPSM)); | ||
|
||
return ( | ||
address( | ||
// NOTE: We hash the sender with the salt to prevent the | ||
// front-running of deployments. | ||
new SavingsUSDSL2Hyperdrive{ | ||
salt: keccak256(abi.encode(msg.sender, _salt)) | ||
}( | ||
__name, | ||
_config, | ||
_adminController, | ||
_target0, | ||
_target1, | ||
_target2, | ||
_target3, | ||
_target4, | ||
PSM | ||
) | ||
) | ||
); | ||
} | ||
} |
174 changes: 174 additions & 0 deletions
174
contracts/src/deployers/savings-usds-l2/SavingsUSDSL2HyperdriveDeployerCoordinator.sol
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,174 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity 0.8.24; | ||
|
||
import { ERC20 } from "openzeppelin/token/ERC20/ERC20.sol"; | ||
import { SafeERC20 } from "openzeppelin/token/ERC20/utils/SafeERC20.sol"; | ||
import { SavingsUSDSL2Conversions } from "../../instances/savings-usds-l2/SavingsUSDSL2Conversions.sol"; | ||
import { IHyperdrive } from "../../interfaces/IHyperdrive.sol"; | ||
import { IPSM } from "../../interfaces/IPSM.sol"; | ||
import { IHyperdriveDeployerCoordinator } from "../../interfaces/IHyperdriveDeployerCoordinator.sol"; | ||
import { SAVINGS_USDS_L2_HYPERDRIVE_DEPLOYER_COORDINATOR_KIND } from "../../libraries/Constants.sol"; | ||
import { ONE } from "../../libraries/FixedPointMath.sol"; | ||
import { HyperdriveDeployerCoordinator } from "../HyperdriveDeployerCoordinator.sol"; | ||
|
||
/// @author DELV | ||
/// @title SavingsUSDSL2HyperdriveDeployerCoordinator | ||
/// @notice The deployer coordinator for the SavingsUSDSL2Hyperdrive | ||
/// implementation. | ||
/// @custom:disclaimer The language used in this code is for coding convenience | ||
/// only, and is not intended to, and does not, have any | ||
/// particular legal or regulatory significance. | ||
contract SavingsUSDSL2HyperdriveDeployerCoordinator is | ||
HyperdriveDeployerCoordinator | ||
{ | ||
using SafeERC20 for ERC20; | ||
|
||
/// @notice The deployer coordinator's kind. | ||
string public constant override kind = | ||
SAVINGS_USDS_L2_HYPERDRIVE_DEPLOYER_COORDINATOR_KIND; | ||
|
||
/// @notice Instantiates the deployer coordinator. | ||
/// @param _name The deployer coordinator's name. | ||
/// @param _factory The factory that this deployer will be registered with. | ||
/// @param _coreDeployer The core deployer. | ||
/// @param _target0Deployer The target0 deployer. | ||
/// @param _target1Deployer The target1 deployer. | ||
/// @param _target2Deployer The target2 deployer. | ||
/// @param _target3Deployer The target3 deployer. | ||
/// @param _target4Deployer The target4 deployer. | ||
constructor( | ||
string memory _name, | ||
address _factory, | ||
address _coreDeployer, | ||
address _target0Deployer, | ||
address _target1Deployer, | ||
address _target2Deployer, | ||
address _target3Deployer, | ||
address _target4Deployer | ||
) | ||
HyperdriveDeployerCoordinator( | ||
_name, | ||
_factory, | ||
_coreDeployer, | ||
_target0Deployer, | ||
_target1Deployer, | ||
_target2Deployer, | ||
_target3Deployer, | ||
_target4Deployer | ||
) | ||
{} | ||
|
||
/// @dev Prepares the coordinator for initialization by drawing funds from | ||
/// the LP, if necessary. | ||
/// @param _hyperdrive The Hyperdrive instance that is being initialized. | ||
/// @param _lp The LP that is initializing the pool. | ||
/// @param _contribution The amount of capital to supply. The units of this | ||
/// quantity are either base or vault shares, depending on the value | ||
/// of `_options.asBase`. | ||
/// @param _options The options that configure how the initialization is | ||
/// settled. | ||
/// @return value The value that should be sent in the initialize transaction. | ||
function _prepareInitialize( | ||
IHyperdrive _hyperdrive, | ||
address _lp, | ||
uint256 _contribution, | ||
IHyperdrive.Options memory _options | ||
) internal override returns (uint256 value) { | ||
// If base is the deposit asset, the initialization will be paid in the | ||
// base token. | ||
address token; | ||
if (_options.asBase) { | ||
token = _hyperdrive.baseToken(); | ||
} | ||
// Otherwise, the initialization will be paid in vault shares. | ||
else { | ||
token = _hyperdrive.vaultSharesToken(); | ||
} | ||
|
||
// Take custody of the contribution and approve Hyperdrive to pull the | ||
// tokens. | ||
ERC20(token).safeTransferFrom(_lp, address(this), _contribution); | ||
ERC20(token).forceApprove(address(_hyperdrive), _contribution); | ||
|
||
return value; | ||
} | ||
|
||
/// @notice Convert an amount of vault shares to an amount of base. | ||
/// @param _shareAmount The vault shares amount. | ||
/// @return The base amount. | ||
function convertToBase( | ||
IPSM _PSM, | ||
uint256 _shareAmount | ||
) public view returns (uint256) { | ||
return SavingsUSDSL2Conversions.convertToBase(_PSM, _shareAmount); | ||
} | ||
|
||
/// @notice Convert an amount of base to an amount of vault shares. | ||
/// @param _baseAmount The base amount. | ||
/// @return The vault shares amount. | ||
function convertToShares( | ||
IPSM _PSM, | ||
uint256 _baseAmount | ||
) public view returns (uint256) { | ||
return SavingsUSDSL2Conversions.convertToShares(_PSM, _baseAmount); | ||
} | ||
|
||
/// @dev We override the message value check since this integration is | ||
/// not payable. | ||
function _checkMessageValue() internal view override { | ||
if (msg.value != 0) { | ||
revert IHyperdriveDeployerCoordinator.NotPayable(); | ||
} | ||
} | ||
|
||
/// @notice Checks the pool configuration to ensure that it is valid. | ||
/// @param _deployConfig The deploy configuration of the Hyperdrive pool. | ||
/// @param _extraData The extra data containing the PSM address. | ||
function _checkPoolConfig( | ||
IHyperdrive.PoolDeployConfig memory _deployConfig, | ||
bytes memory _extraData | ||
) internal view override { | ||
// The Sky PSM contract. This is where the base token will be | ||
// swapped for shares. | ||
require(_extraData.length >= 20, "Invalid _extraData length"); | ||
IPSM PSM = abi.decode(_extraData, (IPSM)); | ||
|
||
// Perform the default checks. | ||
super._checkPoolConfig(_deployConfig, _extraData); | ||
|
||
// Ensure that the vault shares token address is properly configured. | ||
if (address(_deployConfig.vaultSharesToken) != address(PSM.susds())) { | ||
revert IHyperdriveDeployerCoordinator.InvalidVaultSharesToken(); | ||
} | ||
|
||
// Ensure that the base token address is properly configured. | ||
if (address(_deployConfig.baseToken) != address(PSM.usds())) { | ||
revert IHyperdriveDeployerCoordinator.InvalidBaseToken(); | ||
} | ||
|
||
// Ensure that the minimum share reserves are equal to 1e15. This value | ||
// has been tested to prevent arithmetic overflows in the | ||
// `_updateLiquidity` function. | ||
if (_deployConfig.minimumShareReserves != 1e15) { | ||
revert IHyperdriveDeployerCoordinator.InvalidMinimumShareReserves(); | ||
} | ||
|
||
// Ensure that the minimum transaction amount are equal to 1e15. This | ||
// value has been tested to prevent precision issues. | ||
if (_deployConfig.minimumTransactionAmount != 1e15) { | ||
revert IHyperdriveDeployerCoordinator | ||
.InvalidMinimumTransactionAmount(); | ||
} | ||
} | ||
|
||
/// @dev Gets the initial vault share price of the Hyperdrive pool. | ||
/// @return The initial vault share price of the Hyperdrive pool. | ||
function _getInitialVaultSharePrice( | ||
IHyperdrive.PoolDeployConfig memory, // unused _deployConfig | ||
bytes memory _extraData | ||
) internal view override returns (uint256) { | ||
require(_extraData.length >= 20, "Invalid _extraData length"); | ||
IPSM _PSM = abi.decode(_extraData, (IPSM)); | ||
return convertToBase(_PSM, ONE); | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
contracts/src/deployers/savings-usds-l2/SavingsUSDSL2Target0Deployer.sol
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,43 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity 0.8.24; | ||
|
||
import { SavingsUSDSL2Target0 } from "../../instances/savings-usds-l2/SavingsUSDSL2Target0.sol"; | ||
import { IHyperdrive } from "../../interfaces/IHyperdrive.sol"; | ||
import { IHyperdriveAdminController } from "../../interfaces/IHyperdriveAdminController.sol"; | ||
import { IHyperdriveTargetDeployer } from "../../interfaces/IHyperdriveTargetDeployer.sol"; | ||
import { IPSM } from "../../interfaces/IPSM.sol"; | ||
|
||
/// @author DELV | ||
/// @title SavingsUSDSL2Target0Deployer | ||
/// @notice The target0 deployer for the SavingsUSDSL2Hyperdrive implementation. | ||
/// @custom:disclaimer The language used in this code is for coding convenience | ||
/// only, and is not intended to, and does not, have any | ||
/// particular legal or regulatory significance. | ||
contract SavingsUSDSL2Target0Deployer is IHyperdriveTargetDeployer { | ||
/// @notice Deploys a target0 instance with the given parameters. | ||
/// @param _config The configuration of the Hyperdrive pool. | ||
/// @param _adminController The admin controller that will specify the | ||
/// admin parameters for this instance. | ||
/// @param _salt The create2 salt used in the deployment. | ||
/// @return The address of the newly deployed SavingsUSDSL2Target0 instance. | ||
function deployTarget( | ||
IHyperdrive.PoolConfig memory _config, | ||
IHyperdriveAdminController _adminController, | ||
bytes memory _extraData, | ||
bytes32 _salt | ||
) external returns (address) { | ||
// The PSM contract. This is where the base token will be swapped | ||
// for shares. | ||
require(_extraData.length >= 20, "Invalid _extraData length"); | ||
IPSM PSM = abi.decode(_extraData, (IPSM)); | ||
|
||
return | ||
address( | ||
// NOTE: We hash the sender with the salt to prevent the | ||
// front-running of deployments. | ||
new SavingsUSDSL2Target0{ | ||
salt: keccak256(abi.encode(msg.sender, _salt)) | ||
}(_config, _adminController, PSM) | ||
); | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
contracts/src/deployers/savings-usds-l2/SavingsUSDSL2Target1Deployer.sol
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,43 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity 0.8.24; | ||
|
||
import { SavingsUSDSL2Target1 } from "../../instances/savings-usds-l2/SavingsUSDSL2Target1.sol"; | ||
import { IHyperdrive } from "../../interfaces/IHyperdrive.sol"; | ||
import { IHyperdriveAdminController } from "../../interfaces/IHyperdriveAdminController.sol"; | ||
import { IHyperdriveTargetDeployer } from "../../interfaces/IHyperdriveTargetDeployer.sol"; | ||
import { IPSM } from "../../interfaces/IPSM.sol"; | ||
|
||
/// @author DELV | ||
/// @title SavingsUSDSL2Target1Deployer | ||
/// @notice The target1 deployer for the SavingsUSDSL2Hyperdrive implementation. | ||
/// @custom:disclaimer The language used in this code is for coding convenience | ||
/// only, and is not intended to, and does not, have any | ||
/// particular legal or regulatory significance. | ||
contract SavingsUSDSL2Target1Deployer is IHyperdriveTargetDeployer { | ||
/// @notice Deploys a target1 instance with the given parameters. | ||
/// @param _config The configuration of the Hyperdrive pool. | ||
/// @param _adminController The admin controller that will specify the | ||
/// admin parameters for this instance. | ||
/// @param _salt The create2 salt used in the deployment. | ||
/// @return The address of the newly deployed SavingsUSDSL2Target1 instance. | ||
function deployTarget( | ||
IHyperdrive.PoolConfig memory _config, | ||
IHyperdriveAdminController _adminController, | ||
bytes memory _extraData, | ||
bytes32 _salt | ||
) external returns (address) { | ||
// The PSM contract. This is where the base token will be swapped | ||
// for shares. | ||
require(_extraData.length >= 20, "Invalid _extraData length"); | ||
IPSM PSM = abi.decode(_extraData, (IPSM)); | ||
|
||
return | ||
address( | ||
// NOTE: We hash the sender with the salt to prevent the | ||
// front-running of deployments. | ||
new SavingsUSDSL2Target1{ | ||
salt: keccak256(abi.encode(msg.sender, _salt)) | ||
}(_config, _adminController, PSM) | ||
); | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
contracts/src/deployers/savings-usds-l2/SavingsUSDSL2Target2Deployer.sol
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,43 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity 0.8.24; | ||
|
||
import { SavingsUSDSL2Target2 } from "../../instances/savings-usds-l2/SavingsUSDSL2Target2.sol"; | ||
import { IHyperdrive } from "../../interfaces/IHyperdrive.sol"; | ||
import { IHyperdriveAdminController } from "../../interfaces/IHyperdriveAdminController.sol"; | ||
import { IHyperdriveTargetDeployer } from "../../interfaces/IHyperdriveTargetDeployer.sol"; | ||
import { IPSM } from "../../interfaces/IPSM.sol"; | ||
|
||
/// @author DELV | ||
/// @title SavingsUSDSL2Target2Deployer | ||
/// @notice The target2 deployer for the SavingsUSDSL2Hyperdrive implementation. | ||
/// @custom:disclaimer The language used in this code is for coding convenience | ||
/// only, and is not intended to, and does not, have any | ||
/// particular legal or regulatory significance. | ||
contract SavingsUSDSL2Target2Deployer is IHyperdriveTargetDeployer { | ||
/// @notice Deploys a target2 instance with the given parameters. | ||
/// @param _config The configuration of the Hyperdrive pool. | ||
/// @param _adminController The admin controller that will specify the | ||
/// admin parameters for this instance. | ||
/// @param _salt The create2 salt used in the deployment. | ||
/// @return The address of the newly deployed SavingsUSDSL2Target2 instance. | ||
function deployTarget( | ||
IHyperdrive.PoolConfig memory _config, | ||
IHyperdriveAdminController _adminController, | ||
bytes memory _extraData, | ||
bytes32 _salt | ||
) external returns (address) { | ||
// The PSM contract. This is where the base token will be swapped | ||
// for shares. | ||
require(_extraData.length >= 20, "Invalid _extraData length"); | ||
IPSM PSM = abi.decode(_extraData, (IPSM)); | ||
|
||
return | ||
address( | ||
// NOTE: We hash the sender with the salt to prevent the | ||
// front-running of deployments. | ||
new SavingsUSDSL2Target2{ | ||
salt: keccak256(abi.encode(msg.sender, _salt)) | ||
}(_config, _adminController, PSM) | ||
); | ||
} | ||
} |
Oops, something went wrong.