Commit eb454ac7 authored by Tarun Khasnavis's avatar Tarun Khasnavis Committed by GitHub

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: default avatarTarun Khasnavis <tarunkhasnavis@Taruns-MacBook-Pro.local>
Co-authored-by: default avatartre <tremarkley@gmail.com>
parent 1c22d5f2
---
'@eth-optimism/contracts-bedrock': patch
---
Add data field to faucet contract drip parameters
......@@ -55,10 +55,20 @@
"name": "recipient",
"type": "address"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
},
{
"internalType": "bytes32",
"name": "nonce",
"type": "bytes32"
},
{
"internalType": "uint32",
"name": "gasLimit",
"type": "uint32"
}
],
"internalType": "struct Faucet.DripParameters",
......
......@@ -76,10 +76,20 @@
"name": "recipient",
"type": "address"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
},
{
"internalType": "bytes32",
"name": "nonce",
"type": "bytes32"
},
{
"internalType": "uint32",
"name": "gasLimit",
"type": "uint32"
}
],
"internalType": "struct Faucet.DripParameters",
......
......@@ -2,6 +2,7 @@
pragma solidity 0.8.15;
import { IFaucetAuthModule } from "./authmodules/IFaucetAuthModule.sol";
import { SafeCall } from "../../libraries/SafeCall.sol";
/// @title SafeSend
/// @notice Sends ETH to a recipient account without triggering any code.
......@@ -25,7 +26,9 @@ contract Faucet {
/// @notice Parameters for a drip.
struct DripParameters {
address payable recipient;
bytes data;
bytes32 nonce;
uint32 gasLimit;
}
/// @notice Parameters for authentication.
......@@ -113,14 +116,17 @@ contract Faucet {
"Faucet: drip parameters could not be verified by security module"
);
// Verify recepient is not the faucet address.
require(_params.recipient != address(this), "Faucet: cannot drip to itself");
// Set the next timestamp at which this auth id can be used.
timeouts[_auth.module][_auth.id] = block.timestamp + config.ttl;
// Mark the nonce as used.
nonces[_auth.id][_params.nonce] = true;
// Execute a safe transfer of ETH to the recipient account.
new SafeSend{ value: config.amount }(_params.recipient);
// Execute transfer of ETH to the recipient account.
SafeCall.call(_params.recipient, _params.gasLimit, config.amount, _params.data);
emit Drip(config.name, _auth.id, config.amount, _params.recipient);
}
......
......@@ -106,6 +106,8 @@ contract FaucetTest is Faucet_Initializer {
function test_authAdmin_drip_succeeds() external {
_enableFaucetAuthModules();
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory data = "0x";
uint32 gasLimit = 200000;
bytes memory signature = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes(optimistNftFamName),
......@@ -119,7 +121,7 @@ contract FaucetTest is Faucet_Initializer {
vm.prank(nonAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
Faucet.AuthParameters(optimistNftFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
);
}
......@@ -127,6 +129,8 @@ contract FaucetTest is Faucet_Initializer {
function test_nonAdmin_drip_fails() external {
_enableFaucetAuthModules();
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory data = "0x";
uint32 gasLimit = 200000;
bytes memory signature = issueProofWithEIP712Domain(
nonAdminKey,
bytes(optimistNftFamName),
......@@ -141,7 +145,7 @@ contract FaucetTest is Faucet_Initializer {
vm.prank(nonAdmin);
vm.expectRevert("Faucet: drip parameters could not be verified by security module");
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
Faucet.AuthParameters(optimistNftFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
);
}
......@@ -149,6 +153,8 @@ contract FaucetTest is Faucet_Initializer {
function test_drip_optimistNftSendsCorrectAmount_succeeds() external {
_enableFaucetAuthModules();
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory data = "0x";
uint32 gasLimit = 200000;
bytes memory signature = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes(optimistNftFamName),
......@@ -163,7 +169,7 @@ contract FaucetTest is Faucet_Initializer {
uint256 recipientBalanceBefore = address(fundsReceiver).balance;
vm.prank(nonAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
Faucet.AuthParameters(optimistNftFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
);
uint256 recipientBalanceAfter = address(fundsReceiver).balance;
......@@ -173,6 +179,8 @@ contract FaucetTest is Faucet_Initializer {
function test_drip_githubSendsCorrectAmount_succeeds() external {
_enableFaucetAuthModules();
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory data = "0x";
uint32 gasLimit = 200000;
bytes memory signature = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes(githubFamName),
......@@ -187,7 +195,7 @@ contract FaucetTest is Faucet_Initializer {
uint256 recipientBalanceBefore = address(fundsReceiver).balance;
vm.prank(nonAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
);
uint256 recipientBalanceAfter = address(fundsReceiver).balance;
......@@ -197,6 +205,8 @@ contract FaucetTest is Faucet_Initializer {
function test_drip_emitsEvent_succeeds() external {
_enableFaucetAuthModules();
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory data = "0x";
uint32 gasLimit = 200000;
bytes memory signature = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes(githubFamName),
......@@ -213,7 +223,7 @@ contract FaucetTest is Faucet_Initializer {
vm.prank(nonAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
);
}
......@@ -221,6 +231,8 @@ contract FaucetTest is Faucet_Initializer {
function test_drip_disabledModule_reverts() external {
_enableFaucetAuthModules();
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory data = "0x";
uint32 gasLimit = 200000;
bytes memory signature = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes(githubFamName),
......@@ -234,7 +246,7 @@ contract FaucetTest is Faucet_Initializer {
vm.startPrank(faucetContractAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
);
......@@ -242,7 +254,7 @@ contract FaucetTest is Faucet_Initializer {
vm.expectRevert("Faucet: provided auth module is not supported by this faucet");
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
);
vm.stopPrank();
......@@ -251,6 +263,8 @@ contract FaucetTest is Faucet_Initializer {
function test_drip_preventsReplayAttacks_succeeds() external {
_enableFaucetAuthModules();
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory data = "0x";
uint32 gasLimit = 200000;
bytes memory signature = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes(githubFamName),
......@@ -264,13 +278,13 @@ contract FaucetTest is Faucet_Initializer {
vm.startPrank(faucetContractAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
);
vm.expectRevert("Faucet: nonce has already been used");
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature)
);
vm.stopPrank();
......@@ -279,6 +293,8 @@ contract FaucetTest is Faucet_Initializer {
function test_drip_beforeTimeout_reverts() external {
_enableFaucetAuthModules();
bytes32 nonce0 = faucetHelper.consumeNonce();
bytes memory data = "0x";
uint32 gasLimit = 200000;
bytes memory signature0 = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes(githubFamName),
......@@ -292,7 +308,7 @@ contract FaucetTest is Faucet_Initializer {
vm.startPrank(faucetContractAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce0),
Faucet.DripParameters(payable(fundsReceiver), data, nonce0, gasLimit),
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature0)
);
......@@ -310,7 +326,7 @@ contract FaucetTest is Faucet_Initializer {
vm.expectRevert("Faucet: auth cannot be used yet because timeout has not elapsed");
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce1),
Faucet.DripParameters(payable(fundsReceiver), data, nonce1, gasLimit),
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature1)
);
vm.stopPrank();
......@@ -319,6 +335,8 @@ contract FaucetTest is Faucet_Initializer {
function test_drip_afterTimeout_succeeds() external {
_enableFaucetAuthModules();
bytes32 nonce0 = faucetHelper.consumeNonce();
bytes memory data = "0x";
uint32 gasLimit = 200000;
bytes memory signature0 = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes(githubFamName),
......@@ -332,7 +350,7 @@ contract FaucetTest is Faucet_Initializer {
vm.startPrank(faucetContractAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce0),
Faucet.DripParameters(payable(fundsReceiver), data, nonce0, gasLimit),
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature0)
);
......@@ -350,7 +368,7 @@ contract FaucetTest is Faucet_Initializer {
vm.warp(startingTimestamp + 1 days + 1 seconds);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce1),
Faucet.DripParameters(payable(fundsReceiver), data, nonce1, gasLimit),
Faucet.AuthParameters(githubFam, keccak256(abi.encodePacked(fundsReceiver)), signature1)
);
vm.stopPrank();
......
......@@ -81,6 +81,8 @@ contract AdminFaucetAuthModuleTest is Test {
/// @notice Assert that verify returns true for valid proofs signed by admins.
function test_adminProof_verify_succeeds() external {
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory data = "0x";
uint32 gasLimit = 200000;
address fundsReceiver = makeAddr("fundsReceiver");
bytes memory proof = issueProofWithEIP712Domain(
adminKey,
......@@ -96,7 +98,9 @@ contract AdminFaucetAuthModuleTest is Test {
vm.prank(nonAdmin);
assertEq(
adminFam.verify(
Faucet.DripParameters(payable(fundsReceiver), nonce), keccak256(abi.encodePacked(fundsReceiver)), proof
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
keccak256(abi.encodePacked(fundsReceiver)),
proof
),
true
);
......@@ -105,6 +109,8 @@ contract AdminFaucetAuthModuleTest is Test {
/// @notice Assert that verify returns false for proofs signed by nonadmins.
function test_nonAdminProof_verify_succeeds() external {
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory data = "0x";
uint32 gasLimit = 200000;
address fundsReceiver = makeAddr("fundsReceiver");
bytes memory proof = issueProofWithEIP712Domain(
nonAdminKey,
......@@ -120,7 +126,9 @@ contract AdminFaucetAuthModuleTest is Test {
vm.prank(admin);
assertEq(
adminFam.verify(
Faucet.DripParameters(payable(fundsReceiver), nonce), keccak256(abi.encodePacked(fundsReceiver)), proof
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
keccak256(abi.encodePacked(fundsReceiver)),
proof
),
false
);
......@@ -130,6 +138,8 @@ contract AdminFaucetAuthModuleTest is Test {
/// than the id in the call to verify.
function test_proofWithWrongId_verify_succeeds() external {
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory data = "0x";
uint32 gasLimit = 200000;
address fundsReceiver = makeAddr("fundsReceiver");
address randomAddress = makeAddr("randomAddress");
bytes memory proof = issueProofWithEIP712Domain(
......@@ -146,7 +156,9 @@ contract AdminFaucetAuthModuleTest is Test {
vm.prank(admin);
assertEq(
adminFam.verify(
Faucet.DripParameters(payable(fundsReceiver), nonce), keccak256(abi.encodePacked(randomAddress)), proof
Faucet.DripParameters(payable(fundsReceiver), data, nonce, gasLimit),
keccak256(abi.encodePacked(randomAddress)),
proof
),
false
);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment