Skip to content

Commit eb454ac

Browse files
tarunkhasnavisTarun Khasnavistremarkley
authored
Update Faucet contract to use bridging on drip function (#10621)
* adding bridging to the faucet drip call * updating the logic based on suggesstions * adding changeset * fixing ci issue * update auth module tests * final fix * lint fix * update snapshots * update changeset * change to patch --------- Co-authored-by: Tarun Khasnavis <tarunkhasnavis@Taruns-MacBook-Pro.local> Co-authored-by: tre <tremarkley@gmail.com>
1 parent 1c22d5f commit eb454ac

File tree

6 files changed

+79
-18
lines changed

6 files changed

+79
-18
lines changed

.changeset/witty-pants-move.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@eth-optimism/contracts-bedrock': patch
3+
---
4+
5+
Add data field to faucet contract drip parameters

packages/contracts-bedrock/snapshots/abi/AdminFaucetAuthModule.json

+10
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,20 @@
5555
"name": "recipient",
5656
"type": "address"
5757
},
58+
{
59+
"internalType": "bytes",
60+
"name": "data",
61+
"type": "bytes"
62+
},
5863
{
5964
"internalType": "bytes32",
6065
"name": "nonce",
6166
"type": "bytes32"
67+
},
68+
{
69+
"internalType": "uint32",
70+
"name": "gasLimit",
71+
"type": "uint32"
6272
}
6373
],
6474
"internalType": "struct Faucet.DripParameters",

packages/contracts-bedrock/snapshots/abi/Faucet.json

+10
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,20 @@
7676
"name": "recipient",
7777
"type": "address"
7878
},
79+
{
80+
"internalType": "bytes",
81+
"name": "data",
82+
"type": "bytes"
83+
},
7984
{
8085
"internalType": "bytes32",
8186
"name": "nonce",
8287
"type": "bytes32"
88+
},
89+
{
90+
"internalType": "uint32",
91+
"name": "gasLimit",
92+
"type": "uint32"
8393
}
8494
],
8595
"internalType": "struct Faucet.DripParameters",

packages/contracts-bedrock/src/periphery/faucet/Faucet.sol

+8-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
pragma solidity 0.8.15;
33

44
import { IFaucetAuthModule } from "./authmodules/IFaucetAuthModule.sol";
5+
import { SafeCall } from "../../libraries/SafeCall.sol";
56

67
/// @title SafeSend
78
/// @notice Sends ETH to a recipient account without triggering any code.
@@ -25,7 +26,9 @@ contract Faucet {
2526
/// @notice Parameters for a drip.
2627
struct DripParameters {
2728
address payable recipient;
29+
bytes data;
2830
bytes32 nonce;
31+
uint32 gasLimit;
2932
}
3033

3134
/// @notice Parameters for authentication.
@@ -113,14 +116,17 @@ contract Faucet {
113116
"Faucet: drip parameters could not be verified by security module"
114117
);
115118

119+
// Verify recepient is not the faucet address.
120+
require(_params.recipient != address(this), "Faucet: cannot drip to itself");
121+
116122
// Set the next timestamp at which this auth id can be used.
117123
timeouts[_auth.module][_auth.id] = block.timestamp + config.ttl;
118124

119125
// Mark the nonce as used.
120126
nonces[_auth.id][_params.nonce] = true;
121127

122-
// Execute a safe transfer of ETH to the recipient account.
123-
new SafeSend{ value: config.amount }(_params.recipient);
128+
// Execute transfer of ETH to the recipient account.
129+
SafeCall.call(_params.recipient, _params.gasLimit, config.amount, _params.data);
124130

125131
emit Drip(config.name, _auth.id, config.amount, _params.recipient);
126132
}

packages/contracts-bedrock/test/periphery/faucet/Faucet.t.sol

