diff --git a/.gitignore b/.gitignore index 55e83b0ad..06cd23427 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,7 @@ dist/ .idea/ .DS_Store addresses/localhost/ +addresses/tenderly/ tmp/ # Foundry diff --git a/addresses/arb_mainnet/vyJoins.json b/addresses/arb_mainnet/vyJoins.json new file mode 100644 index 000000000..5159bfc0e --- /dev/null +++ b/addresses/arb_mainnet/vyJoins.json @@ -0,0 +1,5 @@ +{ + "dataType": "Map", + "value": [] + } + \ No newline at end of file diff --git a/addresses/arb_mainnet/vyTokens.json b/addresses/arb_mainnet/vyTokens.json new file mode 100644 index 000000000..9cca0d645 --- /dev/null +++ b/addresses/arb_mainnet/vyTokens.json @@ -0,0 +1,4 @@ +{ + "dataType": "Map", + "value": [] +} diff --git a/addresses/mainnet/vyJoins.json b/addresses/mainnet/vyJoins.json new file mode 100644 index 000000000..5159bfc0e --- /dev/null +++ b/addresses/mainnet/vyJoins.json @@ -0,0 +1,5 @@ +{ + "dataType": "Map", + "value": [] + } + \ No newline at end of file diff --git a/addresses/mainnet/vyTokens.json b/addresses/mainnet/vyTokens.json new file mode 100644 index 000000000..9cca0d645 --- /dev/null +++ b/addresses/mainnet/vyTokens.json @@ -0,0 +1,4 @@ +{ + "dataType": "Map", + "value": [] +} diff --git a/contracts/ERC20Mock.sol b/contracts/ERC20Mock.sol index 7f47ac9bb..9719f8c64 100644 --- a/contracts/ERC20Mock.sol +++ b/contracts/ERC20Mock.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; -import "@yield-protocol/utils-v2/contracts/token/ERC20Permit.sol"; +import "@yield-protocol/utils-v2/src/token/ERC20Permit.sol"; contract ERC20Mock is ERC20Permit { diff --git a/contracts/IdentityOracle.sol b/contracts/IdentityOracle.sol index e1271d5a4..ece7ad295 100644 --- a/contracts/IdentityOracle.sol +++ b/contracts/IdentityOracle.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.15; -import "@yield-protocol/vault-v2/contracts/interfaces/IOracle.sol"; +import "@yield-protocol/vault-v2/src/interfaces/IOracle.sol"; contract IdentityOracle is IOracle { function peek( diff --git a/contracts/Importer.sol b/contracts/Importer.sol index b7662bfe5..38f947907 100644 --- a/contracts/Importer.sol +++ b/contracts/Importer.sol @@ -1,48 +1,56 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.8.13; -import "@yield-protocol/vault-v2/contracts/modules/HealerModule.sol"; -import "@yield-protocol/vault-v2/contracts/modules/RepayFromLadleModule.sol"; -import "@yield-protocol/vault-v2/contracts/oracles/accumulator/AccumulatorMultiOracle.sol"; -import "@yield-protocol/vault-v2/contracts/oracles/chainlink/ChainlinkMultiOracle.sol"; -import "@yield-protocol/vault-v2/contracts/oracles/chainlink/ChainlinkUSDMultiOracle.sol"; -import "@yield-protocol/vault-v2/contracts/oracles/chainlink/ChainlinkL2USDMultiOracle.sol"; -import "@yield-protocol/vault-v2/contracts/oracles/compound/CompoundMultiOracle.sol"; -import "@yield-protocol/vault-v2/contracts/oracles/composite/CompositeMultiOracle.sol"; -import "@yield-protocol/vault-v2/contracts/oracles/compound/CTokenMultiOracle.sol"; -import "@yield-protocol/vault-v2/contracts/oracles/uniswap/UniswapV3Oracle.sol"; -import "@yield-protocol/vault-v2/contracts/oracles/lido/LidoOracle.sol"; -import "@yield-protocol/vault-v2/contracts/oracles/lido/IWstETH.sol"; -import "@yield-protocol/vault-v2/contracts/oracles/yearn/YearnVaultMultiOracle.sol"; -import "@yield-protocol/vault-v2/contracts/oracles/yearn/IYvToken.sol"; -// import "@yield-protocol/vault-v2/contracts/oracles/crab/CrabOracle.sol"; -import "@yield-protocol/vault-v2/contracts/oracles/yieldspace/YieldSpaceMultiOracle.sol"; -// import "@yield-protocol/vault-v2/contracts/oracles/rocket/RETHOracle.sol"; -import "@yield-protocol/vault-v2/contracts/other/tether/TetherJoin.sol"; -import "@yield-protocol/vault-v2/contracts/other/notional/NotionalJoin.sol"; -import "@yield-protocol/vault-v2/contracts/other/notional/NotionalMultiOracle.sol"; -import "@yield-protocol/vault-v2/contracts/other/notional/Transfer1155Module.sol"; -import "@yield-protocol/vault-v2/contracts/other/notional/ERC1155Mock.sol"; -import "@yield-protocol/vault-v2/contracts/other/ether/WrapEtherModule.sol"; -import "@yield-protocol/vault-v2/contracts/utils/Giver.sol"; -import "@yield-protocol/vault-v2/contracts/Join.sol"; -import "@yield-protocol/vault-v2/contracts/FlashJoin.sol"; -import "@yield-protocol/vault-v2/contracts/FYToken.sol"; -import "@yield-protocol/vault-v2/contracts/Cauldron.sol"; -import "@yield-protocol/vault-v2/contracts/Ladle.sol"; -import "@yield-protocol/vault-v2/contracts/Witch.sol"; +import "@yield-protocol/vault-v2/src/modules/HealerModule.sol"; +import "@yield-protocol/vault-v2/src/modules/RepayFromLadleModule.sol"; +import "@yield-protocol/vault-v2/src/oracles/accumulator/AccumulatorMultiOracle.sol"; +import "@yield-protocol/vault-v2/src/oracles/chainlink/ChainlinkMultiOracle.sol"; +import "@yield-protocol/vault-v2/src/oracles/chainlink/ChainlinkUSDMultiOracle.sol"; +import "@yield-protocol/vault-v2/src/oracles/chainlink/ChainlinkL2USDMultiOracle.sol"; +import "@yield-protocol/vault-v2/src/oracles/compound/CompoundMultiOracle.sol"; +import "@yield-protocol/vault-v2/src/oracles/composite/CompositeMultiOracle.sol"; +import "@yield-protocol/vault-v2/src/oracles/compound/CTokenMultiOracle.sol"; +import "@yield-protocol/vault-v2/src/oracles/uniswap/UniswapV3Oracle.sol"; +import "@yield-protocol/vault-v2/src/oracles/lido/LidoOracle.sol"; +import "@yield-protocol/vault-v2/src/oracles/lido/IWstETH.sol"; +import "@yield-protocol/vault-v2/src/oracles/yearn/YearnVaultMultiOracle.sol"; +import "@yield-protocol/vault-v2/src/oracles/yearn/IYvToken.sol"; +// import "@yield-protocol/vault-v2/src/oracles/crab/CrabOracle.sol"; +import "@yield-protocol/vault-v2/src/oracles/yieldspace/YieldSpaceMultiOracle.sol"; +// import "@yield-protocol/vault-v2/src/oracles/rocket/RETHOracle.sol"; +import "@yield-protocol/vault-v2/src/other/tether/TetherJoin.sol"; +import "@yield-protocol/vault-v2/src/other/notional/NotionalJoin.sol"; +import "@yield-protocol/vault-v2/src/other/notional/NotionalMultiOracle.sol"; +import "@yield-protocol/vault-v2/src/other/notional/Transfer1155Module.sol"; +import "@yield-protocol/vault-v2/src/other/notional/ERC1155Mock.sol"; +import "@yield-protocol/vault-v2/src/modules/WrapEtherModule.sol"; +import "@yield-protocol/vault-v2/src/utils/Giver.sol"; +import "@yield-protocol/vault-v2/src/Join.sol"; +import "@yield-protocol/vault-v2/src/FlashJoin.sol"; +import "@yield-protocol/vault-v2/src/FYToken.sol"; +import "@yield-protocol/vault-v2/src/Cauldron.sol"; +import "@yield-protocol/vault-v2/src/Ladle.sol"; +import "@yield-protocol/vault-v2/src/Witch.sol"; import "@yield-protocol/yieldspace-tv/src/YieldMath.sol"; import "@yield-protocol/yieldspace-tv/src/Pool/Pool.sol"; import "@yield-protocol/yieldspace-tv/src/Pool/Modules/PoolNonTv.sol"; import "@yield-protocol/yieldspace-tv/src/Pool/Modules/PoolYearnVault.sol"; import "@yield-protocol/yieldspace-tv/src/Pool/Modules/PoolEuler.sol"; import "@yield-protocol/yieldspace-tv/src/oracle/PoolOracle.sol"; -import "@yield-protocol/utils-v2/contracts/utils/Timelock.sol"; -import "@yield-protocol/utils-v2/contracts/utils/EmergencyBrake.sol"; -import "@yield-protocol/utils-v2/contracts/utils/Assert.sol"; -import "@yield-protocol/strategy-v2/contracts/Strategy.sol"; +import "@yield-protocol/utils-v2/src/utils/Timelock.sol"; +import "@yield-protocol/utils-v2/src/utils/EmergencyBrake.sol"; +import "@yield-protocol/utils-v2/src/utils/Assert.sol"; +import "@yield-protocol/strategy-v2/src/Strategy.sol"; // import "@yield-protocol/vault-v2/contracts/oracles/strategy/StrategyOracle.sol"; -import "@yield-protocol/vault-v2/contracts/other/contango/ContangoLadle.sol"; -import "@yield-protocol/vault-v2/contracts/other/contango/ContangoWitch.sol"; -import "@yield-protocol/yvarb/contracts/YieldStEthLever.sol"; -import "@yield-protocol/yvarb/contracts/YieldNotionalLever.sol"; \ No newline at end of file +import "@yield-protocol/vault-v2/src/other/contango/ContangoLadle.sol"; +import "@yield-protocol/vault-v2/src/other/contango/ContangoWitch.sol"; +// import "@yield-protocol/yvarb/contracts/YieldStEthLever.sol"; +// import "@yield-protocol/yvarb/contracts/YieldNotionalLever.sol"; +import "@yield-protocol/vault-v2/src/variable/VRCauldron.sol"; +import "@yield-protocol/vault-v2/src/variable/VRLadle.sol"; +import "@yield-protocol/vault-v2/src/variable/VRWitch.sol"; +import "@yield-protocol/vault-v2/src/variable/VYToken.sol"; +import "@yield-protocol/vault-v2/src/variable/VRRouter.sol"; +import "@yield-protocol/vault-v2/src/oracles/VariableInterestRateOracle.sol"; +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; \ No newline at end of file diff --git a/contracts/OldEmergencyBrake.sol b/contracts/OldEmergencyBrake.sol index b4dad45ed..71acd4f96 100644 --- a/contracts/OldEmergencyBrake.sol +++ b/contracts/OldEmergencyBrake.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "@yield-protocol/utils-v2/contracts/access/AccessControl.sol"; +import "@yield-protocol/utils-v2/src/access/AccessControl.sol"; interface IEmergencyBrake { diff --git a/contracts/RegistryInterfaces.sol b/contracts/RegistryInterfaces.sol index b5b695ecc..c57142bd2 100644 --- a/contracts/RegistryInterfaces.sol +++ b/contracts/RegistryInterfaces.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.0; -import "@yield-protocol/vault-v2/contracts/interfaces/DataTypes.sol"; +import "@yield-protocol/vault-v2/src/interfaces/DataTypes.sol"; import "@yield-protocol/yieldspace-tv/src/interfaces/IPool.sol"; diff --git a/contracts/Roller.sol b/contracts/Roller.sol index 3553d26c7..06842ffa9 100644 --- a/contracts/Roller.sol +++ b/contracts/Roller.sol @@ -3,12 +3,12 @@ pragma solidity >=0.8.15; import "erc3156/contracts/interfaces/IERC3156FlashBorrower.sol"; import "erc3156/contracts/interfaces/IERC3156FlashLender.sol"; import "@yield-protocol/yieldspace-tv/src/interfaces/IMaturingToken.sol"; -import "@yield-protocol/vault-v2/contracts/interfaces/IFYToken.sol"; +import "@yield-protocol/vault-v2/src/interfaces/IFYToken.sol"; // import "@yield-protocol/vault-interfaces/src/ILadle.sol"; import "@yield-protocol/yieldspace-tv/src/interfaces/IPool.sol"; // import "@yield-protocol/strategy-v2/contracts/IStrategy.sol"; -import "@yield-protocol/utils-v2/contracts/token/MinimalTransferHelper.sol"; -import "@yield-protocol/utils-v2/contracts/access/AccessControl.sol"; +import "@yield-protocol/utils-v2/src/token/MinimalTransferHelper.sol"; +import "@yield-protocol/utils-v2/src/access/AccessControl.sol"; interface ILadle { function joins(bytes6) external view returns (address); diff --git a/contracts/Solvency.sol b/contracts/Solvency.sol index df35d7448..6817a5725 100644 --- a/contracts/Solvency.sol +++ b/contracts/Solvency.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.15; -import "@yield-protocol/vault-v2/contracts/interfaces/DataTypes.sol"; -import "@yield-protocol/vault-v2/contracts/interfaces/IFYToken.sol"; -import "@yield-protocol/utils-v2/contracts/math/WDiv.sol"; -import "@yield-protocol/utils-v2/contracts/cast/CastU256I256.sol"; +import "@yield-protocol/vault-v2/src/interfaces/DataTypes.sol"; +import "@yield-protocol/vault-v2/src/interfaces/IFYToken.sol"; +import "@yield-protocol/utils-v2/src/utils/Math.sol"; +import "@yield-protocol/utils-v2/src/utils/Cast.sol"; import "./RegistryInterfaces.sol"; interface INotionalJoin { @@ -14,8 +14,8 @@ interface INotionalJoin { /// aggregated ETH value of fyToken in circulation against the aggregated ETH value /// of all assets in the Joins contract Solvency { - using CastU256I256 for uint256; - using WDiv for uint256; + using Cast for uint256; + using Math for uint256; bytes6 constant public ETH = 0x303000000000; address constant public FCASH = 0x1344A36A1B56144C3Bc62E7757377D288fDE0369; diff --git a/contracts/Trader.sol b/contracts/Trader.sol index 9d11a069a..aa50a9a35 100644 --- a/contracts/Trader.sol +++ b/contracts/Trader.sol @@ -3,10 +3,10 @@ pragma solidity >=0.8.15; import "erc3156/contracts/interfaces/IERC3156FlashBorrower.sol"; import "erc3156/contracts/interfaces/IERC3156FlashLender.sol"; import "@yield-protocol/yieldspace-tv/src/interfaces/IMaturingToken.sol"; -import "@yield-protocol/vault-v2/contracts/interfaces/IFYToken.sol"; +import "@yield-protocol/vault-v2/src/interfaces/IFYToken.sol"; import "@yield-protocol/yieldspace-tv/src/interfaces/IPool.sol"; -import "@yield-protocol/utils-v2/contracts/token/MinimalTransferHelper.sol"; -import "@yield-protocol/utils-v2/contracts/access/AccessControl.sol"; +import "@yield-protocol/utils-v2/src/token/MinimalTransferHelper.sol"; +import "@yield-protocol/utils-v2/src/access/AccessControl.sol"; interface ITrader { function authorize(address grantee) external; diff --git a/contracts/deprecated/OldEmergencyBrake.sol b/contracts/deprecated/OldEmergencyBrake.sol index b4dad45ed..71acd4f96 100644 --- a/contracts/deprecated/OldEmergencyBrake.sol +++ b/contracts/deprecated/OldEmergencyBrake.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "@yield-protocol/utils-v2/contracts/access/AccessControl.sol"; +import "@yield-protocol/utils-v2/src/access/AccessControl.sol"; interface IEmergencyBrake { diff --git a/contracts/deprecated/OldWitch.sol b/contracts/deprecated/OldWitch.sol index 5aa3c4fca..8e3795c82 100644 --- a/contracts/deprecated/OldWitch.sol +++ b/contracts/deprecated/OldWitch.sol @@ -1,25 +1,22 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.6; -import "@yield-protocol/utils-v2/contracts/access/AccessControl.sol"; -import "@yield-protocol/vault-v2/contracts/interfaces/ILadle.sol"; -import "@yield-protocol/vault-v2/contracts/interfaces/ICauldron.sol"; -import "@yield-protocol/vault-v2/contracts/interfaces/IJoin.sol"; -import "@yield-protocol/vault-v2/contracts/interfaces/DataTypes.sol"; -import "@yield-protocol/utils-v2/contracts/math/WMul.sol"; -import "@yield-protocol/utils-v2/contracts/math/WMulUp.sol"; -import "@yield-protocol/utils-v2/contracts/math/WDiv.sol"; -import "@yield-protocol/utils-v2/contracts/math/WDivUp.sol"; -import "@yield-protocol/utils-v2/contracts/cast/CastU256U128.sol"; -import "@yield-protocol/utils-v2/contracts/cast/CastU256U32.sol"; +import "@yield-protocol/utils-v2/src/access/AccessControl.sol"; +import "@yield-protocol/vault-v2/src/interfaces/ILadle.sol"; +import "@yield-protocol/vault-v2/src/interfaces/ICauldron.sol"; +import "@yield-protocol/vault-v2/src/interfaces/IJoin.sol"; +import "@yield-protocol/vault-v2/src/interfaces/DataTypes.sol"; +import "@yield-protocol/utils-v2/src/utils/Math.sol"; +import "@yield-protocol/utils-v2/src/utils/Cast.sol"; + contract OldWitch is AccessControl() { - using WMul for uint256; - using WMulUp for uint256; - using WDiv for uint256; - using WDivUp for uint256; - using CastU256U128 for uint256; - using CastU256U32 for uint256; + using Math for uint256; + using Math for uint256; + using Math for uint256; + using Math for uint256; + using Cast for uint256; + using Cast for uint256; event Point(bytes32 indexed param, address value); event IlkSet(bytes6 indexed ilkId, uint32 duration, uint64 initialOffer, uint96 line, uint24 dust, uint8 dec); diff --git a/contracts/deprecated/StrategyV1.sol b/contracts/deprecated/StrategyV1.sol index 166d06ed1..62e40865d 100644 --- a/contracts/deprecated/StrategyV1.sol +++ b/contracts/deprecated/StrategyV1.sol @@ -1,16 +1,15 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.13; -import "@yield-protocol/utils-v2/contracts/access/AccessControl.sol"; -import "@yield-protocol/utils-v2/contracts/token/SafeERC20Namer.sol"; -import "@yield-protocol/utils-v2/contracts/token/MinimalTransferHelper.sol"; -import "@yield-protocol/utils-v2/contracts/token/IERC20.sol"; -import "@yield-protocol/utils-v2/contracts/token/ERC20Rewards.sol"; -import "@yield-protocol/utils-v2/contracts/cast/CastU256I128.sol"; -import "@yield-protocol/utils-v2/contracts/cast/CastU128I128.sol"; -import "@yield-protocol/vault-v2/contracts/interfaces/DataTypes.sol"; -import "@yield-protocol/vault-v2/contracts/interfaces/ICauldron.sol"; -import "@yield-protocol/vault-v2/contracts/interfaces/ILadle.sol"; +import "@yield-protocol/utils-v2/src/access/AccessControl.sol"; +import "@yield-protocol/utils-v2/src/token/SafeERC20Namer.sol"; +import "@yield-protocol/utils-v2/src/token/MinimalTransferHelper.sol"; +import "@yield-protocol/utils-v2/src/token/IERC20.sol"; +import "@yield-protocol/utils-v2/src/token/ERC20Rewards.sol"; +import "@yield-protocol/utils-v2/src/utils/Cast.sol"; +import "@yield-protocol/vault-v2/src/interfaces/DataTypes.sol"; +import "@yield-protocol/vault-v2/src/interfaces/ICauldron.sol"; +import "@yield-protocol/vault-v2/src/interfaces/ILadle.sol"; import "@yield-protocol/yieldspace-tv/src/interfaces/IPool.sol"; import "./YieldMathExtensions.sol"; @@ -29,9 +28,7 @@ contract StrategyV1 is AccessControl, ERC20Rewards { using DivUp for uint256; using MinimalTransferHelper for IERC20; using YieldMathExtensions for IPool; - using CastU256U128 for uint256; // Inherited from ERC20Rewards - using CastU256I128 for uint256; - using CastU128I128 for uint128; + using Cast for uint256; // Inherited from ERC20Rewards event YieldSet(ILadle ladle, ICauldron cauldron); event TokenJoinReset(address join); diff --git a/contracts/wands/CollateralWandBase.sol b/contracts/wands/CollateralWandBase.sol index c43e24f99..02e5e5ef5 100644 --- a/contracts/wands/CollateralWandBase.sol +++ b/contracts/wands/CollateralWandBase.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.13; -import '@yield-protocol/vault-v2/contracts/interfaces/ICauldronGov.sol'; -import '@yield-protocol/vault-v2/contracts/interfaces/IOracle.sol'; -import '@yield-protocol/vault-v2/contracts/interfaces/ILadleGov.sol'; -import '@yield-protocol/vault-v2/contracts/interfaces/IJoin.sol'; -import '@yield-protocol/utils-v2/contracts/access/AccessControl.sol'; -import '@yield-protocol/utils-v2/contracts/token/IERC20Metadata.sol'; -import {IEmergencyBrake} from '@yield-protocol/utils-v2/contracts/utils/EmergencyBrake.sol'; +import '@yield-protocol/vault-v2/src/interfaces/ICauldronGov.sol'; +import '@yield-protocol/vault-v2/src/interfaces/IOracle.sol'; +import '@yield-protocol/vault-v2/src/interfaces/ILadleGov.sol'; +import '@yield-protocol/vault-v2/src/interfaces/IJoin.sol'; +import '@yield-protocol/utils-v2/src/access/AccessControl.sol'; +import '@yield-protocol/utils-v2/src/token/IERC20Metadata.sol'; +import {IEmergencyBrake} from '@yield-protocol/utils-v2/src/utils/EmergencyBrake.sol'; interface IWitchCustom { //// @dev Function to set the auction limit on the witch diff --git a/contracts/wands/FCashWand.sol b/contracts/wands/FCashWand.sol index 12cff3f27..9c0b30e59 100644 --- a/contracts/wands/FCashWand.sol +++ b/contracts/wands/FCashWand.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.13; import './CollateralWandBase.sol'; -import '@yield-protocol/vault-v2/contracts/interfaces/DataTypes.sol'; -import '@yield-protocol/vault-v2/contracts/other/notional/NotionalJoin.sol'; +import '@yield-protocol/vault-v2/src/interfaces/DataTypes.sol'; +import '@yield-protocol/vault-v2/src/other/notional/NotionalJoin.sol'; interface INotionalMultiOracle{ function setSource( diff --git a/contracts/wands/SeriesWand.sol b/contracts/wands/SeriesWand.sol index 27ba4be9c..71ebd4b10 100644 --- a/contracts/wands/SeriesWand.sol +++ b/contracts/wands/SeriesWand.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.13; -import '@yield-protocol/vault-v2/contracts/interfaces/ICauldronGov.sol'; -import '@yield-protocol/vault-v2/contracts/interfaces/ILadleGov.sol'; -import '@yield-protocol/vault-v2/contracts/interfaces/IJoin.sol'; -import '@yield-protocol/vault-v2/contracts/interfaces/IFYToken.sol'; -import '@yield-protocol/utils-v2/contracts/access/AccessControl.sol'; -import {IEmergencyBrake} from '@yield-protocol/utils-v2/contracts/utils/EmergencyBrake.sol'; +import '@yield-protocol/vault-v2/src/interfaces/ICauldronGov.sol'; +import '@yield-protocol/vault-v2/src/interfaces/ILadleGov.sol'; +import '@yield-protocol/vault-v2/src/interfaces/IJoin.sol'; +import '@yield-protocol/vault-v2/src/interfaces/IFYToken.sol'; +import '@yield-protocol/utils-v2/src/access/AccessControl.sol'; +import {IEmergencyBrake} from '@yield-protocol/utils-v2/src/utils/EmergencyBrake.sol'; /// @dev A wand to create new series. /// @author @iamsahu diff --git a/package.json b/package.json index 4e05e7f5a..5c7d850ae 100644 --- a/package.json +++ b/package.json @@ -28,10 +28,10 @@ "@typechain/ethers-v5": "^10.0.0", "@typechain/hardhat": "^6.0.0", "@types/mocha": "^8.0.0", - "@yield-protocol/strategy-v2": "2.0.0", - "@yield-protocol/utils-v2": "2.6.9-rc.1", - "@yield-protocol/vault-v2": "0.18.10-rc.1", - "@yield-protocol/yieldspace-tv": "0.1.9-rc.3", + "@yield-protocol/strategy-v2": "^2.0.3", + "@yield-protocol/utils-v2": "^2.6.16", + "@yield-protocol/vault-v2": "../vault-v2/yield-protocol-vault-v2-0.18.13.tgz", + "@yield-protocol/yieldspace-tv": "^0.1.11", "chai": "4.2.0", "dss-interfaces": "0.1.1", "erc3156": "^0.4.8", diff --git a/scripts/fragments/assetsAndSeries/addVRIlk.ts b/scripts/fragments/assetsAndSeries/addVRIlk.ts new file mode 100644 index 000000000..e9da5c5cf --- /dev/null +++ b/scripts/fragments/assetsAndSeries/addVRIlk.ts @@ -0,0 +1,23 @@ +// Add an existing ilk to a series + +import { VRCauldron } from '../../../typechain' +import { Ilk, Series } from '../../governance/confTypes' +import { getName, indent } from '../../../shared/helpers' + +export const addVRIlk = async ( + cauldron: VRCauldron, + ilk: Ilk, + nesting: number = 0 +): Promise> => { + console.log() + console.log(indent(nesting, `ADD_ILK_TO_SERIES`)) + const proposal: Array<{ target: string; data: string }> = [] + + proposal.push({ + target: cauldron.address, + data: cauldron.interface.encodeFunctionData('addIlks', [ilk.baseId, [ilk.ilkId]]), + }) + console.log(indent(nesting, `addIlks ${getName(ilk.baseId)}: ${getName(ilk.ilkId)}`)) + + return proposal +} diff --git a/scripts/fragments/assetsAndSeries/makeVRBase.ts b/scripts/fragments/assetsAndSeries/makeVRBase.ts new file mode 100644 index 000000000..fafbb50d0 --- /dev/null +++ b/scripts/fragments/assetsAndSeries/makeVRBase.ts @@ -0,0 +1,40 @@ +// Make an asset into a base. +// - A lending oracle is set for the new base +// - The asset is added to the Witch. + +import { getName, indent } from '../../../shared/helpers' +import { IOracle, Join__factory, EmergencyBrake, VRCauldron, VRWitch, Witch } from '../../../typechain' +import { addBaseToWitch } from '../witch/addBaseToWitch' +import { Base } from '../../governance/confTypes' + +export const makeVRBase = async ( + ownerAcc: any, + cloak: EmergencyBrake, + rateOracle: IOracle, + cauldron: VRCauldron, + witch: VRWitch, + base: Base, + joins: Map, + nesting: number = 0 +): Promise> => { + console.log() + console.log(indent(nesting, `MAKE_BASE`)) + let proposal: Array<{ target: string; data: string }> = [] + const join = Join__factory.connect(joins.getOrThrow(base.assetId)!, ownerAcc) + + proposal = proposal.concat(await addBaseToWitch(cloak, witch as unknown as Witch, base.assetId, join, nesting + 1)) + + // Add the asset as a base + proposal.push({ + target: cauldron.address, + data: cauldron.interface.encodeFunctionData('setRateOracle', [base.assetId, rateOracle.address]), + }) + console.log(indent(nesting, `Rate Oracle ${rateOracle.address} added for Asset ${getName(base.assetId)}`)) + proposal.push({ + target: cauldron.address, + data: cauldron.interface.encodeFunctionData('addBase', [base.assetId]), + }) + console.log(indent(nesting, `Asset ${getName(base.assetId)} made into base using ${rateOracle.address}`)) + + return proposal +} diff --git a/scripts/fragments/assetsAndSeries/orchestrateJoin.ts b/scripts/fragments/assetsAndSeries/orchestrateJoin.ts index 58b16bb9c..47aefd7fd 100644 --- a/scripts/fragments/assetsAndSeries/orchestrateJoin.ts +++ b/scripts/fragments/assetsAndSeries/orchestrateJoin.ts @@ -1,8 +1,7 @@ -import { id } from '@yield-protocol/utils-v2' import { EmergencyBrake, Timelock, AccessControl__factory, Join } from '../../../typechain' import { revokeRoot } from '../permissions/revokeRoot' import { addAsHostToCloak } from '../cloak/addAsHostToCloak' -import { indent } from '../../../shared/helpers' +import { indent, id } from '../../../shared/helpers' export const orchestrateJoin = async ( deployer: string, diff --git a/scripts/fragments/core/orchestrateVRCauldron.ts b/scripts/fragments/core/orchestrateVRCauldron.ts new file mode 100644 index 000000000..821157440 --- /dev/null +++ b/scripts/fragments/core/orchestrateVRCauldron.ts @@ -0,0 +1,48 @@ +import { ROOT } from '../../../shared/constants' +import { EmergencyBrake, Timelock, VRCauldron } from '../../../typechain' +import { revokeRoot } from '../permissions/revokeRoot' +import { indent, id } from '../../../shared/helpers' + +/** + * @dev This script orchestrates the Cauldron + * The Cloak gets ROOT access. Root access is removed from the deployer. + * The Timelock gets access to governance functions. + */ +export const orchestrateVRCauldron = async ( + deployer: string, + cauldron: VRCauldron, + timelock: Timelock, + cloak: EmergencyBrake, + nesting: number = 0 +): Promise> => { + console.log() + console.log(indent(nesting, `ORCHESTRATE_VR_CAULDRON`)) + let proposal: Array<{ target: string; data: string }> = [] + // Give access to each of the governance functions to the timelock, through a proposal to bundle them + // Give ROOT to the cloak, revoke ROOT from the deployer + proposal.push({ + target: cauldron.address, + data: cauldron.interface.encodeFunctionData('grantRoles', [ + [ + id(cauldron.interface, 'addAsset(bytes6,address)'), + id(cauldron.interface, 'addBase(bytes6)'), + id(cauldron.interface, 'addIlks(bytes6,bytes6[])'), + id(cauldron.interface, 'setDebtLimits(bytes6,bytes6,uint96,uint24,uint8)'), + id(cauldron.interface, 'setRateOracle(bytes6,address)'), + id(cauldron.interface, 'setSpotOracle(bytes6,bytes6,address,uint32)'), + ], + timelock.address, + ]), + }) + console.log(indent(nesting, `cauldron.grantRoles(gov, timelock)`)) + + proposal.push({ + target: cauldron.address, + data: cauldron.interface.encodeFunctionData('grantRole', [ROOT, cloak.address]), + }) + console.log(indent(nesting, `cauldron.grantRole(ROOT, cloak)`)) + + proposal = proposal.concat(await revokeRoot(cauldron, deployer, nesting + 1)) + + return proposal +} diff --git a/scripts/fragments/core/orchestrateVRLadle.ts b/scripts/fragments/core/orchestrateVRLadle.ts new file mode 100644 index 000000000..5dc5df5f0 --- /dev/null +++ b/scripts/fragments/core/orchestrateVRLadle.ts @@ -0,0 +1,99 @@ +import { ROOT } from '../../../shared/constants' +import { VRCauldron, VRLadle, EmergencyBrake, Timelock } from '../../../typechain' +import { revokeRoot } from '../permissions/revokeRoot' +import { indent, id } from '../../../shared/helpers' + +/** + * @dev This script orchestrates the Ladle + * The Cloak gets ROOT access. Root access is removed from the deployer. + * The Timelock gets access to governance functions. + * The Ladle gets access to the permissioned functions in Cauldron + * Emergency plans are registered + */ +export const orchestrateVRLadle = async ( + deployer: string, + cauldron: VRCauldron, + ladle: VRLadle, + timelock: Timelock, + cloak: EmergencyBrake, + nesting: number = 0 +): Promise> => { + console.log() + console.log(indent(nesting, `ORCHESTRATE_VR_LADLE`)) + let proposal: Array<{ target: string; data: string }> = [] + + // Give access to each of the governance functions to the timelock, through a proposal to bundle them + // Give ROOT to the cloak, revoke ROOT from the deployer + // Orchestrate Ladle to use the permissioned functions in Cauldron + // Store a plan for isolating Cauldron from Ladle + + proposal.push({ + target: ladle.address, + data: ladle.interface.encodeFunctionData('grantRole', [ROOT, cloak.address]), + }) + console.log(indent(nesting, `ladle.grantRole(ROOT, cloak)`)) + + proposal.push({ + target: ladle.address, + data: ladle.interface.encodeFunctionData('grantRoles', [ + [ + id(ladle.interface, 'addJoin(bytes6,address)'), + id(ladle.interface, 'addToken(address,bool)'), + id(ladle.interface, 'addIntegration(address,bool)'), + id(ladle.interface, 'setFee(uint256)'), + ], + timelock.address, + ]), + }) + console.log(indent(nesting, `ladle.grantRoles(gov, timelock)`)) + + proposal.push({ + target: cauldron.address, + data: cauldron.interface.encodeFunctionData('grantRoles', [ + [ + id(cauldron.interface, 'build(address,bytes12,bytes6,bytes6)'), + id(cauldron.interface, 'destroy(bytes12)'), + id(cauldron.interface, 'tweak(bytes12,bytes6,bytes6)'), + id(cauldron.interface, 'give(bytes12,address)'), + id(cauldron.interface, 'pour(bytes12,int128,int128)'), + id(cauldron.interface, 'stir(bytes12,bytes12,uint128,uint128)'), + ], + ladle.address, + ]), + }) + console.log(indent(nesting, `cauldron.grantRoles(ladle)`)) + + proposal.push({ + target: cloak.address, + data: cloak.interface.encodeFunctionData('add', [ + ladle.address, + [ + { + host: cauldron.address, + signature: id(cauldron.interface, 'build(address,bytes12,bytes6,bytes6)'), + }, + { + host: cauldron.address, + signature: id(cauldron.interface, 'destroy(bytes12)'), + }, + { + host: cauldron.address, + signature: id(cauldron.interface, 'tweak(bytes12,bytes6,bytes6)'), + }, + { + host: cauldron.address, + signature: id(cauldron.interface, 'pour(bytes12,int128,int128)'), + }, + { + host: cauldron.address, + signature: id(cauldron.interface, 'stir(bytes12,bytes12,uint128,uint128)'), + }, + ], + ]), + }) + console.log(indent(nesting, `cloak.add(ladle to cauldron)`)) + + proposal = proposal.concat(await revokeRoot(cauldron, deployer, nesting + 1)) + + return proposal +} diff --git a/scripts/fragments/core/orchestrateVRWitch.ts b/scripts/fragments/core/orchestrateVRWitch.ts new file mode 100644 index 000000000..19fc1cf64 --- /dev/null +++ b/scripts/fragments/core/orchestrateVRWitch.ts @@ -0,0 +1,44 @@ +/** + * @dev This script orchestrates Witch V2 + */ + +import { ROOT } from '../../../shared/constants' +import { EmergencyBrake, Timelock, VRWitch } from '../../../typechain' +import { revokeRoot } from '../permissions/revokeRoot' +import { indent, id } from '../../../shared/helpers' + +export const orchestrateVRWitch = async ( + deployer: string, + witch: VRWitch, + timelock: Timelock, + cloak: EmergencyBrake, + nesting: number = 0 +): Promise> => { + console.log() + console.log(indent(nesting, `ORCHESTRATE_VR_WITCH`)) + let proposal: Array<{ target: string; data: string }> = [] + + proposal.push({ + target: witch.address, + data: witch.interface.encodeFunctionData('grantRole', [ROOT, cloak.address]), + }) + console.log(indent(nesting, `ladle.grantRole(ROOT, cloak)`)) + + proposal.push({ + target: witch.address, + data: witch.interface.encodeFunctionData('grantRoles', [ + [ + id(witch.interface, 'point(bytes32,address)'), + id(witch.interface, 'setAuctioneerReward(uint256)'), + id(witch.interface, 'setProtected(address,bool)'), + id(witch.interface, 'setLineAndLimit(bytes6,bytes6,uint32,uint64,uint64,uint128)'), + ], + timelock.address, + ]), + }) + console.log(indent(nesting, `witch.grantRoles(timelock)`)) + + proposal = proposal.concat(await revokeRoot(witch, deployer, nesting + 1)) + + return proposal +} diff --git a/scripts/fragments/core/orchestrateVRWitchToVRCauldron.ts b/scripts/fragments/core/orchestrateVRWitchToVRCauldron.ts new file mode 100644 index 000000000..b20b14698 --- /dev/null +++ b/scripts/fragments/core/orchestrateVRWitchToVRCauldron.ts @@ -0,0 +1,46 @@ +/** + * @dev This script orchestrates VRWitch + */ + +import { VRCauldron, EmergencyBrake, VRWitch } from '../../../typechain' +import { indent, id } from '../../../shared/helpers' + +export const orchestrateVRWitchToVRCauldron = async ( + cloak: EmergencyBrake, + cauldron: VRCauldron, + witch: VRWitch, + nesting: number = 0 +): Promise> => { + console.log() + console.log(indent(nesting, `ORCHESTRATE_VR_WITCH_TO_VR_CAULDRON`)) + const proposal: Array<{ target: string; data: string }> = [] + + proposal.push({ + target: cauldron.address, + data: cauldron.interface.encodeFunctionData('grantRoles', [ + [id(cauldron.interface, 'give(bytes12,address)'), id(cauldron.interface, 'slurp(bytes12,uint128,uint128)')], + witch.address, + ]), + }) + console.log(indent(nesting, `cauldron.grantRoles(witch)`)) + + proposal.push({ + target: cloak.address, + data: cloak.interface.encodeFunctionData('add', [ + witch.address, + [ + { + host: cauldron.address, + signature: id(cauldron.interface, 'give(bytes12,address)'), + }, + { + host: cauldron.address, + signature: id(cauldron.interface, 'slurp(bytes12,uint128,uint128)'), + }, + ], + ]), + }) + console.log(indent(nesting, `cloak.add(witch give and slurp)`)) + + return proposal +} diff --git a/scripts/fragments/ladle/addJoin.ts b/scripts/fragments/ladle/addJoin.ts index 5374f362e..d6c5c6e0c 100644 --- a/scripts/fragments/ladle/addJoin.ts +++ b/scripts/fragments/ladle/addJoin.ts @@ -2,9 +2,9 @@ * @dev This script registers one join with the ladle. */ -import { id } from '@yield-protocol/utils-v2' +// import { id } from "../../../" import { Ladle, Join, EmergencyBrake } from '../../../typechain' -import { getName, indent } from '../../../shared/helpers' +import { getName, indent, id } from '../../../shared/helpers' export const addJoin = async ( cloak: EmergencyBrake, diff --git a/scripts/fragments/oracles/orchestrateVariableInterestOracle.ts b/scripts/fragments/oracles/orchestrateVariableInterestOracle.ts new file mode 100644 index 000000000..1a7f5863e --- /dev/null +++ b/scripts/fragments/oracles/orchestrateVariableInterestOracle.ts @@ -0,0 +1,50 @@ +import { ROOT } from '../../../shared/constants' +import { VariableInterestRateOracle, EmergencyBrake, Timelock } from '../../../typechain' +import { revokeRoot } from '../permissions/revokeRoot' +import { indent, id } from '../../../shared/helpers' + +/** + * @dev This script permissions a AccumulatorMultiOracle + * + * The Timelock and Cloak get ROOT access. Root access is removed from the deployer. + * The Timelock gets access to governance functions. + */ + +export const orchestrateVariableInterestRateOracle = async ( + deployer: string, + variableInterestRateOracle: VariableInterestRateOracle, + timelock: Timelock, + cloak: EmergencyBrake, + nesting: number = 0 +): Promise> => { + console.log() + console.log(indent(nesting, `ORCHESTRATE_VARIABLE_INTEREST_RATE_ORACLE`)) + // Give access to each of the governance functions to the timelock, through a proposal to bundle them + // Give ROOT to the cloak, revoke ROOT from the deployer + let proposal: Array<{ target: string; data: string }> = [] + + proposal.push({ + target: variableInterestRateOracle.address, + data: variableInterestRateOracle.interface.encodeFunctionData('grantRoles', [ + [ + id( + variableInterestRateOracle.interface, + 'setInterestRateParameters(bytes6,bytes6,uint256,uint256,uint256,uint256,uint256,bytes6[])' + ), + id(variableInterestRateOracle.interface, 'updateParameters(bytes6,bytes6,uint256,uint256,uint256,uint256)'), + ], + timelock.address, + ]), + }) + console.log(indent(nesting, `variableInterestRateOracle.grantRoles(gov, timelock)`)) + + proposal.push({ + target: variableInterestRateOracle.address, + data: variableInterestRateOracle.interface.encodeFunctionData('grantRole', [ROOT, cloak.address]), + }) + console.log(indent(nesting, `variableInterestRateOracle.grantRole(ROOT, cloak)`)) + + proposal = proposal.concat(await revokeRoot(variableInterestRateOracle, deployer, nesting + 1)) + + return proposal +} diff --git a/scripts/fragments/oracles/setVariableInterestRateOracleParams.ts b/scripts/fragments/oracles/setVariableInterestRateOracleParams.ts new file mode 100644 index 000000000..7921f13ff --- /dev/null +++ b/scripts/fragments/oracles/setVariableInterestRateOracleParams.ts @@ -0,0 +1,53 @@ +/** + * @dev This script replaces one or more chi data sources in the AccumulatorMultiOracle. + */ + +import { getName, indent } from '../../../shared/helpers' +import { VariableInterestRateOracle } from '../../../typechain' +import { VariableInterestRateOracleSource } from '../../governance/confTypes' + +export const setVariableInterestRateOracleParams = async ( + variableInterestRateOracle: VariableInterestRateOracle, + sources: VariableInterestRateOracleSource[], + nesting: number = 0 +): Promise> => { + console.log() + console.log(indent(nesting, `UPDATE_VARIABLE_INTEREST_RATE_ORACLE_SOURCES`)) + console.log(indent(nesting, `accumulator oracle: ${variableInterestRateOracle.address}`)) + + // Build proposal + const proposal: Array<{ target: string; data: string }> = [] + for (let item of sources) { + const source = await variableInterestRateOracle.sources(item.baseId, item.kind) + + if (source.lastUpdated.isZero()) { + proposal.push({ + target: variableInterestRateOracle.address, + data: variableInterestRateOracle.interface.encodeFunctionData('setInterestRateParameters', [ + item.baseId, + item.kind, + item.optimalUsageRate, + item.accumulated, + item.baseVariableBorrowRate, + item.slope1, + item.slope2, + item.ilks, + ]), + }) + console.log( + indent( + nesting, + `VariableInterestRateOracle(${getName(item.baseId)}/${getName(item.kind)}): ${item.optimalUsageRate}, ${ + item.accumulated + },${item.baseVariableBorrowRate}, ${item.slope1}, ${item.slope2}, ${item.ilks}` + ) + ) + } else { + console.log( + indent(nesting, `VariableInterestRateOracle(${getName(item.baseId)}/${getName(item.kind)}): already set`) + ) + } + } + + return proposal +} diff --git a/scripts/fragments/oracles/updateVariableInterestRateOracleSources.ts b/scripts/fragments/oracles/updateVariableInterestRateOracleSources.ts new file mode 100644 index 000000000..bc57382c5 --- /dev/null +++ b/scripts/fragments/oracles/updateVariableInterestRateOracleSources.ts @@ -0,0 +1,51 @@ +/** + * @dev This script replaces one or more chi data sources in the AccumulatorMultiOracle. + */ + +import { getName, indent } from '../../../shared/helpers' +import { VariableInterestRateOracle } from '../../../typechain' +import { VariableInterestRateOracleSource } from '../../governance/confTypes' + +export const updateVariableInterestRateOracleSources = async ( + variableInterestRateOracle: VariableInterestRateOracle, + sources: VariableInterestRateOracleSource[], + nesting: number = 0 +): Promise> => { + console.log() + console.log(indent(nesting, `UPDATE_VARIABLE_INTEREST_RATE_ORACLE_SOURCES`)) + console.log(indent(nesting, `accumulator oracle: ${variableInterestRateOracle.address}`)) + + // Build proposal + const proposal: Array<{ target: string; data: string }> = [] + for (let item of sources) { + const source = await variableInterestRateOracle.sources(item.baseId, item.kind) + + if (source.lastUpdated.isZero()) { + proposal.push({ + target: variableInterestRateOracle.address, + data: variableInterestRateOracle.interface.encodeFunctionData('updateParameters', [ + item.baseId, + item.kind, + item.optimalUsageRate, + item.baseVariableBorrowRate, + item.slope1, + item.slope2, + ]), + }) + console.log( + indent( + nesting, + `VariableInterestRateOracle(${getName(item.baseId)}/${getName(item.kind)}): ${item.optimalUsageRate}, ${ + item.accumulated + },${item.baseVariableBorrowRate}, ${item.slope1}, ${item.slope2}, ${item.ilks}` + ) + ) + } else { + console.log( + indent(nesting, `VariableInterestRateOracle(${getName(item.baseId)}/${getName(item.kind)}): already set`) + ) + } + } + + return proposal +} diff --git a/scripts/fragments/other/orchestrateVRRouter.ts b/scripts/fragments/other/orchestrateVRRouter.ts new file mode 100644 index 000000000..0e1185a50 --- /dev/null +++ b/scripts/fragments/other/orchestrateVRRouter.ts @@ -0,0 +1,23 @@ +import { Ladle, VRRouter } from '../../../typechain' +import { indent } from '../../../shared/helpers' + +/** + * @dev This script orchestrates the VRRouter + */ +export const orchestrateVRRouter = async ( + router: VRRouter, + ladle: Ladle, + nesting: number = 0 +): Promise> => { + console.log() + console.log(indent(nesting, `ORCHESTRATE_VRROUTER`)) + let proposal: Array<{ target: string; data: string }> = [] + + proposal.push({ + target: router.address, + data: router.interface.encodeFunctionData('initialize', [ladle.address]), + }) + console.log(indent(nesting, `vrRouter.initialize(ladle)`)) + + return proposal +} diff --git a/scripts/fragments/other/orchestrateVYToken.ts b/scripts/fragments/other/orchestrateVYToken.ts new file mode 100644 index 000000000..3ed5ba1b2 --- /dev/null +++ b/scripts/fragments/other/orchestrateVYToken.ts @@ -0,0 +1,54 @@ +import { ROOT } from '../../../shared/constants' +import { EmergencyBrake, Timelock, VYToken, Join__factory, Ladle, Router, VRRouter } from '../../../typechain' +import { revokeRoot } from '../permissions/revokeRoot' +import { indent, id } from '../../../shared/helpers' + +/** + * @dev This script orchestrates the VYToken + * The Cloak gets ROOT access. Root access is removed from the deployer. + * The Timelock gets access to governance functions. + */ +export const orchestrateVYToken = async ( + deployer: string, + vyToken: VYToken, + timelock: Timelock, + router: VRRouter, + cloak: EmergencyBrake, + nesting: number = 0 +): Promise> => { + console.log() + console.log(indent(nesting, `ORCHESTRATE_VYTOKEN`)) + let proposal: Array<{ target: string; data: string }> = [] + // Give access to each of the governance functions to the timelock, through a proposal to bundle them + // Give ROOT to the cloak, revoke ROOT from the deployer + + proposal.push({ + target: vyToken.address, + data: vyToken.interface.encodeFunctionData('grantRoles', [ + [id(vyToken.interface, 'deposit(address,uint256)'), id(vyToken.interface, 'mint(address,uint256)')], + router.address, + ]), + }) + console.log(indent(nesting, `vyToken.grantRoles([deposit, mint], router)`)) + + const join = Join__factory.connect(await vyToken.join(), vyToken.signer) + + proposal.push({ + target: join.address, + data: join.interface.encodeFunctionData('grantRoles', [ + [id(join.interface, 'join(address,uint128)'), id(join.interface, 'exit(address,uint128)')], + vyToken.address, + ]), + }) + console.log(indent(nesting, `join.grantRoles(gov, vyToken)`)) + + proposal.push({ + target: vyToken.address, + data: vyToken.interface.encodeFunctionData('grantRole', [ROOT, cloak.address]), + }) + console.log(indent(nesting, `vyToken.grantRole(ROOT, cloak)`)) + + proposal = proposal.concat(await revokeRoot(vyToken, deployer, nesting + 1)) + + return proposal +} diff --git a/scripts/fragments/witch/addBaseToWitch.ts b/scripts/fragments/witch/addBaseToWitch.ts index a4e0f8079..1df9e9a92 100644 --- a/scripts/fragments/witch/addBaseToWitch.ts +++ b/scripts/fragments/witch/addBaseToWitch.ts @@ -2,8 +2,7 @@ * @dev This script registers one fyToken with the ladle. */ -import { id } from '@yield-protocol/utils-v2' -import { getName, indent } from '../../../shared/helpers' +import { getName, indent, id } from '../../../shared/helpers' import { Witch, Join, EmergencyBrake } from '../../../typechain' export const addBaseToWitch = async ( diff --git a/scripts/fragments/witch/addIlkToWitch.ts b/scripts/fragments/witch/addIlkToWitch.ts index 04120e09a..2551ee6d8 100644 --- a/scripts/fragments/witch/addIlkToWitch.ts +++ b/scripts/fragments/witch/addIlkToWitch.ts @@ -3,8 +3,7 @@ * @notice Make sure you define auctionLineAndLimit in the ilk config. */ -import { id } from '@yield-protocol/utils-v2' -import { getName, indent } from '../../../shared/helpers' +import { getName, indent, id } from '../../../shared/helpers' import { Witch, Join, EmergencyBrake } from '../../../typechain' import { setLineAndLimit } from '../witch/setLineAndLimit' import { Ilk } from '../../governance/confTypes' diff --git a/scripts/governance/add/addVariableRate/deployBaseContracts/Steps.md b/scripts/governance/add/addVariableRate/deployBaseContracts/Steps.md new file mode 100644 index 000000000..34f203547 --- /dev/null +++ b/scripts/governance/add/addVariableRate/deployBaseContracts/Steps.md @@ -0,0 +1,26 @@ +# Orchestration & deployment for Variable Rate Lending/Borrowing +1. Deploy VRLadle, VRCauldron, VRWitch, VYTokens +2. Revoke deployer permissions +3. Grant permissions to VRLadle on VRCauldron + 1. Pour + 2. build + 3. destroy + 4. tweak + 5. stir + 6. give +4. Grant permissions to timelock on VRLadle + 1. addJoin + 2. addModule + 3. addToken + 4. addIntegration + 5. setFee +5. Grant permissions to timelock on VRCauldron + 1. addAsset + 2. setDebtLimits + 3. setRateOracle + 4. setSpotOracle + 5. addBase + 6. addIlks +5. Grant permissions to VRWitch on VRCauldron + 1. give + 2. slurp \ No newline at end of file diff --git a/scripts/governance/add/addVariableRate/deployBaseContracts/addVariableRate.sh b/scripts/governance/add/addVariableRate/deployBaseContracts/addVariableRate.sh new file mode 100755 index 000000000..339993f49 --- /dev/null +++ b/scripts/governance/add/addVariableRate/deployBaseContracts/addVariableRate.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -eux +export HERE=$(dirname $0) +export CONF=$PWD/$HERE/variableRate.arbitrum.config +RUN="npx hardhat run --network tenderly" + +$RUN $HERE/../../../../../shared/deploy.ts +$RUN $HERE/addVariableRateBase.ts +$RUN $HERE/../../../../../shared/approve.ts +$RUN $HERE/../../../../../shared/execute.ts +# $RUN $HERE/../../../../../shared/vrStandardBorrowingTest.ts +$RUN $HERE/../../../../../shared/vyTokenTest.ts \ No newline at end of file diff --git a/scripts/governance/add/addVariableRate/deployBaseContracts/addVariableRateBase.ts b/scripts/governance/add/addVariableRate/deployBaseContracts/addVariableRateBase.ts new file mode 100644 index 000000000..019092769 --- /dev/null +++ b/scripts/governance/add/addVariableRate/deployBaseContracts/addVariableRateBase.ts @@ -0,0 +1,154 @@ +import { + VR_CAULDRON, + VR_LADLE, + VR_WITCH, + TIMELOCK, + ACCUMULATOR, + CLOAK, + VARIABLE_RATE_ORACLE, + VR_ROUTER, +} from '../../../../../shared/constants' +import { getOwnerOrImpersonate, propose } from '../../../../../shared/helpers' +import { + VRCauldron__factory, + VRLadle__factory, + VRWitch__factory, + Timelock__factory, + AccumulatorMultiOracle__factory, + EmergencyBrake__factory, + Cauldron__factory, + Ladle__factory, + IOracle, + Witch, + VYToken__factory, + Join__factory, + VariableInterestRateOracle__factory, + VRRouter__factory, +} from '../../../../../typechain' +import { addAsset } from '../../../../fragments/assetsAndSeries/addAsset' +import { addVRIlk } from '../../../../fragments/assetsAndSeries/addVRIlk' +import { makeIlk } from '../../../../fragments/assetsAndSeries/makeIlk' +import { makeVRBase } from '../../../../fragments/assetsAndSeries/makeVRBase' +import { orchestrateJoin } from '../../../../fragments/assetsAndSeries/orchestrateJoin' +import { orchestrateVRCauldron } from '../../../../fragments/core/orchestrateVRCauldron' +import { orchestrateVRLadle } from '../../../../fragments/core/orchestrateVRLadle' +import { orchestrateVRWitch } from '../../../../fragments/core/orchestrateVRWitch' +import { addIntegration } from '../../../../fragments/ladle/addIntegration' +import { orchestrateVariableInterestRateOracle } from '../../../../fragments/oracles/orchestrateVariableInterestOracle' +import { updateAccumulatorSources } from '../../../../fragments/oracles/updateAccumulatorSources' +import { setVariableInterestRateOracleParams } from '../../../../fragments/oracles/setVariableInterestRateOracleParams' +import { orchestrateVYToken } from '../../../../fragments/other/orchestrateVYToken' +import { addToken } from '../../../../fragments/ladle/addToken' +import { orchestrateVRRouter } from '../../../../fragments/other/orchestrateVRRouter' + +const { + developer, + deployers, + protocol, + governance, + accumulatorSources, + variableInterestRateOracleSources, + assetsToAdd, + basesToAdd, + joins, + ilks, + vyTokens, + vyTokensToAdd, +} = require(process.env.CONF!) + +;(async () => { + const ownerAcc = await getOwnerOrImpersonate(developer) + const vrCauldron = VRCauldron__factory.connect(protocol().getOrThrow(VR_CAULDRON)!, ownerAcc) + const cauldron = Cauldron__factory.connect(protocol().getOrThrow(VR_CAULDRON)!, ownerAcc) + const vrLadle = VRLadle__factory.connect(protocol().getOrThrow(VR_LADLE)!, ownerAcc) + const ladle = Ladle__factory.connect(protocol().getOrThrow(VR_LADLE)!, ownerAcc) + const witch = VRWitch__factory.connect(protocol().getOrThrow(VR_WITCH)!, ownerAcc) + const timelock = Timelock__factory.connect(governance.getOrThrow(TIMELOCK)!, ownerAcc) + const cloak = EmergencyBrake__factory.connect(governance.getOrThrow(CLOAK)!, ownerAcc) + const vrRouter = VRRouter__factory.connect(protocol().getOrThrow(VR_ROUTER)!, ownerAcc) + const variableInterestRateOracle = VariableInterestRateOracle__factory.connect( + protocol().getOrThrow(VARIABLE_RATE_ORACLE)!, + ownerAcc + ) + + // Build the proposal + let proposal: Array<{ target: string; data: string }> = [] + + proposal = proposal.concat( + await orchestrateVariableInterestRateOracle( + deployers.getOrThrow(variableInterestRateOracle.address)!, + variableInterestRateOracle, + timelock, + cloak, + 0 + ) + ) + + // proposal = proposal.concat(await updateAccumulatorSources(accumulatorOracle, accumulatorSources)) + + proposal = proposal.concat( + await orchestrateVRCauldron(deployers.getOrThrow(cauldron.address)!, vrCauldron, timelock, cloak, 0) + ) + proposal = proposal.concat( + await orchestrateVRLadle(deployers.getOrThrow(ladle.address)!, vrCauldron, vrLadle, timelock, cloak, 0) + ) + proposal = proposal.concat(await addIntegration(ladle, protocol().getOrThrow('wrapEtherModule')!)) + + proposal = proposal.concat(await orchestrateVRWitch(deployers.getOrThrow(witch.address)!, witch, timelock, cloak, 0)) + proposal = proposal.concat(await orchestrateVRRouter(vrRouter, ladle)) + + for (const asset of assetsToAdd) { + proposal = proposal.concat( + await orchestrateJoin( + deployers.getOrThrow(joins.getOrThrow(asset.assetId)!)!, + timelock, + cloak, + Join__factory.connect(joins.getOrThrow(asset.assetId)!, ownerAcc) + ) + ) + proposal = proposal.concat(await addAsset(ownerAcc, cloak, cauldron, ladle, asset, joins)) + proposal = proposal.concat(await addToken(ladle, asset.address)) + } + + proposal = proposal.concat( + await setVariableInterestRateOracleParams(variableInterestRateOracle, variableInterestRateOracleSources) + ) + + //makeBase + for (const base of basesToAdd) { + proposal = proposal.concat( + await makeVRBase( + ownerAcc, + cloak, + variableInterestRateOracle as unknown as IOracle, + vrCauldron, + witch, + base, + joins + ) + ) + } + //makeIlk + for (const ilk of ilks) { + proposal = proposal.concat(await makeIlk(ownerAcc, cloak, cauldron, witch as unknown as Witch, ilk, joins)) + proposal = proposal.concat(await addVRIlk(vrCauldron, ilk)) + } + + // OrchestrateVYToken + for (const vyToken of vyTokensToAdd) { + const vyTokenContract = VYToken__factory.connect(vyTokens.getOrThrow(vyToken)!, ownerAcc) + proposal = proposal.concat( + await orchestrateVYToken( + deployers.getOrThrow(vyTokenContract.address)!, + vyTokenContract, + timelock, + vrRouter, + cloak, + 0 + ) + ) + proposal = proposal.concat(await addIntegration(ladle, vyTokenContract.address)) + proposal = proposal.concat(await addToken(ladle, vyTokenContract.address)) + } + if (proposal.length > 0) await propose(timelock, proposal, developer) +})() diff --git a/scripts/governance/add/addVariableRate/deployBaseContracts/proposal.txt b/scripts/governance/add/addVariableRate/deployBaseContracts/proposal.txt new file mode 100644 index 000000000..7187d4362 --- /dev/null +++ b/scripts/governance/add/addVariableRate/deployBaseContracts/proposal.txt @@ -0,0 +1 @@ +0x8719c4c6a5e84b7bfa3389b58439d28cc16f5a65ea931eb14b42bbc1356a0167 0xbaae8abf0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b00000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000ea000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001260000000000000000000000000000000000000000000000000000000000000132000000000000000000000000000000000000000000000000000000000000014800000000000000000000000000000000000000000000000000000000000001540000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000017c0000000000000000000000000000000000000000000000000000000000000188000000000000000000000000000000000000000000000000000000000000019a00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000202000000000000000000000000000000000000000000000000000000000000021800000000000000000000000000000000000000000000000000000000000002240000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000024c0000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000000000000000026a0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000029800000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000312000000000000000000000000000000000000000000000000000000000000031e0000000000000000000000000000000000000000000000000000000000000328000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003460000000000000000000000000000000000000000000000000000000000000352000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000037e000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000039e00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003fe0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041c0000000000000000000000000000000000000000000000000000000000000428000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000452000000000000000000000000000000000000000000000000000000000000045e000000000000000000000000000000000000000000000000000000000000046a00000000000000000000000000000000000000000000000000000000000004760000000000000000000000000000000000000000000000000000000000000482000000000000000000000000000000000000000000000000000000000000049400000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000004ac00000000000000000000000000000000000000000000000000000000000004b800000000000000000000000000000000000000000000000000000000000004c400000000000000000000000000000000000000000000000000000000000004d600000000000000000000000000000000000000000000000000000000000004e200000000000000000000000000000000000000000000000000000000000004ee0000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c57300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000124effae35300000000000000000000000000000000000000000000000000000000000000400000000000000000000000003b870db67a45611cf4723d44487eaf398fac51e30000000000000000000000000000000000000000000000000000000000000006e665f9e4000000000000000000000000000000000000000000000000000000007766e00b0000000000000000000000000000000000000000000000000000000053eecb7700000000000000000000000000000000000000000000000000000000d3fc152b00000000000000000000000000000000000000000000000000000000480d411a000000000000000000000000000000000000000000000000000000008ef6bdfa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c57300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc00000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c5730000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004444faded0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034084c37699a8d84ddd93dafaf4ec899032823a1000000000000000000000000000000000000000000000000000000000000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc000000000000000000000000000000000000000000000000000000000000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e4effae35300000000000000000000000000000000000000000000000000000000000000400000000000000000000000003b870db67a45611cf4723d44487eaf398fac51e3000000000000000000000000000000000000000000000000000000000000000449c29d2b00000000000000000000000000000000000000000000000000000000f6252c7100000000000000000000000000000000000000000000000000000000f888f2200000000000000000000000000000000000000000000000000000000069fe0e2d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c57300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000124effae35300000000000000000000000000000000000000000000000000000000000000400000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f0000000000000000000000000000000000000000000000000000000000000006272c0a6e00000000000000000000000000000000000000000000000000000000782006b600000000000000000000000000000000000000000000000000000000b9af392000000000000000000000000000000000000000000000000000000000798a828b00000000000000000000000000000000000000000000000000000000ae8ad492000000000000000000000000000000000000000000000000000000002458028a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001a4f92bcb0d0000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c573272c0a6e00000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c573782006b600000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c573b9af392000000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c573ae8ad49200000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c5732458028a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a3e0ba5a37deab11e5206d7cb73206cd40437d5e00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc00000000000000000000000000000000000000000000000000000000000000000000000000000000a3e0ba5a37deab11e5206d7cb73206cd40437d5e000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e4effae35300000000000000000000000000000000000000000000000000000000000000400000000000000000000000003b870db67a45611cf4723d44487eaf398fac51e300000000000000000000000000000000000000000000000000000000000000041295bd080000000000000000000000000000000000000000000000000000000083c462a9000000000000000000000000000000000000000000000000000000008a7f997c000000000000000000000000000000000000000000000000000000003fa3c3220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a3e0ba5a37deab11e5206d7cb73206cd40437d5e0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004444faded0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034084c37699a8d84ddd93dafaf4ec899032823a100000000000000000000000000000000000000000000000000000000000000000000000000000000d91579a4b0ce5b365a6f45310fd20a1cda54f8df0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004444faded0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034084c37699a8d84ddd93dafaf4ec899032823a100000000000000000000000000000000000000000000000000000000000000000000000000000000d91579a4b0ce5b365a6f45310fd20a1cda54f8df00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc00000000000000000000000000000000000000000000000000000000000000000000000000000000d91579a4b0ce5b365a6f45310fd20a1cda54f8df00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000084effae35300000000000000000000000000000000000000000000000000000000000000400000000000000000000000003b870db67a45611cf4723d44487eaf398fac51e30000000000000000000000000000000000000000000000000000000000000001f06c2dfc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c57300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044e665f9e43030000000000000000000000000000000000000000000000000000000000000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000000000000000000000d91579a4b0ce5b365a6f45310fd20a1cda54f8df000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a4effae35300000000000000000000000000000000000000000000000000000000000000400000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f0000000000000000000000000000000000000000000000000000000000000002ceae3abd0000000000000000000000000000000000000000000000000000000012e5ff77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e4f92bcb0d0000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000d91579a4b0ce5b365a6f45310fd20a1cda54f8dfceae3abd00000000000000000000000000000000000000000000000000000000000000000000000000000000d91579a4b0ce5b365a6f45310fd20a1cda54f8df12e5ff7700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004449c29d2b3030000000000000000000000000000000000000000000000000000000000000000000000000000000000000d91579a4b0ce5b365a6f45310fd20a1cda54f8df000000000000000000000000000000000000000000000000000000000000000000000000000000003823bb68db2a43ae247c4d82486a8d134305a4810000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004444faded0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034084c37699a8d84ddd93dafaf4ec899032823a1000000000000000000000000000000000000000000000000000000000000000000000000000000003823bb68db2a43ae247c4d82486a8d134305a48100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc000000000000000000000000000000000000000000000000000000000000000000000000000000003823bb68db2a43ae247c4d82486a8d134305a48100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000084effae35300000000000000000000000000000000000000000000000000000000000000400000000000000000000000003b870db67a45611cf4723d44487eaf398fac51e30000000000000000000000000000000000000000000000000000000000000001f06c2dfc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c57300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044e665f9e430310000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000000000000000000000000000000000000003823bb68db2a43ae247c4d82486a8d134305a481000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a4effae35300000000000000000000000000000000000000000000000000000000000000400000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f0000000000000000000000000000000000000000000000000000000000000002ceae3abd0000000000000000000000000000000000000000000000000000000012e5ff77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e4f92bcb0d0000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000003823bb68db2a43ae247c4d82486a8d134305a481ceae3abd000000000000000000000000000000000000000000000000000000000000000000000000000000003823bb68db2a43ae247c4d82486a8d134305a48112e5ff7700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004449c29d2b30310000000000000000000000000000000000000000000000000000000000000000000000000000000000003823bb68db2a43ae247c4d82486a8d134305a48100000000000000000000000000000000000000000000000000000000000000000000000000000000a92bcfb3d5d4c7e62b92f73e1b362f39150d4a220000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004444faded0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034084c37699a8d84ddd93dafaf4ec899032823a100000000000000000000000000000000000000000000000000000000000000000000000000000000a92bcfb3d5d4c7e62b92f73e1b362f39150d4a2200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc00000000000000000000000000000000000000000000000000000000000000000000000000000000a92bcfb3d5d4c7e62b92f73e1b362f39150d4a2200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000084effae35300000000000000000000000000000000000000000000000000000000000000400000000000000000000000003b870db67a45611cf4723d44487eaf398fac51e30000000000000000000000000000000000000000000000000000000000000001f06c2dfc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c57300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044e665f9e43032000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000a92bcfb3d5d4c7e62b92f73e1b362f39150d4a22000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a4effae35300000000000000000000000000000000000000000000000000000000000000400000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f0000000000000000000000000000000000000000000000000000000000000002ceae3abd0000000000000000000000000000000000000000000000000000000012e5ff77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e4f92bcb0d0000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a92bcfb3d5d4c7e62b92f73e1b362f39150d4a22ceae3abd00000000000000000000000000000000000000000000000000000000000000000000000000000000a92bcfb3d5d4c7e62b92f73e1b362f39150d4a2212e5ff7700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004449c29d2b3032000000000000000000000000000000000000000000000000000000000000000000000000000000000000a92bcfb3d5d4c7e62b92f73e1b362f39150d4a2200000000000000000000000000000000000000000000000000000000000000000000000000000000949a79cdd2556d6cd3f64db018862757a5b117360000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004444faded0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034084c37699a8d84ddd93dafaf4ec899032823a100000000000000000000000000000000000000000000000000000000000000000000000000000000949a79cdd2556d6cd3f64db018862757a5b1173600000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc00000000000000000000000000000000000000000000000000000000000000000000000000000000949a79cdd2556d6cd3f64db018862757a5b1173600000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000084effae35300000000000000000000000000000000000000000000000000000000000000400000000000000000000000003b870db67a45611cf4723d44487eaf398fac51e30000000000000000000000000000000000000000000000000000000000000001f06c2dfc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c57300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044e665f9e43138000000000000000000000000000000000000000000000000000000000000000000000000000000000000853d955acef822db058eb8505911ed77f175b99e00000000000000000000000000000000000000000000000000000000000000000000000000000000949a79cdd2556d6cd3f64db018862757a5b11736000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a4effae35300000000000000000000000000000000000000000000000000000000000000400000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f0000000000000000000000000000000000000000000000000000000000000002ceae3abd0000000000000000000000000000000000000000000000000000000012e5ff77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e4f92bcb0d0000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000949a79cdd2556d6cd3f64db018862757a5b11736ceae3abd00000000000000000000000000000000000000000000000000000000000000000000000000000000949a79cdd2556d6cd3f64db018862757a5b1173612e5ff7700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004449c29d2b3138000000000000000000000000000000000000000000000000000000000000000000000000000000000000949a79cdd2556d6cd3f64db018862757a5b1173600000000000000000000000000000000000000000000000000000000000000000000000000000000d91579a4b0ce5b365a6f45310fd20a1cda54f8df00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7ceae3abd00000000000000000000000000000000000000000000000000000000000000000000000000000000a3e0ba5a37deab11e5206d7cb73206cd40437d5e0000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a4f92bcb0d000000000000000000000000a3e0ba5a37deab11e5206d7cb73206cd40437d5e00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000d91579a4b0ce5b365a6f45310fd20a1cda54f8dfceae3abd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c57300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044480d411a303000000000000000000000000000000000000000000000000000000000000000000000000000000000000095750d6f5fba4ed1cc4dc42d2c01dfd3db9a11ec00000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c573000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000247766e00b3030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003823bb68db2a43ae247c4d82486a8d134305a48100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7ceae3abd00000000000000000000000000000000000000000000000000000000000000000000000000000000a3e0ba5a37deab11e5206d7cb73206cd40437d5e0000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a4f92bcb0d000000000000000000000000a3e0ba5a37deab11e5206d7cb73206cd40437d5e000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000003823bb68db2a43ae247c4d82486a8d134305a481ceae3abd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c57300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044480d411a303100000000000000000000000000000000000000000000000000000000000000000000000000000000000095750d6f5fba4ed1cc4dc42d2c01dfd3db9a11ec00000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c573000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000247766e00b303100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c573000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000848ef6bdfa30300000000000000000000000000000000000000000000000000000000000003030000000000000000000000000000000000000000000000000000000000000000000000000000000000000cdce5c87f691058b61f3a65913f1a3cbcbad9f5200000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c573000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a4d3fc152b3030000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000960000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c5730000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008453eecb77303000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001303000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c573000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000848ef6bdfa30300000000000000000000000000000000000000000000000000000000000003031000000000000000000000000000000000000000000000000000000000000000000000000000000000000cdce5c87f691058b61f3a65913f1a3cbcbad9f520000000000000000000000000000000000000000000000000000000000144b5000000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c573000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a4d3fc152b3030000000000000000000000000000000000000000000000000000000000000303100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000960000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000000000000000000000a3e0ba5a37deab11e5206d7cb73206cd40437d5e000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c43fa3c322303100000000000000000000000000000000000000000000000000000000000030300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000006f05b59d3b200000000000000000000000000000000000000000000000000000af4c6210feba00000000000000000000000000000000000000000000000003635c9adc5dea00000000000000000000000000000000000000000000000000000000000000000000000000000000000003823bb68db2a43ae247c4d82486a8d134305a48100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde712e5ff7700000000000000000000000000000000000000000000000000000000000000000000000000000000a3e0ba5a37deab11e5206d7cb73206cd40437d5e0000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a4f92bcb0d000000000000000000000000a3e0ba5a37deab11e5206d7cb73206cd40437d5e000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000003823bb68db2a43ae247c4d82486a8d134305a48112e5ff770000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f344ec425240c3abce3705f1bb485c6e38e6c5730000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008453eecb7730300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000130310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031d73fc7bb97c7ced7296d21b0e5cde9e797326a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7159c03dd000000000000000000000000000000000000000000000000000000000000000000000000000000003b870db67a45611cf4723d44487eaf398fac51e300000000000000000000000000000000000000000000000000000000000000000000000000000000d91579a4b0ce5b365a6f45310fd20a1cda54f8df000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a4effae353000000000000000000000000000000000000000000000000000000000000004000000000000000000000000031d73fc7bb97c7ced7296d21b0e5cde9e797326a0000000000000000000000000000000000000000000000000000000000000002ceae3abd0000000000000000000000000000000000000000000000000000000012e5ff77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031d73fc7bb97c7ced7296d21b0e5cde9e797326a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc0000000000000000000000000000000000000000000000000000000000000000000000000000000031d73fc7bb97c7ced7296d21b0e5cde9e797326a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004444faded0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034084c37699a8d84ddd93dafaf4ec899032823a1000000000000000000000000000000000000000000000000000000000000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044f888f22000000000000000000000000031d73fc7bb97c7ced7296d21b0e5cde9e797326a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000565daf9a2d2336685dfa0fa2f4df84a5d6683af000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7159c03dd000000000000000000000000000000000000000000000000000000000000000000000000000000003b870db67a45611cf4723d44487eaf398fac51e3000000000000000000000000000000000000000000000000000000000000000000000000000000003823bb68db2a43ae247c4d82486a8d134305a481000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a4effae3530000000000000000000000000000000000000000000000000000000000000040000000000000000000000000565daf9a2d2336685dfa0fa2f4df84a5d6683af00000000000000000000000000000000000000000000000000000000000000002ceae3abd0000000000000000000000000000000000000000000000000000000012e5ff770000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000565daf9a2d2336685dfa0fa2f4df84a5d6683af000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc00000000000000000000000000000000000000000000000000000000000000000000000000000000565daf9a2d2336685dfa0fa2f4df84a5d6683af00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004444faded0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034084c37699a8d84ddd93dafaf4ec899032823a1000000000000000000000000000000000000000000000000000000000000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044f888f220000000000000000000000000565daf9a2d2336685dfa0fa2f4df84a5d6683af000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000035e88ae82b2a821709625bd134a89e16119fdc8b00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7159c03dd000000000000000000000000000000000000000000000000000000000000000000000000000000003b870db67a45611cf4723d44487eaf398fac51e300000000000000000000000000000000000000000000000000000000000000000000000000000000a92bcfb3d5d4c7e62b92f73e1b362f39150d4a22000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a4effae353000000000000000000000000000000000000000000000000000000000000004000000000000000000000000035e88ae82b2a821709625bd134a89e16119fdc8b0000000000000000000000000000000000000000000000000000000000000002ceae3abd0000000000000000000000000000000000000000000000000000000012e5ff77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035e88ae82b2a821709625bd134a89e16119fdc8b00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc0000000000000000000000000000000000000000000000000000000000000000000000000000000035e88ae82b2a821709625bd134a89e16119fdc8b0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004444faded0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034084c37699a8d84ddd93dafaf4ec899032823a1000000000000000000000000000000000000000000000000000000000000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044f888f22000000000000000000000000035e88ae82b2a821709625bd134a89e16119fdc8b0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000008b570c1639a38c0064a1060b60a34bffbb68851900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7159c03dd000000000000000000000000000000000000000000000000000000000000000000000000000000003b870db67a45611cf4723d44487eaf398fac51e300000000000000000000000000000000000000000000000000000000000000000000000000000000949a79cdd2556d6cd3f64db018862757a5b11736000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a4effae35300000000000000000000000000000000000000000000000000000000000000400000000000000000000000008b570c1639a38c0064a1060b60a34bffbb6885190000000000000000000000000000000000000000000000000000000000000002ceae3abd0000000000000000000000000000000000000000000000000000000012e5ff7700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008b570c1639a38c0064a1060b60a34bffbb68851900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044de02cde7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082375994c79e902286d347c9ede644ea12659fcc000000000000000000000000000000000000000000000000000000000000000000000000000000008b570c1639a38c0064a1060b60a34bffbb6885190000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004444faded0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034084c37699a8d84ddd93dafaf4ec899032823a1000000000000000000000000000000000000000000000000000000000000000000000000000000002502f102c6e4f484db2ab4ffc9dc0268fdef666f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044f888f2200000000000000000000000008b570c1639a38c0064a1060b60a34bffbb688519000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/scripts/governance/add/addVariableRate/deployBaseContracts/variableRate.arbitrum.config.ts b/scripts/governance/add/addVariableRate/deployBaseContracts/variableRate.arbitrum.config.ts new file mode 100644 index 000000000..a579851f2 --- /dev/null +++ b/scripts/governance/add/addVariableRate/deployBaseContracts/variableRate.arbitrum.config.ts @@ -0,0 +1,737 @@ +import { + ACCUMULATOR, + CHAINLINKUSD, + CHI, + DAI, + ETH, + USDT, + RATE, + TIMELOCK, + USDC, + VARIABLE_RATE_ORACLE, + VR_CAULDRON, + VR_CAULDRON_IMPLEMENTATION, + VR_LADLE, + VR_LADLE_IMPLEMENTATION, + VR_ROUTER, + VR_WITCH, + VR_WITCH_IMPLEMENTATION, + VYDAI, + VYDAI_IMPLEMENTATION, + VYETH, + VYETH_IMPLEMENTATION, + VYUSDT, + VYUSDT_IMPLEMENTATION, + VYUSDC, + VYUSDC_IMPLEMENTATION, + WAD, + ONEUSDC, +} from '../../../../../shared/constants' +import { Accumulator, Asset, Base, ContractDeployment, Ilk, VariableInterestRateOracleSource } from '../../../confTypes' +import * as base_config from '../../../base.arb_mainnet.config' +import { readAddressMappingIfExists } from '../../../../../shared/helpers' +import { parseUnits } from 'ethers/lib/utils' +import { VRCauldron__factory, VRLadle__factory, VRWitch__factory, VYToken__factory } from '../../../../../typechain' +import { BigNumber } from 'ethers/lib/ethers' + +export const assets: Map = base_config.assets +export const developer: string = '0x06FB6f89eAA936d4Cfe58FfA071cf8EAe17ac9AB' +export const deployer: string = '0x06FB6f89eAA936d4Cfe58FfA071cf8EAe17ac9AB' +export const governance: Map = base_config.governance +export const protocol = () => readAddressMappingIfExists('protocol.json') +export const joins = readAddressMappingIfExists('vyJoins.json') +export const deployers: Map = base_config.deployers +export const whales: Map = base_config.whales +export const vyTokens: Map = base_config.vyTokens + +export const contractDeployments: ContractDeployment[] = [ + { + addressFile: 'vyJoins.json', + name: ETH, + contract: 'Join', + args: [() => assets.getOrThrow(ETH)!], + }, + { + addressFile: 'vyJoins.json', + name: DAI, + contract: 'Join', + args: [() => assets.getOrThrow(DAI)!], + }, + { + addressFile: 'vyJoins.json', + name: USDC, + contract: 'Join', + args: [() => assets.getOrThrow(USDC)!], + }, + { + addressFile: 'vyJoins.json', + name: USDT, + contract: 'Join', + args: [() => assets.getOrThrow(USDT)!], + }, + { + addressFile: 'protocol.json', + name: VR_CAULDRON_IMPLEMENTATION, + contract: 'VRCauldron', + args: [], + }, + { + addressFile: 'protocol.json', + name: VR_CAULDRON, + contract: 'ERC1967Proxy', + args: [ + () => protocol().getOrThrow(VR_CAULDRON_IMPLEMENTATION)!, + () => VRCauldron__factory.createInterface().encodeFunctionData('initialize', [governance.getOrThrow(TIMELOCK)!]), + ], + }, + { + addressFile: 'protocol.json', + name: VR_ROUTER, + contract: 'VRRouter', + args: [], + }, + { + addressFile: 'protocol.json', + name: VR_LADLE_IMPLEMENTATION, + contract: 'VRLadle', + args: [ + () => protocol().getOrThrow(VR_CAULDRON)!, + () => protocol().getOrThrow(VR_ROUTER)!, + () => assets.getOrThrow(ETH)!, + ], + }, + { + addressFile: 'protocol.json', + name: VR_LADLE, + contract: 'ERC1967Proxy', + args: [ + () => protocol().getOrThrow(VR_LADLE_IMPLEMENTATION)!, + () => VRLadle__factory.createInterface().encodeFunctionData('initialize', [governance.getOrThrow(TIMELOCK)!]), + ], + }, + { + addressFile: 'protocol.json', + name: VR_WITCH_IMPLEMENTATION, + contract: 'VRWitch', + args: [() => protocol().getOrThrow(VR_CAULDRON)!, () => protocol().getOrThrow(VR_LADLE)!], + }, + { + addressFile: 'protocol.json', + name: VR_WITCH, + contract: 'ERC1967Proxy', + args: [ + () => protocol().getOrThrow(VR_WITCH_IMPLEMENTATION)!, + () => + VRWitch__factory.createInterface().encodeFunctionData('initialize', [ + protocol().getOrThrow(VR_LADLE), + governance.getOrThrow(TIMELOCK)!, + ]), + ], + }, + { + addressFile: 'protocol.json', + name: VARIABLE_RATE_ORACLE, + contract: 'VariableInterestRateOracle', + args: [() => protocol().getOrThrow(VR_CAULDRON)!, () => protocol().getOrThrow(VR_LADLE)!], + }, + { + addressFile: 'vyTokens.json', + name: VYETH_IMPLEMENTATION, + contract: 'VYToken', + args: [ + () => ETH, + () => protocol().getOrThrow(VARIABLE_RATE_ORACLE)!, + () => joins.getOrThrow(ETH)!, + () => 'Variable Yield ETH', + () => 'vyETH', + ], + libs: { + SafeERC20Namer: protocol().getOrThrow('safeERC20Namer')!, + }, + }, + { + addressFile: 'vyTokens.json', + name: VYETH, + contract: 'ERC1967Proxy', + args: [ + () => vyTokens.getOrThrow(VYETH_IMPLEMENTATION)!, + () => + VYToken__factory.createInterface().encodeFunctionData('initialize', [ + governance.getOrThrow(TIMELOCK)!, + 'VYETH', + 'VYETH', + 18, + ]), + ], + }, + { + addressFile: 'vyTokens.json', + name: VYDAI_IMPLEMENTATION, + contract: 'VYToken', + args: [ + () => DAI, + () => protocol().getOrThrow(VARIABLE_RATE_ORACLE)!, + () => joins.getOrThrow(DAI), + () => 'Variable Yield DAI', + () => 'vyDAI', + ], + libs: { + SafeERC20Namer: protocol().getOrThrow('safeERC20Namer')!, + }, + }, + { + addressFile: 'vyTokens.json', + name: VYDAI, + contract: 'ERC1967Proxy', + args: [ + () => vyTokens.getOrThrow(VYDAI_IMPLEMENTATION)!, + () => + VYToken__factory.createInterface().encodeFunctionData('initialize', [ + governance.getOrThrow(TIMELOCK)!, + 'VYDAI', + 'VYDAI', + 18, + ]), + ], + }, + { + addressFile: 'vyTokens.json', + name: VYUSDC_IMPLEMENTATION, + contract: 'VYToken', + args: [ + () => USDC, + () => protocol().getOrThrow(VARIABLE_RATE_ORACLE)!, + () => joins.getOrThrow(USDC), + () => 'Variable Yield USDC', + () => 'vyUSDC', + ], + libs: { + SafeERC20Namer: protocol().getOrThrow('safeERC20Namer')!, + }, + }, + { + addressFile: 'vyTokens.json', + name: VYUSDC, + contract: 'ERC1967Proxy', + args: [ + () => vyTokens.getOrThrow(VYUSDC_IMPLEMENTATION)!, + () => + VYToken__factory.createInterface().encodeFunctionData('initialize', [ + governance.getOrThrow(TIMELOCK)!, + 'VYUSDC', + 'VYUSDC', + 6, + ]), + ], + }, + { + addressFile: 'vyTokens.json', + name: VYUSDT_IMPLEMENTATION, + contract: 'VYToken', + args: [ + () => USDT, + () => protocol().getOrThrow(VARIABLE_RATE_ORACLE)!, + () => joins.getOrThrow(USDT), + () => 'Variable Yield USDT', + () => 'vyUSDT', + ], + libs: { + SafeERC20Namer: protocol().getOrThrow('safeERC20Namer')!, + }, + }, + { + addressFile: 'vyTokens.json', + name: VYUSDT, + contract: 'ERC1967Proxy', + args: [ + () => vyTokens.getOrThrow(VYUSDT_IMPLEMENTATION)!, + () => + VYToken__factory.createInterface().encodeFunctionData('initialize', [ + governance.getOrThrow(TIMELOCK)!, + 'YVUSDT', + 'VYUSDT', + 18, + ]), + ], + }, +] + +export const assetsToAdd: Asset[] = [ + { + assetId: ETH, + address: assets.getOrThrow(ETH), + }, + { + assetId: DAI, + address: assets.getOrThrow(DAI), + }, + { + assetId: USDC, + address: assets.getOrThrow(USDC), + }, + { + assetId: USDT, + address: assets.getOrThrow(USDT), + }, +] + +export const basesToAdd: Base[] = [ + { + assetId: ETH, + address: assets.getOrThrow(ETH), + rateOracle: protocol().getOrThrow(VARIABLE_RATE_ORACLE)! as string, + }, + { + assetId: DAI, + address: assets.getOrThrow(DAI), + rateOracle: protocol().getOrThrow(VARIABLE_RATE_ORACLE)! as string, + }, + { + assetId: USDC, + address: assets.getOrThrow(USDC), + rateOracle: protocol().getOrThrow(VARIABLE_RATE_ORACLE)! as string, + }, + { + assetId: USDT, + address: assets.getOrThrow(USDT), + rateOracle: protocol().getOrThrow(VARIABLE_RATE_ORACLE)! as string, + }, +] + +export const accumulatorSources: Accumulator[] = [ + { + baseId: ETH, + kind: RATE, + startRate: WAD, + perSecondRate: WAD, + }, + { + baseId: DAI, + kind: RATE, + startRate: WAD, + perSecondRate: WAD, + }, + { + baseId: USDT, + kind: RATE, + startRate: WAD, + perSecondRate: WAD, + }, + { + baseId: USDC, + kind: RATE, + startRate: WAD, + perSecondRate: WAD, + }, +] + +export const variableInterestRateOracleSources: VariableInterestRateOracleSource[] = [ + { + baseId: ETH, + kind: RATE, + optimalUsageRate: BigNumber.from('450000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('3000000'), + ilks: [DAI, USDC, USDT], + }, + { + baseId: ETH, + kind: CHI, + optimalUsageRate: BigNumber.from('450000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('3000000'), + ilks: [DAI, USDC, USDT], + }, + { + baseId: DAI, + kind: RATE, + optimalUsageRate: BigNumber.from('900000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('600000'), + ilks: [ETH, USDT, USDC], + }, + { + baseId: DAI, + kind: CHI, + optimalUsageRate: BigNumber.from('900000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('600000'), + ilks: [ETH, USDT, USDC], + }, + { + baseId: USDC, + kind: RATE, + optimalUsageRate: BigNumber.from('900000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('600000'), + ilks: [ETH, DAI, USDT], + }, + { + baseId: USDC, + kind: CHI, + optimalUsageRate: BigNumber.from('900000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('600000'), + ilks: [ETH, DAI, USDT], + }, + { + baseId: USDT, + kind: RATE, + optimalUsageRate: BigNumber.from('900000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('600000'), + ilks: [ETH, DAI, USDC], + }, + { + baseId: USDT, + kind: CHI, + optimalUsageRate: BigNumber.from('900000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('600000'), + ilks: [ETH, DAI, USDC], + }, +] + +const ilksETH: Ilk[] = [ + { + baseId: ETH, + ilkId: DAI, + asset: assetsToAdd[1], + collateralization: { + baseId: ETH, + ilkId: DAI, + oracle: protocol().getOrThrow(CHAINLINKUSD)!, + ratio: 1400000, + }, + debtLimits: { + baseId: ETH, + ilkId: DAI, + line: 50, + dust: 1, + dec: 18, + }, + auctionLineAndLimit: { + baseId: ETH, + ilkId: DAI, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1400000), + max: WAD.mul(100000), // $100k + }, + }, + { + baseId: ETH, + ilkId: USDC, + asset: assetsToAdd[1], + collateralization: { + baseId: ETH, + ilkId: USDC, + oracle: protocol().getOrThrow(CHAINLINKUSD)!, + ratio: 1400000, + }, + debtLimits: { + baseId: ETH, + ilkId: USDC, + line: 50, + dust: 1, + dec: 18, + }, + auctionLineAndLimit: { + baseId: ETH, + ilkId: USDC, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1400000), + max: WAD.mul(100000), // $100k + }, + }, + { + baseId: ETH, + ilkId: USDT, + asset: assetsToAdd[1], + collateralization: { + baseId: ETH, + ilkId: USDT, + oracle: protocol().getOrThrow(CHAINLINKUSD)!, + ratio: 1330000, + }, + debtLimits: { + baseId: ETH, + ilkId: USDT, + line: 50, + dust: 1, + dec: 18, + }, + auctionLineAndLimit: { + baseId: ETH, + ilkId: USDT, + duration: 3600, + vaultProportion: parseUnits('0.5'), + collateralProportion: parseUnits('0.78947368'), // 105 / 133 + max: parseUnits('1000'), + }, + }, +] + +const ilksDAI: Ilk[] = [ + { + baseId: DAI, + ilkId: USDC, + asset: assetsToAdd[2], + collateralization: { + baseId: DAI, + ilkId: USDC, + oracle: protocol().getOrThrow(CHAINLINKUSD)!, + ratio: 1100000, + }, + debtLimits: { + baseId: DAI, + ilkId: USDC, + line: 100000, + dust: 100, + dec: 18, + }, + auctionLineAndLimit: { + baseId: DAI, + ilkId: USDC, + duration: 3600, + vaultProportion: WAD, + collateralProportion: WAD.mul(1050000).div(1100000), + max: ONEUSDC.mul(100000), + }, + }, + { + baseId: DAI, + ilkId: USDT, + asset: assetsToAdd[1], + collateralization: { + baseId: DAI, + ilkId: USDT, + oracle: protocol().getOrThrow(CHAINLINKUSD)!, + ratio: 1330000, + }, + debtLimits: { + baseId: DAI, + ilkId: USDT, + line: 100000, + dust: 100, + dec: 18, + }, + auctionLineAndLimit: { + baseId: DAI, + ilkId: USDT, + duration: 3600, + vaultProportion: parseUnits('0.5'), + collateralProportion: parseUnits('0.78947368'), // 105 / 133 + max: parseUnits('1000'), + }, + }, + { + baseId: DAI, + ilkId: ETH, + asset: assetsToAdd[1], + collateralization: { + baseId: DAI, + ilkId: ETH, + oracle: protocol().getOrThrow(CHAINLINKUSD)!, + ratio: 1400000, + }, + debtLimits: { + baseId: DAI, + ilkId: ETH, + line: 100000, + dust: 100, + dec: 18, + }, + auctionLineAndLimit: { + baseId: DAI, + ilkId: ETH, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1400000), + max: WAD.mul(100000), // $100k + }, + }, +] + +const ilksUSDC: Ilk[] = [ + { + baseId: USDC, + ilkId: DAI, + asset: assetsToAdd[2], + collateralization: { + baseId: USDC, + ilkId: DAI, + oracle: protocol().getOrThrow(CHAINLINKUSD)!, + ratio: 1100000, + }, + debtLimits: { + baseId: USDC, + ilkId: DAI, + line: 100000, + dust: 100, + dec: 6, + }, + auctionLineAndLimit: { + baseId: USDC, + ilkId: DAI, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1400000), + max: WAD.mul(100), // $100k + }, + }, + { + baseId: USDC, + ilkId: USDT, + asset: assetsToAdd[1], + collateralization: { + baseId: USDC, + ilkId: USDT, + oracle: protocol().getOrThrow(CHAINLINKUSD)!, + ratio: 1330000, + }, + debtLimits: { + baseId: USDC, + ilkId: USDT, + line: 100000, + dust: 100, + dec: 6, + }, + auctionLineAndLimit: { + baseId: USDC, + ilkId: USDT, + duration: 3600, + vaultProportion: parseUnits('0.5'), + collateralProportion: parseUnits('0.78947368'), // 105 / 133 + max: parseUnits('1000'), + }, + }, + { + baseId: USDC, + ilkId: ETH, + asset: assetsToAdd[1], + collateralization: { + baseId: USDC, + ilkId: ETH, + oracle: protocol().getOrThrow(CHAINLINKUSD)!, + ratio: 1400000, + }, + debtLimits: { + baseId: USDC, + ilkId: ETH, + line: 100000, + dust: 100, + dec: 6, + }, + auctionLineAndLimit: { + baseId: USDC, + ilkId: ETH, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1400000), + max: WAD.mul(100), // $100k + }, + }, +] + +const ilksUSDT: Ilk[] = [ + { + baseId: USDT, + ilkId: USDC, + asset: assetsToAdd[2], + collateralization: { + baseId: USDT, + ilkId: USDC, + oracle: protocol().getOrThrow(CHAINLINKUSD)!, + ratio: 1100000, + }, + debtLimits: { + baseId: USDT, + ilkId: USDC, + line: 100000, + dust: 100, + dec: 6, + }, + auctionLineAndLimit: { + baseId: USDT, + ilkId: USDC, + duration: 3600, + vaultProportion: WAD, + collateralProportion: WAD.mul(1050000).div(1100000), + max: base_config.ONEUSDT.mul(10000000), + }, + }, + { + baseId: USDT, + ilkId: DAI, + asset: assetsToAdd[1], + collateralization: { + baseId: USDT, + ilkId: USDT, + oracle: protocol().getOrThrow(CHAINLINKUSD)!, + ratio: 1100000, + }, + debtLimits: { + baseId: USDT, + ilkId: DAI, + line: 100000, + dust: 100, + dec: 6, + }, + auctionLineAndLimit: { + baseId: USDT, + ilkId: DAI, + duration: 3600, + vaultProportion: WAD, + collateralProportion: WAD.mul(1050000).div(1100000), + max: WAD.mul(10000000), + }, + }, + { + baseId: USDT, + ilkId: ETH, + asset: assetsToAdd[1], + collateralization: { + baseId: USDT, + ilkId: ETH, + oracle: protocol().getOrThrow(CHAINLINKUSD)!, + ratio: 1400000, + }, + debtLimits: { + baseId: USDT, + ilkId: ETH, + line: 100000, + dust: 100, + dec: 6, + }, + auctionLineAndLimit: { + baseId: USDT, + ilkId: ETH, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1400000), + max: WAD.mul(100), // $100k + }, + }, +] + +export const ilks = [ilksETH, ilksDAI, ilksUSDC, ilksUSDT] + +export const vyTokensToAdd = [VYETH, VYDAI, VYUSDC, VYUSDT] diff --git a/scripts/governance/add/addVariableRate/deployBaseContracts/variableRate.mainnet.config.ts b/scripts/governance/add/addVariableRate/deployBaseContracts/variableRate.mainnet.config.ts new file mode 100644 index 000000000..c3189cd3b --- /dev/null +++ b/scripts/governance/add/addVariableRate/deployBaseContracts/variableRate.mainnet.config.ts @@ -0,0 +1,737 @@ +import { + ACCUMULATOR, + CHAINLINK, + CHI, + DAI, + ETH, + FRAX, + ONEUSDC, + RATE, + TIMELOCK, + USDC, + VARIABLE_RATE_ORACLE, + VR_CAULDRON, + VR_CAULDRON_IMPLEMENTATION, + VR_LADLE, + VR_LADLE_IMPLEMENTATION, + VR_ROUTER, + VR_WITCH, + VR_WITCH_IMPLEMENTATION, + VYDAI, + VYDAI_IMPLEMENTATION, + VYETH, + VYETH_IMPLEMENTATION, + VYFRAX, + VYFRAX_IMPLEMENTATION, + VYUSDC, + VYUSDC_IMPLEMENTATION, + WAD, +} from '../../../../../shared/constants' +import { Accumulator, Asset, Base, ContractDeployment, Ilk, VariableInterestRateOracleSource } from '../../../confTypes' +import * as base_config from '../../../base.mainnet.config' +import { readAddressMappingIfExists } from '../../../../../shared/helpers' +import { parseUnits } from 'ethers/lib/utils' +import { VRCauldron__factory, VRLadle__factory, VRWitch__factory, VYToken__factory } from '../../../../../typechain' +import { BigNumber } from 'ethers/lib/ethers' + +export const assets: Map = base_config.assets +export const developer: string = '0x06FB6f89eAA936d4Cfe58FfA071cf8EAe17ac9AB' +export const deployer: string = '0x06FB6f89eAA936d4Cfe58FfA071cf8EAe17ac9AB' +export const governance: Map = base_config.governance +export const protocol = () => readAddressMappingIfExists('protocol.json') +export const joins = readAddressMappingIfExists('vyJoins.json') +export const deployers: Map = base_config.deployers +export const whales: Map = base_config.whales +export const vyTokens: Map = base_config.vyTokens + +export const contractDeployments: ContractDeployment[] = [ + { + addressFile: 'vyJoins.json', + name: ETH, + contract: 'Join', + args: [() => assets.getOrThrow(ETH)!], + }, + { + addressFile: 'vyJoins.json', + name: DAI, + contract: 'Join', + args: [() => assets.getOrThrow(DAI)!], + }, + { + addressFile: 'vyJoins.json', + name: USDC, + contract: 'Join', + args: [() => assets.getOrThrow(USDC)!], + }, + { + addressFile: 'vyJoins.json', + name: FRAX, + contract: 'Join', + args: [() => assets.getOrThrow(FRAX)!], + }, + { + addressFile: 'protocol.json', + name: VR_CAULDRON_IMPLEMENTATION, + contract: 'VRCauldron', + args: [], + }, + { + addressFile: 'protocol.json', + name: VR_CAULDRON, + contract: 'ERC1967Proxy', + args: [ + () => protocol().getOrThrow(VR_CAULDRON_IMPLEMENTATION)!, + () => VRCauldron__factory.createInterface().encodeFunctionData('initialize', [governance.getOrThrow(TIMELOCK)!]), + ], + }, + { + addressFile: 'protocol.json', + name: VR_ROUTER, + contract: 'VRRouter', + args: [], + }, + { + addressFile: 'protocol.json', + name: VR_LADLE_IMPLEMENTATION, + contract: 'VRLadle', + args: [ + () => protocol().getOrThrow(VR_CAULDRON)!, + () => protocol().getOrThrow(VR_ROUTER)!, + () => assets.getOrThrow(ETH)!, + ], + }, + { + addressFile: 'protocol.json', + name: VR_LADLE, + contract: 'ERC1967Proxy', + args: [ + () => protocol().getOrThrow(VR_LADLE_IMPLEMENTATION)!, + () => VRLadle__factory.createInterface().encodeFunctionData('initialize', [governance.getOrThrow(TIMELOCK)!]), + ], + }, + { + addressFile: 'protocol.json', + name: VR_WITCH_IMPLEMENTATION, + contract: 'VRWitch', + args: [() => protocol().getOrThrow(VR_CAULDRON)!, () => protocol().getOrThrow(VR_LADLE)!], + }, + { + addressFile: 'protocol.json', + name: VR_WITCH, + contract: 'ERC1967Proxy', + args: [ + () => protocol().getOrThrow(VR_WITCH_IMPLEMENTATION)!, + () => + VRWitch__factory.createInterface().encodeFunctionData('initialize', [ + protocol().getOrThrow(VR_LADLE), + governance.getOrThrow(TIMELOCK)!, + ]), + ], + }, + { + addressFile: 'protocol.json', + name: VARIABLE_RATE_ORACLE, + contract: 'VariableInterestRateOracle', + args: [() => protocol().getOrThrow(VR_CAULDRON)!, () => protocol().getOrThrow(VR_LADLE)!], + }, + { + addressFile: 'vyTokens.json', + name: VYETH_IMPLEMENTATION, + contract: 'VYToken', + args: [ + () => ETH, + () => protocol().getOrThrow(VARIABLE_RATE_ORACLE)!, + () => joins.getOrThrow(ETH)!, + () => 'Variable Yield ETH', + () => 'vyETH', + ], + libs: { + SafeERC20Namer: protocol().getOrThrow('safeERC20Namer')!, + }, + }, + { + addressFile: 'vyTokens.json', + name: VYETH, + contract: 'ERC1967Proxy', + args: [ + () => vyTokens.getOrThrow(VYETH_IMPLEMENTATION)!, + () => VYToken__factory.createInterface().encodeFunctionData('initialize', [governance.getOrThrow(TIMELOCK)!]), + ], + }, + { + addressFile: 'vyTokens.json', + name: VYDAI_IMPLEMENTATION, + contract: 'VYToken', + args: [ + () => DAI, + () => protocol().getOrThrow(VARIABLE_RATE_ORACLE)!, + () => joins.getOrThrow(DAI), + () => 'Variable Yield DAI', + () => 'vyDAI', + ], + libs: { + SafeERC20Namer: protocol().getOrThrow('safeERC20Namer')!, + }, + }, + { + addressFile: 'vyTokens.json', + name: VYDAI, + contract: 'ERC1967Proxy', + args: [ + () => vyTokens.getOrThrow(VYDAI_IMPLEMENTATION)!, + () => VYToken__factory.createInterface().encodeFunctionData('initialize', [governance.getOrThrow(TIMELOCK)!]), + ], + }, + { + addressFile: 'vyTokens.json', + name: VYUSDC_IMPLEMENTATION, + contract: 'VYToken', + args: [ + () => USDC, + () => protocol().getOrThrow(VARIABLE_RATE_ORACLE)!, + () => joins.getOrThrow(USDC), + () => 'Variable Yield USDC', + () => 'vyUSDC', + ], + libs: { + SafeERC20Namer: protocol().getOrThrow('safeERC20Namer')!, + }, + }, + { + addressFile: 'vyTokens.json', + name: VYUSDC, + contract: 'ERC1967Proxy', + args: [ + () => vyTokens.getOrThrow(VYUSDC_IMPLEMENTATION)!, + () => VYToken__factory.createInterface().encodeFunctionData('initialize', [governance.getOrThrow(TIMELOCK)!]), + ], + }, + { + addressFile: 'vyTokens.json', + name: VYFRAX_IMPLEMENTATION, + contract: 'VYToken', + args: [ + () => FRAX, + () => protocol().getOrThrow(VARIABLE_RATE_ORACLE)!, + () => joins.getOrThrow(FRAX), + () => 'Variable Yield FRAX', + () => 'vyFRAX', + ], + libs: { + SafeERC20Namer: protocol().getOrThrow('safeERC20Namer')!, + }, + }, + { + addressFile: 'vyTokens.json', + name: VYFRAX, + contract: 'ERC1967Proxy', + args: [ + () => vyTokens.getOrThrow(VYFRAX_IMPLEMENTATION)!, + () => VYToken__factory.createInterface().encodeFunctionData('initialize', [governance.getOrThrow(TIMELOCK)!]), + ], + }, +] + +export const assetsToAdd: Asset[] = [ + { + assetId: ETH, + address: assets.getOrThrow(ETH), + }, + { + assetId: DAI, + address: assets.getOrThrow(DAI), + }, + { + assetId: USDC, + address: assets.getOrThrow(USDC), + }, + { + assetId: FRAX, + address: assets.getOrThrow(FRAX), + }, +] + +export const basesToAdd: Base[] = [ + { + assetId: ETH, + address: assets.getOrThrow(ETH), + rateOracle: protocol().getOrThrow(VARIABLE_RATE_ORACLE)! as string, + }, + { + assetId: DAI, + address: assets.getOrThrow(DAI), + rateOracle: protocol().getOrThrow(VARIABLE_RATE_ORACLE)! as string, + }, + { + assetId: USDC, + address: assets.getOrThrow(USDC), + rateOracle: protocol().getOrThrow(VARIABLE_RATE_ORACLE)! as string, + }, + { + assetId: FRAX, + address: assets.getOrThrow(FRAX), + rateOracle: protocol().getOrThrow(VARIABLE_RATE_ORACLE)! as string, + }, +] + +// export const accumulatorSources: Accumulator[] = [ +// { +// baseId: ETH, +// kind: RATE, +// startRate: WAD, +// perSecondRate: WAD, +// }, +// { +// baseId: DAI, +// kind: RATE, +// startRate: WAD, +// perSecondRate: WAD, +// }, +// { +// baseId: FRAX, +// kind: RATE, +// startRate: WAD, +// perSecondRate: WAD, +// }, +// { +// baseId: USDC, +// kind: RATE, +// startRate: WAD, +// perSecondRate: WAD, +// }, +// ] + +export const variableInterestRateOracleSources: VariableInterestRateOracleSource[] = [ + { + baseId: ETH, + kind: RATE, + optimalUsageRate: BigNumber.from('450000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('3000000'), + ilks: [DAI, USDC, FRAX], + }, + { + baseId: ETH, + kind: CHI, + optimalUsageRate: BigNumber.from('450000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('3000000'), + ilks: [DAI, USDC, FRAX], + }, + { + baseId: DAI, + kind: RATE, + optimalUsageRate: BigNumber.from('900000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('600000'), + ilks: [ETH, FRAX, USDC], + }, + { + baseId: DAI, + kind: CHI, + optimalUsageRate: BigNumber.from('900000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('600000'), + ilks: [ETH, FRAX, USDC], + }, + { + baseId: USDC, + kind: RATE, + optimalUsageRate: BigNumber.from('900000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('600000'), + ilks: [ETH, DAI, FRAX], + }, + { + baseId: USDC, + kind: CHI, + optimalUsageRate: BigNumber.from('900000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('600000'), + ilks: [ETH, DAI, FRAX], + }, + { + baseId: FRAX, + kind: RATE, + optimalUsageRate: BigNumber.from('900000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('600000'), + ilks: [ETH, DAI, USDC], + }, + { + baseId: FRAX, + kind: CHI, + optimalUsageRate: BigNumber.from('900000'), + accumulated: BigNumber.from('1000000000000000000'), + baseVariableBorrowRate: BigNumber.from('0'), + slope1: BigNumber.from('40000'), + slope2: BigNumber.from('600000'), + ilks: [ETH, DAI, USDC], + }, +] + +const ilksETH: Ilk[] = [ + { + baseId: ETH, + ilkId: DAI, + asset: assetsToAdd[1], + collateralization: { + baseId: ETH, + ilkId: DAI, + oracle: protocol().getOrThrow(CHAINLINK)! as string, + ratio: 1400000, + }, + debtLimits: { + baseId: ETH, + ilkId: DAI, + line: 50, + dust: 1, + dec: 18, + }, + auctionLineAndLimit: { + baseId: ETH, + ilkId: DAI, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1400000), + max: WAD.mul(100000), // $100k + }, + }, + { + baseId: ETH, + ilkId: USDC, + asset: assetsToAdd[1], + collateralization: { + baseId: ETH, + ilkId: USDC, + oracle: protocol().getOrThrow(CHAINLINK)! as string, + ratio: 1400000, + }, + debtLimits: { + baseId: ETH, + ilkId: USDC, + line: 50, + dust: 1, + dec: 18, + }, + auctionLineAndLimit: { + baseId: ETH, + ilkId: USDC, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1400000), + max: ONEUSDC.mul(100000), // $100k + }, + }, + { + baseId: ETH, + ilkId: FRAX, + asset: assetsToAdd[1], + collateralization: { + baseId: ETH, + ilkId: FRAX, + oracle: protocol().getOrThrow(CHAINLINK)! as string, + ratio: 1150000, + }, + debtLimits: { + baseId: ETH, + ilkId: FRAX, + line: 50, + dust: 1, + dec: 18, + }, + auctionLineAndLimit: { + baseId: ETH, + ilkId: FRAX, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1150000), + max: WAD.mul(100000), + }, + }, +] + +const ilksDAI: Ilk[] = [ + { + baseId: DAI, + ilkId: USDC, + asset: assetsToAdd[2], + collateralization: { + baseId: DAI, + ilkId: USDC, + oracle: protocol().getOrThrow(CHAINLINK)! as string, + ratio: 1100000, + }, + debtLimits: { + baseId: DAI, + ilkId: USDC, + line: 100000, + dust: 1000, + dec: 18, + }, + auctionLineAndLimit: { + baseId: DAI, + ilkId: USDC, + duration: 3600, + vaultProportion: WAD, + collateralProportion: WAD.mul(1050000).div(1100000), + max: ONEUSDC.mul(100000), + }, + }, + { + baseId: DAI, + ilkId: ETH, + asset: { + assetId: ETH, + address: assets.getOrThrow(ETH)!, + }, + collateralization: { + baseId: DAI, + ilkId: ETH, + oracle: protocol().getOrThrow(CHAINLINK)!, + ratio: 1400000, + }, + debtLimits: { + baseId: DAI, + ilkId: ETH, + line: 100000, + dust: 1000, + dec: 18, + }, + auctionLineAndLimit: { + baseId: DAI, + ilkId: ETH, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1400000), + max: WAD.mul(100), // $100k + }, + }, + { + baseId: DAI, + ilkId: FRAX, + asset: { + assetId: FRAX, + address: assets.getOrThrow(FRAX)!, + }, + collateralization: { + baseId: DAI, + ilkId: FRAX, + oracle: protocol().getOrThrow(CHAINLINK)!, + ratio: 1150000, + }, + debtLimits: { + baseId: DAI, + ilkId: FRAX, + line: 100000, + dust: 1000, + dec: 18, + }, + auctionLineAndLimit: { + baseId: DAI, + ilkId: FRAX, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1150000), + max: WAD.mul(100000), + }, + }, +] + +const ilksUSDC: Ilk[] = [ + { + baseId: USDC, + ilkId: ETH, + asset: { + assetId: ETH, + address: assets.getOrThrow(ETH)!, + }, + collateralization: { + baseId: USDC, + ilkId: ETH, + oracle: protocol().getOrThrow(CHAINLINK)!, + ratio: 1400000, + }, + debtLimits: { + baseId: USDC, + ilkId: ETH, + line: 100000, + dust: 1000, + dec: 6, + }, + auctionLineAndLimit: { + baseId: USDC, + ilkId: ETH, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1400000), + max: WAD.mul(100), // $100k + }, + }, + { + baseId: USDC, + ilkId: DAI, + asset: { + assetId: DAI, + address: assets.getOrThrow(DAI)!, + }, + collateralization: { + baseId: USDC, + ilkId: DAI, + oracle: protocol().getOrThrow(CHAINLINK)!, + ratio: 1100000, + }, + debtLimits: { + baseId: USDC, + ilkId: DAI, + line: 100000, + dust: 1000, + dec: 6, + }, + auctionLineAndLimit: { + baseId: USDC, + ilkId: DAI, + duration: 3600, + vaultProportion: WAD, + collateralProportion: WAD.mul(1050000).div(1100000), + max: WAD.mul(100000), + }, + }, + { + baseId: USDC, + ilkId: FRAX, + asset: { + assetId: FRAX, + address: assets.getOrThrow(FRAX)!, + }, + collateralization: { + baseId: USDC, + ilkId: FRAX, + oracle: protocol().getOrThrow(CHAINLINK)!, + ratio: 1150000, + }, + debtLimits: { + baseId: USDC, + ilkId: FRAX, + line: 100000, + dust: 1000, + dec: 6, + }, + auctionLineAndLimit: { + baseId: USDC, + ilkId: FRAX, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1150000), + max: WAD.mul(100000), + }, + }, +] + +const ilksFRAX: Ilk[] = [ + { + baseId: FRAX, + ilkId: USDC, + asset: { + assetId: FRAX, + address: assets.getOrThrow(FRAX)!, + }, + collateralization: { + baseId: FRAX, + ilkId: USDC, + oracle: protocol().getOrThrow(CHAINLINK)!, + ratio: 1100000, + }, + debtLimits: { + baseId: FRAX, + ilkId: USDC, + line: 100000, + dust: 1000, + dec: 18, + }, + auctionLineAndLimit: { + baseId: FRAX, + ilkId: USDC, + duration: 3600, + vaultProportion: WAD, + collateralProportion: WAD.mul(1050000).div(1100000), + max: ONEUSDC.mul(100000), + }, + }, + { + baseId: FRAX, + ilkId: ETH, + asset: { + assetId: ETH, + address: assets.getOrThrow(ETH)!, + }, + collateralization: { + baseId: FRAX, + ilkId: ETH, + oracle: protocol().getOrThrow(CHAINLINK)!, + ratio: 1400000, + }, + debtLimits: { + baseId: FRAX, + ilkId: ETH, + line: 100000, + dust: 1000, + dec: 18, + }, + auctionLineAndLimit: { + baseId: FRAX, + ilkId: ETH, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1400000), + max: WAD.mul(100), // $100k + }, + }, + { + baseId: FRAX, + ilkId: DAI, + asset: { + assetId: DAI, + address: assets.getOrThrow(DAI)!, + }, + collateralization: { + baseId: FRAX, + ilkId: DAI, + oracle: protocol().getOrThrow(CHAINLINK)!, + ratio: 1150000, + }, + debtLimits: { + baseId: FRAX, + ilkId: DAI, + line: 100000, + dust: 1000, + dec: 18, + }, + auctionLineAndLimit: { + baseId: FRAX, + ilkId: DAI, + duration: 3600, + vaultProportion: WAD.div(2), + collateralProportion: WAD.mul(1050000).div(1150000), + max: WAD.mul(100000), + }, + }, +] + +export const ilks = [ilksETH, ilksDAI, ilksUSDC, ilksFRAX] + +export const vyTokensToAdd = [VYETH, VYDAI, VYUSDC, VYFRAX] diff --git a/scripts/governance/base.arb_mainnet.config.ts b/scripts/governance/base.arb_mainnet.config.ts index df2b8c9c3..6aaece84f 100644 --- a/scripts/governance/base.arb_mainnet.config.ts +++ b/scripts/governance/base.arb_mainnet.config.ts @@ -32,7 +32,7 @@ export const fyTokens = readAddressMappingIfExists('fyTokens.json') export const pools = readAddressMappingIfExists('pools.json') export const joins = readAddressMappingIfExists('joins.json') export const strategyAddresses = readAddressMappingIfExists('strategies.json') // TODO: Name clash :( - +export const vyTokens = readAddressMappingIfExists('vyTokens.json') export const chainId = 42161 export const developer: string = '0xC7aE076086623ecEA2450e364C838916a043F9a8' export const whales: Map = new Map([ @@ -297,8 +297,8 @@ const ilkUSDCETH: Ilk = { } const ilkUSDCDAI: Ilk = { - baseId: DAI, - ilkId: USDC, + baseId: USDC, + ilkId: DAI, asset: { assetId: DAI, address: assets.getOrThrow(DAI)!, diff --git a/scripts/governance/base.mainnet.config.ts b/scripts/governance/base.mainnet.config.ts index 3f7826a6e..6fe3ab216 100644 --- a/scripts/governance/base.mainnet.config.ts +++ b/scripts/governance/base.mainnet.config.ts @@ -81,6 +81,7 @@ export const protocol = readAddressMappingIfExists('protocol.json') export const governance = readAddressMappingIfExists('governance.json') export const deployers = readAddressMappingIfExists('deployers.json') export const fyTokens = readAddressMappingIfExists('fyTokens.json') +export const vyTokens = readAddressMappingIfExists('vyTokens.json') export const pools = readAddressMappingIfExists('pools.json') export const joins = readAddressMappingIfExists('joins.json') export const strategyAddresses = readAddressMappingIfExists('strategies.json') // TODO: Name clash :( @@ -89,7 +90,7 @@ export const chainId = 1 export const developer = '0xC7aE076086623ecEA2450e364C838916a043F9a8' export const whales: Map = new Map([ - [ETH, '0xd51a44d3fae010294c616388b506acda1bfaae46'], + [ETH, '0xF04a5cC80B1E94C69B48f5ee68a08CD2F09A7c3E'], [DAI, '0x16b34ce9a6a6f7fc2dd25ba59bf7308e7b38e186'], [USDC, '0xcffad3200574698b78f32232aa9d63eabd290703'], [WBTC, '0xd51a44d3fae010294c616388b506acda1bfaae46'], @@ -914,8 +915,8 @@ const ilkUSDCETH: Ilk = { } const ilkUSDCDAI: Ilk = { - baseId: DAI, - ilkId: USDC, + baseId: USDC, + ilkId: DAI, asset: { assetId: DAI, address: assets.getOrThrow(DAI)!, diff --git a/scripts/governance/confTypes.ts b/scripts/governance/confTypes.ts index f6da11adc..01ed7106f 100644 --- a/scripts/governance/confTypes.ts +++ b/scripts/governance/confTypes.ts @@ -58,6 +58,17 @@ export interface Accumulator { perSecondRate: BigNumber } +export interface VariableInterestRateOracleSource { + baseId: string + kind: string + accumulated: BigNumber + optimalUsageRate: BigNumber + baseVariableBorrowRate: BigNumber + slope1: BigNumber + slope2: BigNumber + ilks: string[] +} + export interface Base extends Asset { rateOracle: string } diff --git a/shared/constants.ts b/shared/constants.ts index 9df2bf34f..ac5db6fd6 100644 --- a/shared/constants.ts +++ b/shared/constants.ts @@ -164,8 +164,16 @@ export const SAFE_ERC20_NAMER = 'safeERC20Namer' export const YIELDMATH = 'yieldMath' export const CAULDRON = 'cauldron' export const LADLE = 'ladle' +export const VR_CAULDRON = 'vrCauldron' +export const VR_CAULDRON_IMPLEMENTATION = 'vrCauldronImplementation' +export const VR_LADLE = 'vrLadle' +export const VR_LADLE_IMPLEMENTATION = 'vrLadleImplementation' export const REPAY_FROM_LADLE_MODULE = 'repayFromLadleModule' export const WITCH = 'witch' +export const VR_WITCH = 'vrWitch' +export const VR_WITCH_IMPLEMENTATION = 'vrWitchImplementation' +export const VR_ROUTER = 'vrRouter' +export const VARIABLE_RATE_ORACLE = 'variableRateOracle' export const ROLLER = 'roller' export const WITCH_V1 = 'witchV1' export const CHAINLINK = 'chainlinkOracle' @@ -296,6 +304,18 @@ export const FYFRAX2209 = stringToBytes6('0307') // Incorrectly labelled export const FYFRAX2212 = stringToBytes6('1808') export const FYFRAX2303 = stringToBytes6('1809') +// Variable Rate Tokens +export const VYETH = stringToBytes6('VY1' + ETH) +export const VYETH_IMPLEMENTATION = 'vyETHimplementation' +export const VYDAI = stringToBytes6('VY2' + DAI) +export const VYDAI_IMPLEMENTATION = 'vyDAIimplementation' +export const VYUSDC = stringToBytes6('VY3' + USDC) +export const VYUSDC_IMPLEMENTATION = 'vyUSDCimplementation' +export const VYFRAX = stringToBytes6('VY4' + FRAX) +export const VYFRAX_IMPLEMENTATION = 'vyFRAXimplementation' +export const VYUSDT = stringToBytes6('VY4' + USDT) +export const VYUSDT_IMPLEMENTATION = 'vyUSDTimplementation' + export const DISPLAY_NAMES = new Map([ [CHI, 'CHI'], [RATE, 'RATE'], diff --git a/shared/helpers.ts b/shared/helpers.ts index 27ae40b0e..d14872594 100644 --- a/shared/helpers.ts +++ b/shared/helpers.ts @@ -8,6 +8,7 @@ import { BaseProvider } from '@ethersproject/providers' import { Timelock } from '../typechain' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' import { DISPLAY_NAMES } from './constants' +import { Interface } from 'ethers/lib/utils' /// --------- PROPOSAL EXECUTION --------- @@ -303,3 +304,7 @@ export const tenderlyVerify = async (name: string, contract: BaseContract) => { console.log(`${getName(name)} at ${contract.address} verified on tenderly`) } } + +export const id = (interfaces: Interface, func: string) => { + return interfaces.getSighash(func) +} diff --git a/shared/vrStandardBorrowingTest.ts b/shared/vrStandardBorrowingTest.ts new file mode 100644 index 000000000..a64fce1c7 --- /dev/null +++ b/shared/vrStandardBorrowingTest.ts @@ -0,0 +1,76 @@ +import { BigNumber } from 'ethers' +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { impersonate, getOwnerOrImpersonate } from './helpers' +import { ERC20__factory, IOracle__factory, VRCauldron__factory, VRLadle__factory } from '../typechain' +import { VR_CAULDRON, VR_LADLE, WAD } from './constants' +const { developer, ilks, assets, whales, protocol } = require(process.env.CONF as string) + +/** + * @dev This script tests borrowing + */ +;(async () => { + let ownerAcc = await getOwnerOrImpersonate(developer, WAD) + let whaleAcc: SignerWithAddress + + const cauldron = VRCauldron__factory.connect(protocol().getOrThrow(VR_CAULDRON)!, ownerAcc) + const ladle = VRLadle__factory.connect(protocol().getOrThrow(VR_LADLE)!, ownerAcc) + + let oracle + + for (const ilk of ilks) { + const collateral = ERC20__factory.connect(assets.get(ilk.ilkId)!, ownerAcc) + + oracle = IOracle__factory.connect(ilk.collateralization.oracle, ownerAcc) + + whaleAcc = await impersonate(whales.get(ilk.ilkId) as string, WAD.mul(10)) + console.log(`ilk.ilkId: ${ilk.ilkId}`) + console.log(`ilk.baseId: ${ilk.baseId}`) + const dust = (await cauldron.debt(ilk.baseId, ilk.ilkId)).min + const base = ERC20__factory.connect(assets.get(ilk.baseId)!, ownerAcc) + const ratio = (await cauldron.spotOracles(ilk.baseId, ilk.ilkId)).ratio + + var borrowed = BigNumber.from(10) + .pow(await base.decimals()) + .mul(dust) + const posted = ( + await oracle.peek( + ilk.baseId + '0000000000000000000000000000000000000000000000000000', + ilk.ilkId + '0000000000000000000000000000000000000000000000000000', + borrowed + ) + )[0] + .mul(ratio) + .div(1000000) + .mul(101) + .div(100) + + const collateralBalanceBefore = await collateral.balanceOf(whaleAcc.address) + + // Build vault + let data = await (await ladle.connect(whaleAcc).build(ilk.baseId, ilk.ilkId, 0)).wait() + + const vaultId = data.logs[0].topics[1].slice(0, 26) + console.log(`vault: ${vaultId}`) + + var name = await collateral.callStatic.name() + var baseName = await base.callStatic.name() + // Post collateral and borrow + const collateralJoinAddress = await ladle.joins(ilk.ilkId) + const baseJoinAddress = await ladle.joins(ilk.baseId) + console.log(`posting ${posted} ${name} out of ${await collateral.balanceOf(whaleAcc.address)}`) + await collateral.connect(whaleAcc).approve(collateralJoinAddress, posted) + console.log(`borrowing ${borrowed} ${baseName}`) + await ladle.connect(whaleAcc).pour(vaultId, whaleAcc.address, posted, borrowed) + console.log(`posted and borrowed`) + + if ((await cauldron.balances(vaultId)).art.toString() !== borrowed.toString()) throw 'art mismatch' + if ((await cauldron.balances(vaultId)).ink.toString() !== posted.toString()) throw 'ink mismatch' + + await base.connect(whaleAcc).approve(baseJoinAddress, borrowed) + console.log(`repaying ${borrowed} ${baseName} and withdrawing ${posted} ${name}`) + await ladle.connect(whaleAcc).pour(vaultId, whaleAcc.address, posted.mul(-1), borrowed.mul(-1)) + console.log(`repaid and withdrawn`) + if ((await collateral.balanceOf(whaleAcc.address)).toString() !== collateralBalanceBefore.toString()) + throw 'balance mismatch' + } +})() diff --git a/shared/vyTokenTest.ts b/shared/vyTokenTest.ts new file mode 100644 index 000000000..d62010ecb --- /dev/null +++ b/shared/vyTokenTest.ts @@ -0,0 +1,52 @@ +import { BigNumber } from 'ethers' +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { impersonate, getOwnerOrImpersonate } from './helpers' +import { + ERC20__factory, + IOracle__factory, + Ladle__factory, + VRCauldron__factory, + VRLadle__factory, + VYToken__factory, +} from '../typechain' +import { VR_CAULDRON, VR_LADLE, WAD } from './constants' +const { developer, ilks, assets, whales, protocol, vyTokensToAdd, vyTokens } = require(process.env.CONF as string) + +/** + * @dev This script tests borrowing + */ +;(async () => { + let ownerAcc = await getOwnerOrImpersonate(developer, WAD) + let whaleAcc: SignerWithAddress + let ladleAcc: SignerWithAddress + + const cauldron = VRCauldron__factory.connect(protocol().getOrThrow(VR_CAULDRON)!, ownerAcc) + const ladle = Ladle__factory.connect(protocol().getOrThrow(VR_LADLE)!, ownerAcc) + + let oracle + ladleAcc = await impersonate(ladle.address, WAD.mul(10)) + for (const vyToken of vyTokensToAdd) { + const vyTokenContract = VYToken__factory.connect(vyTokens.get(vyToken)!, ownerAcc) + const underlyingId = await vyTokenContract.underlyingId() + const underlyingAddress = await vyTokenContract.underlying() + const underlyingJoinAddress = await ladle.joins(underlyingId) + const underlying = ERC20__factory.connect(underlyingAddress, ownerAcc) + const amount = BigNumber.from(10) + .pow(await underlying.decimals()) + .mul(100) + whaleAcc = await impersonate(whales.get(underlyingId) as string, WAD.mul(10)) + + await underlying.connect(whaleAcc).approve(ladle.address, amount) + await ladle + .connect(whaleAcc) + .batch([ + ladle.interface.encodeFunctionData('transfer', [underlyingAddress, underlyingJoinAddress, amount]), + ladle.interface.encodeFunctionData('route', [ + vyTokenContract.address, + vyTokenContract.interface.encodeFunctionData('deposit', [whaleAcc.address, amount]), + ]), + ]) + + // await vyTokenContract.connect(ladleAcc).deposit(whaleAcc.address, amount) + } +})() diff --git a/yarn.lock b/yarn.lock index 076bd2f30..ec49eb108 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3106,17 +3106,10 @@ resolved "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz" integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== -"@yield-protocol/strategy-v2@2.0.0": - version "2.0.0" - resolved "https://registry.npmjs.org/@yield-protocol/strategy-v2/-/strategy-v2-2.0.0.tgz" - integrity sha512-3kmIxsNhY/gVgnKo+33jcW2g4V9ij5dO7EGP1oY++fZYg3jNUiFpao8hoBpdSG0vOH4VcPfktwnA+Pr7MxNUZQ== - -"@yield-protocol/utils-v2@2.6.9-rc.1": - version "2.6.9-rc.1" - resolved "https://registry.npmjs.org/@yield-protocol/utils-v2/-/utils-v2-2.6.9-rc.1.tgz" - integrity sha512-5DnMJOETEtZcGEVOjRXMD+ZSgc6andk/rCpqDVsimi5F76x/4+clZVfvV2kPTSe1+4liEhhXuq0YDrQTv8dMXg== - dependencies: - ethereumjs-util "^7.0.8" +"@yield-protocol/strategy-v2@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@yield-protocol/strategy-v2/-/strategy-v2-2.0.3.tgz#74f678812b04ea630784cbff30c26916d816cd54" + integrity sha512-P6HY8tqHVwnXUkF59SYB16F8YNYUbVeQ1wjA/ziRu/wlLbnf7MXDqP+XD1SU5HTSgC0BSReVfsq9aHliamnOLg== "@yield-protocol/utils-v2@^2.4.2": version "2.6.8" @@ -3125,20 +3118,24 @@ dependencies: ethereumjs-util "^7.0.8" +"@yield-protocol/utils-v2@^2.6.16": + version "2.6.16" + resolved "https://registry.yarnpkg.com/@yield-protocol/utils-v2/-/utils-v2-2.6.16.tgz#ba5a8a0a3f52407ea84a17c8c8b7a2cf3397c7da" + integrity sha512-Y0zSzog0k1pPamyY8YDxs1z0qr+CLJV52Bs3NNBcfKSxNxW/8xcFdyEDKZeRTP+DS4phdQ4fP8XjRATGW2YCDw== + "@yield-protocol/vault-interfaces@^2.3.0-rc4": version "2.5.0" resolved "https://registry.npmjs.org/@yield-protocol/vault-interfaces/-/vault-interfaces-2.5.0.tgz" integrity sha512-aoIn1tTADJaIiNPHoy7EswvFZZXZFUhJfYPEJdakLvfGruhfoPXm/Wl2aq/A1qmuniov5RDuvpWENZsBNaEgRw== -"@yield-protocol/vault-v2@0.18.10-rc.1": - version "0.18.10-rc.1" - resolved "https://registry.yarnpkg.com/@yield-protocol/vault-v2/-/vault-v2-0.18.10-rc.1.tgz#0dcd524ebbc2b132a42bf818cfd1f65ac8b1d0c7" - integrity sha512-pfRwpopK/w9ezsMFgmUV8KX5LPxz9BnIXHA++13wUu35lquEqRxWyOwjbycwTbabU8ynxnEZb5OSOOK0u/kLhw== +"@yield-protocol/vault-v2@../vault-v2/yield-protocol-vault-v2-0.18.13.tgz": + version "0.18.13" + resolved "../vault-v2/yield-protocol-vault-v2-0.18.13.tgz#801ea6903b35166d4ae037f29f79a266d2d8b54e" -"@yield-protocol/yieldspace-tv@0.1.9-rc.3": - version "0.1.9-rc.3" - resolved "https://registry.npmjs.org/@yield-protocol/yieldspace-tv/-/yieldspace-tv-0.1.9-rc.3.tgz" - integrity sha512-Es9rf9oegKkHX0C/oIHv32mrWmyaTBbE7RAm5OL5HfNGmZqBY2lfEKbSod/XCdHmzee4Hacul5pgyQ53XUIvhA== +"@yield-protocol/yieldspace-tv@^0.1.11": + version "0.1.11" + resolved "https://registry.yarnpkg.com/@yield-protocol/yieldspace-tv/-/yieldspace-tv-0.1.11.tgz#099a610b56c129068ec9917ca5a62e7ef6ef10ac" + integrity sha512-EvhfHEXlVk+Sg/z7GgBhXRUdMZUk+VxgeLpuL+CyHRBCgo2XTZWczrnkUGoUmCnSXz2RjoLoyjTIAXL2cvoLVg== "@yield-protocol/yvarb@^1.0.1-rc2": version "1.0.1-rc2" @@ -6764,6 +6761,14 @@ eth-sig-util@3.0.0: tweetnacl "^1.0.0" tweetnacl-util "^0.15.0" +eth-sig-util@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" + integrity sha512-iNZ576iTOGcfllftB73cPB5AN+XUQAT/T8xzsILsghXC1o8gJUqe3RHlcDqagu+biFpYQ61KQrZZJza8eRSYqw== + dependencies: + ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" + ethereumjs-util "^5.1.1" + eth-sig-util@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-3.0.1.tgz" @@ -6880,6 +6885,13 @@ ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.8: bn.js "^4.11.8" ethereumjs-util "^6.0.0" +"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": + version "0.6.8" + resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0" + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + ethereumjs-account@3.0.0, ethereumjs-account@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz"