Skip to content

Commit efaf7f8

Browse files
committed
refactor: move operator receiver functionality from BeaconDeposit to BlockRewardController
1 parent f80b363 commit efaf7f8

File tree

8 files changed

+49
-142
lines changed

8 files changed

+49
-142
lines changed

src/pol/BeaconDeposit.sol

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,6 @@ contract BeaconDeposit is IBeaconDeposit, ERC165 {
6262
/// @dev The mapping of public keys to operator change requests.
6363
mapping(bytes => QueuedOperator) public queuedOperator;
6464

65-
/// @dev The mapping of operators to their receiver addresses.
66-
mapping(address => address) public operatorReceivers;
67-
6865
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
6966
/* VIEWS */
7067
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
@@ -184,21 +181,6 @@ contract BeaconDeposit is IBeaconDeposit, ERC165 {
184181
emit OperatorUpdated(pubkey, newOperator, oldOperator);
185182
}
186183

187-
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
188-
/* OPERATOR RECEIVERS */
189-
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
190-
191-
/**
192-
* @notice Sets or updates the receiver address for an operator's base bgt rewards
193-
* @dev Only the operator can set their receiver
194-
* @param receiver The address that will receive base bgt rewards. Set to address(0) to receive rewards directly to operator
195-
*/
196-
function setOperatorReceiver(address receiver) external {
197-
address oldReceiver = operatorReceivers[msg.sender];
198-
operatorReceivers[msg.sender] = receiver;
199-
emit OperatorReceiverUpdated(msg.sender, oldReceiver, receiver);
200-
}
201-
202184
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
203185
/* INTERNAL */
204186
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
@@ -234,4 +216,4 @@ contract BeaconDeposit is IBeaconDeposit, ERC165 {
234216
}
235217
}
236218
}
237-
}
219+
}

src/pol/interfaces/IBeaconDeposit.sol

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,6 @@ interface IBeaconDeposit is IPOLErrors {
4545
*/
4646
event OperatorUpdated(bytes indexed pubkey, address newOperator, address previousOperator);
4747

48-
/// @notice Emitted when an operator sets or changes their receiver address
49-
/// @param operator The operator address that changed their receiver
50-
/// @param oldReceiver The previous receiver address (zero if first time setting)
51-
/// @param newReceiver The new receiver address (zero if clearing receiver)
52-
event OperatorReceiverUpdated(address indexed operator, address indexed oldReceiver, address indexed newReceiver);
53-
54-
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
55-
/* STORAGE */
56-
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
57-
58-
/**
59-
* @notice Mapping of operators to their receiver addresses for base rewards
60-
* @dev Returns address(0) if no receiver is set
61-
*/
62-
function operatorReceivers(address) external view returns (address);
63-
6448
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
6549
/* VIEWS */
6650
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
@@ -118,11 +102,4 @@ interface IBeaconDeposit is IPOLErrors {
118102
* @param pubkey The pubkey of the validator.
119103
*/
120104
function acceptOperatorChange(bytes calldata pubkey) external;
121-
122-
/**
123-
* @notice Sets or updates the receiver address for an operator's base rewards
124-
* @dev Only the operator can set their receiver
125-
* @param receiver The address that will receive base rewards. Set to address(0) to receive rewards directly
126-
*/
127-
function setOperatorReceiver(address receiver) external;
128-
}
105+
}