+31-13
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ contract FaucetTest is Faucet_Initializer {
106106
function test_authAdmin_drip_succeeds() external {
107107
_enableFaucetAuthModules();
108108
bytes32 nonce = faucetHelper.consumeNonce();
109+
bytes memory data = "0x";
110+
uint32 gasLimit = 200000;
109111
bytes memory signature = issueProofWithEIP712Domain(
110112
faucetAuthAdminKey,
111113
bytes(optimistNftFamName),
@@ -119,14 +121,16 @@ contract FaucetTest is Faucet_Initializer {
119121

120122
vm.prank(nonAdmin);
121123
faucet.drip(
122-
Faucet.DripParameters(payable(fundsReceiver), nonce),
124+
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
123125
Faucet.AuthParameters(optimistNftFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
124126
);
125127
}
126128

127129
function test_nonAdmin_drip_fails() external {
128130
_enableFaucetAuthModules();
129131
bytes32 nonce = faucetHelper.consumeNonce();
132+
bytes memory data = "0x";
133+
uint32 gasLimit = 200000;
130134
bytes memory signature = issueProofWithEIP712Domain(
131135
nonAdminKey,
132136
bytes(optimistNftFamName),
@@ -141,14 +145,16 @@ contract FaucetTest is Faucet_Initializer {
141145
vm.prank(nonAdmin);
142146
vm.expectRevert("Faucet: drip parameters could not be verified by security module");
143147
faucet.drip(
144-
Faucet.DripParameters(payable(fundsReceiver), nonce),
148+
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
145149
Faucet.AuthParameters(optimistNftFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
146150
);
147151
}
148152

149153
function test_drip_optimistNftSendsCorrectAmount_succeeds() external {
150154
_enableFaucetAuthModules();
151155
bytes32 nonce = faucetHelper.consumeNonce();
156+
bytes memory data = "0x";
157+
uint32 gasLimit = 200000;
152158
bytes memory signature = issueProofWithEIP712Domain(
153159
faucetAuthAdminKey,
154160
bytes(optimistNftFamName),
@@ -163,7 +169,7 @@ contract FaucetTest is Faucet_Initializer {
163169
uint256 recipientBalanceBefore = address(fundsReceiver).balance;
164170
vm.prank(nonAdmin);
165171
faucet.drip(
166-
Faucet.DripParameters(payable(fundsReceiver), nonce),
172+
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
167173
Faucet.AuthParameters(optimistNftFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
168174
);
169175
uint256 recipientBalanceAfter = address(fundsReceiver).balance;
@@ -173,6 +179,8 @@ contract FaucetTest is Faucet_Initializer {
173179
function test_drip_githubSendsCorrectAmount_succeeds() external {
174180
_enableFaucetAuthModules();
175181
bytes32 nonce = faucetHelper.consumeNonce();
182+
bytes memory data = "0x";
183+
uint32 gasLimit = 200000;
176184
bytes memory signature = issueProofWithEIP712Domain(
177185
faucetAuthAdminKey,
178186
bytes(githubFamName),
@@ -187,7 +195,7 @@ contract FaucetTest is Faucet_Initializer {
187195
uint256 recipientBalanceBefore = address(fundsReceiver).balance;
188196
vm.prank(nonAdmin);
189197
faucet.drip(
190-
Faucet.DripParameters(payable(fundsReceiver), nonce),
198+
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
191199
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
192200
);
193201
uint256 recipientBalanceAfter = address(fundsReceiver).balance;
@@ -197,6 +205,8 @@ contract FaucetTest is Faucet_Initializer {
197205
function test_drip_emitsEvent_succeeds() external {
198206
_enableFaucetAuthModules();
199207
bytes32 nonce = faucetHelper.consumeNonce();
208+
bytes memory data = "0x";
209+
uint32 gasLimit = 200000;
200210
bytes memory signature = issueProofWithEIP712Domain(
201211
faucetAuthAdminKey,
202212
bytes(githubFamName),
@@ -213,14 +223,16 @@ contract FaucetTest is Faucet_Initializer {
213223

214224
vm.prank(nonAdmin);
215225
faucet.drip(
216-
Faucet.DripParameters(payable(fundsReceiver), nonce),
226+
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
217227
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
218228
);
219229
}
220230

221231
function test_drip_disabledModule_reverts() external {
222232
_enableFaucetAuthModules();
223233
bytes32 nonce = faucetHelper.consumeNonce();
234+
bytes memory data = "0x";
235+
uint32 gasLimit = 200000;
224236
bytes memory signature = issueProofWithEIP712Domain(
225237
faucetAuthAdminKey,
226238
bytes(githubFamName),
@@ -234,15 +246,15 @@ contract FaucetTest is Faucet_Initializer {
234246

235247
vm.startPrank(faucetContractAdmin);
236248
faucet.drip(
237-
Faucet.DripParameters(payable(fundsReceiver), nonce),
249+
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
238250
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
239251
);
240252

241253
faucet.configure(githubFam, Faucet.ModuleConfig("GithubModule", false, 1 days, 0.05 ether));
242254

243255
vm.expectRevert("Faucet: provided auth module is not supported by this faucet");
244256
faucet.drip(
245-
Faucet.DripParameters(payable(fundsReceiver), nonce),
257+
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
246258
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
247259
);
248260
vm.stopPrank();
@@ -251,6 +263,8 @@ contract FaucetTest is Faucet_Initializer {
251263
function test_drip_preventsReplayAttacks_succeeds() external {
252264
_enableFaucetAuthModules();
253265
bytes32 nonce = faucetHelper.consumeNonce();
266+
bytes memory data = "0x";
267+
uint32 gasLimit = 200000;
254268
bytes memory signature = issueProofWithEIP712Domain(
255269
faucetAuthAdminKey,
256270
bytes(githubFamName),
@@ -264,13 +278,13 @@ contract FaucetTest is Faucet_Initializer {
264278

265279
vm.startPrank(faucetContractAdmin);
266280
faucet.drip(
267-
Faucet.DripParameters(payable(fundsReceiver), nonce),
281+
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
268282
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
269283
);
270284

271285
vm.expectRevert("Faucet: nonce has already been used");
272286
faucet.drip(
273-
Faucet.DripParameters(payable(fundsReceiver), nonce),
287+
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
274288
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
275289
);
276290
vm.stopPrank();
@@ -279,6 +293,8 @@ contract FaucetTest is Faucet_Initializer {
279293
function test_drip_beforeTimeout_reverts() external {
280294
_enableFaucetAuthModules();
281295
bytes32 nonce0 = faucetHelper.consumeNonce();
296+
bytes memory data = "0x";
297+
uint32 gasLimit = 200000;
282298
bytes memory signature0 = issueProofWithEIP712Domain(
283299
faucetAuthAdminKey,
284300
bytes(githubFamName),
@@ -292,7 +308,7 @@ contract FaucetTest is Faucet_Initializer {
292308

293309
vm.startPrank(faucetContractAdmin);
294310
faucet.drip(
295-
Faucet.DripParameters(payable(fundsReceiver), nonce0),
311+
Faucet.DripParameters(payable(fundsReceiver), data, nonce0, gasLimit),
296312
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature0)
297313
);
298314

@@ -310,7 +326,7 @@ contract FaucetTest is Faucet_Initializer {
310326

311327
vm.expectRevert("Faucet: auth cannot be used yet because timeout has not elapsed");
312328
faucet.drip(
313-
Faucet.DripParameters(payable(fundsReceiver), nonce1),
329+
Faucet.DripParameters(payable(fundsReceiver), data, nonce1, gasLimit),
314330
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature1)
315331
);
316332
vm.stopPrank();
@@ -319,6 +335,8 @@ contract FaucetTest is Faucet_Initializer {
319335
function test_drip_afterTimeout_succeeds() external {
320336
_enableFaucetAuthModules();
321337
bytes32 nonce0 = faucetHelper.consumeNonce();
338+
bytes memory data = "0x";
339+
uint32 gasLimit = 200000;
322340
bytes memory signature0 = issueProofWithEIP712Domain(
323341
faucetAuthAdminKey,
324342
bytes(githubFamName),
@@ -332,7 +350,7 @@ contract FaucetTest is Faucet_Initializer {
332350

333351
vm.startPrank(faucetContractAdmin);
334352
faucet.drip(
335-
Faucet.DripParameters(payable(fundsReceiver), nonce0),
353+
Faucet.DripParameters(payable(fundsReceiver), data, nonce0, gasLimit),
336354
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature0)
337355
);
338356

@@ -350,7 +368,7 @@ contract FaucetTest is Faucet_Initializer {
350368

351369
vm.warp(startingTimestamp + 1 days + 1 seconds);
352370
faucet.drip(
353-
Faucet.DripParameters(payable(fundsReceiver), nonce1),
371+
Faucet.DripParameters(payable(fundsReceiver), data, nonce1, gasLimit),
354372
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature1)
355373
);
356374
vm.stopPrank();

packages/contracts-bedrock/test/periphery/faucet/authmodules/AdminFaucetAuthModule.t.sol

+15-3
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ contract AdminFaucetAuthModuleTest is Test {
8181
/// @notice Assert that verify returns true for valid proofs signed by admins.
8282
function test_adminProof_verify_succeeds() external {
8383
bytes32 nonce = faucetHelper.consumeNonce();
84+
bytes memory data = "0x";
85+
uint32 gasLimit = 200000;
8486
address fundsReceiver = makeAddr("fundsReceiver");
8587
bytes memory proof = issueProofWithEIP712Domain(
8688
adminKey,
@@ -96,7 +98,9 @@ contract AdminFaucetAuthModuleTest is Test {
9698
vm.prank(nonAdmin);
9799
assertEq(
98100
adminFam.verify(
99-
Faucet.DripParameters(payable(fundsReceiver), nonce), keccak256(abi.encodePacked(fundsReceiver)), proof
101+
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
102+
keccak256(abi.encodePacked(fundsReceiver)),
103+
proof
100104
),
101105
true
102106
);
@@ -105,6 +109,8 @@ contract AdminFaucetAuthModuleTest is Test {
105109
/// @notice Assert that verify returns false for proofs signed by nonadmins.
106110
function test_nonAdminProof_verify_succeeds() external {
107111
bytes32 nonce = faucetHelper.consumeNonce();
112+
bytes memory data = "0x";
113+
uint32 gasLimit = 200000;
108114
address fundsReceiver = makeAddr("fundsReceiver");
109115
bytes memory proof = issueProofWithEIP712Domain(
110116
nonAdminKey,
@@ -120,7 +126,9 @@ contract AdminFaucetAuthModuleTest is Test {
120126
vm.prank(admin);
121127
assertEq(
122128
adminFam.verify(
123-
Faucet.DripParameters(payable(fundsReceiver), nonce), keccak256(abi.encodePacked(fundsReceiver)), proof
129+
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
130+
keccak256(abi.encodePacked(fundsReceiver)),
131+
proof
124132
),
125133
false
126134
);
@@ -130,6 +138,8 @@ contract AdminFaucetAuthModuleTest is Test {
130138
/// than the id in the call to verify.
131139
function test_proofWithWrongId_verify_succeeds() external {
132140
bytes32 nonce = faucetHelper.consumeNonce();
141+
bytes memory data = "0x";
142+
uint32 gasLimit = 200000;
133143
address fundsReceiver = makeAddr("fundsReceiver");
134144
address randomAddress = makeAddr("randomAddress");
135145
bytes memory proof = issueProofWithEIP712Domain(
@@ -146,7 +156,9 @@ contract AdminFaucetAuthModuleTest is Test {
146156
vm.prank(admin);
147157
assertEq(
148158
adminFam.verify(
149-
Faucet.DripParameters(payable(fundsReceiver), nonce), keccak256(abi.encodePacked(randomAddress)), proof
159+
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
160+
keccak256(abi.encodePacked(randomAddress)),
161+
proof
150162
),
151163
false
152164
);

0 commit comments

Comments
 (0)