Skip to content

Commit

Permalink
fix(contract) remove fallback free allocation if not defined in creat…
Browse files Browse the repository at this point in the history
…e town flow (#1483)

Signed-off-by: Evan Salzbrenner <[email protected]>
Co-authored-by: Crystal Lemire <[email protected]>
Co-authored-by: Evan Salzbrenner <[email protected]>
  • Loading branch information
3 people authored Nov 18, 2024
1 parent b27d5af commit 14056e4
Show file tree
Hide file tree
Showing 20 changed files with 389 additions and 125 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"address": "0x3b29c3e2ceB2ADEa69f702D2C408F022978B9B06"
"address": "0xc8A8C0fe5333eE22ca686E3ede8bFd325534684B"
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ contract DeploySpaceProxyInitializer is Deployer {
vm.startBroadcast(deployer);
SpaceProxyInitializer proxyInitializer = new SpaceProxyInitializer();
vm.stopBroadcast();

return address(proxyInitializer);
}
}
22 changes: 12 additions & 10 deletions contracts/src/spaces/facets/membership/MembershipBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ abstract contract MembershipBase is IMembershipBase {
if (info.freeAllocation > 0) {
_verifyFreeAllocation(info.freeAllocation);
ds.freeAllocation = info.freeAllocation;
} else {
ds.freeAllocation = IPlatformRequirements(ds.spaceFactory)
.getMembershipMintLimit();
}

ds.freeAllocationEnabled = true;
Expand Down Expand Up @@ -162,14 +159,19 @@ abstract contract MembershipBase is IMembershipBase {
// get free allocation
uint256 freeAllocation = _getMembershipFreeAllocation();

if (ds.pricingModule != address(0))
return
IMembershipPricing(ds.pricingModule).getPrice(
freeAllocation,
totalSupply
);
uint256 membershipPrice = IMembershipPricing(ds.pricingModule).getPrice(
freeAllocation,
totalSupply
);

IPlatformRequirements platform = IPlatformRequirements(_getSpaceFactory());

uint256 minPrice = platform.getMembershipMinPrice();
uint256 fixedFee = platform.getMembershipFee();

if (membershipPrice < minPrice) return fixedFee;

return IPlatformRequirements(ds.spaceFactory).getMembershipMinPrice();
return membershipPrice;
}

function _setMembershipRenewalPrice(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,9 @@ contract TieredLogPricingOracleV3 is IMembershipPricing, IntrospectionFacet {
}

function _calculateStablePrice(
uint256 freeAllocation,
uint256,
uint256 totalMinted
) internal pure returns (uint256) {
// Free allocation handling
if (freeAllocation > 0 && totalMinted < freeAllocation) {
return 0;
}

// Define minted tiers
uint256 tier1 = 100;
uint256 tier2 = 1000;
Expand All @@ -124,23 +119,20 @@ contract TieredLogPricingOracleV3 is IMembershipPricing, IntrospectionFacet {
uint256 basePriceTier2 = 1000; // $10.00
uint256 basePriceTier3 = 10000; // $100.00

if (totalMinted > tier3) {
return basePriceTier3;
} else if (totalMinted > tier2) {
// Logarithmic scaling for tier 2
uint256 logScale = _calculateLogScale(totalMinted);
return logScale * 22 + basePriceTier2;
} else if (totalMinted > tier1) {
if (totalMinted <= tier1) {
// Logarithmic scaling for tier 1
uint256 logScale = _calculateLogScale(totalMinted == 0 ? 1 : totalMinted);
return logScale / 2 + basePriceTier1; // Dividing by 2 is an arbitrary scaling factor
} else if (totalMinted <= tier2) {
// Logarithmic scaling for tier 2
uint256 logScale = _calculateLogScale(totalMinted);
return logScale * 3 + basePriceTier1;
} else if (totalMinted <= tier3) {
// Logarithmic scaling for tier 3
uint256 logScale = _calculateLogScale(totalMinted);
return logScale * 22 + basePriceTier2;
} else {
// Below tier 1
if (freeAllocation > totalMinted) return 0;

// Logarithmic scaling for tier 0
uint256 logScale = _calculateLogScale(totalMinted == 0 ? 1 : totalMinted);
return logScale / 2 + basePriceTier1; // // Dividing by 2 is an arbitrary scaling factor
return basePriceTier3;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

// contracts

// debuggging

contract AuthorizedClaimers is IAuthorizedClaimers, EIP712, Nonces {
// keccak256("Authorize(address owner,address claimer,uint256 nonce,uint256 expiry)")
bytes32 private constant _AUTHORIZE_TYPEHASH =
Expand Down
2 changes: 0 additions & 2 deletions contracts/test/mocks/MockDiamond.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ import {DeployIntrospection} from "contracts/scripts/deployments/facets/DeployIn
import {DeployManagedProxy} from "contracts/scripts/deployments/facets/DeployManagedProxy.s.sol";
import {MultiInit} from "contracts/src/diamond/initializers/MultiInit.sol";

// debuggging

/// @title MockDiamondHelper
/// @notice Used to create a diamond with all the facets we need for testing
contract MockDiamondHelper {
Expand Down
4 changes: 3 additions & 1 deletion contracts/test/spaces/BaseSetup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {DeployBaseRegistry} from "contracts/scripts/deployments/diamonds/DeployB
* @dev - This contract is inherited by all other test contracts, it will create one diamond contract which represent the factory contract that creates all spaces
*/
contract BaseSetup is TestUtils, SpaceHelper {
uint256 internal constant FREE_ALLOCATION = 1_000;
string public constant LINKED_WALLET_MESSAGE = "Link your external wallet";
bytes32 private constant _LINKED_WALLET_TYPEHASH =
0x6bb89d031fcd292ecd4c0e6855878b7165cebc3a2f35bc6bbac48c088dd8325c;
Expand Down Expand Up @@ -86,7 +87,7 @@ contract BaseSetup is TestUtils, SpaceHelper {

address internal pricingModule;
address internal fixedPricingModule;

address internal tieredPricingModule;
SimpleAccountFactory internal simpleAccountFactory;

IEntitlementChecker internal entitlementChecker;
Expand Down Expand Up @@ -171,6 +172,7 @@ contract BaseSetup is TestUtils, SpaceHelper {
"BaseSetupEveryoneSpace"
);
everyoneSpaceInfo.membership.settings.pricingModule = fixedPricingModule;
everyoneSpaceInfo.membership.settings.freeAllocation = FREE_ALLOCATION;

vm.startPrank(founder);
// create a dummy space so the next one starts at 1
Expand Down
1 change: 1 addition & 0 deletions contracts/test/spaces/architect/Architect.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ contract ArchitectTest is

SpaceInfo memory spaceInfo = _createEveryoneSpaceInfo(spaceName);
spaceInfo.membership.settings.pricingModule = pricingModule;
spaceInfo.membership.settings.freeAllocation = FREE_ALLOCATION;

vm.prank(founder);
address spaceInstance = createSpaceFacet.createSpace(spaceInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ contract IntegrationCreateSpace is

SpaceInfo memory spaceInfo = _createUserSpaceInfo(spaceId, users);
spaceInfo.membership.settings.pricingModule = pricingModule;
spaceInfo.membership.settings.freeAllocation = FREE_ALLOCATION;
spaceInfo.membership.permissions = new string[](1);
spaceInfo.membership.permissions[0] = Permissions.Read;

Expand Down Expand Up @@ -154,6 +155,7 @@ contract IntegrationCreateSpace is
// create space with default channel
SpaceInfo memory spaceInfo = _createEveryoneSpaceInfo(spaceId);
spaceInfo.membership.settings.pricingModule = pricingModule;
spaceInfo.membership.settings.freeAllocation = FREE_ALLOCATION;

vm.prank(founder);
address newSpace = createSpaceFacet.createSpace(spaceInfo);
Expand Down
9 changes: 9 additions & 0 deletions contracts/test/spaces/membership/MembershipBaseSetup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ contract MembershipBaseSetup is
address internal feeRecipient;

address internal userSpace;
address internal dynamicSpace;

function setUp() public virtual override {
super.setUp();
Expand All @@ -88,10 +89,18 @@ contract MembershipBaseSetup is
allowedUsers
);
userSpaceInfo.membership.settings.pricingModule = fixedPricingModule;
userSpaceInfo.membership.settings.freeAllocation = FREE_ALLOCATION;

IArchitectBase.SpaceInfo memory dynamicSpaceInfo = _createUserSpaceInfo(
"DynamicSpace",
allowedUsers
);
dynamicSpaceInfo.membership.settings.pricingModule = pricingModule;

vm.startPrank(founder);
// user space is a space where only alice and charlie are allowed along with the founder
userSpace = CreateSpaceFacet(spaceFactory).createSpace(userSpaceInfo);
dynamicSpace = CreateSpaceFacet(spaceFactory).createSpace(dynamicSpaceInfo);
vm.stopPrank();

membership = MembershipFacet(userSpace);
Expand Down
10 changes: 9 additions & 1 deletion contracts/test/spaces/membership/unit/MembershipJoinSpace.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ contract MembershipJoinSpaceTest is
assertEq(membershipToken.balanceOf(alice), 1);
}

function test_joinDynamicSpace() external {
uint256 membershipFee = platformReqs.getMembershipFee();

vm.deal(alice, membershipFee);
vm.startPrank(alice);
MembershipFacet(dynamicSpace).joinSpace{value: membershipFee}(alice);
vm.stopPrank();
}

function test_joinSpaceMultipleTimes()
external
givenAliceHasMintedMembership
Expand Down Expand Up @@ -377,7 +386,6 @@ contract MembershipJoinSpaceTest is
vm.prank(founder);
membership.setMembershipLimit(1);

assertTrue(membership.getMembershipPrice() == 0);
assertTrue(membership.getMembershipLimit() == 1);

vm.prank(alice);
Expand Down
5 changes: 4 additions & 1 deletion contracts/test/spaces/membership/unit/MembershipRenew.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,16 @@ contract MembershipRenewTest is MembershipBaseSetup, IERC5643Base {
assertEq(membershipToken.balanceOf(alice), 1);
assertEq(membershipToken.ownerOf(tokenId), alice);

uint256 renewalPrice = membership.getMembershipRenewalPrice(tokenId);
vm.deal(alice, renewalPrice);

uint256 expiration = membership.expiresAt(tokenId);
vm.expectEmit(address(membership));
emit SubscriptionUpdate(
tokenId,
uint64(expiration + membership.getMembershipDuration())
);
membership.renewMembership(tokenId);
membership.renewMembership{value: renewalPrice}(tokenId);

assertEq(membershipToken.balanceOf(alice), 1);
}
Expand Down
33 changes: 18 additions & 15 deletions packages/sdk/src/mediaWithEntitlements.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
* @group with-entitlements
*/

import { makeUserContextFromWallet, makeTestClient, createVersionedSpace } from './util.test'
import {
makeUserContextFromWallet,
makeTestClient,
createVersionedSpace,
getFreeSpacePricingSetup,
} from './util.test'
import { makeDefaultChannelStreamId, makeSpaceStreamId } from './id'
import { ethers, Wallet } from 'ethers'
import { Client } from './client'
Expand All @@ -13,7 +18,6 @@ import {
NoopRuleData,
Permission,
createSpaceDapp,
findDynamicPricingModule,
} from '@river-build/web3'
import { SignerContext } from './signerContext'
import { makeBaseChainConfig } from './riverConfig'
Expand Down Expand Up @@ -55,22 +59,21 @@ describe('mediaWithEntitlements', () => {
await provider.fundWallet()
const spaceDapp = createSpaceDapp(provider, baseConfig.chainConfig)

const pricingModules = await spaceDapp.listPricingModules()
const dynamicPricingModule = findDynamicPricingModule(pricingModules)
expect(dynamicPricingModule).toBeDefined()

const { fixedPricingModuleAddress, freeAllocation, price } = await getFreeSpacePricingSetup(
spaceDapp,
)
// create a space stream,
const membershipInfo: LegacyMembershipStruct = {
settings: {
name: 'Everyone',
symbol: 'MEMBER',
price: 0,
price,
maxSupply: 1000,
duration: 0,
currency: ETH_ADDRESS,
feeRecipient: bobClient.userId,
freeAllocation: 0,
pricingModule: dynamicPricingModule!.module,
freeAllocation,
pricingModule: fixedPricingModuleAddress,
},
permissions: [Permission.Read, Permission.Write],
requirements: {
Expand Down Expand Up @@ -154,22 +157,22 @@ describe('mediaWithEntitlements', () => {
await provider.fundWallet()
const spaceDapp = createSpaceDapp(provider, baseConfig.chainConfig)

const pricingModules = await spaceDapp.listPricingModules()
const dynamicPricingModule = findDynamicPricingModule(pricingModules)
expect(dynamicPricingModule).toBeDefined()
const { fixedPricingModuleAddress, freeAllocation, price } = await getFreeSpacePricingSetup(
spaceDapp,
)

// create a space stream,
const membershipInfo: LegacyMembershipStruct = {
settings: {
name: 'Everyone',
symbol: 'MEMBER',
price: 0,
price,
maxSupply: 1000,
duration: 0,
currency: ETH_ADDRESS,
feeRecipient: bobClient.userId,
freeAllocation: 0,
pricingModule: dynamicPricingModule!.module,
freeAllocation,
pricingModule: fixedPricingModuleAddress,
},
permissions: [Permission.Read, Permission.Write],
requirements: {
Expand Down
19 changes: 11 additions & 8 deletions packages/sdk/src/membershipManagement.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
*/

import { dlog } from '@river-build/dlog'
import { makeUserContextFromWallet, createVersionedSpace } from './util.test'
import {
makeUserContextFromWallet,
createVersionedSpace,
getFreeSpacePricingSetup,
} from './util.test'
import {
isValidStreamId,
makeDefaultChannelStreamId,
Expand All @@ -18,7 +22,6 @@ import {
LegacyMembershipStruct,
NoopRuleData,
ETH_ADDRESS,
findDynamicPricingModule,
} from '@river-build/web3'
import { makeBaseChainConfig } from './riverConfig'

Expand All @@ -37,9 +40,9 @@ describe('membershipManagement', () => {
const spaceDapp = createSpaceDapp(bobProvider, baseConfig.chainConfig)

// create a user stream
const pricingModules = await spaceDapp.listPricingModules()
const dynamicPricingModule = findDynamicPricingModule(pricingModules)
expect(dynamicPricingModule).toBeDefined()
const { fixedPricingModuleAddress, freeAllocation, price } = await getFreeSpacePricingSetup(
spaceDapp,
)

// create a space stream,
log('Bob created user, about to create space')
Expand All @@ -48,13 +51,13 @@ describe('membershipManagement', () => {
settings: {
name: 'Everyone',
symbol: 'MEMBER',
price: 0,
price,
maxSupply: 1000,
duration: 0,
currency: ETH_ADDRESS,
feeRecipient: userIdFromAddress(bobsContext.creatorAddress),
freeAllocation: 0,
pricingModule: dynamicPricingModule!.module,
freeAllocation,
pricingModule: fixedPricingModuleAddress,
},
permissions: [Permission.Read, Permission.Write],
requirements: {
Expand Down
Loading

0 comments on commit 14056e4

Please sign in to comment.