From 37b862be2722972c7c318e49edfcdc4e45f8dbd7 Mon Sep 17 00:00:00 2001 From: Elliot Date: Sat, 30 Mar 2024 21:10:14 -0700 Subject: [PATCH 01/22] mip-b16 Signed-off-by: Elliot --- src/proposals/mips/mip-b16/MIP-B16.md | 34 ++++++++ src/proposals/mips/mip-b16/mip-b16.sol | 106 +++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 src/proposals/mips/mip-b16/MIP-B16.md create mode 100644 src/proposals/mips/mip-b16/mip-b16.sol diff --git a/src/proposals/mips/mip-b16/MIP-B16.md b/src/proposals/mips/mip-b16/MIP-B16.md new file mode 100644 index 000000000..54082c334 --- /dev/null +++ b/src/proposals/mips/mip-b16/MIP-B16.md @@ -0,0 +1,34 @@ +Authors: Elliot, Ana + +**Summary**: Activate reward emissions for WELL on Base + +**Overview** + +The community has recently voted to implement the new Multichain Governor +contract to govern the Moonwell Protocol. Additionally, a new multichain WELL +token utilizing the xERC20 token standard has been ratified for usage on Base, +which is a significant milestone for the community. By adopting this new Base +native WELL token, tokenholders can now stake their tokens directly on Base and +participate in onchain governance voting. The Safety Module was deployed on Base +and is registered in the Multichain Vote Collection contract as a source of +voting power, allowing users securing the protocol to participate in governance. + +Initially, rewards were set to 0 on the new Safety Module on Base. This proposal +aims to enable rewards for users in the Safety Module with the new Base native +WELL token. + +Before this configuration is able to occur, ample time should be given to the +community to bridge their Wormhole wrapped WELL from Base, to Moonbeam and back +in the Base native form. Initial estimates of this migration time are at minimum +6 days if all Wormhole Wrapped WELL was constantly bridged from Base back to +Moonbeam and Wormhole did not delay transfers. + +Implementation: A proposal will be created by Solidity Labs that sets and funds +rewards that will be given to all Safety Module Stakers. Warden Finance will +provide recommendations on initial reward speeds. + +Conclusion: Adding rewards to the Safety Module on Base creates incentives for +users to backstop the protocol with the new Base native WELL token. Staking WELL +in the Safety Module not only gives community members the ability to earn native +yield on their holdings, but also presents an easy way to get involved in +governance as WELL is automatically self delegated. diff --git a/src/proposals/mips/mip-b16/mip-b16.sol b/src/proposals/mips/mip-b16/mip-b16.sol new file mode 100644 index 000000000..f4cc3467d --- /dev/null +++ b/src/proposals/mips/mip-b16/mip-b16.sol @@ -0,0 +1,106 @@ +//SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.19; + +import {Ownable2StepUpgradeable} from "@openzeppelin-contracts-upgradeable/contracts/access/Ownable2StepUpgradeable.sol"; +import {Ownable} from "@openzeppelin-contracts/contracts/access/Ownable.sol"; + +import "@forge-std/Test.sol"; + +import {Timelock} from "@protocol/Governance/deprecated/Timelock.sol"; +import {Addresses} from "@proposals/Addresses.sol"; +import {IStakedWell} from "@protocol/IStakedWell.sol"; +import {HybridProposal} from "@proposals/proposalTypes/HybridProposal.sol"; +import {MockERC20Params} from "@test/mock/MockERC20Params.sol"; +import {TemporalGovernor} from "@protocol/Governance/TemporalGovernor.sol"; +import {ITemporalGovernor} from "@protocol/Governance/ITemporalGovernor.sol"; +import {MultichainGovernor} from "@protocol/Governance/MultichainGovernor/MultichainGovernor.sol"; +import {ParameterValidation} from "@proposals/utils/ParameterValidation.sol"; +import {WormholeTrustedSender} from "@protocol/Governance/WormholeTrustedSender.sol"; +import {MultichainGovernorDeploy} from "@protocol/Governance/MultichainGovernor/MultichainGovernorDeploy.sol"; +import {ITokenSaleDistributorProxy} from "@protocol/tokensale/ITokenSaleDistributorProxy.sol"; + +/// DO_VALIDATE=true DO_PRINT=true DO_BUILD=true DO_RUN=true forge script +/// src/proposals/mips/mip-b16/mip-b16.sol:mipb16 +contract mipb16 is + HybridProposal, + MultichainGovernorDeploy, + ParameterValidation +{ + string public constant name = "MIP-B16"; + + /// TODO this is TBD and based on the current state of the system + uint256 public constant REWARD_SPEED = 1e18; + + constructor() { + bytes memory proposalDescription = abi.encodePacked( + vm.readFile("./src/proposals/mips/mip-b16/MIP-B16.md") + ); + + _setProposalDescription(proposalDescription); + } + + /// @notice proposal's actions happen only on base + function primaryForkId() public view override returns (uint256) { + return baseForkId; + } + + /// run this action through the Multichain Governor + function build(Addresses addresses) public override { + /// Base actions + + _pushHybridAction( + addresses.getAddress("stkWELL_PROXY"), + abi.encodeWithSignature( + "configureAsset(uint128,address)", + REWARD_SPEED, + addresses.getAddress("stkWELL_PROXY") + ), + "Set reward speed for the Safety Module on Base", + false + ); + } + + function run(Addresses addresses, address) public override { + vm.selectFork(moonbeamForkId); + + /// safety check to ensure no base actions are run + require( + baseActions.length == 1, + "MIP-M26: should have no base actions" + ); + require( + moonbeamActions.length == 0, + "MIP-M26: should have no base actions" + ); + + /// only run actions on Base + _runMoonbeamMultichainGovernor(addresses, address(1000000000)); + + vm.selectFork(baseForkId); + _runBase(addresses.getAddress("TEMPORAL_GOVERNOR")); + } + + /// TODO fill out validations on Base + function validate(Addresses addresses, address) public override { + vm.selectFork(baseForkId); + + address stkWellProxy = addresses.getAddress("stkWELL_PROXY"); + ( + uint128 emissionsPerSecond, + uint128 lastUpdateTimestamp, + + ) = IStakedWell(stkWellProxy).assets(stkWellProxy); + + assertEq( + emissionsPerSecond, + REWARD_SPEED, + "MIP-M26: emissionsPerSecond incorrect" + ); + + assertGt( + lastUpdateTimestamp, + 0, + "MIP-M26: lastUpdateTimestamp not set" + ); + } +} From be57de08a6e57588d436eed6649dc9e0911a3399 Mon Sep 17 00:00:00 2001 From: Elliot Date: Sat, 30 Mar 2024 21:10:40 -0700 Subject: [PATCH 02/22] add assets Signed-off-by: Elliot --- src/IStakedWell.sol | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/IStakedWell.sol b/src/IStakedWell.sol index bfc87a217..3ea0c5424 100644 --- a/src/IStakedWell.sol +++ b/src/IStakedWell.sol @@ -29,6 +29,18 @@ interface IStakedWell { uint256 blockNumber ) external view returns (uint256); + /// @notice view the reward speed for stkWELL + function assets( + address + ) + external + view + returns ( + uint128 emissionsPerSecond, + uint128 lastUpdateTimestamp, + uint256 index + ); + function redeem(address to, uint256 amount) external; function mint(address to, uint256 amount) external; From f19b09500abfbfba87b8b756bf5454fb0a58a6f5 Mon Sep 17 00:00:00 2001 From: Elliot Date: Sat, 30 Mar 2024 21:38:35 -0700 Subject: [PATCH 03/22] add deploy impl Signed-off-by: Elliot --- .../MultichainGovernor/MultichainGovernorDeploy.sol | 4 ++++ test/integration/MultichainProposal.t.sol | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/Governance/MultichainGovernor/MultichainGovernorDeploy.sol b/src/Governance/MultichainGovernor/MultichainGovernorDeploy.sol index 89e417cae..28ec3561b 100644 --- a/src/Governance/MultichainGovernor/MultichainGovernorDeploy.sol +++ b/src/Governance/MultichainGovernor/MultichainGovernorDeploy.sol @@ -197,6 +197,10 @@ contract MultichainGovernorDeploy is Test { ); } + function deployStkWellImpl() public returns (address) { + return deployCode("StakedWell.sol:StakedWell"); + } + function deployStakedWell( address stakedToken, address rewardToken, diff --git a/test/integration/MultichainProposal.t.sol b/test/integration/MultichainProposal.t.sol index 335d085f2..833ddb1bb 100644 --- a/test/integration/MultichainProposal.t.sol +++ b/test/integration/MultichainProposal.t.sol @@ -124,6 +124,8 @@ contract MultichainProposalTest is proposalC = new mipm23c(); proposalF = new mipm25(); + proposalC.buildCalldata(addresses); /// build calldata for bgg test + address[] memory proposalsArray = new address[](1); proposalsArray[0] = address(proposalF); From 115fd0ec30c7a17cce2d3525183bc42b851e7f61 Mon Sep 17 00:00:00 2001 From: Elliot Date: Mon, 1 Apr 2024 16:18:29 -0700 Subject: [PATCH 04/22] teardown before building and running Signed-off-by: Elliot --- src/proposals/MIPProposal.s.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/proposals/MIPProposal.s.sol b/src/proposals/MIPProposal.s.sol index ed6b9f6b2..2ffe10410 100644 --- a/src/proposals/MIPProposal.s.sol +++ b/src/proposals/MIPProposal.s.sol @@ -66,9 +66,9 @@ abstract contract MIPProposal is Script { if (DO_AFTER_DEPLOY_SETUP) afterDeploySetup(addresses); vm.stopBroadcast(); + if (DO_TEARDOWN) teardown(addresses, deployerAddress); if (DO_BUILD) build(addresses); if (DO_RUN) run(addresses, deployerAddress); - if (DO_TEARDOWN) teardown(addresses, deployerAddress); if (DO_VALIDATE) validate(addresses, deployerAddress); /// todo print out actual proposal calldata if (DO_PRINT) { From fbd4e893c9945fa2616ec7612197800f5032584d Mon Sep 17 00:00:00 2001 From: Elliot Date: Mon, 1 Apr 2024 16:19:15 -0700 Subject: [PATCH 05/22] updated proposal description Signed-off-by: Elliot --- src/proposals/mips/mip-b16/MIP-B16.md | 68 +++++++++++++++------------ 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/src/proposals/mips/mip-b16/MIP-B16.md b/src/proposals/mips/mip-b16/MIP-B16.md index 54082c334..0105c79d4 100644 --- a/src/proposals/mips/mip-b16/MIP-B16.md +++ b/src/proposals/mips/mip-b16/MIP-B16.md @@ -1,34 +1,42 @@ -Authors: Elliot, Ana +# MIP-B16 Base Safety Module Activation -**Summary**: Activate reward emissions for WELL on Base +**Authors**: Elliot, Ana + +**Summary** + +This proposal aims to activate reward emissions for the new Safety Module on +Base, incentivizing users to help secure the Moonwell protocol through staking +and participate in onchain governance. **Overview** -The community has recently voted to implement the new Multichain Governor -contract to govern the Moonwell Protocol. Additionally, a new multichain WELL -token utilizing the xERC20 token standard has been ratified for usage on Base, -which is a significant milestone for the community. By adopting this new Base -native WELL token, tokenholders can now stake their tokens directly on Base and -participate in onchain governance voting. The Safety Module was deployed on Base -and is registered in the Multichain Vote Collection contract as a source of -voting power, allowing users securing the protocol to participate in governance. - -Initially, rewards were set to 0 on the new Safety Module on Base. This proposal -aims to enable rewards for users in the Safety Module with the new Base native -WELL token. - -Before this configuration is able to occur, ample time should be given to the -community to bridge their Wormhole wrapped WELL from Base, to Moonbeam and back -in the Base native form. Initial estimates of this migration time are at minimum -6 days if all Wormhole Wrapped WELL was constantly bridged from Base back to -Moonbeam and Wormhole did not delay transfers. - -Implementation: A proposal will be created by Solidity Labs that sets and funds -rewards that will be given to all Safety Module Stakers. Warden Finance will -provide recommendations on initial reward speeds. - -Conclusion: Adding rewards to the Safety Module on Base creates incentives for -users to backstop the protocol with the new Base native WELL token. Staking WELL -in the Safety Module not only gives community members the ability to earn native -yield on their holdings, but also presents an easy way to get involved in -governance as WELL is automatically self delegated. +The Moonwell community has recently approved the implementation of a new +multichain governor contract to govern the Moonwell protocol. Additionally, a +new Base native WELL token utilizing the xERC20 token standard has been approved +for usage, which is a significant milestone for the community. By adopting this +new Base native WELL token, tokenholders will soon be able to stake their WELL +directly on Base and vote in onchain governance. A new Safety Module has already +been deployed on Base and is registered in the Multichain Vote Collection +contract as a source of voting power, allowing users securing the protocol to +participate in governance. Initially, rewards were set to 0 on the new Safety +Module on Base. This proposal aims to enable rewards for users in the Safety +Module with the new Base native WELL token. + +**Implementation** + +This proposal will set and fund rewards that will be distributed to all Safety +Module stakers on Base. Initial reward speeds will be set to the value +recommended by emissions admin Warden Finance of 0.8962755116489610000 WELL per +second. **Voting** + +A "Yay" vote indicates your support for enabling reward emissions for the Safety +Module on Base, as outlined in this proposal. A "Nay" vote indicates your +opposition to enabling reward emissions for the Safety Module on Base. + +**Conclusion** + +Adding rewards to the Safety Module on Base creates incentives for users to +backstop the protocol with the new Base native WELL token. Staking WELL in the +Safety Module not only gives community members the ability to earn native yield +on their holdings, but also presents an easy way to get involved in governance +as WELL is automatically self delegated. From 0963c00f9d87eea532545a15e714ce150286a2d2 Mon Sep 17 00:00:00 2001 From: Elliot Date: Mon, 1 Apr 2024 16:19:36 -0700 Subject: [PATCH 06/22] teardown not pure Signed-off-by: Elliot --- src/proposals/proposalTypes/HybridProposal.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/proposals/proposalTypes/HybridProposal.sol b/src/proposals/proposalTypes/HybridProposal.sol index b305a72a9..403ac034d 100644 --- a/src/proposals/proposalTypes/HybridProposal.sol +++ b/src/proposals/proposalTypes/HybridProposal.sol @@ -441,7 +441,7 @@ abstract contract HybridProposal is function build(Addresses) public virtual override {} - function teardown(Addresses, address) public pure virtual override {} + function teardown(Addresses, address) public virtual override {} function run(Addresses, address) public virtual override {} From e65a7839bdaf3c9352ee8dabb94d6c18afbec2da Mon Sep 17 00:00:00 2001 From: Elliot Date: Mon, 1 Apr 2024 16:20:45 -0700 Subject: [PATCH 07/22] add approval transferFrom action from msig to ecosystem reserve controller Signed-off-by: Elliot --- src/proposals/mips/mip-b16/mip-b16.sol | 74 +++++++++++++++++--------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/src/proposals/mips/mip-b16/mip-b16.sol b/src/proposals/mips/mip-b16/mip-b16.sol index f4cc3467d..9f8a33a08 100644 --- a/src/proposals/mips/mip-b16/mip-b16.sol +++ b/src/proposals/mips/mip-b16/mip-b16.sol @@ -1,23 +1,16 @@ //SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.19; -import {Ownable2StepUpgradeable} from "@openzeppelin-contracts-upgradeable/contracts/access/Ownable2StepUpgradeable.sol"; -import {Ownable} from "@openzeppelin-contracts/contracts/access/Ownable.sol"; +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@forge-std/Test.sol"; -import {Timelock} from "@protocol/Governance/deprecated/Timelock.sol"; import {Addresses} from "@proposals/Addresses.sol"; import {IStakedWell} from "@protocol/IStakedWell.sol"; import {HybridProposal} from "@proposals/proposalTypes/HybridProposal.sol"; -import {MockERC20Params} from "@test/mock/MockERC20Params.sol"; -import {TemporalGovernor} from "@protocol/Governance/TemporalGovernor.sol"; -import {ITemporalGovernor} from "@protocol/Governance/ITemporalGovernor.sol"; -import {MultichainGovernor} from "@protocol/Governance/MultichainGovernor/MultichainGovernor.sol"; +import {TemporalGovernor} from "@protocol/governance/TemporalGovernor.sol"; import {ParameterValidation} from "@proposals/utils/ParameterValidation.sol"; -import {WormholeTrustedSender} from "@protocol/Governance/WormholeTrustedSender.sol"; -import {MultichainGovernorDeploy} from "@protocol/Governance/MultichainGovernor/MultichainGovernorDeploy.sol"; -import {ITokenSaleDistributorProxy} from "@protocol/tokensale/ITokenSaleDistributorProxy.sol"; +import {MultichainGovernorDeploy} from "@protocol/governance/multichain/MultichainGovernorDeploy.sol"; /// DO_VALIDATE=true DO_PRINT=true DO_BUILD=true DO_RUN=true forge script /// src/proposals/mips/mip-b16/mip-b16.sol:mipb16 @@ -28,8 +21,11 @@ contract mipb16 is { string public constant name = "MIP-B16"; - /// TODO this is TBD and based on the current state of the system - uint256 public constant REWARD_SPEED = 1e18; + /// this is and based on Warden's recommendation for reward speeds + uint256 public constant REWARD_SPEED = 896275511648961000; + + /// @notice the amount of WELL to be sent to the Safety Module for funding 41 days of rewards + uint256 public constant WELL_AMOUNT = 3_174_966.37 * 1e18; constructor() { bytes memory proposalDescription = abi.encodePacked( @@ -44,10 +40,38 @@ contract mipb16 is return baseForkId; } + function teardown(Addresses addresses, address) public override { + deal( + addresses.getAddress("xWELL_PROXY"), + addresses.getAddress("FOUNDATION_MULTISIG"), + WELL_AMOUNT + ); + + /// approve the Temporal Governor to spend xWELL + vm.startPrank(addresses.getAddress("FOUNDATION_MULTISIG")); + ERC20(addresses.getAddress("xWELL_PROXY")).approve( + addresses.getAddress("TEMPORAL_GOVERNOR"), + WELL_AMOUNT + ); + vm.stopPrank(); + } + /// run this action through the Multichain Governor function build(Addresses addresses) public override { /// Base actions + _pushHybridAction( + addresses.getAddress("xWELL_PROXY"), + abi.encodeWithSignature( + "transferFrom(address,address,uint256)", + addresses.getAddress("FOUNDATION_MULTISIG"), + addresses.getAddress("ECOSYSTEM_RESERVE_PROXY"), + WELL_AMOUNT + ), + "Transfer xWELL rewards to Ecosystem Reserve Proxy on Base", + false + ); + _pushHybridAction( addresses.getAddress("stkWELL_PROXY"), abi.encodeWithSignature( @@ -61,26 +85,21 @@ contract mipb16 is } function run(Addresses addresses, address) public override { - vm.selectFork(moonbeamForkId); - /// safety check to ensure no base actions are run require( - baseActions.length == 1, - "MIP-M26: should have no base actions" + baseActions.length == 2, + "MIP-B16: should have two base actions" ); + require( moonbeamActions.length == 0, - "MIP-M26: should have no base actions" + "MIP-B16: should have no moonbeam actions" ); - /// only run actions on Base - _runMoonbeamMultichainGovernor(addresses, address(1000000000)); - - vm.selectFork(baseForkId); _runBase(addresses.getAddress("TEMPORAL_GOVERNOR")); } - /// TODO fill out validations on Base + /// @notice validations on Base function validate(Addresses addresses, address) public override { vm.selectFork(baseForkId); @@ -94,13 +113,20 @@ contract mipb16 is assertEq( emissionsPerSecond, REWARD_SPEED, - "MIP-M26: emissionsPerSecond incorrect" + "MIP-B16: emissionsPerSecond incorrect" ); assertGt( lastUpdateTimestamp, 0, - "MIP-M26: lastUpdateTimestamp not set" + "MIP-B16: lastUpdateTimestamp not set" + ); + assertEq( + ERC20(addresses.getAddress("xWELL_PROXY")).balanceOf( + addresses.getAddress("ECOSYSTEM_RESERVE_PROXY") + ), + WELL_AMOUNT, + "MIP-B16: ecosystem reserve not funded" ); } } From b6ebd1c3a098b4cbcbe78e69c7ca98f2f0edca4d Mon Sep 17 00:00:00 2001 From: Elliot Date: Mon, 1 Apr 2024 16:21:07 -0700 Subject: [PATCH 08/22] fix imports Signed-off-by: Elliot --- src/proposals/mips/mip-m25/mip-m25.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/proposals/mips/mip-m25/mip-m25.sol b/src/proposals/mips/mip-m25/mip-m25.sol index 8c4bc0e65..5d8cb4f37 100644 --- a/src/proposals/mips/mip-m25/mip-m25.sol +++ b/src/proposals/mips/mip-m25/mip-m25.sol @@ -9,10 +9,10 @@ import "@forge-std/Test.sol"; import {Addresses} from "@proposals/Addresses.sol"; import {HybridProposal} from "@proposals/proposalTypes/HybridProposal.sol"; import {MockERC20Params} from "@test/mock/MockERC20Params.sol"; -import {TemporalGovernor} from "@protocol/Governance/TemporalGovernor.sol"; -import {ITemporalGovernor} from "@protocol/Governance/ITemporalGovernor.sol"; +import {TemporalGovernor} from "@protocol/governance/TemporalGovernor.sol"; +import {ITemporalGovernor} from "@protocol/governance/ITemporalGovernor.sol"; import {ParameterValidation} from "@proposals/utils/ParameterValidation.sol"; -import {WormholeTrustedSender} from "@protocol/Governance/WormholeTrustedSender.sol"; +import {WormholeTrustedSender} from "@protocol/governance/WormholeTrustedSender.sol"; import {ITokenSaleDistributorProxy} from "@protocol/tokensale/ITokenSaleDistributorProxy.sol"; /// DO_VALIDATE=true DO_DEPLOY=true DO_PRINT=true DO_BUILD=true DO_RUN=true forge script From 0fcb7cee6273f26218242a4a1c29738b756672c1 Mon Sep 17 00:00:00 2001 From: Elliot Date: Tue, 2 Apr 2024 15:19:05 -0700 Subject: [PATCH 09/22] remove unused import Signed-off-by: Elliot --- src/proposals/mips/mip-b16/mip-b16.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/src/proposals/mips/mip-b16/mip-b16.sol b/src/proposals/mips/mip-b16/mip-b16.sol index 9f8a33a08..81c54bf4e 100644 --- a/src/proposals/mips/mip-b16/mip-b16.sol +++ b/src/proposals/mips/mip-b16/mip-b16.sol @@ -8,7 +8,6 @@ import "@forge-std/Test.sol"; import {Addresses} from "@proposals/Addresses.sol"; import {IStakedWell} from "@protocol/IStakedWell.sol"; import {HybridProposal} from "@proposals/proposalTypes/HybridProposal.sol"; -import {TemporalGovernor} from "@protocol/governance/TemporalGovernor.sol"; import {ParameterValidation} from "@proposals/utils/ParameterValidation.sol"; import {MultichainGovernorDeploy} from "@protocol/governance/multichain/MultichainGovernorDeploy.sol"; From a7f82ee02cdfddff2d7c9e1b0e4f68873c9c542e Mon Sep 17 00:00:00 2001 From: Elliot Date: Tue, 2 Apr 2024 16:57:06 -0700 Subject: [PATCH 10/22] total supply change implies sender has non zero buffer cap --- certora/specs/ERC20.spec | 12 +++++++++++- certora/specs/IERC20.spec | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/certora/specs/ERC20.spec b/certora/specs/ERC20.spec index 0097d3a6a..c06835337 100644 --- a/certora/specs/ERC20.spec +++ b/certora/specs/ERC20.spec @@ -285,8 +285,18 @@ rule noChangeTotalSupply(env e) { f(e, args); uint256 totalSupplyAfter = totalSupply(); + uint128 rateLimitPerSecond; + uint112 bufferCap; + uint32 lastBufferUsedTime; + uint112 bufferStored; + uint112 midpoint; + + rateLimitPerSecond, bufferCap, lastBufferUsedTime, bufferStored, midpoint = rateLimits(e.msg.sender); + + assert (totalSupplyAfter > totalSupplyBefore && bufferCap(e.msg.sender) > assert_uint256(midpoint)) => + bufferCap(e.msg.sender) != 0; assert totalSupplyAfter > totalSupplyBefore => f.selector == sig:mint(address,uint256).selector; - assert totalSupplyAfter < totalSupplyBefore => f.selector == sig:burn(address,uint256).selector; + assert totalSupplyAfter < totalSupplyBefore => f.selector == sig:burn(address,uint256).selector && bufferCap(e.msg.sender) != 0; } /* diff --git a/certora/specs/IERC20.spec b/certora/specs/IERC20.spec index b69a006f4..41794ac24 100644 --- a/certora/specs/IERC20.spec +++ b/certora/specs/IERC20.spec @@ -20,4 +20,5 @@ methods { function rateLimitPerSecond(address) external returns (uint256) envfree; function minBufferCap() external returns (uint112) envfree; function maxRateLimitPerSecond() external returns (uint128) envfree; + function rateLimits(address) external returns (uint128, uint112, uint32, uint112, uint112) envfree; } From 450cb20d668c1f9ca0f54a4c66a8648c03b00d03 Mon Sep 17 00:00:00 2001 From: Elliot Date: Sat, 6 Apr 2024 11:37:40 -0700 Subject: [PATCH 11/22] remove teardown, add moonbeam propose simulation Signed-off-by: Elliot --- src/proposals/mips/mip-b16/mip-b16.sol | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/proposals/mips/mip-b16/mip-b16.sol b/src/proposals/mips/mip-b16/mip-b16.sol index 81c54bf4e..632506308 100644 --- a/src/proposals/mips/mip-b16/mip-b16.sol +++ b/src/proposals/mips/mip-b16/mip-b16.sol @@ -18,7 +18,7 @@ contract mipb16 is MultichainGovernorDeploy, ParameterValidation { - string public constant name = "MIP-B16"; + string public constant name = "MIP-B17"; /// this is and based on Warden's recommendation for reward speeds uint256 public constant REWARD_SPEED = 896275511648961000; @@ -39,21 +39,7 @@ contract mipb16 is return baseForkId; } - function teardown(Addresses addresses, address) public override { - deal( - addresses.getAddress("xWELL_PROXY"), - addresses.getAddress("FOUNDATION_MULTISIG"), - WELL_AMOUNT - ); - - /// approve the Temporal Governor to spend xWELL - vm.startPrank(addresses.getAddress("FOUNDATION_MULTISIG")); - ERC20(addresses.getAddress("xWELL_PROXY")).approve( - addresses.getAddress("TEMPORAL_GOVERNOR"), - WELL_AMOUNT - ); - vm.stopPrank(); - } + function teardown(Addresses addresses, address) public override {} /// run this action through the Multichain Governor function build(Addresses addresses) public override { @@ -94,6 +80,11 @@ contract mipb16 is moonbeamActions.length == 0, "MIP-B16: should have no moonbeam actions" ); + vm.selectFork(moonbeamForkId); + + _runMoonbeamMultichainGovernor(addresses, address(1000000000)); + + vm.selectFork(baseForkId); _runBase(addresses.getAddress("TEMPORAL_GOVERNOR")); } From 4c047102b2c0ca23ec3c7c66680af35136c73ff2 Mon Sep 17 00:00:00 2001 From: Elliot Date: Sat, 6 Apr 2024 11:38:45 -0700 Subject: [PATCH 12/22] use only moonbeam or moonbase chainid to fetch wormhole core address Signed-off-by: Elliot --- src/proposals/proposalTypes/HybridProposal.sol | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/proposals/proposalTypes/HybridProposal.sol b/src/proposals/proposalTypes/HybridProposal.sol index 403ac034d..c0dd72b0d 100644 --- a/src/proposals/proposalTypes/HybridProposal.sol +++ b/src/proposals/proposalTypes/HybridProposal.sol @@ -235,7 +235,13 @@ abstract contract HybridProposal is } return getTargetsPayloadsValues( - addresses.getAddress("WORMHOLE_CORE"), + addresses.getAddress( + "WORMHOLE_CORE", + block.chainid == baseChainId || + block.chainid == moonBeamChainId + ? moonBeamChainId + : moonBaseChainId + ), temporalGovernor ); } From 105702c531e4ff96b0776230d6106947ed594238 Mon Sep 17 00:00:00 2001 From: Elliot Date: Sat, 6 Apr 2024 12:02:55 -0700 Subject: [PATCH 13/22] index check gt Signed-off-by: Elliot --- test/integration/MultichainProposal.t.sol | 29 +++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/test/integration/MultichainProposal.t.sol b/test/integration/MultichainProposal.t.sol index 180c0d189..ef99c3166 100644 --- a/test/integration/MultichainProposal.t.sol +++ b/test/integration/MultichainProposal.t.sol @@ -277,6 +277,31 @@ contract MultichainProposalTest is ); } + function testNoBaseWormholeCoreAddressInProposal() public { + address wormholeBase = addresses.getAddress( + "WORMHOLE_CORE", + baseChainId + ); + vm.selectFork(moonbeamForkId); + uint256[] memory proposals = governor.liveProposals(); + for (uint256 i = 0; i < proposals.length; i++) { + if (proposals[i] == 4) { + continue; + } + + (address[] memory targets, , ) = governor.getProposalData( + proposals[i] + ); + + for (uint256 j = 0; j < targets.length; j++) { + require( + targets[j] != wormholeBase, + "targeted wormhole core base address on moonbeam" + ); + } + } + } + function testGetAllMarketConfigs() public { MultiRewardDistributor mrd = MultiRewardDistributor( addresses.getAddress("MRD_PROXY") @@ -2411,7 +2436,7 @@ contract MultichainProposalTest is ) = stkwell.assets(address(stkwell)); assertEq(1e18, emissionsPerSecond, "emissions per second"); - assertEq(1e18, index, "rewards per second"); + assertGt(index, 1, "rewards per second"); assertEq( block.timestamp, lastUpdateTimestamp, @@ -2593,7 +2618,7 @@ contract MultichainProposalTest is ) = stkwell.assets(address(stkwell)); assertEq(1e18, emissionsPerSecond, "emissions per second"); - assertEq(1e18, index, "rewards per second"); + assertGt(index, 1, "rewards per second"); assertEq( block.timestamp, lastUpdateTimestamp, From 55832023f95b12f48214d596f166c16cc1a65f40 Mon Sep 17 00:00:00 2001 From: Elliot Date: Sat, 6 Apr 2024 12:03:23 -0700 Subject: [PATCH 14/22] resubmission language Signed-off-by: Elliot --- src/proposals/mips/mip-b16/MIP-B16.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/proposals/mips/mip-b16/MIP-B16.md b/src/proposals/mips/mip-b16/MIP-B16.md index 0105c79d4..473eea13c 100644 --- a/src/proposals/mips/mip-b16/MIP-B16.md +++ b/src/proposals/mips/mip-b16/MIP-B16.md @@ -1,14 +1,20 @@ -# MIP-B16 Base Safety Module Activation +# MIP-B16 Base Safety Module Activation Resubmission **Authors**: Elliot, Ana -**Summary** +## Simple Summary + +The original proposal was approved but contained an error that prevented +successful execution on Moonbeam. This issue has been corrected in this +resubmission. + +## Summary This proposal aims to activate reward emissions for the new Safety Module on Base, incentivizing users to help secure the Moonwell protocol through staking and participate in onchain governance. -**Overview** +## Overview The Moonwell community has recently approved the implementation of a new multichain governor contract to govern the Moonwell protocol. Additionally, a @@ -22,7 +28,7 @@ participate in governance. Initially, rewards were set to 0 on the new Safety Module on Base. This proposal aims to enable rewards for users in the Safety Module with the new Base native WELL token. -**Implementation** +## Implementation This proposal will set and fund rewards that will be distributed to all Safety Module stakers on Base. Initial reward speeds will be set to the value @@ -33,7 +39,7 @@ A "Yay" vote indicates your support for enabling reward emissions for the Safety Module on Base, as outlined in this proposal. A "Nay" vote indicates your opposition to enabling reward emissions for the Safety Module on Base. -**Conclusion** +## Conclusion Adding rewards to the Safety Module on Base creates incentives for users to backstop the protocol with the new Base native WELL token. Staking WELL in the From fa5ee03c261cf7489a4003257404128963a9bd54 Mon Sep 17 00:00:00 2001 From: Elliot Date: Sat, 6 Apr 2024 12:16:50 -0700 Subject: [PATCH 15/22] WELL amount updated Signed-off-by: Elliot --- src/proposals/mips/mip-b16/mip-b16.sol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/proposals/mips/mip-b16/mip-b16.sol b/src/proposals/mips/mip-b16/mip-b16.sol index 632506308..0894c6ff0 100644 --- a/src/proposals/mips/mip-b16/mip-b16.sol +++ b/src/proposals/mips/mip-b16/mip-b16.sol @@ -20,11 +20,12 @@ contract mipb16 is { string public constant name = "MIP-B17"; - /// this is and based on Warden's recommendation for reward speeds + /// @notice this is based on Warden Finance's recommendation for reward speeds uint256 public constant REWARD_SPEED = 896275511648961000; - /// @notice the amount of WELL to be sent to the Safety Module for funding 41 days of rewards - uint256 public constant WELL_AMOUNT = 3_174_966.37 * 1e18; + /// @notice the amount of WELL to be sent to the Safety Module for funding 38 days of rewards + /// 36*86400*.896275511648961000 = 2,787,775.3514329283 WELL, round up to 2,787,776 + uint256 public constant WELL_AMOUNT = 2_787_776 * 1e18; constructor() { bytes memory proposalDescription = abi.encodePacked( From eba1c1c37b9bcb3b33a88208d914868948f00985 Mon Sep 17 00:00:00 2001 From: Elliot Date: Sat, 6 Apr 2024 12:24:29 -0700 Subject: [PATCH 16/22] naming -> resubmission Signed-off-by: Elliot --- src/proposals/mips/mip-b16/mip-b16.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/proposals/mips/mip-b16/mip-b16.sol b/src/proposals/mips/mip-b16/mip-b16.sol index 0894c6ff0..8fd0c263d 100644 --- a/src/proposals/mips/mip-b16/mip-b16.sol +++ b/src/proposals/mips/mip-b16/mip-b16.sol @@ -18,7 +18,7 @@ contract mipb16 is MultichainGovernorDeploy, ParameterValidation { - string public constant name = "MIP-B17"; + string public constant name = "MIP-B16 Resubmission"; /// @notice this is based on Warden Finance's recommendation for reward speeds uint256 public constant REWARD_SPEED = 896275511648961000; From 5762eb1145d67ac8abfa99d8f24e0350bc0e04e6 Mon Sep 17 00:00:00 2001 From: Elliot Date: Sat, 6 Apr 2024 12:24:57 -0700 Subject: [PATCH 17/22] run mip-b16 Signed-off-by: Elliot --- test/integration/MultichainProposal.t.sol | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/integration/MultichainProposal.t.sol b/test/integration/MultichainProposal.t.sol index ef99c3166..f67ad6569 100644 --- a/test/integration/MultichainProposal.t.sol +++ b/test/integration/MultichainProposal.t.sol @@ -34,6 +34,7 @@ import {TokenSaleDistributorInterfaceV1} from "@protocol/views/TokenSaleDistribu import {mipm23c} from "@proposals/mips/mip-m23/mip-m23c.sol"; import {mipm25} from "@proposals/mips/mip-m25/mip-m25.sol"; +import {mipb16} from "@proposals/mips/mip-b16/mip-b16.sol"; import {validateProxy} from "@proposals/utils/ProxyUtils.sol"; import {ITimelock as Timelock} from "@protocol/interfaces/ITimelock.sol"; @@ -96,6 +97,7 @@ contract MultichainProposalTest is mipm23c public proposalC; mipm25 public proposalF; + mipb16 public proposalG; TemporalGovernor public temporalGov; @@ -123,11 +125,13 @@ contract MultichainProposalTest is proposalC = new mipm23c(); proposalF = new mipm25(); + proposalG = new mipb16(); proposalC.buildCalldata(addresses); /// build calldata for bgg test - address[] memory proposalsArray = new address[](1); + address[] memory proposalsArray = new address[](2); proposalsArray[0] = address(proposalF); + proposalsArray[1] = address(proposalG); proposalF.setForkIds(baseForkId, moonbeamForkId); From a569a07836433b19404cf5f857623c1f19c7e985 Mon Sep 17 00:00:00 2001 From: Elliot Date: Sat, 6 Apr 2024 12:51:28 -0700 Subject: [PATCH 18/22] estimated go live date in simple summary of proposal text Signed-off-by: Elliot --- src/proposals/mips/mip-b16/MIP-B16.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/proposals/mips/mip-b16/MIP-B16.md b/src/proposals/mips/mip-b16/MIP-B16.md index 473eea13c..e46828f4a 100644 --- a/src/proposals/mips/mip-b16/MIP-B16.md +++ b/src/proposals/mips/mip-b16/MIP-B16.md @@ -6,7 +6,8 @@ The original proposal was approved but contained an error that prevented successful execution on Moonbeam. This issue has been corrected in this -resubmission. +resubmission. If this proposal passes, the community can expect to have rewards +enabled for the Safety Module on Base on Thursday. ## Summary From 9506191034d96ce29bbeacfaedf7567d422093e1 Mon Sep 17 00:00:00 2001 From: Elliot Date: Tue, 9 Apr 2024 12:18:39 -0700 Subject: [PATCH 19/22] fix merge conflict Signed-off-by: Elliot --- test/integration/MultichainProposal.t.sol | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/integration/MultichainProposal.t.sol b/test/integration/MultichainProposal.t.sol index ed046e841..70042f336 100644 --- a/test/integration/MultichainProposal.t.sol +++ b/test/integration/MultichainProposal.t.sol @@ -2428,11 +2428,7 @@ contract MultichainProposalTest is ) = stkwell.assets(address(stkwell)); assertEq(1e18, emissionsPerSecond, "emissions per second"); -<<<<<<< HEAD assertGt(index, 1, "rewards per second"); -======= - assertGt(index, 0, "index incorrect"); ->>>>>>> 0b5de6e781c5db6e79094da8c773f348e68db2e9 assertEq( block.timestamp, lastUpdateTimestamp, @@ -2614,11 +2610,7 @@ contract MultichainProposalTest is ) = stkwell.assets(address(stkwell)); assertEq(1e18, emissionsPerSecond, "emissions per second"); -<<<<<<< HEAD assertGt(index, 1, "rewards per second"); -======= - assertGt(index, 0, "index incorrect"); ->>>>>>> 0b5de6e781c5db6e79094da8c773f348e68db2e9 assertEq( block.timestamp, lastUpdateTimestamp, From 42faeaecad61dde98767845646dc7ddeb483ebeb Mon Sep 17 00:00:00 2001 From: Elliot Date: Tue, 9 Apr 2024 12:21:18 -0700 Subject: [PATCH 20/22] _runBase function arguments Signed-off-by: Elliot --- src/proposals/mips/mip-b16/mip-b16.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/proposals/mips/mip-b16/mip-b16.sol b/src/proposals/mips/mip-b16/mip-b16.sol index 8fd0c263d..7d759d5d6 100644 --- a/src/proposals/mips/mip-b16/mip-b16.sol +++ b/src/proposals/mips/mip-b16/mip-b16.sol @@ -87,7 +87,7 @@ contract mipb16 is vm.selectFork(baseForkId); - _runBase(addresses.getAddress("TEMPORAL_GOVERNOR")); + _runBase(addresses, addresses.getAddress("TEMPORAL_GOVERNOR")); } /// @notice validations on Base From 1a5bf53731477da63a7cfcf3a1abc5321d81a1d5 Mon Sep 17 00:00:00 2001 From: Elliot Date: Tue, 9 Apr 2024 13:25:05 -0700 Subject: [PATCH 21/22] WORMHOLE_CORE_BASE Signed-off-by: Elliot --- test/integration/MultichainProposal.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/MultichainProposal.t.sol b/test/integration/MultichainProposal.t.sol index 70042f336..c6192bc73 100644 --- a/test/integration/MultichainProposal.t.sol +++ b/test/integration/MultichainProposal.t.sol @@ -269,7 +269,7 @@ contract MultichainProposalTest is function testNoBaseWormholeCoreAddressInProposal() public { address wormholeBase = addresses.getAddress( - "WORMHOLE_CORE", + "WORMHOLE_CORE_BASE", baseChainId ); vm.selectFork(moonbeamForkId); From fc935923839a28b213dde9fd275376b5eb2ee463 Mon Sep 17 00:00:00 2001 From: Elliot <34463580+ElliotFriedman@users.noreply.github.com> Date: Tue, 9 Apr 2024 18:35:50 -0400 Subject: [PATCH 22/22] Update src/proposals/mips/mip-b16/mip-b16.sol --- src/proposals/mips/mip-b16/mip-b16.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/proposals/mips/mip-b16/mip-b16.sol b/src/proposals/mips/mip-b16/mip-b16.sol index 7d759d5d6..c36827cb4 100644 --- a/src/proposals/mips/mip-b16/mip-b16.sol +++ b/src/proposals/mips/mip-b16/mip-b16.sol @@ -71,7 +71,7 @@ contract mipb16 is } function run(Addresses addresses, address) public override { - /// safety check to ensure no base actions are run + /// safety check to ensure no moonbeam actions are run require( baseActions.length == 2, "MIP-B16: should have two base actions"