Commit afcc6e55 authored by tre's avatar tre

add tests

parent 629e9bc0
...@@ -7,19 +7,28 @@ import { AdminFaucetAuthModule } from "../universal/faucet/authmodules/AdminFauc ...@@ -7,19 +7,28 @@ import { AdminFaucetAuthModule } from "../universal/faucet/authmodules/AdminFauc
import { FaucetHelper } from "../testing/helpers/FaucetHelper.sol"; import { FaucetHelper } from "../testing/helpers/FaucetHelper.sol";
contract Faucet_Initializer is Test { contract Faucet_Initializer is Test {
event Drip(
string indexed authModule,
bytes indexed userId,
uint256 amount,
address indexed recipient
);
address internal faucetContractAdmin; address internal faucetContractAdmin;
address internal faucetAuthAdmin; address internal faucetAuthAdmin;
address internal nonAdmin; address internal nonAdmin;
address internal fundsReceiver; address internal fundsReceiver;
uint256 internal faucetAuthAdminKey; uint256 internal faucetAuthAdminKey;
uint256 internal nonAdminKey; uint256 internal nonAdminKey;
uint256 internal startingTimestamp = 1000;
Faucet faucet; Faucet faucet;
AdminFaucetAuthModule adminFam; AdminFaucetAuthModule optimistNftFam;
AdminFaucetAuthModule githubFam;
FaucetHelper faucetHelper; FaucetHelper faucetHelper;
function setUp() public { function setUp() public {
vm.warp(startingTimestamp);
faucetContractAdmin = makeAddr("faucetContractAdmin"); faucetContractAdmin = makeAddr("faucetContractAdmin");
fundsReceiver = makeAddr("fundsReceiver"); fundsReceiver = makeAddr("fundsReceiver");
...@@ -41,15 +50,22 @@ contract Faucet_Initializer is Test { ...@@ -41,15 +50,22 @@ contract Faucet_Initializer is Test {
// Fill faucet with ether. // Fill faucet with ether.
vm.deal(address(faucet), 10 ether); vm.deal(address(faucet), 10 ether);
adminFam = new AdminFaucetAuthModule(faucetAuthAdmin); optimistNftFam = new AdminFaucetAuthModule(faucetAuthAdmin);
adminFam.initialize("AdminFAM"); optimistNftFam.initialize("OptimistNftFam");
githubFam = new AdminFaucetAuthModule(faucetAuthAdmin);
githubFam.initialize("GithubFam");
faucetHelper = new FaucetHelper(); faucetHelper = new FaucetHelper();
} }
function _enableFaucetAuthModule() internal { function _enableFaucetAuthModules() internal {
vm.prank(faucetContractAdmin); vm.prank(faucetContractAdmin);
faucet.configure(adminFam, Faucet.ModuleConfig("OptimistModule", true, 1 days, 1 ether)); faucet.configure(
optimistNftFam,
Faucet.ModuleConfig("OptimistNftModule", true, 1 days, 1 ether)
);
vm.prank(faucetContractAdmin);
faucet.configure(githubFam, Faucet.ModuleConfig("GithubModule", true, 1 days, .05 ether));
} }
/** /**
...@@ -106,15 +122,15 @@ contract FaucetTest is Faucet_Initializer { ...@@ -106,15 +122,15 @@ contract FaucetTest is Faucet_Initializer {
assertEq(faucet.ADMIN(), faucetContractAdmin); assertEq(faucet.ADMIN(), faucetContractAdmin);
} }
function test_AuthAdmin_drip_succeeds() external { function test_authAdmin_drip_succeeds() external {
_enableFaucetAuthModule(); _enableFaucetAuthModules();
bytes32 nonce = faucetHelper.consumeNonce(); bytes32 nonce = faucetHelper.consumeNonce();
bytes memory signature = issueProofWithEIP712Domain( bytes memory signature = issueProofWithEIP712Domain(
faucetAuthAdminKey, faucetAuthAdminKey,
bytes("AdminFAM"), bytes("OptimistNftFam"),
bytes(adminFam.version()), bytes(optimistNftFam.version()),
block.chainid, block.chainid,
address(adminFam), address(optimistNftFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), abi.encodePacked(fundsReceiver),
nonce nonce
...@@ -123,19 +139,19 @@ contract FaucetTest is Faucet_Initializer { ...@@ -123,19 +139,19 @@ contract FaucetTest is Faucet_Initializer {
vm.prank(nonAdmin); vm.prank(nonAdmin);
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce), Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(adminFam, abi.encodePacked(fundsReceiver), signature) Faucet.AuthParameters(optimistNftFam, abi.encodePacked(fundsReceiver), signature)
); );
} }
function test_nonAdmin_drip_fails() external { function test_nonAdmin_drip_fails() external {
_enableFaucetAuthModule(); _enableFaucetAuthModules();
bytes32 nonce = faucetHelper.consumeNonce(); bytes32 nonce = faucetHelper.consumeNonce();
bytes memory signature = issueProofWithEIP712Domain( bytes memory signature = issueProofWithEIP712Domain(
nonAdminKey, nonAdminKey,
bytes("AdminFAM"), bytes("OptimistNftFam"),
bytes(adminFam.version()), bytes(optimistNftFam.version()),
block.chainid, block.chainid,
address(adminFam), address(optimistNftFam),
fundsReceiver, fundsReceiver,
abi.encodePacked(fundsReceiver), abi.encodePacked(fundsReceiver),
nonce nonce
...@@ -145,7 +161,225 @@ contract FaucetTest is Faucet_Initializer { ...@@ -145,7 +161,225 @@ contract FaucetTest is Faucet_Initializer {
vm.expectRevert("Faucet: drip parameters could not be verified by security module"); vm.expectRevert("Faucet: drip parameters could not be verified by security module");
faucet.drip( faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce), Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(adminFam, abi.encodePacked(fundsReceiver), signature) Faucet.AuthParameters(optimistNftFam, abi.encodePacked(fundsReceiver), signature)
);
}
function test_drip_optimistNft_sendsCorrectAmount() external {
_enableFaucetAuthModules();
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory signature = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes("OptimistNftFam"),
bytes(optimistNftFam.version()),
block.chainid,
address(optimistNftFam),
fundsReceiver,
abi.encodePacked(fundsReceiver),
nonce
);
uint256 recipientBalanceBefore = address(fundsReceiver).balance;
vm.prank(nonAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(optimistNftFam, abi.encodePacked(fundsReceiver), signature)
);
uint256 recipientBalanceAfter = address(fundsReceiver).balance;
assertEq(
recipientBalanceAfter - recipientBalanceBefore,
1 ether,
"expect increase of 1 ether"
);
}
function test_drip_github_sendsCorrectAmount() external {
_enableFaucetAuthModules();
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory signature = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes("GithubFam"),
bytes(githubFam.version()),
block.chainid,
address(githubFam),
fundsReceiver,
abi.encodePacked(fundsReceiver),
nonce
);
uint256 recipientBalanceBefore = address(fundsReceiver).balance;
vm.prank(nonAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature)
);
uint256 recipientBalanceAfter = address(fundsReceiver).balance;
assertEq(
recipientBalanceAfter - recipientBalanceBefore,
.05 ether,
"expect increase of .05 ether"
);
}
function test_drip_emitsEvent() external {
_enableFaucetAuthModules();
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory signature = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes("GithubFam"),
bytes(githubFam.version()),
block.chainid,
address(githubFam),
fundsReceiver,
abi.encodePacked(fundsReceiver),
nonce
);
vm.expectEmit(true, true, true, true, address(faucet));
emit Drip("GithubModule", abi.encodePacked(fundsReceiver), .05 ether, fundsReceiver);
vm.prank(nonAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature)
);
}
function test_drip_disabledModule_reverts() external {
_enableFaucetAuthModules();
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory signature = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes("GithubFam"),
bytes(githubFam.version()),
block.chainid,
address(githubFam),
fundsReceiver,
abi.encodePacked(fundsReceiver),
nonce
);
vm.startPrank(faucetContractAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature)
);
faucet.configure(githubFam, Faucet.ModuleConfig("GithubModule", false, 1 days, .05 ether));
vm.expectRevert("Faucet: provided auth module is not supported by this faucet");
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature)
);
vm.stopPrank();
}
function test_drip_preventsReplayAttacks() external {
_enableFaucetAuthModules();
bytes32 nonce = faucetHelper.consumeNonce();
bytes memory signature = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes("GithubFam"),
bytes(githubFam.version()),
block.chainid,
address(githubFam),
fundsReceiver,
abi.encodePacked(fundsReceiver),
nonce
);
vm.startPrank(faucetContractAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature)
);
vm.expectRevert("Faucet: nonce has already been used");
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature)
);
vm.stopPrank();
}
function test_drip_beforeTimeout_reverts() external {
_enableFaucetAuthModules();
bytes32 nonce0 = faucetHelper.consumeNonce();
bytes memory signature0 = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes("GithubFam"),
bytes(githubFam.version()),
block.chainid,
address(githubFam),
fundsReceiver,
abi.encodePacked(fundsReceiver),
nonce0
);
vm.startPrank(faucetContractAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce0),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature0)
);
bytes32 nonce1 = faucetHelper.consumeNonce();
bytes memory signature1 = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes("GithubFam"),
bytes(githubFam.version()),
block.chainid,
address(githubFam),
fundsReceiver,
abi.encodePacked(fundsReceiver),
nonce1
);
vm.expectRevert("Faucet: auth cannot be used yet because timeout has not elapsed");
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce1),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature1)
);
vm.stopPrank();
}
function test_drip_afterTimeout_succeeds() external {
_enableFaucetAuthModules();
bytes32 nonce0 = faucetHelper.consumeNonce();
bytes memory signature0 = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes("GithubFam"),
bytes(githubFam.version()),
block.chainid,
address(githubFam),
fundsReceiver,
abi.encodePacked(fundsReceiver),
nonce0
);
vm.startPrank(faucetContractAdmin);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce0),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature0)
);
bytes32 nonce1 = faucetHelper.consumeNonce();
bytes memory signature1 = issueProofWithEIP712Domain(
faucetAuthAdminKey,
bytes("GithubFam"),
bytes(githubFam.version()),
block.chainid,
address(githubFam),
fundsReceiver,
abi.encodePacked(fundsReceiver),
nonce1
);
vm.warp(startingTimestamp + 1 days + 1 seconds);
faucet.drip(
Faucet.DripParameters(payable(fundsReceiver), nonce1),
Faucet.AuthParameters(githubFam, abi.encodePacked(fundsReceiver), signature1)
); );
vm.stopPrank();
} }
} }
...@@ -21,6 +21,20 @@ contract SafeSend { ...@@ -21,6 +21,20 @@ contract SafeSend {
* @notice Faucet contract that drips ETH to users. * @notice Faucet contract that drips ETH to users.
*/ */
contract Faucet { contract Faucet {
/**
* @notice Emitted on each drip.
* @param authModule The type of authentication that was used for verifying the drip.
* @param userId The id of the user that requested the drip.
* @param amount The amount of funds sent.
* @param recipient The recipient of the drip.
*/
event Drip(
string indexed authModule,
bytes indexed userId,
uint256 amount,
address indexed recipient
);
/** /**
* @notice Parameters for a drip. * @notice Parameters for a drip.
*/ */
...@@ -147,7 +161,12 @@ contract Faucet { ...@@ -147,7 +161,12 @@ contract Faucet {
// Set the next timestamp at which this auth id can be used. // Set the next timestamp at which this auth id can be used.
timeouts[_auth.module][_auth.id] = block.timestamp + config.ttl; timeouts[_auth.module][_auth.id] = block.timestamp + config.ttl;
// Mark the nonce as used.
usedNonces[_auth.id][_params.nonce] = true;
// Execute a safe transfer of ETH to the recipient account. // Execute a safe transfer of ETH to the recipient account.
new SafeSend{ value: config.amount }(_params.recipient); new SafeSend{ value: config.amount }(_params.recipient);
emit Drip(config.name, _auth.id, config.amount, _params.recipient);
} }
} }
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