@towns-protocol/contracts 0.0.302
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +21 -0
- package/README.md +206 -0
- package/docs/permitAndStake_integration_guide.md +266 -0
- package/docs/swap_integration_guide.md +591 -0
- package/package.json +57 -0
- package/scripts/common/DeployBase.s.sol +26 -0
- package/scripts/common/DeployFacet.s.sol +7 -0
- package/scripts/common/Deployer.s.sol +33 -0
- package/scripts/common/Interaction.s.sol +51 -0
- package/scripts/deployments/diamonds/DeployAppRegistry.s.sol +168 -0
- package/scripts/deployments/diamonds/DeployBaseRegistry.s.sol +263 -0
- package/scripts/deployments/diamonds/DeployRiverAirdrop.s.sol +203 -0
- package/scripts/deployments/diamonds/DeployRiverMigration.s.sol +129 -0
- package/scripts/deployments/diamonds/DeployRiverRegistry.s.sol +175 -0
- package/scripts/deployments/diamonds/DeploySpace.s.sol +285 -0
- package/scripts/deployments/diamonds/DeploySpaceFactory.s.sol +416 -0
- package/scripts/deployments/diamonds/DeploySpaceOwner.s.sol +183 -0
- package/scripts/deployments/diamonds/DeploySwapRouter.s.sol +176 -0
- package/scripts/deployments/diamonds/IDiamondInitHelper.sol +11 -0
- package/scripts/deployments/facets/DeployAppAccount.s.sol +51 -0
- package/scripts/deployments/facets/DeployAppRegistryFacet.s.sol +69 -0
- package/scripts/deployments/facets/DeployArchitect.s.sol +51 -0
- package/scripts/deployments/facets/DeployAttestationRegistry.s.sol +36 -0
- package/scripts/deployments/facets/DeployBanning.s.sol +30 -0
- package/scripts/deployments/facets/DeployChannels.s.sol +35 -0
- package/scripts/deployments/facets/DeployCreateSpace.s.sol +42 -0
- package/scripts/deployments/facets/DeployDropFacet.s.sol +49 -0
- package/scripts/deployments/facets/DeployERC721A.s.sol +48 -0
- package/scripts/deployments/facets/DeployERC721ANonTransferable.s.sol +49 -0
- package/scripts/deployments/facets/DeployERC721AQueryable.s.sol +30 -0
- package/scripts/deployments/facets/DeployEntitlementChecker.s.sol +49 -0
- package/scripts/deployments/facets/DeployEntitlementDataQueryable.s.sol +29 -0
- package/scripts/deployments/facets/DeployEntitlementsManager.s.sol +33 -0
- package/scripts/deployments/facets/DeployExecutorFacet.s.sol +60 -0
- package/scripts/deployments/facets/DeployFeatureManager.s.sol +38 -0
- package/scripts/deployments/facets/DeployGuardianFacet.s.sol +39 -0
- package/scripts/deployments/facets/DeployImplementationRegistry.s.sol +36 -0
- package/scripts/deployments/facets/DeployMainnetDelegation.s.sol +43 -0
- package/scripts/deployments/facets/DeployMembership.s.sol +77 -0
- package/scripts/deployments/facets/DeployMembershipMetadata.s.sol +30 -0
- package/scripts/deployments/facets/DeployMembershipToken.s.sol +47 -0
- package/scripts/deployments/facets/DeployMerkleAirdrop.s.sol +37 -0
- package/scripts/deployments/facets/DeployMetadata.s.sol +39 -0
- package/scripts/deployments/facets/DeployMockLegacyArchitect.s.sol +33 -0
- package/scripts/deployments/facets/DeployNodeOperator.s.sol +49 -0
- package/scripts/deployments/facets/DeployNodeRegistry.s.sol +37 -0
- package/scripts/deployments/facets/DeployOperatorRegistry.s.sol +36 -0
- package/scripts/deployments/facets/DeployPartnerRegistry.s.sol +41 -0
- package/scripts/deployments/facets/DeployPlatformRequirements.s.sol +75 -0
- package/scripts/deployments/facets/DeployPrepayFacet.s.sol +31 -0
- package/scripts/deployments/facets/DeployPricingModules.s.sol +36 -0
- package/scripts/deployments/facets/DeployReferrals.s.sol +34 -0
- package/scripts/deployments/facets/DeployReviewFacet.s.sol +31 -0
- package/scripts/deployments/facets/DeployRewardsDistributionV2.s.sol +76 -0
- package/scripts/deployments/facets/DeployRiverConfig.s.sol +41 -0
- package/scripts/deployments/facets/DeployRoles.s.sol +48 -0
- package/scripts/deployments/facets/DeploySchemaRegistry.s.sol +35 -0
- package/scripts/deployments/facets/DeploySignerFacet.s.sol +47 -0
- package/scripts/deployments/facets/DeploySimpleApp.s.sol +10 -0
- package/scripts/deployments/facets/DeploySpaceDelegation.s.sol +43 -0
- package/scripts/deployments/facets/DeploySpaceEntitlementGated.s.sol +31 -0
- package/scripts/deployments/facets/DeploySpaceFactoryInit.s.sol +33 -0
- package/scripts/deployments/facets/DeploySpaceOwnerFacet.s.sol +71 -0
- package/scripts/deployments/facets/DeployStreamRegistry.s.sol +50 -0
- package/scripts/deployments/facets/DeploySwapFacet.s.sol +33 -0
- package/scripts/deployments/facets/DeploySwapRouterFacet.s.sol +38 -0
- package/scripts/deployments/facets/DeployTipping.s.sol +31 -0
- package/scripts/deployments/facets/DeployTokenMigration.s.sol +40 -0
- package/scripts/deployments/facets/DeployTownsPoints.s.sol +53 -0
- package/scripts/deployments/facets/DeployTreasury.s.sol +30 -0
- package/scripts/deployments/facets/DeployUpgradeableBeacon.s.sol +34 -0
- package/scripts/deployments/facets/DeployWalletLink.s.sol +56 -0
- package/scripts/deployments/facets/DeployXChain.s.sol +35 -0
- package/scripts/deployments/utils/DeployAccountFactory.s.sol +40 -0
- package/scripts/deployments/utils/DeployEntitlementGatedExample.s.sol +23 -0
- package/scripts/deployments/utils/DeployEntrypoint.s.sol +28 -0
- package/scripts/deployments/utils/DeployMember.s.sol +95 -0
- package/scripts/deployments/utils/DeployMockDiamond.s.sol +7 -0
- package/scripts/deployments/utils/DeployMockERC20.s.sol +24 -0
- package/scripts/deployments/utils/DeployMockERC721A.s.sol +45 -0
- package/scripts/deployments/utils/DeployMockLegacyMembership.s.sol +29 -0
- package/scripts/deployments/utils/DeployMockMessenger.s.sol +42 -0
- package/scripts/deployments/utils/DeployMockNFT.s.sol +86 -0
- package/scripts/deployments/utils/DeployPoapEntitlement.s.sol +16 -0
- package/scripts/deployments/utils/DeployProxyBatchDelegation.s.sol +112 -0
- package/scripts/deployments/utils/DeploySpaceProxyInitializer.s.sol +28 -0
- package/scripts/deployments/utils/DeployTieredLogPricingV2.s.sol +23 -0
- package/scripts/deployments/utils/DeployTieredLogPricingV3.s.sol +23 -0
- package/scripts/deployments/utils/DeployTownsBase.s.sol +95 -0
- package/scripts/deployments/utils/DeployTownsMainnet.s.sol +66 -0
- package/scripts/deployments/utils/DeployTownsMulti.s.sol +53 -0
- package/scripts/deployments/utils/DeployWrappedTowns.s.sol +52 -0
- package/scripts/deployments/utils/LibLayerZeroValues.sol +34 -0
- package/scripts/deployments/utils/pricing/TieredLogPricing.s.sol +45 -0
- package/scripts/interactions/InteractAirdrop.s.sol +57 -0
- package/scripts/interactions/InteractAlphaPost.s.sol +32 -0
- package/scripts/interactions/InteractAlphaSparse.s.sol +173 -0
- package/scripts/interactions/InteractBaseAlpha.s.sol +84 -0
- package/scripts/interactions/InteractBaseBridge.s.sol +48 -0
- package/scripts/interactions/InteractBridgeLayerZero.s.sol +102 -0
- package/scripts/interactions/InteractClaimCondition.s.sol +56 -0
- package/scripts/interactions/InteractCreateSpace.s.sol +50 -0
- package/scripts/interactions/InteractDiamondCut.s.sol +47 -0
- package/scripts/interactions/InteractDropFacet.s.sol +32 -0
- package/scripts/interactions/InteractEnableNewSnapshotFormat.s.sol +27 -0
- package/scripts/interactions/InteractEnableNode2NodeAuth.s.sol +27 -0
- package/scripts/interactions/InteractMembership.s.sol +42 -0
- package/scripts/interactions/InteractMockERC721A.s.sol +20 -0
- package/scripts/interactions/InteractNodeOperators.s.sol +41 -0
- package/scripts/interactions/InteractPostDeploy.s.sol +59 -0
- package/scripts/interactions/InteractPrepay.s.sol +30 -0
- package/scripts/interactions/InteractRegisterApp.s.sol +61 -0
- package/scripts/interactions/InteractRiverAlpha.s.sol +30 -0
- package/scripts/interactions/InteractRiverAlphaSparse.s.sol +117 -0
- package/scripts/interactions/InteractRiverMainnet.s.sol +27 -0
- package/scripts/interactions/InteractRiverRegistry.s.sol +36 -0
- package/scripts/interactions/InteractRiverRegistrySetBlocklist.s.sol +30 -0
- package/scripts/interactions/InteractRiverRegistrySetFreq.s.sol +27 -0
- package/scripts/interactions/InteractRiverRegistrySetRepl.s.sol +30 -0
- package/scripts/interactions/InteractSetDefaultUri.s.sol +20 -0
- package/scripts/interactions/InteractSetDefaultUriLocalhost.s.sol +19 -0
- package/scripts/interactions/InteractTransferOwnership.s.sol +21 -0
- package/scripts/interactions/InteractUpdateMbRecencyCheck.s.sol +27 -0
- package/scripts/interactions/InteractUpdateMediaChunkCount.s.sol +27 -0
- package/scripts/interactions/InteractUpdateMediaChunkSize.s.sol +27 -0
- package/scripts/interactions/helpers/AlphaHelper.sol +149 -0
- package/scripts/interactions/helpers/RiverConfigValues.sol +22 -0
- package/scripts/interactions/interfaces/IL1StandardBridge.sol +35 -0
- package/scripts/interactions/interfaces/IL2StandardBridge.sol +69 -0
- package/src/airdrop/drop/DropBase.sol +210 -0
- package/src/airdrop/drop/DropClaim.sol +55 -0
- package/src/airdrop/drop/DropFacet.sol +176 -0
- package/src/airdrop/drop/DropGroup.sol +111 -0
- package/src/airdrop/drop/DropStorage.sol +23 -0
- package/src/airdrop/drop/IDropFacet.sol +136 -0
- package/src/airdrop/points/CheckIn.sol +71 -0
- package/src/airdrop/points/ITownsPoints.sol +64 -0
- package/src/airdrop/points/TownsPoints.sol +196 -0
- package/src/airdrop/points/TownsPointsStorage.sol +22 -0
- package/src/apps/BaseApp.sol +62 -0
- package/src/apps/ITownsApp.sol +28 -0
- package/src/apps/SchemaResolver.sol +170 -0
- package/src/apps/facets/attest/AttestationBase.sol +335 -0
- package/src/apps/facets/attest/AttestationLib.sol +64 -0
- package/src/apps/facets/attest/AttestationRegistry.sol +39 -0
- package/src/apps/facets/attest/AttestationStorage.sol +35 -0
- package/src/apps/facets/attest/IAttestationRegistry.sol +43 -0
- package/src/apps/facets/registry/AppRegistryBase.sol +403 -0
- package/src/apps/facets/registry/AppRegistryFacet.sol +173 -0
- package/src/apps/facets/registry/AppRegistryStorage.sol +53 -0
- package/src/apps/facets/registry/IAppRegistry.sol +159 -0
- package/src/apps/facets/schema/ISchema.sol +14 -0
- package/src/apps/facets/schema/SchemaBase.sol +88 -0
- package/src/apps/facets/schema/SchemaLib.sol +14 -0
- package/src/apps/facets/schema/SchemaRegistry.sol +51 -0
- package/src/apps/facets/schema/SchemaStorage.sol +34 -0
- package/src/apps/helpers/ISimpleApp.sol +51 -0
- package/src/apps/helpers/SimpleApp.sol +97 -0
- package/src/apps/helpers/SimpleAppStorage.sol +27 -0
- package/src/base/registry/facets/checker/EntitlementChecker.sol +237 -0
- package/src/base/registry/facets/checker/EntitlementCheckerStorage.sol +28 -0
- package/src/base/registry/facets/checker/IEntitlementChecker.sol +95 -0
- package/src/base/registry/facets/delegation/ISpaceDelegation.sol +69 -0
- package/src/base/registry/facets/delegation/SpaceDelegationFacet.sol +250 -0
- package/src/base/registry/facets/delegation/SpaceDelegationStorage.sol +35 -0
- package/src/base/registry/facets/distribution/v1/IRewardsDistribution.sol +51 -0
- package/src/base/registry/facets/distribution/v1/RewardsDistribution.sol +439 -0
- package/src/base/registry/facets/distribution/v1/RewardsDistributionStorage.sol +32 -0
- package/src/base/registry/facets/distribution/v2/DelegationProxy.sol +53 -0
- package/src/base/registry/facets/distribution/v2/IRewardsDistribution.sol +372 -0
- package/src/base/registry/facets/distribution/v2/RewardsDistributionBase.sol +299 -0
- package/src/base/registry/facets/distribution/v2/RewardsDistributionStorage.sol +37 -0
- package/src/base/registry/facets/distribution/v2/RewardsDistributionV2.sol +392 -0
- package/src/base/registry/facets/distribution/v2/StakingRewards.sol +466 -0
- package/src/base/registry/facets/mainnet/ICrossDomainMessenger.sol +58 -0
- package/src/base/registry/facets/mainnet/IMainnetDelegation.sol +127 -0
- package/src/base/registry/facets/mainnet/MainnetDelegation.sol +119 -0
- package/src/base/registry/facets/mainnet/MainnetDelegationBase.sol +274 -0
- package/src/base/registry/facets/mainnet/MainnetDelegationStorage.sol +36 -0
- package/src/base/registry/facets/operator/INodeOperator.sol +91 -0
- package/src/base/registry/facets/operator/NodeOperatorFacet.sol +189 -0
- package/src/base/registry/facets/operator/NodeOperatorStorage.sol +39 -0
- package/src/base/registry/facets/xchain/IXChain.sol +54 -0
- package/src/base/registry/facets/xchain/XChain.sol +158 -0
- package/src/base/registry/facets/xchain/XChainCheckLib.sol +105 -0
- package/src/base/registry/facets/xchain/XChainLib.sol +46 -0
- package/src/diamond/facets/beacon/UpgradeableBeacon.sol +38 -0
- package/src/diamond/facets/beacon/UpgradeableBeaconFacet.sol +34 -0
- package/src/diamond/facets/governance/votes/Checkpoints.sol +642 -0
- package/src/diamond/facets/governance/votes/Votes.sol +63 -0
- package/src/diamond/facets/governance/votes/VotesBase.sol +274 -0
- package/src/diamond/facets/governance/votes/VotesStorage.sol +21 -0
- package/src/diamond/facets/governance/votes/enumerable/IVotesEnumerable.sol +38 -0
- package/src/diamond/facets/governance/votes/enumerable/VotesEnumerable.sol +39 -0
- package/src/diamond/facets/governance/votes/enumerable/VotesEnumerableLib.sol +102 -0
- package/src/diamond/facets/metadata/IMetadata.sol +27 -0
- package/src/diamond/facets/metadata/MetadataFacet.sol +71 -0
- package/src/diamond/facets/token/ERC5643/ERC5643.sol +51 -0
- package/src/diamond/facets/token/ERC5643/ERC5643Base.sol +48 -0
- package/src/diamond/facets/token/ERC5643/ERC5643Storage.sol +26 -0
- package/src/diamond/facets/token/ERC5643/IERC5643.sol +44 -0
- package/src/diamond/facets/token/ERC721A/ERC721A.sol +270 -0
- package/src/diamond/facets/token/ERC721A/ERC721ABase.sol +829 -0
- package/src/diamond/facets/token/ERC721A/ERC721ANonTransferable.sol +21 -0
- package/src/diamond/facets/token/ERC721A/ERC721AStorage.sol +115 -0
- package/src/diamond/facets/token/ERC721A/IERC721A.sol +283 -0
- package/src/diamond/facets/token/ERC721A/extensions/ERC721AQueryable.sol +134 -0
- package/src/diamond/facets/token/ERC721A/extensions/IERC721AQueryable.sol +83 -0
- package/src/diamond/utils/Context.sol +19 -0
- package/src/factory/SpaceFactoryInit.sol +17 -0
- package/src/factory/facets/architect/Architect.sol +98 -0
- package/src/factory/facets/architect/ArchitectBase.sol +95 -0
- package/src/factory/facets/architect/ArchitectStorage.sol +28 -0
- package/src/factory/facets/architect/IArchitect.sol +155 -0
- package/src/factory/facets/architect/ImplementationStorage.sol +42 -0
- package/src/factory/facets/architect/pricing/IPricingModules.sol +41 -0
- package/src/factory/facets/architect/pricing/PricingModulesBase.sol +89 -0
- package/src/factory/facets/architect/pricing/PricingModulesFacet.sol +40 -0
- package/src/factory/facets/architect/pricing/PricingModulesStorage.sol +30 -0
- package/src/factory/facets/create/CreateSpace.sol +107 -0
- package/src/factory/facets/create/CreateSpaceLib.sol +335 -0
- package/src/factory/facets/create/ICreateSpace.sol +70 -0
- package/src/factory/facets/feature/FeatureConditionLib.sol +53 -0
- package/src/factory/facets/feature/FeatureManagerFacet.sol +66 -0
- package/src/factory/facets/feature/FeatureManagerLib.sol +168 -0
- package/src/factory/facets/feature/IFeatureManagerFacet.sol +73 -0
- package/src/factory/facets/partner/IPartnerRegistry.sol +56 -0
- package/src/factory/facets/partner/PartnerRegistry.sol +57 -0
- package/src/factory/facets/partner/PartnerRegistryBase.sol +132 -0
- package/src/factory/facets/partner/PartnerRegistryStorage.sol +40 -0
- package/src/factory/facets/platform/requirements/IPlatformRequirements.sol +143 -0
- package/src/factory/facets/platform/requirements/PlatformRequirementsBase.sol +124 -0
- package/src/factory/facets/platform/requirements/PlatformRequirementsFacet.sol +122 -0
- package/src/factory/facets/platform/requirements/PlatformRequirementsStorage.sol +41 -0
- package/src/factory/facets/registry/IImplementationRegistry.sol +46 -0
- package/src/factory/facets/registry/ImplementationRegistry.sol +64 -0
- package/src/factory/facets/registry/ImplementationRegistryStorage.sol +28 -0
- package/src/factory/facets/wallet-link/IWalletLink.sol +218 -0
- package/src/factory/facets/wallet-link/WalletLink.sol +108 -0
- package/src/factory/facets/wallet-link/WalletLinkBase.sol +492 -0
- package/src/factory/facets/wallet-link/interfaces/IDelegateRegistry.sol +63 -0
- package/src/factory/facets/wallet-link/interfaces/IDelegateRegistryV1.sol +35 -0
- package/src/factory/facets/wallet-link/interfaces/ISCL_EIP6565.sol +24 -0
- package/src/factory/facets/wallet-link/libraries/SolanaUtils.sol +161 -0
- package/src/factory/facets/wallet-link/libraries/WalletLib.sol +62 -0
- package/src/river/registry/facets/config/IRiverConfig.sol +117 -0
- package/src/river/registry/facets/config/RiverConfig.sol +174 -0
- package/src/river/registry/facets/node/INodeRegistry.sol +69 -0
- package/src/river/registry/facets/node/NodeRegistry.sol +143 -0
- package/src/river/registry/facets/operator/IOperatorRegistry.sol +28 -0
- package/src/river/registry/facets/operator/OperatorRegistry.sol +86 -0
- package/src/river/registry/facets/stream/IStreamRegistry.sol +184 -0
- package/src/river/registry/facets/stream/StreamRegistry.sol +396 -0
- package/src/river/registry/libraries/RegistryErrors.sol +24 -0
- package/src/river/registry/libraries/RegistryStorage.sol +181 -0
- package/src/router/ISwapRouter.sol +226 -0
- package/src/router/Permit2Hash.sol +92 -0
- package/src/router/SwapRouter.sol +463 -0
- package/src/router/SwapRouterStorage.sol +21 -0
- package/src/spaces/entitlements/ICrossChainEntitlement.sol +22 -0
- package/src/spaces/entitlements/IEntitlement.sol +61 -0
- package/src/spaces/entitlements/PolymarketEntitlement.sol +79 -0
- package/src/spaces/entitlements/poap/IPOAP.sol +26 -0
- package/src/spaces/entitlements/poap/PoapEntitlement.sol +56 -0
- package/src/spaces/entitlements/rule/IRuleEntitlement.sol +174 -0
- package/src/spaces/entitlements/rule/RuleEntitlement.sol +183 -0
- package/src/spaces/entitlements/rule/RuleEntitlementV2.sol +219 -0
- package/src/spaces/entitlements/user/IUserEntitlement.sol +24 -0
- package/src/spaces/entitlements/user/UserEntitlement.sol +273 -0
- package/src/spaces/facets/DependencyLib.sol +60 -0
- package/src/spaces/facets/Entitled.sol +172 -0
- package/src/spaces/facets/Permissions.sol +21 -0
- package/src/spaces/facets/account/AppAccount.sol +93 -0
- package/src/spaces/facets/account/AppAccountBase.sol +275 -0
- package/src/spaces/facets/account/AppAccountStorage.sol +63 -0
- package/src/spaces/facets/account/IAppAccount.sol +71 -0
- package/src/spaces/facets/account/SignerFacet.sol +26 -0
- package/src/spaces/facets/banning/Banning.sol +41 -0
- package/src/spaces/facets/banning/BanningBase.sol +33 -0
- package/src/spaces/facets/banning/BanningStorage.sol +23 -0
- package/src/spaces/facets/banning/IBanning.sol +35 -0
- package/src/spaces/facets/channels/ChannelBase.sol +87 -0
- package/src/spaces/facets/channels/ChannelService.sol +177 -0
- package/src/spaces/facets/channels/ChannelStorage.sol +34 -0
- package/src/spaces/facets/channels/Channels.sol +80 -0
- package/src/spaces/facets/channels/IChannel.sol +98 -0
- package/src/spaces/facets/dispatcher/DispatcherBase.sol +86 -0
- package/src/spaces/facets/dispatcher/DispatcherStorage.sol +21 -0
- package/src/spaces/facets/dispatcher/IDispatcher.sol +6 -0
- package/src/spaces/facets/entitlements/EntitlementsManager.sol +49 -0
- package/src/spaces/facets/entitlements/EntitlementsManagerBase.sol +87 -0
- package/src/spaces/facets/entitlements/EntitlementsManagerService.sol +142 -0
- package/src/spaces/facets/entitlements/EntitlementsManagerStorage.sol +34 -0
- package/src/spaces/facets/entitlements/IEntitlementsManager.sol +67 -0
- package/src/spaces/facets/entitlements/extensions/EntitlementDataQueryable.sol +153 -0
- package/src/spaces/facets/entitlements/extensions/IEntitlementDataQueryable.sol +32 -0
- package/src/spaces/facets/executor/ExecutorBase.sol +564 -0
- package/src/spaces/facets/executor/ExecutorFacet.sol +178 -0
- package/src/spaces/facets/executor/ExecutorStorage.sol +99 -0
- package/src/spaces/facets/executor/GroupLib.sol +128 -0
- package/src/spaces/facets/executor/IExecutor.sol +287 -0
- package/src/spaces/facets/executor/hooks/HookBase.sol +172 -0
- package/src/spaces/facets/executor/hooks/HookLib.sol +38 -0
- package/src/spaces/facets/executor/hooks/IHookBase.sol +48 -0
- package/src/spaces/facets/gated/EntitlementGated.sol +59 -0
- package/src/spaces/facets/gated/EntitlementGatedBase.sol +324 -0
- package/src/spaces/facets/gated/EntitlementGatedStorage.sol +29 -0
- package/src/spaces/facets/gated/IEntitlementGated.sol +55 -0
- package/src/spaces/facets/guardian/GuardianBase.sol +80 -0
- package/src/spaces/facets/guardian/GuardianFacet.sol +43 -0
- package/src/spaces/facets/guardian/GuardianStorage.sol +27 -0
- package/src/spaces/facets/guardian/IGuardian.sol +54 -0
- package/src/spaces/facets/membership/IMembership.sol +216 -0
- package/src/spaces/facets/membership/MembershipBase.sol +272 -0
- package/src/spaces/facets/membership/MembershipFacet.sol +191 -0
- package/src/spaces/facets/membership/MembershipStorage.sol +40 -0
- package/src/spaces/facets/membership/join/MembershipJoin.sol +547 -0
- package/src/spaces/facets/membership/metadata/IMembershipMetadata.sol +9 -0
- package/src/spaces/facets/membership/metadata/MembershipMetadata.sol +32 -0
- package/src/spaces/facets/membership/pricing/IMembershipPricing.sol +18 -0
- package/src/spaces/facets/membership/pricing/fixed/FixedPricing.sol +29 -0
- package/src/spaces/facets/membership/pricing/fixed/FixedPricingStorage.sol +27 -0
- package/src/spaces/facets/membership/pricing/tiered/TieredLogPricingOracleV2.sol +148 -0
- package/src/spaces/facets/membership/pricing/tiered/TieredLogPricingOracleV3.sol +137 -0
- package/src/spaces/facets/membership/token/MembershipToken.sol +25 -0
- package/src/spaces/facets/owner/ISpaceOwner.sol +85 -0
- package/src/spaces/facets/owner/SpaceOwner.sol +174 -0
- package/src/spaces/facets/owner/SpaceOwnerBase.sol +121 -0
- package/src/spaces/facets/owner/SpaceOwnerStorage.sol +41 -0
- package/src/spaces/facets/owner/SpaceOwnerUriBase.sol +54 -0
- package/src/spaces/facets/points/PointsBase.sol +35 -0
- package/src/spaces/facets/prepay/IPrepay.sol +43 -0
- package/src/spaces/facets/prepay/PrepayBase.sol +27 -0
- package/src/spaces/facets/prepay/PrepayFacet.sol +59 -0
- package/src/spaces/facets/prepay/PrepayStorage.sol +26 -0
- package/src/spaces/facets/proxy/ISpaceProxyInitializer.sol +21 -0
- package/src/spaces/facets/proxy/SpaceProxy.sol +15 -0
- package/src/spaces/facets/proxy/SpaceProxyInitializer.sol +55 -0
- package/src/spaces/facets/referrals/IReferrals.sol +98 -0
- package/src/spaces/facets/referrals/ReferralsBase.sol +81 -0
- package/src/spaces/facets/referrals/ReferralsFacet.sol +65 -0
- package/src/spaces/facets/referrals/ReferralsStorage.sol +36 -0
- package/src/spaces/facets/review/IReview.sol +50 -0
- package/src/spaces/facets/review/ReviewFacet.sol +105 -0
- package/src/spaces/facets/review/ReviewStorage.sol +29 -0
- package/src/spaces/facets/roles/IRoles.sol +197 -0
- package/src/spaces/facets/roles/Roles.sol +123 -0
- package/src/spaces/facets/roles/RolesBase.sol +420 -0
- package/src/spaces/facets/roles/RolesStorage.sol +132 -0
- package/src/spaces/facets/swap/ISwapFacet.sol +91 -0
- package/src/spaces/facets/swap/SwapFacet.sol +290 -0
- package/src/spaces/facets/swap/SwapFacetStorage.sol +24 -0
- package/src/spaces/facets/tipping/ITipping.sol +80 -0
- package/src/spaces/facets/tipping/TippingBase.sol +73 -0
- package/src/spaces/facets/tipping/TippingFacet.sol +123 -0
- package/src/spaces/facets/treasury/ITreasury.sol +64 -0
- package/src/spaces/facets/treasury/Treasury.sol +82 -0
- package/src/spaces/facets/xchain/SpaceEntitlementGated.sol +62 -0
- package/src/tokens/Member.sol +246 -0
- package/src/tokens/lock/ILock.sol +42 -0
- package/src/tokens/lock/LockBase.sol +64 -0
- package/src/tokens/lock/LockFacet.sol +44 -0
- package/src/tokens/lock/LockStorage.sol +26 -0
- package/src/tokens/mainnet/claimer/AuthorizedClaimerStorage.sol +26 -0
- package/src/tokens/mainnet/claimer/AuthorizedClaimers.sol +84 -0
- package/src/tokens/mainnet/claimer/IAuthorizedClaimers.sol +36 -0
- package/src/tokens/mainnet/delegation/ProxyBatchDelegation.sol +86 -0
- package/src/tokens/migration/ITokenMigration.sol +35 -0
- package/src/tokens/migration/TokenMigrationFacet.sol +86 -0
- package/src/tokens/migration/TokenMigrationStorage.sol +27 -0
- package/src/tokens/towns/base/IERC7802.sol +30 -0
- package/src/tokens/towns/base/IOptimismMintableERC20.sol +31 -0
- package/src/tokens/towns/base/ISemver.sol +13 -0
- package/src/tokens/towns/base/Towns.sol +283 -0
- package/src/tokens/towns/base/TownsDeployer.sol +32 -0
- package/src/tokens/towns/base/TownsLib.sol +31 -0
- package/src/tokens/towns/base/versions/TownsV2.sol +15 -0
- package/src/tokens/towns/mainnet/ITowns.sol +56 -0
- package/src/tokens/towns/mainnet/Towns.sol +220 -0
- package/src/tokens/towns/mainnet/libs/TokenInflationLib.sol +89 -0
- package/src/tokens/towns/multichain/Towns.sol +19 -0
- package/src/tokens/towns/multichain/wTowns.sol +18 -0
- package/src/utils/Airdrop.sol +156 -0
- package/src/utils/airdrop/merkle/IMerkleAirdrop.sol +55 -0
- package/src/utils/airdrop/merkle/MerkleAirdrop.sol +118 -0
- package/src/utils/airdrop/merkle/MerkleAirdropStorage.sol +29 -0
- package/src/utils/interfaces/AggregatorV3Interface.sol +37 -0
- package/src/utils/interfaces/IMulticall.sol +10 -0
- package/src/utils/interfaces/IWETH.sol +10 -0
- package/src/utils/libraries/BasisPoints.sol +24 -0
- package/src/utils/libraries/Create2Utils.sol +74 -0
- package/src/utils/libraries/CurrencyTransfer.sol +99 -0
- package/src/utils/libraries/CustomRevert.sol +49 -0
- package/src/utils/libraries/Factory.sol +66 -0
- package/src/utils/libraries/StringSet.sol +190 -0
- package/src/utils/libraries/Validator.sol +31 -0
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
import {ITownsPointsBase} from "../../../../airdrop/points/ITownsPoints.sol";
|
|
6
|
+
import {IPartnerRegistry, IPartnerRegistryBase} from "../../../../factory/facets/partner/IPartnerRegistry.sol";
|
|
7
|
+
import {IEntitlement} from "../../../entitlements/IEntitlement.sol";
|
|
8
|
+
import {IRuleEntitlement} from "../../../entitlements/rule/IRuleEntitlement.sol";
|
|
9
|
+
import {IRolesBase} from "../../roles/IRoles.sol";
|
|
10
|
+
import {IMembership} from "../IMembership.sol";
|
|
11
|
+
|
|
12
|
+
// libraries
|
|
13
|
+
import {BasisPoints} from "../../../../utils/libraries/BasisPoints.sol";
|
|
14
|
+
import {CurrencyTransfer} from "../../../../utils/libraries/CurrencyTransfer.sol";
|
|
15
|
+
import {CustomRevert} from "../../../../utils/libraries/CustomRevert.sol";
|
|
16
|
+
import {Permissions} from "../../Permissions.sol";
|
|
17
|
+
|
|
18
|
+
// contracts
|
|
19
|
+
import {ERC5643Base} from "../../../../diamond/facets/token/ERC5643/ERC5643Base.sol";
|
|
20
|
+
import {ERC721ABase} from "../../../../diamond/facets/token/ERC721A/ERC721ABase.sol";
|
|
21
|
+
import {DispatcherBase} from "../../dispatcher/DispatcherBase.sol";
|
|
22
|
+
import {Entitled} from "../../Entitled.sol";
|
|
23
|
+
import {EntitlementGatedBase} from "../../gated/EntitlementGatedBase.sol";
|
|
24
|
+
import {PointsBase} from "../../points/PointsBase.sol";
|
|
25
|
+
import {PrepayBase} from "../../prepay/PrepayBase.sol";
|
|
26
|
+
import {ReferralsBase} from "../../referrals/ReferralsBase.sol";
|
|
27
|
+
import {RolesBase} from "../../roles/RolesBase.sol";
|
|
28
|
+
import {MembershipBase} from "../MembershipBase.sol";
|
|
29
|
+
|
|
30
|
+
/// @title MembershipJoin
|
|
31
|
+
/// @notice Handles the logic for joining a space, including entitlement checks and payment
|
|
32
|
+
/// processing
|
|
33
|
+
/// @dev Inherits from multiple base contracts to provide comprehensive membership functionality
|
|
34
|
+
abstract contract MembershipJoin is
|
|
35
|
+
IRolesBase,
|
|
36
|
+
IPartnerRegistryBase,
|
|
37
|
+
ERC5643Base,
|
|
38
|
+
MembershipBase,
|
|
39
|
+
ReferralsBase,
|
|
40
|
+
DispatcherBase,
|
|
41
|
+
RolesBase,
|
|
42
|
+
EntitlementGatedBase,
|
|
43
|
+
Entitled,
|
|
44
|
+
PrepayBase,
|
|
45
|
+
PointsBase,
|
|
46
|
+
ERC721ABase
|
|
47
|
+
{
|
|
48
|
+
using CustomRevert for bytes4;
|
|
49
|
+
|
|
50
|
+
/// @notice Constant representing the permission to join a space
|
|
51
|
+
bytes32 internal constant JOIN_SPACE = bytes32(abi.encodePacked(Permissions.JoinSpace));
|
|
52
|
+
|
|
53
|
+
/// @notice Constant representing the joinSpace(address) function selector
|
|
54
|
+
bytes4 internal constant JOIN_SPACE_SELECTOR = bytes4(keccak256("joinSpace(address)"));
|
|
55
|
+
|
|
56
|
+
/// @notice Encodes data for joining a space
|
|
57
|
+
/// @param selector The type of transaction (join with or without referral)
|
|
58
|
+
/// @param sender The address of the sender
|
|
59
|
+
/// @param receiver The address of the receiver
|
|
60
|
+
/// @param referralData Additional data for referrals
|
|
61
|
+
/// @return Encoded join space data
|
|
62
|
+
function _encodeJoinSpaceData(
|
|
63
|
+
bytes4 selector,
|
|
64
|
+
address sender,
|
|
65
|
+
address receiver,
|
|
66
|
+
bytes memory referralData
|
|
67
|
+
) internal pure returns (bytes memory) {
|
|
68
|
+
return abi.encode(selector, sender, receiver, referralData);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/// @notice Calculates all pricing details for joining a space
|
|
72
|
+
/// @return joinDetails Struct containing all pricing information
|
|
73
|
+
function _getPricingDetails() internal view returns (PricingDetails memory joinDetails) {
|
|
74
|
+
uint256 totalSupply = _totalSupply();
|
|
75
|
+
uint256 membershipPrice = _getMembershipPrice(totalSupply);
|
|
76
|
+
uint256 freeAllocation = _getMembershipFreeAllocation();
|
|
77
|
+
uint256 prepaidSupply = _getPrepaidSupply();
|
|
78
|
+
|
|
79
|
+
joinDetails.basePrice = membershipPrice;
|
|
80
|
+
if (freeAllocation > totalSupply) {
|
|
81
|
+
return joinDetails;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Check if this is a free join due to prepaid supply
|
|
85
|
+
if (prepaidSupply > 0) {
|
|
86
|
+
joinDetails.isPrepaid = true;
|
|
87
|
+
return joinDetails;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Regular paid join
|
|
91
|
+
joinDetails.amountDue = membershipPrice;
|
|
92
|
+
joinDetails.shouldCharge = true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/// @notice Handles the process of joining a space
|
|
96
|
+
/// @param receiver The address that will receive the membership token
|
|
97
|
+
function _joinSpace(address receiver) internal {
|
|
98
|
+
_validateJoinSpace(receiver);
|
|
99
|
+
|
|
100
|
+
PricingDetails memory joinDetails = _getPricingDetails();
|
|
101
|
+
|
|
102
|
+
// Validate payment if required
|
|
103
|
+
if (joinDetails.shouldCharge && msg.value < joinDetails.amountDue) {
|
|
104
|
+
Membership__InsufficientPayment.selector.revertWith();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Consume prepaid membership if applicable
|
|
108
|
+
if (joinDetails.isPrepaid) _reducePrepay(1);
|
|
109
|
+
|
|
110
|
+
bytes32 transactionId = _registerTransaction(
|
|
111
|
+
receiver,
|
|
112
|
+
_encodeJoinSpaceData(JOIN_SPACE_SELECTOR, msg.sender, receiver, "")
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
(bool isEntitled, bool isCrosschainPending) = _checkEntitlement(
|
|
116
|
+
receiver,
|
|
117
|
+
msg.sender,
|
|
118
|
+
transactionId,
|
|
119
|
+
joinDetails.amountDue
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
if (!isCrosschainPending) {
|
|
123
|
+
if (isEntitled) {
|
|
124
|
+
if (joinDetails.shouldCharge) _chargeForJoinSpace(transactionId, joinDetails);
|
|
125
|
+
_refundBalance(transactionId, receiver);
|
|
126
|
+
_issueToken(receiver);
|
|
127
|
+
} else {
|
|
128
|
+
_rejectMembership(transactionId, receiver);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/// @notice Handles the process of joining a space with a referral
|
|
134
|
+
/// @param receiver The address that will receive the membership token
|
|
135
|
+
/// @param referral The referral information
|
|
136
|
+
function _joinSpaceWithReferral(address receiver, ReferralTypes memory referral) internal {
|
|
137
|
+
_validateJoinSpace(receiver);
|
|
138
|
+
|
|
139
|
+
PricingDetails memory joinDetails = _getPricingDetails();
|
|
140
|
+
|
|
141
|
+
// Validate payment if required
|
|
142
|
+
if (joinDetails.shouldCharge && msg.value < joinDetails.amountDue) {
|
|
143
|
+
Membership__InsufficientPayment.selector.revertWith();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Consume prepaid membership if applicable
|
|
147
|
+
if (joinDetails.isPrepaid) {
|
|
148
|
+
_reducePrepay(1);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
_validateUserReferral(receiver, referral);
|
|
152
|
+
|
|
153
|
+
bytes memory referralData = abi.encode(referral);
|
|
154
|
+
|
|
155
|
+
bytes4 selector = IMembership.joinSpaceWithReferral.selector;
|
|
156
|
+
|
|
157
|
+
bytes32 transactionId = _registerTransaction(
|
|
158
|
+
receiver,
|
|
159
|
+
_encodeJoinSpaceData(selector, msg.sender, receiver, referralData)
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
(bool isEntitled, bool isCrosschainPending) = _checkEntitlement(
|
|
163
|
+
receiver,
|
|
164
|
+
msg.sender,
|
|
165
|
+
transactionId,
|
|
166
|
+
joinDetails.amountDue
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
if (!isCrosschainPending) {
|
|
170
|
+
if (isEntitled) {
|
|
171
|
+
if (joinDetails.shouldCharge)
|
|
172
|
+
_chargeForJoinSpaceWithReferral(transactionId, joinDetails);
|
|
173
|
+
|
|
174
|
+
_refundBalance(transactionId, receiver);
|
|
175
|
+
_issueToken(receiver);
|
|
176
|
+
} else {
|
|
177
|
+
_rejectMembership(transactionId, receiver);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function _rejectMembership(bytes32 transactionId, address receiver) internal {
|
|
183
|
+
_deleteCapturedData(transactionId);
|
|
184
|
+
_refundBalance(transactionId, receiver);
|
|
185
|
+
emit MembershipTokenRejected(receiver);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function _validateUserReferral(address receiver, ReferralTypes memory referral) internal view {
|
|
189
|
+
if (referral.userReferral != address(0)) {
|
|
190
|
+
if (referral.userReferral == receiver || referral.userReferral == msg.sender) {
|
|
191
|
+
Membership__InvalidAddress.selector.revertWith();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/// @notice Checks if a user is entitled to join the space and handles the entitlement process
|
|
197
|
+
/// @dev This function checks both local and crosschain entitlements
|
|
198
|
+
/// @param receiver The address of the user trying to join the space
|
|
199
|
+
/// @param transactionId The unique identifier for this join transaction
|
|
200
|
+
/// @return isEntitled A boolean indicating whether the user is entitled to join
|
|
201
|
+
/// @return isCrosschainPending A boolean indicating if a crosschain entitlement check is
|
|
202
|
+
/// pending
|
|
203
|
+
function _checkEntitlement(
|
|
204
|
+
address receiver,
|
|
205
|
+
address sender,
|
|
206
|
+
bytes32 transactionId,
|
|
207
|
+
uint256 requiredAmount
|
|
208
|
+
) internal virtual returns (bool isEntitled, bool isCrosschainPending) {
|
|
209
|
+
IRolesBase.Role[] memory roles = _getRolesWithPermission(Permissions.JoinSpace);
|
|
210
|
+
|
|
211
|
+
// PHASE 1: Check LOCAL entitlements first (no payment needed)
|
|
212
|
+
if (_checkLocalEntitlements(roles, receiver)) return (true, false);
|
|
213
|
+
|
|
214
|
+
// PHASE 2: No local entitlements passed - check crosschain entitlements
|
|
215
|
+
return _checkCrosschainEntitlements(roles, receiver, sender, transactionId, requiredAmount);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/// @notice Checks local entitlements
|
|
219
|
+
/// @param receiver The address to check entitlements for
|
|
220
|
+
/// @return isLocallyEntitled True if user has local entitlements
|
|
221
|
+
function _checkLocalEntitlements(
|
|
222
|
+
IRolesBase.Role[] memory roles,
|
|
223
|
+
address receiver
|
|
224
|
+
) internal view returns (bool isLocallyEntitled) {
|
|
225
|
+
address[] memory linkedWallets = _getLinkedWalletsWithUser(receiver);
|
|
226
|
+
|
|
227
|
+
for (uint256 i; i < roles.length; ++i) {
|
|
228
|
+
if (roles[i].disabled) continue;
|
|
229
|
+
|
|
230
|
+
for (uint256 j; j < roles[i].entitlements.length; ++j) {
|
|
231
|
+
IEntitlement entitlement = IEntitlement(roles[i].entitlements[j]);
|
|
232
|
+
|
|
233
|
+
// Check local entitlements first
|
|
234
|
+
if (
|
|
235
|
+
!entitlement.isCrosschain() &&
|
|
236
|
+
entitlement.isEntitled(IN_TOWN, linkedWallets, JOIN_SPACE)
|
|
237
|
+
) {
|
|
238
|
+
// Local entitlement passed - return true (payment handled by existing flow)
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/// @notice Handles crosschain entitlement checks with proper payment distribution
|
|
247
|
+
/// @param receiver The address to check entitlements for
|
|
248
|
+
/// @param sender The address sending the transaction
|
|
249
|
+
/// @param transactionId The transaction identifier
|
|
250
|
+
/// @param requiredAmount The required payment amount
|
|
251
|
+
/// @return isEntitled Whether user is entitled (always false for crosschain)
|
|
252
|
+
/// @return isCrosschainPending Whether crosschain checks are pending
|
|
253
|
+
function _checkCrosschainEntitlements(
|
|
254
|
+
IRolesBase.Role[] memory roles,
|
|
255
|
+
address receiver,
|
|
256
|
+
address sender,
|
|
257
|
+
bytes32 transactionId,
|
|
258
|
+
uint256 requiredAmount
|
|
259
|
+
) internal returns (bool isEntitled, bool isCrosschainPending) {
|
|
260
|
+
bool paymentSent = false;
|
|
261
|
+
|
|
262
|
+
for (uint256 i; i < roles.length; ++i) {
|
|
263
|
+
if (roles[i].disabled) continue;
|
|
264
|
+
|
|
265
|
+
for (uint256 j; j < roles[i].entitlements.length; ++j) {
|
|
266
|
+
IEntitlement entitlement = IEntitlement(roles[i].entitlements[j]);
|
|
267
|
+
|
|
268
|
+
if (entitlement.isCrosschain()) {
|
|
269
|
+
if (!paymentSent) {
|
|
270
|
+
// Send only the required amount to crosschain check
|
|
271
|
+
// Excess will be handled by existing refund mechanisms
|
|
272
|
+
_requestEntitlementCheckV2(
|
|
273
|
+
receiver,
|
|
274
|
+
sender,
|
|
275
|
+
transactionId,
|
|
276
|
+
IRuleEntitlement(address(entitlement)),
|
|
277
|
+
roles[i].id,
|
|
278
|
+
requiredAmount
|
|
279
|
+
);
|
|
280
|
+
paymentSent = true;
|
|
281
|
+
} else {
|
|
282
|
+
_requestEntitlementCheckV2(
|
|
283
|
+
receiver,
|
|
284
|
+
sender,
|
|
285
|
+
transactionId,
|
|
286
|
+
IRuleEntitlement(address(entitlement)),
|
|
287
|
+
roles[i].id,
|
|
288
|
+
0
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
isCrosschainPending = true;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return (false, isCrosschainPending);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/// @notice Processes the charge for joining a space without referral
|
|
300
|
+
/// @param transactionId The unique identifier for this join transaction
|
|
301
|
+
/// @param joinDetails The pricing details for this join
|
|
302
|
+
function _chargeForJoinSpace(
|
|
303
|
+
bytes32 transactionId,
|
|
304
|
+
PricingDetails memory joinDetails
|
|
305
|
+
) internal {
|
|
306
|
+
(bytes4 selector, address sender, address receiver, ) = abi.decode(
|
|
307
|
+
_getCapturedData(transactionId),
|
|
308
|
+
(bytes4, address, address, bytes)
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
if (selector != JOIN_SPACE_SELECTOR) {
|
|
312
|
+
Membership__InvalidTransactionType.selector.revertWith();
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
uint256 protocolFee = _collectProtocolFee(sender, joinDetails.basePrice);
|
|
316
|
+
uint256 ownerProceeds = joinDetails.amountDue - protocolFee;
|
|
317
|
+
|
|
318
|
+
_afterChargeForJoinSpace(
|
|
319
|
+
transactionId,
|
|
320
|
+
sender,
|
|
321
|
+
receiver,
|
|
322
|
+
joinDetails.amountDue,
|
|
323
|
+
ownerProceeds,
|
|
324
|
+
joinDetails.basePrice
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/// @notice Processes the charge for joining a space with referral
|
|
329
|
+
/// @param transactionId The unique identifier for this join transaction
|
|
330
|
+
/// @param joinDetails The pricing details for this join
|
|
331
|
+
function _chargeForJoinSpaceWithReferral(
|
|
332
|
+
bytes32 transactionId,
|
|
333
|
+
PricingDetails memory joinDetails
|
|
334
|
+
) internal {
|
|
335
|
+
(bytes4 selector, address sender, address receiver, bytes memory referralData) = abi.decode(
|
|
336
|
+
_getCapturedData(transactionId),
|
|
337
|
+
(bytes4, address, address, bytes)
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
if (selector != IMembership.joinSpaceWithReferral.selector) {
|
|
341
|
+
Membership__InvalidTransactionType.selector.revertWith();
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
ReferralTypes memory referral = abi.decode(referralData, (ReferralTypes));
|
|
345
|
+
|
|
346
|
+
uint256 ownerProceeds;
|
|
347
|
+
{
|
|
348
|
+
uint256 protocolFee = _collectProtocolFee(sender, joinDetails.basePrice);
|
|
349
|
+
|
|
350
|
+
uint256 partnerFee = _collectPartnerFee(
|
|
351
|
+
sender,
|
|
352
|
+
referral.partner,
|
|
353
|
+
joinDetails.basePrice
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
uint256 referralFee = _collectReferralCodeFee(
|
|
357
|
+
sender,
|
|
358
|
+
referral.userReferral,
|
|
359
|
+
referral.referralCode,
|
|
360
|
+
joinDetails.basePrice
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
ownerProceeds = joinDetails.amountDue - protocolFee - partnerFee - referralFee;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
_afterChargeForJoinSpace(
|
|
367
|
+
transactionId,
|
|
368
|
+
sender,
|
|
369
|
+
receiver,
|
|
370
|
+
joinDetails.amountDue,
|
|
371
|
+
ownerProceeds,
|
|
372
|
+
joinDetails.basePrice
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function _afterChargeForJoinSpace(
|
|
377
|
+
bytes32 transactionId,
|
|
378
|
+
address payer,
|
|
379
|
+
address receiver,
|
|
380
|
+
uint256 paymentRequired,
|
|
381
|
+
uint256 ownerProceeds,
|
|
382
|
+
uint256 membershipPrice
|
|
383
|
+
) internal {
|
|
384
|
+
// account for owner's proceeds
|
|
385
|
+
if (ownerProceeds != 0) _transferIn(payer, ownerProceeds);
|
|
386
|
+
|
|
387
|
+
_releaseCapturedValue(transactionId, paymentRequired);
|
|
388
|
+
_deleteCapturedData(transactionId);
|
|
389
|
+
|
|
390
|
+
_mintMembershipPoints(receiver, membershipPrice);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/// @notice Issues a membership token to the receiver
|
|
394
|
+
/// @param receiver The address that will receive the membership token
|
|
395
|
+
function _issueToken(address receiver) internal {
|
|
396
|
+
// get token id
|
|
397
|
+
uint256 tokenId = _nextTokenId();
|
|
398
|
+
|
|
399
|
+
// set renewal price for token
|
|
400
|
+
_setMembershipRenewalPrice(tokenId, _getMembershipPrice(_totalSupply()));
|
|
401
|
+
|
|
402
|
+
// mint membership
|
|
403
|
+
_safeMint(receiver, 1);
|
|
404
|
+
|
|
405
|
+
// set expiration of membership
|
|
406
|
+
_renewSubscription(tokenId, _getMembershipDuration());
|
|
407
|
+
|
|
408
|
+
// emit event
|
|
409
|
+
emit MembershipTokenIssued(receiver, tokenId);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/// @notice Validates if a user can join the space
|
|
413
|
+
/// @param receiver The address that will receive the membership token
|
|
414
|
+
function _validateJoinSpace(address receiver) internal view {
|
|
415
|
+
if (receiver == address(0)) Membership__InvalidAddress.selector.revertWith();
|
|
416
|
+
uint256 membershipSupplyLimit = _getMembershipSupplyLimit();
|
|
417
|
+
if (membershipSupplyLimit != 0 && _totalSupply() >= membershipSupplyLimit) {
|
|
418
|
+
Membership__MaxSupplyReached.selector.revertWith();
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/// @notice Refunds the balance to the sender if necessary
|
|
423
|
+
/// @param transactionId The unique identifier for this join transaction
|
|
424
|
+
/// @param sender The address of the sender to refund
|
|
425
|
+
function _refundBalance(bytes32 transactionId, address sender) internal {
|
|
426
|
+
uint256 userValue = _getCapturedValue(transactionId);
|
|
427
|
+
if (userValue > 0) {
|
|
428
|
+
_releaseCapturedValue(transactionId, userValue);
|
|
429
|
+
CurrencyTransfer.transferCurrency(
|
|
430
|
+
_getMembershipCurrency(),
|
|
431
|
+
address(this),
|
|
432
|
+
sender,
|
|
433
|
+
userValue
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/// @notice Collects the referral fee if applicable
|
|
439
|
+
/// @param payer The address of the payer
|
|
440
|
+
/// @param referralCode The referral code used
|
|
441
|
+
/// @param membershipPrice The price of the membership
|
|
442
|
+
/// @return referralFee The amount of referral fee collected
|
|
443
|
+
function _collectReferralCodeFee(
|
|
444
|
+
address payer,
|
|
445
|
+
address userReferral,
|
|
446
|
+
string memory referralCode,
|
|
447
|
+
uint256 membershipPrice
|
|
448
|
+
) internal returns (uint256 referralFee) {
|
|
449
|
+
if (bytes(referralCode).length != 0) {
|
|
450
|
+
Referral memory referral = _referralInfo(referralCode);
|
|
451
|
+
|
|
452
|
+
if (referral.recipient == address(0) || referral.basisPoints == 0) return 0;
|
|
453
|
+
|
|
454
|
+
referralFee = BasisPoints.calculate(membershipPrice, referral.basisPoints);
|
|
455
|
+
|
|
456
|
+
CurrencyTransfer.transferCurrency(
|
|
457
|
+
_getMembershipCurrency(),
|
|
458
|
+
payer,
|
|
459
|
+
referral.recipient,
|
|
460
|
+
referralFee
|
|
461
|
+
);
|
|
462
|
+
} else if (userReferral != address(0)) {
|
|
463
|
+
if (userReferral == payer) return 0;
|
|
464
|
+
|
|
465
|
+
referralFee = BasisPoints.calculate(membershipPrice, _defaultBpsFee());
|
|
466
|
+
|
|
467
|
+
CurrencyTransfer.transferCurrency(
|
|
468
|
+
_getMembershipCurrency(),
|
|
469
|
+
payer,
|
|
470
|
+
userReferral,
|
|
471
|
+
referralFee
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/// @notice Collects the partner fee if applicable
|
|
477
|
+
/// @param payer The address of the payer
|
|
478
|
+
/// @param partner The address of the partner
|
|
479
|
+
/// @param membershipPrice The price of the membership
|
|
480
|
+
/// @return partnerFee The amount of partner fee collected
|
|
481
|
+
function _collectPartnerFee(
|
|
482
|
+
address payer,
|
|
483
|
+
address partner,
|
|
484
|
+
uint256 membershipPrice
|
|
485
|
+
) internal returns (uint256 partnerFee) {
|
|
486
|
+
if (partner == address(0)) return 0;
|
|
487
|
+
|
|
488
|
+
Partner memory partnerInfo = IPartnerRegistry(_getSpaceFactory()).partnerInfo(partner);
|
|
489
|
+
|
|
490
|
+
if (partnerInfo.fee == 0) return 0;
|
|
491
|
+
|
|
492
|
+
partnerFee = BasisPoints.calculate(membershipPrice, partnerInfo.fee);
|
|
493
|
+
|
|
494
|
+
CurrencyTransfer.transferCurrency(
|
|
495
|
+
_getMembershipCurrency(),
|
|
496
|
+
payer,
|
|
497
|
+
partnerInfo.recipient,
|
|
498
|
+
partnerFee
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
function _renewMembership(address payer, uint256 tokenId) internal {
|
|
503
|
+
address receiver = _ownerOf(tokenId);
|
|
504
|
+
|
|
505
|
+
if (receiver == address(0)) Membership__InvalidAddress.selector.revertWith();
|
|
506
|
+
|
|
507
|
+
uint256 duration = _getMembershipDuration();
|
|
508
|
+
uint256 membershipPrice = _getMembershipRenewalPrice(tokenId, _totalSupply());
|
|
509
|
+
|
|
510
|
+
if (membershipPrice > msg.value) Membership__InvalidPayment.selector.revertWith();
|
|
511
|
+
|
|
512
|
+
_mintMembershipPoints(receiver, membershipPrice);
|
|
513
|
+
|
|
514
|
+
uint256 protocolFee = _collectProtocolFee(payer, membershipPrice);
|
|
515
|
+
|
|
516
|
+
uint256 remainingDue = membershipPrice - protocolFee;
|
|
517
|
+
if (remainingDue > 0) _transferIn(payer, remainingDue);
|
|
518
|
+
|
|
519
|
+
uint256 excess = msg.value - membershipPrice;
|
|
520
|
+
if (excess > 0) {
|
|
521
|
+
CurrencyTransfer.transferCurrency(
|
|
522
|
+
_getMembershipCurrency(),
|
|
523
|
+
address(this),
|
|
524
|
+
payer,
|
|
525
|
+
excess
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
_renewSubscription(tokenId, uint64(duration));
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/// @notice Mints points to a member based on their paid amount
|
|
533
|
+
/// @dev This function handles point minting for both new joins and renewals
|
|
534
|
+
/// @param receiver The address receiving the points
|
|
535
|
+
/// @param paidAmount The amount paid for membership
|
|
536
|
+
function _mintMembershipPoints(address receiver, uint256 paidAmount) internal {
|
|
537
|
+
// calculate points and credit them
|
|
538
|
+
address airdropDiamond = _getAirdropDiamond();
|
|
539
|
+
uint256 points = _getPoints(
|
|
540
|
+
airdropDiamond,
|
|
541
|
+
ITownsPointsBase.Action.JoinSpace,
|
|
542
|
+
abi.encode(paidAmount)
|
|
543
|
+
);
|
|
544
|
+
_mintPoints(airdropDiamond, receiver, points);
|
|
545
|
+
_mintPoints(airdropDiamond, _owner(), points);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
interface IMembershipMetadata {
|
|
5
|
+
/// @notice Emits an event to trigger metadata refresh when the space info is updated
|
|
6
|
+
function refreshMetadata() external;
|
|
7
|
+
|
|
8
|
+
function tokenURI(uint256 tokenId) external view returns (string memory);
|
|
9
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
|
|
6
|
+
import {IMembershipMetadata} from "./IMembershipMetadata.sol";
|
|
7
|
+
import {IERC4906} from "@openzeppelin/contracts/interfaces/IERC4906.sol";
|
|
8
|
+
import {IERC721A} from "src/diamond/facets/token/ERC721A/IERC721A.sol";
|
|
9
|
+
|
|
10
|
+
// libraries
|
|
11
|
+
import {TokenOwnableStorage} from "@towns-protocol/diamond/src/facets/ownable/token/TokenOwnableStorage.sol";
|
|
12
|
+
import {LibString} from "solady/utils/LibString.sol";
|
|
13
|
+
|
|
14
|
+
// contracts
|
|
15
|
+
|
|
16
|
+
import {Facet} from "@towns-protocol/diamond/src/facets/Facet.sol";
|
|
17
|
+
import {ERC721ABase} from "src/diamond/facets/token/ERC721A/ERC721ABase.sol";
|
|
18
|
+
|
|
19
|
+
contract MembershipMetadata is IMembershipMetadata, ERC721ABase, Facet {
|
|
20
|
+
/// @inheritdoc IMembershipMetadata
|
|
21
|
+
function refreshMetadata() external {
|
|
22
|
+
emit IERC4906.BatchMetadataUpdate(0, type(uint256).max);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function tokenURI(uint256 tokenId) public view returns (string memory) {
|
|
26
|
+
if (!_exists(tokenId)) revert URIQueryForNonexistentToken();
|
|
27
|
+
TokenOwnableStorage.Layout storage ds = TokenOwnableStorage.layout();
|
|
28
|
+
string memory baseURI = IERC721A(ds.collection).tokenURI(ds.tokenId);
|
|
29
|
+
string memory tokenIdStr = LibString.toString(tokenId);
|
|
30
|
+
return string.concat(baseURI, "/token/", tokenIdStr);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
|
|
6
|
+
// libraries
|
|
7
|
+
|
|
8
|
+
// contracts
|
|
9
|
+
|
|
10
|
+
interface IMembershipPricing {
|
|
11
|
+
function name() external view returns (string memory);
|
|
12
|
+
|
|
13
|
+
function description() external view returns (string memory);
|
|
14
|
+
|
|
15
|
+
function setPrice(uint256 price) external;
|
|
16
|
+
|
|
17
|
+
function getPrice(uint256 freeAllocation, uint256 totalMinted) external view returns (uint256);
|
|
18
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
import {IMembershipPricing} from "src/spaces/facets/membership/pricing/IMembershipPricing.sol";
|
|
6
|
+
|
|
7
|
+
// libraries
|
|
8
|
+
import {FixedPricingStorage} from "./FixedPricingStorage.sol";
|
|
9
|
+
|
|
10
|
+
// contracts
|
|
11
|
+
import {IntrospectionFacet} from "@towns-protocol/diamond/src/facets/introspection/IntrospectionFacet.sol";
|
|
12
|
+
|
|
13
|
+
contract FixedPricing is IMembershipPricing, IntrospectionFacet {
|
|
14
|
+
string public name = "FixedPricing";
|
|
15
|
+
string public description = "Fixed pricing for membership";
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
__IntrospectionBase_init();
|
|
19
|
+
_addInterface(type(IMembershipPricing).interfaceId);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function setPrice(uint256 price) external {
|
|
23
|
+
FixedPricingStorage.layout().priceBySpace[msg.sender] = price;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getPrice(uint256, uint256) external view returns (uint256) {
|
|
27
|
+
return FixedPricingStorage.layout().priceBySpace[msg.sender];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
|
|
6
|
+
// libraries
|
|
7
|
+
|
|
8
|
+
// contracts
|
|
9
|
+
|
|
10
|
+
library FixedPricingStorage {
|
|
11
|
+
// keccak256(abi.encode(uint256(keccak256("spaces.facets.membership.pricing.fixed.storage")) -
|
|
12
|
+
// 1))
|
|
13
|
+
// & ~bytes32(uint256(0xff))
|
|
14
|
+
bytes32 internal constant STORAGE_SLOT =
|
|
15
|
+
0xd905de679d8ee984e33da0498883a319db2532b35c6b45e3d77ada3832c5b000;
|
|
16
|
+
|
|
17
|
+
struct Layout {
|
|
18
|
+
mapping(address => uint256) priceBySpace;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function layout() internal pure returns (Layout storage ds) {
|
|
22
|
+
bytes32 slot = STORAGE_SLOT;
|
|
23
|
+
assembly {
|
|
24
|
+
ds.slot := slot
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|