@@ -258,6 +258,102 @@ contract BlockRewardControllerTest is POLTest {
258
258
assertApproxEqAbs (reward, expected, maxDelta);
259
259
}
260
260
261
+ /// @dev Should process rewards with operator receiver set
262
+ function test_ProcessRewardsWithReceiver () public {
263
+ test_SetDistributor ();
264
+ test_SetBaseRate ();
265
+
266
+ address receiver = makeAddr ("receiver " );
267
+ // Set receiver for operator
268
+ vm.prank (operator);
269
+ BeaconDepositMock (beaconDepositContract).setOperatorReceiver (receiver);
270
+
271
+ // Verify receiver is set correctly
272
+ assertEq (BeaconDepositMock (beaconDepositContract).operatorReceivers (operator), receiver);
273
+
274
+ // Process rewards - should mint base rewards to receiver instead of operator
275
+ vm.prank (address (distributor));
276
+ vm.expectEmit (true , true , true , true );
277
+ emit IBlockRewardController.BlockRewardProcessed (valData.pubkey, DISTRIBUTE_FOR_TIMESTAMP, 1 ether, 0 );
278
+
279
+ // expect call to mint BGT to the receiver instead of operator
280
+ vm.expectCall (address (bgt), abi.encodeCall (IBGT.mint, (receiver, 1.0 ether)));
281
+ blockRewardController.processRewards (valData.pubkey, DISTRIBUTE_FOR_TIMESTAMP, true );
282
+ }
283
+
284
+ /// @dev Should process rewards with operator receiver cleared
285
+ function test_ProcessRewardsWithReceiverCleared () public {
286
+ test_SetDistributor ();
287
+ test_SetBaseRate ();
288
+
289
+ address receiver = makeAddr ("receiver " );
290
+ // First set a receiver
291
+ vm.prank (operator);
292
+ BeaconDepositMock (beaconDepositContract).setOperatorReceiver (receiver);
293
+
294
+ // Then clear it by setting to address(0)
295
+ vm.prank (operator);
296
+ BeaconDepositMock (beaconDepositContract).setOperatorReceiver (address (0 ));
297
+
298
+ // Verify receiver is cleared
299
+ assertEq (BeaconDepositMock (beaconDepositContract).operatorReceivers (operator), address (0 ));
300
+
301
+ // Process rewards - should mint base rewards to operator since receiver is cleared
302
+ vm.prank (address (distributor));
303
+ vm.expectEmit (true , true , true , true );
304
+ emit IBlockRewardController.BlockRewardProcessed (valData.pubkey, DISTRIBUTE_FOR_TIMESTAMP, 1 ether, 0 );
305
+
306
+ // expect call to mint BGT to the operator since receiver is cleared
307
+ vm.expectCall (address (bgt), abi.encodeCall (IBGT.mint, (operator, 1.0 ether)));
308
+ blockRewardController.processRewards (valData.pubkey, DISTRIBUTE_FOR_TIMESTAMP, true );
309
+ }
310
+
311
+ /// @dev Should process rewards with no receiver set (default case)
312
+ function test_ProcessRewardsWithNoReceiver () public {
313
+ test_SetDistributor ();
314
+ test_SetBaseRate ();
315
+
316
+ // Verify no receiver is set
317
+ assertEq (BeaconDepositMock (beaconDepositContract).operatorReceivers (operator), address (0 ));
318
+
319
+ // Process rewards - should mint base rewards to operator since no receiver set
320
+ vm.prank (address (distributor));
321
+ vm.expectEmit (true , true , true , true );
322
+ emit IBlockRewardController.BlockRewardProcessed (valData.pubkey, DISTRIBUTE_FOR_TIMESTAMP, 1 ether, 0 );
323
+
324
+ // expect call to mint BGT to the operator since no receiver set
325
+ vm.expectCall (address (bgt), abi.encodeCall (IBGT.mint, (operator, 1.0 ether)));
326
+ blockRewardController.processRewards (valData.pubkey, DISTRIBUTE_FOR_TIMESTAMP, true );
327
+ }
328
+
329
+ /// @dev Should process rewards correctly when multiple operators have different receiver settings
330
+ function test_ProcessRewardsMultipleOperators () public {
331
+ test_SetDistributor ();
332
+ test_SetBaseRate ();
333
+
334
+ // Setup second operator and validator
335
+ address operator2 = makeAddr ("operator2 " );
336
+ bytes memory pubkey2 = bytes ("validator2 " );
337
+ BeaconDepositMock (beaconDepositContract).setOperator (pubkey2, operator2);
338
+
339
+ // Setup receivers
340
+ address receiver1 = makeAddr ("receiver1 " );
341
+ vm.prank (operator);
342
+ BeaconDepositMock (beaconDepositContract).setOperatorReceiver (receiver1);
343
+
344
+ // Don't set receiver for operator2
345
+
346
+ // Process rewards for first operator - should go to receiver1
347
+ vm.prank (address (distributor));
348
+ vm.expectCall (address (bgt), abi.encodeCall (IBGT.mint, (receiver1, 1.0 ether)));
349
+ blockRewardController.processRewards (valData.pubkey, DISTRIBUTE_FOR_TIMESTAMP, true );
350
+
351
+ // Process rewards for second operator - should go to operator2
352
+ vm.prank (address (distributor));
353
+ vm.expectCall (address (bgt), abi.encodeCall (IBGT.mint, (operator2, 1.0 ether)));
354
+ blockRewardController.processRewards (pubkey2, DISTRIBUTE_FOR_TIMESTAMP, true );
355
+ }
356
+
261
357
/// @dev Should bound compute rewards correctly to its theoretical limits
262
358
function testFuzz_ComputeRewards (
263
359
uint256 boostPower ,
0 commit comments