Skip to content

Commit 01b3daa

Browse files
committed
Refactor MembershipJoin and related tests to utilize dynamic membership pricing. Updated join functions to calculate total payment based on current membership price, enhancing consistency across membership transactions and improving code clarity.
1 parent 98cb210 commit 01b3daa

File tree

8 files changed

+114
-83
lines changed

8 files changed

+114
-83
lines changed

packages/contracts/src/spaces/facets/membership/join/MembershipJoin.sol

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -315,8 +315,7 @@ abstract contract MembershipJoin is
315315
sender,
316316
receiver,
317317
joinDetails.amountDue,
318-
ownerProceeds,
319-
joinDetails.basePrice
318+
ownerProceeds
320319
);
321320
}
322321

@@ -363,8 +362,7 @@ abstract contract MembershipJoin is
363362
sender,
364363
receiver,
365364
joinDetails.amountDue,
366-
ownerProceeds,
367-
joinDetails.basePrice
365+
ownerProceeds
368366
);
369367
}
370368

@@ -373,16 +371,15 @@ abstract contract MembershipJoin is
373371
address payer,
374372
address receiver,
375373
uint256 paymentRequired,
376-
uint256 ownerProceeds,
377-
uint256 membershipPrice
374+
uint256 ownerProceeds
378375
) internal {
379376
// account for owner's proceeds
380377
if (ownerProceeds != 0) _transferIn(payer, ownerProceeds);
381378

382379
_releaseCapturedValue(transactionId, paymentRequired);
383380
_deleteCapturedData(transactionId);
384381

385-
_mintMembershipPoints(receiver, membershipPrice);
382+
_mintMembershipPoints(receiver, paymentRequired);
386383
}
387384

388385
/// @notice Issues a membership token to the receiver
@@ -524,7 +521,7 @@ abstract contract MembershipJoin is
524521
);
525522
}
526523

527-
_mintMembershipPoints(receiver, basePrice);
524+
_mintMembershipPoints(receiver, totalRequired);
528525
_renewSubscription(tokenId, uint64(duration));
529526
}
530527

packages/contracts/test/spaces/membership/MembershipBaseSetup.sol

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,9 @@ contract MembershipBaseSetup is
130130
}
131131

132132
modifier givenAliceHasPaidMembership() {
133-
hoax(alice, MEMBERSHIP_PRICE);
134-
membership.joinSpace{value: MEMBERSHIP_PRICE}(alice);
133+
uint256 membershipPrice = membership.getMembershipPrice();
134+
hoax(alice, membershipPrice);
135+
membership.joinSpace{value: membershipPrice}(alice);
135136
assertEq(membershipToken.balanceOf(alice), 1);
136137
_;
137138
}

packages/contracts/test/spaces/membership/unit/MembershipJoinSpace.t.sol

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {IEntitlementGated, IEntitlementGatedBase} from "src/spaces/facets/gated/
1111

1212
// libraries
1313
import {BasisPoints} from "src/utils/libraries/BasisPoints.sol";
14+
import {FixedPointMathLib} from "solady/utils/FixedPointMathLib.sol";
1415

1516
// contracts
1617
import {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();

packages/contracts/test/spaces/membership/unit/MembershipJoinSpaceWithReferral.t.sol

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,22 @@ contract MembershipJoinSpaceWithReferralTest is
5858
referralCode: ""
5959
});
6060

61-
vm.deal(alice, MEMBERSHIP_PRICE);
61+
uint256 totalPrice = membership.getMembershipPrice();
62+
vm.deal(alice, totalPrice);
6263
vm.prank(alice);
63-
membership.joinSpaceWithReferral{value: MEMBERSHIP_PRICE}(alice, referral);
64+
membership.joinSpaceWithReferral{value: totalPrice}(alice, referral);
6465

6566
uint256 protocolFee = BasisPoints.calculate(
6667
MEMBERSHIP_PRICE,
6768
platformReqs.getMembershipBps()
6869
);
70+
uint256 minFee = platformReqs.getMembershipFee();
71+
protocolFee = protocolFee > minFee ? protocolFee : minFee;
6972

7073
address protocol = platformReqs.getFeeRecipient();
7174

7275
assertEq(protocol.balance, protocolFee);
73-
assertEq(address(membership).balance, MEMBERSHIP_PRICE - protocolFee);
76+
assertEq(address(membership).balance, MEMBERSHIP_PRICE); // Space gets base price
7477
}
7578

7679
function test_revertWhen_joinSpaceWithReferral_partnerReferral(
@@ -90,9 +93,10 @@ contract MembershipJoinSpaceWithReferralTest is
9093
referralCode: ""
9194
});
9295

93-
vm.deal(alice, MEMBERSHIP_PRICE);
96+
uint256 totalPrice = membership.getMembershipPrice();
97+
vm.deal(alice, totalPrice);
9498
vm.prank(alice);
95-
membership.joinSpaceWithReferral{value: MEMBERSHIP_PRICE}(alice, referral);
99+
membership.joinSpaceWithReferral{value: totalPrice}(alice, referral);
96100

97101
uint256 protocolFee = BasisPoints.calculate(
98102
MEMBERSHIP_PRICE,
@@ -101,9 +105,13 @@ contract MembershipJoinSpaceWithReferralTest is
101105

102106
uint256 partnerFee = BasisPoints.calculate(MEMBERSHIP_PRICE, partner.fee);
103107

108+
uint256 minFee = platformReqs.getMembershipFee();
109+
protocolFee = protocolFee > minFee ? protocolFee : minFee;
110+
104111
assertEq(partner.account.balance, partnerFee, "partner fee");
105112
assertEq(platformReqs.getFeeRecipient().balance, protocolFee);
106-
assertEq(address(membership).balance, MEMBERSHIP_PRICE - protocolFee - partnerFee);
113+
// With fee-added model, space gets base price minus partner fee only
114+
assertEq(address(membership).balance, MEMBERSHIP_PRICE - partnerFee);
107115
}
108116

109117
function test_revertWhen_joinSpaceWithReferral_referralCodeRegistered()
@@ -128,14 +136,17 @@ contract MembershipJoinSpaceWithReferralTest is
128136
referralCode: referral.referralCode
129137
});
130138

131-
vm.deal(alice, MEMBERSHIP_PRICE);
139+
uint256 totalPrice = membership.getMembershipPrice();
140+
vm.deal(alice, totalPrice);
132141
vm.prank(alice);
133-
membership.joinSpaceWithReferral{value: MEMBERSHIP_PRICE}(alice, membershipReferral);
142+
membership.joinSpaceWithReferral{value: totalPrice}(alice, membershipReferral);
134143

135144
uint256 protocolFee = BasisPoints.calculate(
136145
MEMBERSHIP_PRICE,
137146
platformReqs.getMembershipBps()
138147
);
148+
uint256 minFee = platformReqs.getMembershipFee();
149+
protocolFee = protocolFee > minFee ? protocolFee : minFee;
139150

140151
uint256 referralFee = BasisPoints.calculate(
141152
MEMBERSHIP_PRICE,
@@ -144,7 +155,8 @@ contract MembershipJoinSpaceWithReferralTest is
144155

145156
assertEq(platformReqs.getFeeRecipient().balance, protocolFee);
146157
assertEq(referralRecipient.balance, referralFee);
147-
assertEq(address(membership).balance, MEMBERSHIP_PRICE - protocolFee - referralFee);
158+
// With fee-added model, space gets base price minus referral fee only
159+
assertEq(address(membership).balance, MEMBERSHIP_PRICE - referralFee);
148160
assertEq(alice.balance, 0);
149161
assertEq(membershipToken.balanceOf(alice), 1);
150162
}
@@ -159,19 +171,23 @@ contract MembershipJoinSpaceWithReferralTest is
159171
referralCode: ""
160172
});
161173

162-
vm.deal(alice, MEMBERSHIP_PRICE);
174+
uint256 totalPrice = membership.getMembershipPrice();
175+
vm.deal(alice, totalPrice);
163176
vm.prank(alice);
164-
membership.joinSpaceWithReferral{value: MEMBERSHIP_PRICE}(alice, referral);
177+
membership.joinSpaceWithReferral{value: totalPrice}(alice, referral);
165178

166179
uint256 protocolFee = BasisPoints.calculate(
167180
MEMBERSHIP_PRICE,
168181
platformReqs.getMembershipBps()
169182
);
183+
uint256 minFee = platformReqs.getMembershipFee();
184+
protocolFee = protocolFee > minFee ? protocolFee : minFee;
170185

171186
uint256 referralFee = BasisPoints.calculate(MEMBERSHIP_PRICE, referrals.defaultBpsFee());
172187

173188
assertEq(bob.balance, referralFee);
174-
assertEq(address(membership).balance, MEMBERSHIP_PRICE - protocolFee - referralFee);
189+
// With fee-added model, space gets base price minus referral fee only
190+
assertEq(address(membership).balance, MEMBERSHIP_PRICE - referralFee);
175191
assertEq(membershipToken.balanceOf(alice), 1);
176192
}
177193

packages/contracts/test/spaces/membership/unit/MembershipPricingModules.t.sol

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {MembershipBaseSetup} from "../MembershipBaseSetup.sol";
77
//interfaces
88

99
//libraries
10+
import {FixedPointMathLib} from "solady/utils/FixedPointMathLib.sol";
1011

1112
//contracts
1213

@@ -44,13 +45,20 @@ contract MembershipPricingModulesTest is MembershipBaseSetup {
4445
}
4546

4647
function test_setMembershipPrice() public givenMembershipHasPrice {
47-
assertEq(membership.getMembershipPrice(), MEMBERSHIP_PRICE);
48+
uint256 expectedPrice = MEMBERSHIP_PRICE + membership.getProtocolFee();
49+
assertEq(membership.getMembershipPrice(), expectedPrice);
4850

4951
uint256 newPrice = 2 ether;
5052

5153
vm.prank(founder);
5254
membership.setMembershipPrice(newPrice);
5355

54-
assertEq(membership.getMembershipPrice(), newPrice);
56+
uint256 protocolFee = (platformReqs.getMembershipBps() * newPrice) / 10000;
57+
uint256 minFee = platformReqs.getMembershipFee();
58+
59+
protocolFee = FixedPointMathLib.max(protocolFee, minFee);
60+
61+
expectedPrice = newPrice + protocolFee;
62+
assertEq(membership.getMembershipPrice(), expectedPrice);
5563
}
5664
}

0 commit comments

Comments
 (0)