-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Description
[SC-2] Comprehensive Foundry Test Suite for FishnetWallet
Labels: smart-contract, testing, priority:high, week-3-4
Assignee: Yash
Context
Per the Source of Truth (Section 10, Week 3-4 deliverable), the FishnetWallet needs a comprehensive Foundry test suite covering all permit validation paths, owner functions, and edge cases. The contract is security-critical — it gates real fund execution.
Test File
File: contracts/test/FishnetWallet.t.sol
1. Test Setup
- Deploy
FishnetWalletwith test owner and test signer addresses - Fund wallet with test ETH (e.g.,
vm.deal) - Deploy a mock target contract (simple
receive()+ a state-changing function) - Helper function:
_signPermit(FishnetPermit memory permit, uint256 signerPrivateKey)— generates valid EIP712 signature off-chain usingvm.sign - Helper function:
_buildPermit(...)— constructs permit struct with defaults
2. Happy Path Tests
-
test_executeValidPermit— sign valid permit, callexecute(), verify:- Target contract receives the call with correct calldata
- Target receives correct ETH value
- Nonce is marked as used
ActionExecutedevent emitted with correct args
-
test_executeMultiplePermitsSequentially— execute 3 permits with incrementing nonces, all succeed -
test_executeWithZeroValue— permit withvalue = 0(pure function call, no ETH transfer) -
test_executeComplexCalldata— permit with realistic swap calldata (Uniswap-like selector + params)
3. Permit Validation Failure Tests
Each test verifies the specific revert reason:
-
test_revert_expiredPermit— setpermit.expirytoblock.timestamp - 1, expect revert"permit expired" -
test_revert_usedNonce— execute once with nonce=1, try again with nonce=1, expect revert"nonce already used" -
test_revert_targetMismatch—permit.target = addressA, callexecute(addressB, ...), expect revert"target mismatch" -
test_revert_calldataMismatch—permit.calldataHash = keccak256(dataA), call withdataB, expect revert"calldata mismatch" -
test_revert_walletMismatch—permit.wallet = otherAddress(not this contract), expect revert"wallet mismatch" -
test_revert_invalidSignature— sign with a random key (notfishnetSigner), expect revert"invalid signature" -
test_revert_zeroAddressSigner— signature that recovers toaddress(0), expect revert
4. Pause Tests
-
test_revert_executeWhenPaused— owner pauses wallet, valid permit still reverts with"wallet paused" -
test_executeAfterUnpause— pause, unpause, then execute succeeds -
test_revert_pauseByNonOwner— non-owner callspause(), expect revert"not owner" -
test_pauseEmitsEvent—pause()emitsPausedevent -
test_unpauseEmitsEvent—unpause()emitsUnpausedevent
5. Owner Function Tests
-
test_setSigner— owner callssetSigner(newSigner):- Old signer's permits no longer work
- New signer's permits work
SignerUpdatedevent emitted
-
test_revert_setSignerByNonOwner— non-owner callssetSigner, expect revert -
test_withdraw— owner withdraws ETH, verify balance transferred -
test_revert_withdrawByNonOwner— non-owner callswithdraw, expect revert -
test_receiveETH— send ETH directly to wallet, verify balance increases
6. Edge Case Tests
-
test_revert_executionFailure— target contract reverts (e.g.,revert("nope")), outer call reverts with"execution failed" -
test_executeExactExpiry—permit.expiry == block.timestamp(boundary condition), should succeed -
test_nonceOrdering— nonces don't need to be sequential (nonce=5, then nonce=2, then nonce=99 all work if unused) -
test_reentryProtection— target contract tries to re-enterexecute()during callback, verify behavior (should fail due to nonce already used) -
test_largeNonce—nonce = type(uint256).max, verify it works -
test_chainIdMismatch— permit signed with wrong chainId, signature recovery produces wrong address, expect revert
7. Gas Benchmarks
-
test_gasExecute— measure gas for a standard execute call, log it -
test_gasDeniedPermit— measure gas for a denied (expired) permit, log it - Ensure execute cost is reasonable (target: < 80k gas excluding target call)
Acceptance Criteria
- All tests pass with
forge test -vvv - Every revert path has a dedicated test verifying the exact error message
- No test relies on hardcoded block numbers or timestamps (use
vm.warp,vm.roll) - Happy path tests verify both state changes and events
- Edge cases cover boundary conditions (exact expiry, max nonce, zero value)
- Gas benchmarks documented for core operations
Reactions are currently unavailable