@@ -11,6 +11,7 @@ import {IEntitlementGated, IEntitlementGatedBase} from "src/spaces/facets/gated/
1111
1212// libraries
1313import {BasisPoints} from "src/utils/libraries/BasisPoints.sol " ;
14+ import {FixedPointMathLib} from "solady/utils/FixedPointMathLib.sol " ;
1415
1516// contracts
1617import {MembershipFacet} from "src/spaces/facets/membership/MembershipFacet.sol " ;
@@ -32,13 +33,13 @@ contract MembershipJoinSpaceTest is
3233 }
3334
3435 function test_joinDynamicSpace () external {
35- uint256 membershipFee = MembershipFacet (dynamicSpace).getMembershipPrice ();
36+ uint256 totalPrice = MembershipFacet (dynamicSpace).getMembershipPrice ();
3637
37- vm.deal (alice, membershipFee );
38+ vm.deal (alice, totalPrice );
3839 vm.prank (alice);
39- MembershipFacet (dynamicSpace).joinSpace {value: membershipFee }(alice);
40+ MembershipFacet (dynamicSpace).joinSpace {value: totalPrice }(alice);
4041
41- assertEq (IERC20 (riverAirdrop).balanceOf (alice), _getPoints (membershipFee ));
42+ assertEq (IERC20 (riverAirdrop).balanceOf (alice), _getPoints (totalPrice ));
4243 }
4344
4445 function test_joinSpaceMultipleTimes ()
@@ -90,25 +91,29 @@ contract MembershipJoinSpaceTest is
9091 /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
9192
9293 function test_joinPaidSpace () external givenMembershipHasPrice {
93- vm.deal (alice, MEMBERSHIP_PRICE);
94+ uint256 totalPrice = membership.getMembershipPrice ();
95+
96+ vm.deal (alice, totalPrice);
9497 vm.prank (alice);
95- membership.joinSpace {value: MEMBERSHIP_PRICE }(alice);
98+ membership.joinSpace {value: totalPrice }(alice);
9699
97100 assertEq (membershipToken.balanceOf (alice), 1 );
98101 assertEq (alice.balance, 0 );
99- assertEq (IERC20 (riverAirdrop).balanceOf (alice), _getPoints (MEMBERSHIP_PRICE ));
102+ assertEq (IERC20 (riverAirdrop).balanceOf (alice), _getPoints (totalPrice ));
100103 }
101104
102105 function test_fuzz_joinSpace_refundOnSuccess (
103106 uint256 overPayment
104107 ) external givenMembershipHasPrice {
105- overPayment = bound (overPayment, MEMBERSHIP_PRICE, 100 * MEMBERSHIP_PRICE);
108+ uint256 totalPrice = membership.getMembershipPrice ();
109+ overPayment = bound (overPayment, totalPrice, 100 * totalPrice);
106110
107111 _joinSpaceWithCrosschainValidation (bob, overPayment, NodeVoteStatus.PASSED, true );
108112 }
109113
110114 function test_joinSpace_refundOnFail () external givenMembershipHasPrice {
111- _joinSpaceWithCrosschainValidation (bob, MEMBERSHIP_PRICE, NodeVoteStatus.FAILED, false );
115+ uint256 membershipPrice = membership.getMembershipPrice ();
116+ _joinSpaceWithCrosschainValidation (bob, membershipPrice, NodeVoteStatus.FAILED, false );
112117 }
113118
114119 function test_joinSpace_withValueAndFreeAllocation () external {
@@ -136,16 +141,18 @@ contract MembershipJoinSpaceTest is
136141 }
137142
138143 function test_joinSpace_priceChangesMidTransaction () external givenMembershipHasPrice {
139- vm.deal (bob, MEMBERSHIP_PRICE);
144+ uint256 membershipPrice = membership.getMembershipPrice ();
145+
146+ vm.deal (bob, membershipPrice);
140147 assertEq (membershipToken.balanceOf (bob), 0 );
141148
142149 vm.recordLogs ();
143150 vm.prank (bob);
144- membership.joinSpace {value: MEMBERSHIP_PRICE }(bob);
151+ membership.joinSpace {value: membershipPrice }(bob);
145152 Vm.Log[] memory logs = vm.getRecordedLogs ();
146153
147154 vm.prank (founder);
148- membership.setMembershipPrice (MEMBERSHIP_PRICE * 2 );
155+ membership.setMembershipPrice (membershipPrice * 2 );
149156
150157 (
151158 ,
@@ -166,7 +173,7 @@ contract MembershipJoinSpaceTest is
166173 }
167174
168175 assertEq (membershipToken.balanceOf (bob), 0 );
169- assertEq (bob.balance, MEMBERSHIP_PRICE );
176+ assertEq (bob.balance, membershipPrice );
170177 assertEq (IERC20 (riverAirdrop).balanceOf (bob), 0 );
171178 }
172179
@@ -178,14 +185,16 @@ contract MembershipJoinSpaceTest is
178185 membership.setMembershipPrice (fee);
179186 vm.stopPrank ();
180187
181- vm.deal (alice, fee);
188+ // Total price = base price + protocol fee
189+ uint256 totalPrice = membership.getMembershipPrice ();
190+ vm.deal (alice, totalPrice);
182191 vm.prank (alice);
183- membership.joinSpace {value: fee }(alice);
192+ membership.joinSpace {value: totalPrice }(alice);
184193
185194 assertEq (membershipToken.balanceOf (alice), 1 );
186195 assertEq (alice.balance, 0 );
187- assertEq (IERC20 (riverAirdrop).balanceOf (alice), _getPoints (fee ));
188- assertEq (membership.revenue (), 0 );
196+ assertEq (IERC20 (riverAirdrop).balanceOf (alice), _getPoints (totalPrice ));
197+ assertEq (membership.revenue (), fee); // Space gets the base price
189198 }
190199
191200 function test_getProtocolFee () external view {
@@ -195,13 +204,17 @@ contract MembershipJoinSpaceTest is
195204 }
196205
197206 function test_getProtocolFee_withPriceAboveMinPrice () external {
198- vm.prank (founder);
199- membership.setMembershipPrice (1 ether);
207+ uint256 basePrice = 1 ether ;
200208
201- uint256 price = membership.getMembershipPrice ();
209+ vm.prank (founder);
210+ membership.setMembershipPrice (basePrice);
202211 uint256 protocolFee = membership.getProtocolFee ();
203212
204- assertEq (protocolFee, BasisPoints.calculate (price, platformReqs.getMembershipBps ()));
213+ uint256 expectedProtocolFee = platformReqs.getMembershipFee (); // Min fee for 1 ether
214+ uint256 bpsFee = BasisPoints.calculate (basePrice, platformReqs.getMembershipBps ());
215+ expectedProtocolFee = FixedPointMathLib.max (bpsFee, expectedProtocolFee);
216+
217+ assertEq (protocolFee, expectedProtocolFee);
205218 }
206219
207220 /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
@@ -391,7 +404,7 @@ contract MembershipJoinSpaceTest is
391404 givenMembershipHasPrice
392405 givenJoinspaceHasAdditionalCrosschainEntitlements
393406 {
394- uint256 payment = MEMBERSHIP_PRICE ;
407+ uint256 payment = membership. getMembershipPrice () ;
395408 vm.deal (bob, payment);
396409
397410 vm.recordLogs ();
@@ -426,7 +439,7 @@ contract MembershipJoinSpaceTest is
426439 // Verify successful join with proper refund
427440 assertEq (membershipToken.balanceOf (bob), 1 );
428441 assertEq (bob.balance, 0 ); // Exact payment, no refund
429- assertEq (IERC20 (riverAirdrop).balanceOf (bob), _getPoints (MEMBERSHIP_PRICE ));
442+ assertEq (IERC20 (riverAirdrop).balanceOf (bob), _getPoints (payment ));
430443 }
431444
432445 /// @dev Test payment refund with multiple crosschain entitlements - failure case
@@ -435,7 +448,7 @@ contract MembershipJoinSpaceTest is
435448 givenMembershipHasPrice
436449 givenJoinspaceHasAdditionalCrosschainEntitlements
437450 {
438- uint256 payment = MEMBERSHIP_PRICE ;
451+ uint256 payment = membership. getMembershipPrice () ;
439452 vm.deal (bob, payment);
440453
441454 vm.recordLogs ();
@@ -615,8 +628,9 @@ contract MembershipJoinSpaceTest is
615628 if (expectSuccess) {
616629 assertEq (membershipToken.balanceOf (user), initialTokenBalance + 1 );
617630 if (payment > 0 ) {
618- assertEq (user.balance, initialBalance + payment - MEMBERSHIP_PRICE);
619- assertEq (IERC20 (riverAirdrop).balanceOf (user), _getPoints (MEMBERSHIP_PRICE));
631+ uint256 totalPrice = membership.getMembershipPrice ();
632+ assertEq (user.balance, initialBalance + payment - totalPrice);
633+ assertEq (IERC20 (riverAirdrop).balanceOf (user), _getPoints (totalPrice));
620634 }
621635 } else {
622636 assertEq (membershipToken.balanceOf (user), initialTokenBalance);
@@ -627,7 +641,7 @@ contract MembershipJoinSpaceTest is
627641
628642 /// @dev Helper to validate payment distribution and verify single payment for multiple entitlements
629643 function _validateSinglePaymentForMultipleCrosschainEntitlements (address user ) internal {
630- uint256 payment = MEMBERSHIP_PRICE ;
644+ uint256 payment = membership. getMembershipPrice () ;
631645 vm.deal (user, payment);
632646
633647 vm.recordLogs ();
0 commit comments