@@ -549,7 +549,7 @@ contract BoostCoreTest is Test {
549549 vm.stopPrank ();
550550 }
551551
552- function testFuzzClaimIncentive_ProtocolFeeTransfer (uint256 rewardAmount , uint64 additionalProtocolFee ) public {
552+ function testFuzzClaimIncentive_ProtocolFeeTransfer (uint256 rewardAmount , uint64 additionalProtocolFee ) internal {
553553 uint160 claimant = uint160 (makeAddr ("claimant " ));
554554 uint16 claimLimit = 1_000 ;
555555 additionalProtocolFee = uint64 (bound (additionalProtocolFee, 0 , 9_000 ));
@@ -619,6 +619,108 @@ contract BoostCoreTest is Test {
619619 assertEq (0 , mockERC20.balanceOf (address (boostCore)), "unclaimedFunds In boost core " );
620620 }
621621
622+ function testFuzzTopUpAndClaimIncentive_ProtocolFeeTransfer (uint256 rewardAmount , uint64 additionalProtocolFee )
623+ public
624+ {
625+ uint160 claimant = uint160 (makeAddr ("claimant " ));
626+ uint16 claimLimit = 100 ;
627+ additionalProtocolFee = uint64 (bound (additionalProtocolFee, 0 , 9_000 ));
628+ rewardAmount = bound (rewardAmount, 10_000 , (type (uint256 ).max >> 15 ) / claimLimit);
629+ uint64 totalFee = uint64 (boostCore.protocolFee ()) + additionalProtocolFee;
630+ uint256 amountToMint = (rewardAmount + rewardAmount * totalFee / boostCore.FEE_DENOMINATOR ()) * claimLimit;
631+ mockERC20.mint (address (this ), amountToMint);
632+ mockERC20.approve (address (budget), amountToMint);
633+ budget.allocate (
634+ abi.encode (
635+ ABudget.Transfer ({
636+ assetType: ABudget.AssetType.ERC20 ,
637+ asset: address (mockERC20),
638+ target: address (this ),
639+ data: abi.encode (ABudget.FungiblePayload ({amount: amountToMint}))
640+ })
641+ )
642+ );
643+ address feeReceiver = makeAddr ("0xfee " );
644+ boostCore.setProtocolFeeReceiver (feeReceiver);
645+
646+ bytes memory createBoostCalldata =
647+ _makeValidCreateCalldataWithVariableRewardAmount (1 , rewardAmount, claimLimit, additionalProtocolFee);
648+
649+ // Create the boost
650+ boostCore.createBoost (createBoostCalldata);
651+
652+ // Get the boost and incentive contract
653+ BoostLib.Boost memory boost = boostCore.getBoost (0 );
654+ ERC20Incentive incentive = ERC20Incentive (address (boost.incentives[0 ]));
655+
656+ _do_topup (amountToMint, claimLimit, rewardAmount);
657+
658+ // Calculate expected fee
659+ uint256 claimAmount = incentive.reward ();
660+ uint256 protocolFeePercentage = boost.protocolFee;
661+
662+ uint256 expectedFee = (claimAmount * protocolFeePercentage) / boostCore.FEE_DENOMINATOR ();
663+
664+ // Mint an ERC721 token to the claimant
665+
666+ for (uint160 tokenId = 1 ; tokenId < 102 ; tokenId++ ) {
667+ hoax (address (claimant + tokenId));
668+ mockERC721.mint {value: 0.1 ether }(address (this ));
669+
670+ // Record initial balances
671+ uint256 initialFeeReceiverBalance = mockERC20.balanceOf (feeReceiver);
672+
673+ // Prepare claim data
674+ bytes memory data = abi.encode (address (this ), abi.encode (tokenId));
675+
676+ // Expect the fee ProtocolFeesCollected event
677+ vm.expectEmit ();
678+ emit BoostCore.ProtocolFeesCollected (0 , 0 , expectedFee, feeReceiver);
679+
680+ // Perform claim
681+ hoax (address (claimant + tokenId));
682+ boostCore.claimIncentive (0 , 0 , address (0 ), data);
683+
684+ // Verify fee transfer
685+ assertApproxEqAbs (
686+ mockERC20.balanceOf (feeReceiver),
687+ initialFeeReceiverBalance + expectedFee,
688+ boostCore.DUST_THRESHOLD (),
689+ "Protocol fee not transferred correctly "
690+ );
691+ }
692+
693+ //assertEq(0, mockERC20.balanceOf(address(boostCore)), "unclaimedFunds In boost core");
694+ }
695+
696+ function _do_topup (uint256 amountToMint , uint256 claimLimit , uint256 rewardAmount ) internal {
697+ mockERC20.mint (address (this ), amountToMint);
698+ mockERC20.approve (address (budget), amountToMint);
699+
700+ budget.allocate (
701+ abi.encode (
702+ ABudget.Transfer ({
703+ assetType: ABudget.AssetType.ERC20 ,
704+ asset: address (mockERC20),
705+ target: address (this ),
706+ data: abi.encode (ABudget.FungiblePayload ({amount: amountToMint}))
707+ })
708+ )
709+ );
710+
711+ bytes memory topupCalldata = abi.encode (
712+ ERC20Incentive .InitPayload ({
713+ asset: address (mockERC20),
714+ strategy: AERC20Incentive.Strategy.POOL,
715+ reward: rewardAmount,
716+ limit: claimLimit,
717+ manager: address (budget)
718+ })
719+ );
720+
721+ boostCore.topupIncentiveFromBudget (0 , 0 , topupCalldata, address (budget));
722+ }
723+
622724 function testClaimIncentive_ProtocolFeeTransfer () public {
623725 address feeReceiver = address (0xfee );
624726 boostCore.setProtocolFeeReceiver (feeReceiver);
@@ -991,7 +1093,7 @@ contract BoostCoreTest is Test {
9911093 strategy: AERC20Incentive.Strategy.POOL,
9921094 reward: rewardAmount,
9931095 limit: limit,
994- manager: address (boostCore )
1096+ manager: address (budget )
9951097 })
9961098 )
9971099 });
0 commit comments