src/pol/interfaces/IBlockRewardController.sol

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ interface IBlockRewardController is IPOLErrors {
5959
/// @param amount The amount of base BGT minted
6060
event BaseMinted(address indexed operator, address indexed receiver, uint256 indexed amount);
6161

62+
/// @notice Emitted when an operator sets or changes their receiver address
63+
/// @param operator The operator address that changed their receiver
64+
/// @param oldReceiver The previous receiver address (zero if first time setting)
65+
/// @param newReceiver The new receiver address (zero if clearing receiver)
66+
event OperatorReceiverUpdated(address indexed operator, address indexed oldReceiver, address indexed newReceiver);
67+
6268
/// @notice Returns the constant base rate for BGT.
6369
/// @return The constant base amount of BGT to be minted in the current block.
6470
function baseRate() external view returns (uint256);
@@ -158,4 +164,11 @@ interface IBlockRewardController is IPOLErrors {
158164
* @param _distributor The new distributor contract.
159165
*/
160166
function setDistributor(address _distributor) external;
167+
168+
/**
169+
* @notice Sets or updates the receiver address for an operator's base BGT rewards
170+
* @dev Only the operator can set their receiver
171+
* @param receiver The address that will receive base BGT rewards. Set to address(0) to receive rewards directly
172+
*/
173+
function setOperatorReceiver(address receiver) external;
161174
}

src/pol/rewards/BlockRewardController.sol

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ contract BlockRewardController is IBlockRewardController, OwnableUpgradeable, UU
6363
/// @notice The reward convexity param in the function, determines how fast it converges to its max, 18 dec.
6464
int256 public rewardConvexity;
6565

66+
/// @notice The mapping of operators to their receiver addresses for base rewards
67+
mapping(address => address) public operatorReceivers;
68+
6669
/// @custom:oz-upgrades-unsafe-allow constructor
6770
constructor() {
6871
_disableInitializers();
@@ -237,7 +240,7 @@ contract BlockRewardController is IBlockRewardController, OwnableUpgradeable, UU
237240
address operator = beaconDepositContract.getOperator(pubkey);
238241

239242
// Check if the operator has set a receiver for their base rewards
240-
address receiver = beaconDepositContract.operatorReceivers(operator);
243+
address receiver = operatorReceivers[operator];
241244
// If no receiver is set (address(0)), mint to operator directly
242245
if (base > 0) {
243246
address mintTo = receiver == address(0) ? operator : receiver;
@@ -250,4 +253,19 @@ contract BlockRewardController is IBlockRewardController, OwnableUpgradeable, UU
250253

251254
return reward;
252255
}
256+
257+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
258+
/* OPERATOR RECEIVERS */
259+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
260+
261+
/**
262+
* @notice Sets or updates the receiver address for an operator's base BGT rewards
263+
* @dev Only the operator can set their receiver
264+
* @param receiver The address that will receive base BGT rewards. Set to address(0) to receive rewards directly
265+
*/
266+
function setOperatorReceiver(address receiver) external {
267+
address oldReceiver = operatorReceivers[msg.sender];
268+
operatorReceivers[msg.sender] = receiver;
269+
emit OperatorReceiverUpdated(msg.sender, oldReceiver, receiver);
270+
}
253271
}

test/mock/pol/BeaconDepositMock.sol

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ pragma solidity 0.8.26;
33

44
contract BeaconDepositMock {
55
mapping(bytes => address) public pubkeyToOperator;
6-
mapping(address => address) public operatorReceivers;
76

87
function setOperator(bytes memory pubkey, address operator) public {
98
pubkeyToOperator[pubkey] = operator;
@@ -12,8 +11,4 @@ contract BeaconDepositMock {
1211
function getOperator(bytes memory pubkey) public view returns (address) {
1312
return pubkeyToOperator[pubkey];
1413
}
15-
16-
function setOperatorReceiver(address receiver) external {
17-
operatorReceivers[msg.sender] = receiver;
18-
}
19-
}
14+
}

test/mock/pol/NoopBlockRewardController.sol

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,7 @@ contract NoopBlockRewardController is IBlockRewardController {
6262

6363
/// @inheritdoc IBlockRewardController
6464
function setDistributor(address _distributor) external { }
65+
66+
/// @inheritdoc IBlockRewardController
67+
function setOperatorReceiver(address _receiver) external { }
6568
}

test/pol/BeaconDeposit.t.sol

Lines changed: 1 addition & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -224,87 +224,6 @@ contract BeaconDepositTest is Test {
224224
depositContract.acceptOperatorChange(VALIDATOR_PUBKEY);
225225
}
226226

227-
function test_SetOperatorReceiver() public {
228-
test_Deposit();
229-
address receiver = makeAddr("receiver");
230-
231-
vm.prank(operator);
232-
vm.expectEmit(true, true, true, true);
233-
emit IBeaconDeposit.OperatorReceiverUpdated(operator, address(0), receiver);
234-
depositContract.setOperatorReceiver(receiver);
235-
236-
// Verify receiver is set correctly
237-
assertEq(depositContract.operatorReceivers(operator), receiver);
238-
}
239-
240-
function test_SetOperatorReceiver_Update() public {
241-
test_Deposit();
242-
address receiver1 = makeAddr("receiver1");
243-
address receiver2 = makeAddr("receiver2");
244-
245-
// Set initial receiver
246-
vm.prank(operator);
247-
depositContract.setOperatorReceiver(receiver1);
248-
249-
// Update to new receiver
250-
vm.prank(operator);
251-
vm.expectEmit(true, true, true, true);
252-
emit IBeaconDeposit.OperatorReceiverUpdated(operator, receiver1, receiver2);
253-
depositContract.setOperatorReceiver(receiver2);
254-
255-
assertEq(depositContract.operatorReceivers(operator), receiver2);
256-
}
257-
258-
function test_SetOperatorReceiver_Clear() public {
259-
test_Deposit();
260-
address receiver = makeAddr("receiver");
261-
262-
// Set receiver
263-
vm.prank(operator);
264-
depositContract.setOperatorReceiver(receiver);
265-
266-
// Verify receiver is set correctly
267-
assertEq(depositContract.operatorReceivers(operator), receiver);
268-
269-
// Clear receiver by setting to address(0)
270-
vm.prank(operator);
271-
vm.expectEmit(true, true, true, true);
272-
emit IBeaconDeposit.OperatorReceiverUpdated(operator, receiver, address(0));
273-
depositContract.setOperatorReceiver(address(0));
274-
275-
// Verify receiver is cleared
276-
assertEq(depositContract.operatorReceivers(operator), address(0));
277-
}
278-
279-
function test_GetOperatorReceiver_NonExistent() public {
280-
address nonExistentOperator = makeAddr("nonExistentOperator");
281-
282-
// Should return address(0) for non-existent operator
283-
assertEq(depositContract.operatorReceivers(nonExistentOperator), address(0));
284-
}
285-
286-
function test_SetOperatorReceiver_MultipleOperators() public {
287-
test_Deposit();
288-
289-
// Setup second operator and validator using a different pubkey
290-
bytes memory pubkey2 = abi.encodePacked(bytes32("33"), bytes16("17")); // Different value from _create48Byte()
291-
address operator2 = makeAddr("operator2");
292-
vm.deal(operator2, 10_000 ether);
293-
294-
vm.prank(operator2);
295-
depositContract.deposit{ value: 10_000 ether }(pubkey2, _credential(operator2), _create96Byte(), operator2);
296-
297-
// Set different receivers for first operator but not second operator
298-
address receiver1 = makeAddr("receiver1");
299-
300-
vm.prank(operator);
301-
depositContract.setOperatorReceiver(receiver1);
302-
303-
// Verify receivers are set correctly
304-
assertEq(depositContract.operatorReceivers(operator), receiver1);
305-
assertEq(depositContract.operatorReceivers(operator2), address(0));
306-
}
307-
308227
function testFuzz_AcceptOperatorChange_FailsIfNotEnoughTime(uint256 timeElapsed) public {
309228
timeElapsed = _bound(timeElapsed, 0, 1 days - 1);
310229
testFuzz_RequestOperatorChange(newOperator);
@@ -343,4 +262,4 @@ contract BeaconDepositTest is Test {
343262
function _create48Byte() internal pure returns (bytes memory) {
344263
return abi.encodePacked(bytes32("32"), bytes16("16"));
345264
}
346-
}
265+
}

test/pol/BlockRewardController.t.sol

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,10 @@ contract BlockRewardControllerTest is POLTest {
266266
address receiver = makeAddr("receiver");
267267
// Set receiver for operator
268268
vm.prank(operator);
269-
BeaconDepositMock(beaconDepositContract).setOperatorReceiver(receiver);
269+
blockRewardController.setOperatorReceiver(receiver);
270270

271271
// Verify receiver is set correctly
272-
assertEq(BeaconDepositMock(beaconDepositContract).operatorReceivers(operator), receiver);
272+
assertEq(blockRewardController.operatorReceivers(operator), receiver);
273273

274274
// Process rewards - should mint base rewards to receiver instead of operator
275275
vm.prank(address(distributor));
@@ -289,14 +289,14 @@ contract BlockRewardControllerTest is POLTest {
289289
address receiver = makeAddr("receiver");
290290
// First set a receiver
291291
vm.prank(operator);
292-
BeaconDepositMock(beaconDepositContract).setOperatorReceiver(receiver);
292+
blockRewardController.setOperatorReceiver(receiver);
293293

294294
// Then clear it by setting to address(0)
295295
vm.prank(operator);
296-
BeaconDepositMock(beaconDepositContract).setOperatorReceiver(address(0));
296+
blockRewardController.setOperatorReceiver(address(0));
297297

298298
// Verify receiver is cleared
299-
assertEq(BeaconDepositMock(beaconDepositContract).operatorReceivers(operator), address(0));
299+
assertEq(blockRewardController.operatorReceivers(operator), address(0));
300300

301301
// Process rewards - should mint base rewards to operator since receiver is cleared
302302
vm.prank(address(distributor));
@@ -314,7 +314,7 @@ contract BlockRewardControllerTest is POLTest {
314314
test_SetBaseRate();
315315

316316
// Verify no receiver is set
317-
assertEq(BeaconDepositMock(beaconDepositContract).operatorReceivers(operator), address(0));
317+
assertEq(blockRewardController.operatorReceivers(operator), address(0));
318318

319319
// Process rewards - should mint base rewards to operator since no receiver set
320320
vm.prank(address(distributor));
@@ -331,15 +331,15 @@ contract BlockRewardControllerTest is POLTest {
331331
test_SetDistributor();
332332
test_SetBaseRate();
333333

334-
// Setup second operator and validator
334+
// Setup second operator with mock BeaconDeposit
335335
address operator2 = makeAddr("operator2");
336336
bytes memory pubkey2 = bytes("validator2");
337337
BeaconDepositMock(beaconDepositContract).setOperator(pubkey2, operator2);
338338

339-
// Setup receivers
339+
// Setup receivers in BlockRewardController
340340
address receiver1 = makeAddr("receiver1");
341341
vm.prank(operator);
342-
BeaconDepositMock(beaconDepositContract).setOperatorReceiver(receiver1);
342+
blockRewardController.setOperatorReceiver(receiver1);
343343

344344
// Don't set receiver for operator2
345345

@@ -348,7 +348,7 @@ contract BlockRewardControllerTest is POLTest {
348348
vm.expectCall(address(bgt), abi.encodeCall(IBGT.mint, (receiver1, 1.0 ether)));
349349
blockRewardController.processRewards(valData.pubkey, DISTRIBUTE_FOR_TIMESTAMP, true);
350350

351-
// Process rewards for second operator - should go to operator2
351+
// Process rewards for second operator - should go to operator2 directly
352352
vm.prank(address(distributor));
353353
vm.expectCall(address(bgt), abi.encodeCall(IBGT.mint, (operator2, 1.0 ether)));
354354
blockRewardController.processRewards(pubkey2, DISTRIBUTE_FOR_TIMESTAMP, true);

0 commit comments

Comments
 (0)