@@ -6,6 +6,7 @@ import {SuccinctVApp} from "../src/SuccinctVApp.sol";
66import {ISuccinctVApp} from "../src/interfaces/ISuccinctVApp.sol " ;
77import {Merkle} from "../lib/murky/src/Merkle.sol " ;
88import {MockERC20} from "./utils/MockERC20.sol " ;
9+ import {MockStaking} from "../src/mocks/MockStaking.sol " ;
910import {PausableUpgradeable} from
1011 "../lib/openzeppelin-contracts-upgradeable/contracts/utils/PausableUpgradeable.sol " ;
1112
@@ -16,6 +17,9 @@ contract SuccinctVAppRewardsTest is SuccinctVAppTest {
1617 bytes32 [] public rewardLeaves;
1718 bytes32 public rewardsMerkleRoot;
1819 Merkle public merkle;
20+
21+ // Prover for testing prover rewards.
22+ address public testProver;
1923
2024 // Storage slot for rewardsRoot in SuccinctVApp (slot 11 based on contract layout).
2125 uint256 constant REWARDS_ROOT_SLOT = 11 ;
@@ -26,13 +30,17 @@ contract SuccinctVAppRewardsTest is SuccinctVAppTest {
2630 function setUp () public override {
2731 super .setUp ();
2832
29- // Set up test rewards data.
33+ // Create a test prover.
34+ vm.prank (ALICE);
35+ testProver = MockStaking (STAKING).createProver (ALICE, STAKER_FEE_BIPS);
36+
37+ // Set up test rewards data (including a prover).
3038 rewardAccounts = [
3139 makeAddr ("REWARD_1 " ),
3240 makeAddr ("REWARD_2 " ),
3341 makeAddr ("REWARD_3 " ),
3442 makeAddr ("REWARD_4 " ),
35- makeAddr ( " REWARD_5 " )
43+ testProver // Include the prover in rewards
3644 ];
3745 rewardAmounts = [1 ether, 2 ether, 3 ether, 4 ether, 5 ether ];
3846
@@ -91,7 +99,14 @@ contract SuccinctVAppRewardsTest is SuccinctVAppTest {
9199 SuccinctVApp (VAPP).rewardClaim (i, claimer, amount, proof);
92100
93101 // Check post-claim state.
94- assertEq (MockERC20 (PROVE).balanceOf (claimer), amount);
102+ if (claimer == testProver) {
103+ // For provers, PROVE is converted to iPROVE and sent to prover vault.
104+ assertEq (MockERC20 (I_PROVE).balanceOf (claimer), amount);
105+ assertEq (MockERC20 (PROVE).balanceOf (claimer), 0 );
106+ } else {
107+ // For regular accounts, PROVE is sent directly.
108+ assertEq (MockERC20 (PROVE).balanceOf (claimer), amount);
109+ }
95110 vappBalBefore -= amount;
96111 assertEq (MockERC20 (PROVE).balanceOf (VAPP), vappBalBefore);
97112 assertEq (SuccinctVApp (VAPP).isClaimed (i), true );
@@ -173,18 +188,23 @@ contract SuccinctVAppRewardsTest is SuccinctVAppTest {
173188 // Set the rewards root.
174189 _setRewardsRoot (rewardsMerkleRoot);
175190
191+ // Test regular account (not a prover).
192+ uint256 regularAccountIndex = 0 ;
193+ address regularAccount = rewardAccounts[regularAccountIndex];
194+ uint256 amount = rewardAmounts[regularAccountIndex];
195+
176196 // Check initial balances.
177197 uint256 initialVAppBalance = MockERC20 (PROVE).balanceOf (VAPP);
178- uint256 initialClaimerBalance = MockERC20 (PROVE).balanceOf (rewardAccounts[ 0 ] );
198+ uint256 initialClaimerBalance = MockERC20 (PROVE).balanceOf (regularAccount );
179199 assertEq (initialClaimerBalance, 0 );
180200
181201 // Claim reward.
182- bytes32 [] memory proof = merkle.getProof (rewardLeaves, 0 );
183- SuccinctVApp (VAPP).rewardClaim (0 , rewardAccounts[ 0 ], rewardAmounts[ 0 ] , proof);
202+ bytes32 [] memory proof = merkle.getProof (rewardLeaves, regularAccountIndex );
203+ SuccinctVApp (VAPP).rewardClaim (regularAccountIndex, regularAccount, amount , proof);
184204
185205 // Verify transfer occurred.
186- assertEq (MockERC20 (PROVE).balanceOf (rewardAccounts[ 0 ] ), rewardAmounts[ 0 ] );
187- assertEq (MockERC20 (PROVE).balanceOf (VAPP), initialVAppBalance - rewardAmounts[ 0 ] );
206+ assertEq (MockERC20 (PROVE).balanceOf (regularAccount ), amount );
207+ assertEq (MockERC20 (PROVE).balanceOf (VAPP), initialVAppBalance - amount );
188208 }
189209
190210 function test_RewardClaim_DifferentCaller () public {
@@ -262,4 +282,58 @@ contract SuccinctVAppRewardsTest is SuccinctVAppTest {
262282 uint256 expectedRemainingBalance = 100 ether - totalClaimed;
263283 assertEq (MockERC20 (PROVE).balanceOf (VAPP), expectedRemainingBalance);
264284 }
285+
286+ function test_RewardClaim_ToProverVault () public {
287+ // Set the rewards root.
288+ _setRewardsRoot (rewardsMerkleRoot);
289+
290+ // Get the prover index (last one in our array).
291+ uint256 proverIndex = rewardAccounts.length - 1 ;
292+ address proverVault = rewardAccounts[proverIndex];
293+ uint256 amount = rewardAmounts[proverIndex];
294+
295+ // Verify it's recognized as a prover.
296+ assertEq (proverVault, testProver);
297+
298+ // Check initial balances.
299+ uint256 initialVAppBalance = MockERC20 (PROVE).balanceOf (VAPP);
300+ uint256 initialProverPROVEBalance = MockERC20 (PROVE).balanceOf (proverVault);
301+ uint256 initialProveriPROVEBalance = MockERC20 (I_PROVE).balanceOf (proverVault);
302+ assertEq (initialProverPROVEBalance, 0 );
303+ assertEq (initialProveriPROVEBalance, 0 );
304+
305+ // Claim reward for prover.
306+ bytes32 [] memory proof = merkle.getProof (rewardLeaves, proverIndex);
307+ vm.expectEmit (true , true , true , true , VAPP);
308+ emit RewardClaimed (proverIndex, proverVault, amount);
309+ SuccinctVApp (VAPP).rewardClaim (proverIndex, proverVault, amount, proof);
310+
311+ // Verify the prover received iPROVE instead of PROVE.
312+ assertEq (MockERC20 (PROVE).balanceOf (proverVault), 0 );
313+ assertEq (MockERC20 (I_PROVE).balanceOf (proverVault), amount);
314+ assertEq (MockERC20 (PROVE).balanceOf (VAPP), initialVAppBalance - amount);
315+ assertEq (SuccinctVApp (VAPP).isClaimed (proverIndex), true );
316+ }
317+
318+ function test_RewardClaim_MixedAccountTypes () public {
319+ // Set the rewards root.
320+ _setRewardsRoot (rewardsMerkleRoot);
321+
322+ // Claim for regular account (index 0).
323+ bytes32 [] memory proof0 = merkle.getProof (rewardLeaves, 0 );
324+ SuccinctVApp (VAPP).rewardClaim (0 , rewardAccounts[0 ], rewardAmounts[0 ], proof0);
325+
326+ // Verify regular account received PROVE.
327+ assertEq (MockERC20 (PROVE).balanceOf (rewardAccounts[0 ]), rewardAmounts[0 ]);
328+ assertEq (MockERC20 (I_PROVE).balanceOf (rewardAccounts[0 ]), 0 );
329+
330+ // Claim for prover (last index).
331+ uint256 proverIndex = rewardAccounts.length - 1 ;
332+ bytes32 [] memory proofProver = merkle.getProof (rewardLeaves, proverIndex);
333+ SuccinctVApp (VAPP).rewardClaim (proverIndex, testProver, rewardAmounts[proverIndex], proofProver);
334+
335+ // Verify prover received iPROVE.
336+ assertEq (MockERC20 (PROVE).balanceOf (testProver), 0 );
337+ assertEq (MockERC20 (I_PROVE).balanceOf (testProver), rewardAmounts[proverIndex]);
338+ }
265339}
0 commit comments