@@ -104,22 +104,33 @@ contract FirmRelayerTest is FirmTest {
104104 relayer.relay (request, _signPacked (hash, USER_PK));
105105 }
106106
107- function testRevertOnTargetBadSender () public {
107+ function testExecutionCallRevertsAllCalls () public {
108108 (address otherUser , uint256 otherUserPk ) = accountAndKey ("other user " );
109109
110- FirmRelayer.Call memory call = _defaultCallWithData (address (target), abi.encodeCall (target.onlySender, (USER)));
111- FirmRelayer.RelayRequest memory request = _defaultRequestWithCall (call);
110+ FirmRelayer.Call memory call1 = _defaultCallWithData (address (target), abi.encodeCall (target.onlySender, (otherUser)));
111+ FirmRelayer.Call memory call2 = _defaultCallWithData (address (target), abi.encodeCall (target.onlySender, (USER)));
112+
113+ FirmRelayer.RelayRequest memory request = _defaultRequestWithCall (call1);
114+ request.calls = new FirmRelayer.Call [](2 );
115+ request.calls[0 ] = call1;
116+ request.calls[1 ] = call2;
112117 request.from = otherUser;
113118 bytes32 hash = relayer.requestTypedDataHash (request);
114119
115120 bytes memory targetError = abi.encodeWithSelector (RelayTarget.BadSender.selector , USER, otherUser);
116- vm.expectRevert (
117- abi.encodeWithSelector (FirmRelayer.CallExecutionFailed.selector , 0 , address (target), targetError)
121+ assertFailureEvent (
122+ otherUser,
123+ abi.encodeWithSelector (FirmRelayer.CallExecutionFailed.selector , 1 , address (target), targetError)
118124 );
119125 relayer.relay (request, _signPacked (hash, otherUserPk));
126+
127+ // Nonce should have been incremented
128+ assertEq (relayer.getNonce (otherUser), 1 );
129+ // Successful call on target should have been reverted
130+ assertEq (target.lastSender (), address (0 ));
120131 }
121132
122- function testRevertOnAssertionFailure () public {
133+ function testExecutionRevertOnAssertionFailure () public {
123134 bytes32 actualReturnValue = bytes32 (abi.encode (USER));
124135 bytes32 badExpectedValue = bytes32 (uint256 (0 ));
125136
@@ -128,31 +139,60 @@ contract FirmRelayerTest is FirmTest {
128139 FirmRelayer.RelayRequest memory request = _defaultRequestWithCallAndAssertion (call, assertion);
129140
130141 bytes32 hash = relayer.requestTypedDataHash (request);
131- vm.expectRevert (
132- abi.encodeWithSelector (FirmRelayer.AssertionFailed.selector , 0 , actualReturnValue, badExpectedValue)
133- );
142+
143+ assertFailureEvent (USER, abi.encodeWithSelector (FirmRelayer.UnexpectedReturnValue.selector , 0 , actualReturnValue, badExpectedValue));
134144 relayer.relay (request, _signPacked (hash, USER_PK));
145+
146+ // Nonce should have been incremented
147+ assertEq (relayer.getNonce (USER), 1 );
135148 }
136149
137- function testRevertOnAssertionOutOfBounds () public {
150+ function testExecutionRevertOnAssertionOutOfBounds () public {
138151 FirmRelayer.Call memory call = _defaultCallWithData (address (target), abi.encodeCall (target.onlySender, (USER)));
139152 FirmRelayer.Assertion memory assertion = FirmRelayer.Assertion (1 , bytes32 (abi.encode (USER)));
140153 FirmRelayer.RelayRequest memory request = _defaultRequestWithCallAndAssertion (call, assertion);
141154
142155 bytes32 hash = relayer.requestTypedDataHash (request);
143- vm. expectRevert ( abi.encodeWithSelector (FirmRelayer.AssertionPositionOutOfBounds.selector , 0 , 32 ));
156+ assertFailureEvent (USER, abi.encodeWithSelector (FirmRelayer.AssertionPositionOutOfBounds.selector , 0 , 32 ));
144157 relayer.relay (request, _signPacked (hash, USER_PK));
158+
159+ // Nonce should have been incremented
160+ assertEq (relayer.getNonce (USER), 1 );
145161 }
146162
147- function testRevertOnBadAssertionIndex () public {
163+ function testExecutionRevertOnBadAssertionIndex () public {
148164 FirmRelayer.Call memory call = _defaultCallWithData (address (target), abi.encodeCall (target.onlySender, (USER)));
149165 FirmRelayer.Assertion memory assertion = FirmRelayer.Assertion (0 , bytes32 (abi.encode (USER)));
150166 FirmRelayer.RelayRequest memory request = _defaultRequestWithCallAndAssertion (call, assertion);
151167 request.calls[0 ].assertionIndex = 2 ;
152168
153169 bytes32 hash = relayer.requestTypedDataHash (request);
154- vm. expectRevert ( abi.encodeWithSelector (FirmRelayer.BadAssertionIndex.selector , 0 ));
170+ assertFailureEvent (USER, abi.encodeWithSelector (FirmRelayer.BadAssertionIndex.selector , 0 ));
155171 relayer.relay (request, _signPacked (hash, USER_PK));
172+
173+ // Nonce should have been incremented
174+ assertEq (relayer.getNonce (USER), 1 );
175+ }
176+
177+ function testRevertOnInsufficientGas () public {
178+ FirmRelayer.Call memory call = _defaultCallWithData (address (target), abi.encodeCall (target.onlySender, (USER)));
179+ FirmRelayer.RelayRequest memory request = _defaultRequestWithCall (call);
180+ bytes memory sig = _signPacked (relayer.requestTypedDataHash (request), USER_PK);
181+
182+ vm.expectRevert (abi.encodeWithSelector (FirmRelayer.InsufficientGas.selector ));
183+ relayer.relay { gas: call.gas - 100 }(request, sig);
184+
185+ // Nonce not incremented, can relay the same request again
186+ assertEq (relayer.getNonce (USER), 0 );
187+
188+ // Relay should succeed with enough gas (account for buffer)
189+ relayer.relay { gas: call.gas + 40000 }(request, sig);
190+ assertEq (target.lastSender (), USER);
191+ }
192+
193+ function testRevertOnExternalSelfExecute () public {
194+ vm.expectRevert (abi.encodeWithSelector (FirmRelayer.BadExecutionContext.selector ));
195+ relayer.__externalSelfCall_execute (address (this ), new FirmRelayer.Call [](0 ), new FirmRelayer.Assertion [](0 ));
156196 }
157197
158198 function testSelfRelay () public {
@@ -181,7 +221,7 @@ contract FirmRelayerTest is FirmTest {
181221 call.to = to;
182222 call.data = data;
183223 call.value = 0 ;
184- call.gas = 10_000_000 ; // random big value for testing
224+ call.gas = 200_000 ; // random big value for testing
185225 call.assertionIndex = 0 ;
186226 }
187227
@@ -207,6 +247,17 @@ contract FirmRelayerTest is FirmTest {
207247 request.calls[0 ].assertionIndex = 1 ;
208248 }
209249
250+ event RelayExecutionFailed (address indexed relayer , address indexed signer , uint256 nonce , bytes revertData );
251+ function assertFailureEvent (address sender , bytes memory revertData ) internal {
252+ vm.expectEmit (true , true , true , true , address (relayer));
253+ emit RelayExecutionFailed (
254+ address (this ),
255+ sender,
256+ 0 ,
257+ revertData
258+ );
259+ }
260+
210261 // For this test we need to fix both the address of FirmRelayer and chainId so that the hash
211262 // matches a hash generated off-chain with those parameters
212263 // Gen script: https://gist.github.com/izqui/f0379eb81c5e46f79696f88736ce1ffa
0 commit comments