forked from ethereum-optimism/optimism
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSequencerFeeVault.t.sol
140 lines (111 loc) · 5.36 KB
/
SequencerFeeVault.t.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
// Testing utilities
import { FeeVault_Initializer, Reverter } from "./CommonTest.t.sol";
import { StandardBridge } from "../src/universal/StandardBridge.sol";
// Libraries
import { Predeploys } from "../src/libraries/Predeploys.sol";
// Target contract dependencies
import { FeeVault } from "../src/universal/FeeVault.sol";
// Target contract
import { SequencerFeeVault } from "../src/L2/SequencerFeeVault.sol";
contract SequencerFeeVault_Test is FeeVault_Initializer {
/// @dev Sets up the test suite.
function setUp() public override {
super.setUp();
vm.etch(
Predeploys.SEQUENCER_FEE_WALLET,
address(new SequencerFeeVault(recipient, NON_ZERO_VALUE, FeeVault.WithdrawalNetwork.L1)).code
);
vm.label(Predeploys.SEQUENCER_FEE_WALLET, "SequencerFeeVault");
}
/// @dev Tests that the minimum withdrawal amount is correct.
function test_minWithdrawalAmount_succeeds() external {
assertEq(vault.MIN_WITHDRAWAL_AMOUNT(), NON_ZERO_VALUE);
}
/// @dev Tests that the l1 fee wallet is correct.
function test_constructor_succeeds() external {
assertEq(vault.l1FeeWallet(), recipient);
}
/// @dev Tests that the fee vault is able to receive ETH.
function test_receive_succeeds() external {
uint256 balance = address(vault).balance;
vm.prank(alice);
(bool success,) = address(vault).call{ value: 100 }(hex"");
assertEq(success, true);
assertEq(address(vault).balance, balance + 100);
}
/// @dev Tests that `withdraw` reverts if the balance is less than the minimum
/// withdrawal amount.
function test_withdraw_notEnough_reverts() external {
assert(address(vault).balance < vault.MIN_WITHDRAWAL_AMOUNT());
vm.expectRevert("FeeVault: withdrawal amount must be greater than minimum withdrawal amount");
vault.withdraw();
}
/// @dev Tests that `withdraw` successfully initiates a withdrawal to L1.
function test_withdraw_toL1_succeeds() external {
uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1;
vm.deal(address(vault), amount);
// No ether has been withdrawn yet
assertEq(vault.totalProcessed(), 0);
vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));
emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this));
vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));
emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this), FeeVault.WithdrawalNetwork.L1);
// The entire vault's balance is withdrawn
vm.expectCall(
Predeploys.L2_STANDARD_BRIDGE,
address(vault).balance,
abi.encodeWithSelector(StandardBridge.bridgeETHTo.selector, vault.l1FeeWallet(), 35_000, bytes(""))
);
vault.withdraw();
// The withdrawal was successful
assertEq(vault.totalProcessed(), amount);
assertEq(address(vault).balance, ZERO_VALUE);
assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, amount);
}
}
contract SequencerFeeVault_L2Withdrawal_Test is FeeVault_Initializer {
/// @dev Sets up the test suite.
function setUp() public override {
super.setUp();
vm.etch(
Predeploys.SEQUENCER_FEE_WALLET,
address(new SequencerFeeVault(recipient, NON_ZERO_VALUE, FeeVault.WithdrawalNetwork.L2)).code
);
vm.label(Predeploys.SEQUENCER_FEE_WALLET, "SequencerFeeVault");
}
/// @dev Tests that `withdraw` successfully initiates a withdrawal to L2.
function test_withdraw_toL2_succeeds() external {
uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1;
vm.deal(address(vault), amount);
// No ether has been withdrawn yet
assertEq(vault.totalProcessed(), 0);
vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));
emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this));
vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));
emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this), FeeVault.WithdrawalNetwork.L2);
// The entire vault's balance is withdrawn
vm.expectCall(recipient, address(vault).balance, bytes(""));
vault.withdraw();
// The withdrawal was successful
assertEq(vault.totalProcessed(), amount);
assertEq(address(vault).balance, ZERO_VALUE);
assertEq(recipient.balance, amount);
}
/// @dev Tests that `withdraw` fails if the Recipient reverts. This also serves to simulate
/// a situation where insufficient gas is provided to the RECIPIENT.
function test_withdraw_toL2recipientReverts_fails() external {
uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT();
vm.deal(address(vault), amount);
// No ether has been withdrawn yet
assertEq(vault.totalProcessed(), 0);
// Ensure the RECIPIENT reverts
vm.etch(vault.RECIPIENT(), type(Reverter).runtimeCode);
// The entire vault's balance is withdrawn
vm.expectCall(recipient, address(vault).balance, bytes(""));
vm.expectRevert("FeeVault: failed to send ETH to L2 fee recipient");
vault.withdraw();
assertEq(vault.totalProcessed(), 0);
}
}