|
| 1 | +//SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | +pragma solidity 0.8.19; |
| 3 | + |
| 4 | +import "@forge-std/Test.sol"; |
| 5 | + |
| 6 | +import {MErc20} from "@protocol/MErc20.sol"; |
| 7 | +import {IERC20} from "@openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; |
| 8 | + |
| 9 | +import {HybridProposal, ActionType} from "@proposals/proposalTypes/HybridProposal.sol"; |
| 10 | +import {AllChainAddresses as Addresses} from "@proposals/Addresses.sol"; |
| 11 | +import {BASE_FORK_ID} from "@utils/ChainIds.sol"; |
| 12 | +import {ProposalActions} from "@proposals/utils/ProposalActions.sol"; |
| 13 | + |
| 14 | +/// @title MIP-X37: Reserve Reduction for Token Swap |
| 15 | +/// @author Moonwell Contributors |
| 16 | +/// @notice Proposal to reduce reserves from three Base markets and transfer to EOA for swapping: |
| 17 | +/// 1. Reduce 347 WETH from MOONWELL_WETH market |
| 18 | +/// 2. Reduce 490,000 USDC from MOONWELL_USDC market |
| 19 | +/// 3. Reduce 3 cbBTC from MOONWELL_cbBTC market |
| 20 | +/// 4. Transfer all tokens to ANA_EOA for swapping to VIRTUALS and cbXRP |
| 21 | +contract mipx37 is HybridProposal { |
| 22 | + using ProposalActions for *; |
| 23 | + |
| 24 | + string public constant override name = "MIP-X37"; |
| 25 | + |
| 26 | + // Reserve amounts to reduce |
| 27 | + uint256 public constant WETH_AMOUNT = 347e18; // 347 WETH |
| 28 | + uint256 public constant USDC_AMOUNT = 490_000e6; // 490,000 USDC |
| 29 | + uint256 public constant cbBTC_AMOUNT = 3e8; // 3 cbBTC |
| 30 | + |
| 31 | + constructor() { |
| 32 | + bytes memory proposalDescription = abi.encodePacked( |
| 33 | + vm.readFile("./proposals/mips/mip-x37/x37.md") |
| 34 | + ); |
| 35 | + _setProposalDescription(proposalDescription); |
| 36 | + } |
| 37 | + |
| 38 | + function primaryForkId() public pure override returns (uint256) { |
| 39 | + return BASE_FORK_ID; |
| 40 | + } |
| 41 | + |
| 42 | + function deploy(Addresses, address) public override {} |
| 43 | + |
| 44 | + function build(Addresses addresses) public override { |
| 45 | + vm.selectFork(BASE_FORK_ID); |
| 46 | + |
| 47 | + address anaEoa = addresses.getAddress("ANA_EOA"); |
| 48 | + |
| 49 | + // === WETH Reserve Reduction === |
| 50 | + address moonwellWeth = addresses.getAddress("MOONWELL_WETH"); |
| 51 | + address weth = MErc20(moonwellWeth).underlying(); |
| 52 | + |
| 53 | + _pushAction( |
| 54 | + moonwellWeth, |
| 55 | + abi.encodeWithSignature("_reduceReserves(uint256)", WETH_AMOUNT), |
| 56 | + "Reduce 347 WETH reserves from MOONWELL_WETH", |
| 57 | + ActionType.Base |
| 58 | + ); |
| 59 | + |
| 60 | + _pushAction( |
| 61 | + weth, |
| 62 | + abi.encodeWithSignature( |
| 63 | + "transfer(address,uint256)", |
| 64 | + anaEoa, |
| 65 | + WETH_AMOUNT |
| 66 | + ), |
| 67 | + "Transfer 347 WETH to ANA_EOA", |
| 68 | + ActionType.Base |
| 69 | + ); |
| 70 | + |
| 71 | + // === USDC Reserve Reduction === |
| 72 | + address moonwellUsdc = addresses.getAddress("MOONWELL_USDC"); |
| 73 | + address usdc = MErc20(moonwellUsdc).underlying(); |
| 74 | + |
| 75 | + _pushAction( |
| 76 | + moonwellUsdc, |
| 77 | + abi.encodeWithSignature("_reduceReserves(uint256)", USDC_AMOUNT), |
| 78 | + "Reduce 490,000 USDC reserves from MOONWELL_USDC", |
| 79 | + ActionType.Base |
| 80 | + ); |
| 81 | + |
| 82 | + _pushAction( |
| 83 | + usdc, |
| 84 | + abi.encodeWithSignature( |
| 85 | + "transfer(address,uint256)", |
| 86 | + anaEoa, |
| 87 | + USDC_AMOUNT |
| 88 | + ), |
| 89 | + "Transfer 490,000 USDC to ANA_EOA", |
| 90 | + ActionType.Base |
| 91 | + ); |
| 92 | + |
| 93 | + // === cbBTC Reserve Reduction === |
| 94 | + address moonwellCbBtc = addresses.getAddress("MOONWELL_cbBTC"); |
| 95 | + address cbBtc = MErc20(moonwellCbBtc).underlying(); |
| 96 | + |
| 97 | + _pushAction( |
| 98 | + moonwellCbBtc, |
| 99 | + abi.encodeWithSignature("_reduceReserves(uint256)", cbBTC_AMOUNT), |
| 100 | + "Reduce 3 cbBTC reserves from MOONWELL_cbBTC", |
| 101 | + ActionType.Base |
| 102 | + ); |
| 103 | + |
| 104 | + _pushAction( |
| 105 | + cbBtc, |
| 106 | + abi.encodeWithSignature( |
| 107 | + "transfer(address,uint256)", |
| 108 | + anaEoa, |
| 109 | + cbBTC_AMOUNT |
| 110 | + ), |
| 111 | + "Transfer 3 cbBTC to ANA_EOA", |
| 112 | + ActionType.Base |
| 113 | + ); |
| 114 | + } |
| 115 | + |
| 116 | + function teardown(Addresses, address) public pure override {} |
| 117 | + |
| 118 | + function validate(Addresses addresses, address) public override { |
| 119 | + vm.selectFork(BASE_FORK_ID); |
| 120 | + |
| 121 | + address anaEoa = addresses.getAddress("ANA_EOA"); |
| 122 | + |
| 123 | + // Validate WETH transfer |
| 124 | + address weth = MErc20(addresses.getAddress("MOONWELL_WETH")) |
| 125 | + .underlying(); |
| 126 | + uint256 wethBalance = IERC20(weth).balanceOf(anaEoa); |
| 127 | + assertGe(wethBalance, WETH_AMOUNT, "ANA_EOA should have received WETH"); |
| 128 | + |
| 129 | + // Validate USDC transfer |
| 130 | + address usdc = MErc20(addresses.getAddress("MOONWELL_USDC")) |
| 131 | + .underlying(); |
| 132 | + uint256 usdcBalance = IERC20(usdc).balanceOf(anaEoa); |
| 133 | + assertGe(usdcBalance, USDC_AMOUNT, "ANA_EOA should have received USDC"); |
| 134 | + |
| 135 | + // Validate cbBTC transfer |
| 136 | + address cbBtc = MErc20(addresses.getAddress("MOONWELL_cbBTC")) |
| 137 | + .underlying(); |
| 138 | + uint256 cbBtcBalance = IERC20(cbBtc).balanceOf(anaEoa); |
| 139 | + assertGe( |
| 140 | + cbBtcBalance, |
| 141 | + cbBTC_AMOUNT, |
| 142 | + "ANA_EOA should have received cbBTC" |
| 143 | + ); |
| 144 | + } |
| 145 | +} |
0 commit comments