@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.
Files changed (396) hide show
  1. package/LICENSE.txt +21 -0
  2. package/README.md +206 -0
  3. package/docs/permitAndStake_integration_guide.md +266 -0
  4. package/docs/swap_integration_guide.md +591 -0
  5. package/package.json +57 -0
  6. package/scripts/common/DeployBase.s.sol +26 -0
  7. package/scripts/common/DeployFacet.s.sol +7 -0
  8. package/scripts/common/Deployer.s.sol +33 -0
  9. package/scripts/common/Interaction.s.sol +51 -0
  10. package/scripts/deployments/diamonds/DeployAppRegistry.s.sol +168 -0
  11. package/scripts/deployments/diamonds/DeployBaseRegistry.s.sol +263 -0
  12. package/scripts/deployments/diamonds/DeployRiverAirdrop.s.sol +203 -0
  13. package/scripts/deployments/diamonds/DeployRiverMigration.s.sol +129 -0
  14. package/scripts/deployments/diamonds/DeployRiverRegistry.s.sol +175 -0
  15. package/scripts/deployments/diamonds/DeploySpace.s.sol +285 -0
  16. package/scripts/deployments/diamonds/DeploySpaceFactory.s.sol +416 -0
  17. package/scripts/deployments/diamonds/DeploySpaceOwner.s.sol +183 -0
  18. package/scripts/deployments/diamonds/DeploySwapRouter.s.sol +176 -0
  19. package/scripts/deployments/diamonds/IDiamondInitHelper.sol +11 -0
  20. package/scripts/deployments/facets/DeployAppAccount.s.sol +51 -0
  21. package/scripts/deployments/facets/DeployAppRegistryFacet.s.sol +69 -0
  22. package/scripts/deployments/facets/DeployArchitect.s.sol +51 -0
  23. package/scripts/deployments/facets/DeployAttestationRegistry.s.sol +36 -0
  24. package/scripts/deployments/facets/DeployBanning.s.sol +30 -0
  25. package/scripts/deployments/facets/DeployChannels.s.sol +35 -0
  26. package/scripts/deployments/facets/DeployCreateSpace.s.sol +42 -0
  27. package/scripts/deployments/facets/DeployDropFacet.s.sol +49 -0
  28. package/scripts/deployments/facets/DeployERC721A.s.sol +48 -0
  29. package/scripts/deployments/facets/DeployERC721ANonTransferable.s.sol +49 -0
  30. package/scripts/deployments/facets/DeployERC721AQueryable.s.sol +30 -0
  31. package/scripts/deployments/facets/DeployEntitlementChecker.s.sol +49 -0
  32. package/scripts/deployments/facets/DeployEntitlementDataQueryable.s.sol +29 -0
  33. package/scripts/deployments/facets/DeployEntitlementsManager.s.sol +33 -0
  34. package/scripts/deployments/facets/DeployExecutorFacet.s.sol +60 -0
  35. package/scripts/deployments/facets/DeployFeatureManager.s.sol +38 -0
  36. package/scripts/deployments/facets/DeployGuardianFacet.s.sol +39 -0
  37. package/scripts/deployments/facets/DeployImplementationRegistry.s.sol +36 -0
  38. package/scripts/deployments/facets/DeployMainnetDelegation.s.sol +43 -0
  39. package/scripts/deployments/facets/DeployMembership.s.sol +77 -0
  40. package/scripts/deployments/facets/DeployMembershipMetadata.s.sol +30 -0
  41. package/scripts/deployments/facets/DeployMembershipToken.s.sol +47 -0
  42. package/scripts/deployments/facets/DeployMerkleAirdrop.s.sol +37 -0
  43. package/scripts/deployments/facets/DeployMetadata.s.sol +39 -0
  44. package/scripts/deployments/facets/DeployMockLegacyArchitect.s.sol +33 -0
  45. package/scripts/deployments/facets/DeployNodeOperator.s.sol +49 -0
  46. package/scripts/deployments/facets/DeployNodeRegistry.s.sol +37 -0
  47. package/scripts/deployments/facets/DeployOperatorRegistry.s.sol +36 -0
  48. package/scripts/deployments/facets/DeployPartnerRegistry.s.sol +41 -0
  49. package/scripts/deployments/facets/DeployPlatformRequirements.s.sol +75 -0
  50. package/scripts/deployments/facets/DeployPrepayFacet.s.sol +31 -0
  51. package/scripts/deployments/facets/DeployPricingModules.s.sol +36 -0
  52. package/scripts/deployments/facets/DeployReferrals.s.sol +34 -0
  53. package/scripts/deployments/facets/DeployReviewFacet.s.sol +31 -0
  54. package/scripts/deployments/facets/DeployRewardsDistributionV2.s.sol +76 -0
  55. package/scripts/deployments/facets/DeployRiverConfig.s.sol +41 -0
  56. package/scripts/deployments/facets/DeployRoles.s.sol +48 -0
  57. package/scripts/deployments/facets/DeploySchemaRegistry.s.sol +35 -0
  58. package/scripts/deployments/facets/DeploySignerFacet.s.sol +47 -0
  59. package/scripts/deployments/facets/DeploySimpleApp.s.sol +10 -0
  60. package/scripts/deployments/facets/DeploySpaceDelegation.s.sol +43 -0
  61. package/scripts/deployments/facets/DeploySpaceEntitlementGated.s.sol +31 -0
  62. package/scripts/deployments/facets/DeploySpaceFactoryInit.s.sol +33 -0
  63. package/scripts/deployments/facets/DeploySpaceOwnerFacet.s.sol +71 -0
  64. package/scripts/deployments/facets/DeployStreamRegistry.s.sol +50 -0
  65. package/scripts/deployments/facets/DeploySwapFacet.s.sol +33 -0
  66. package/scripts/deployments/facets/DeploySwapRouterFacet.s.sol +38 -0
  67. package/scripts/deployments/facets/DeployTipping.s.sol +31 -0
  68. package/scripts/deployments/facets/DeployTokenMigration.s.sol +40 -0
  69. package/scripts/deployments/facets/DeployTownsPoints.s.sol +53 -0
  70. package/scripts/deployments/facets/DeployTreasury.s.sol +30 -0
  71. package/scripts/deployments/facets/DeployUpgradeableBeacon.s.sol +34 -0
  72. package/scripts/deployments/facets/DeployWalletLink.s.sol +56 -0
  73. package/scripts/deployments/facets/DeployXChain.s.sol +35 -0
  74. package/scripts/deployments/utils/DeployAccountFactory.s.sol +40 -0
  75. package/scripts/deployments/utils/DeployEntitlementGatedExample.s.sol +23 -0
  76. package/scripts/deployments/utils/DeployEntrypoint.s.sol +28 -0
  77. package/scripts/deployments/utils/DeployMember.s.sol +95 -0
  78. package/scripts/deployments/utils/DeployMockDiamond.s.sol +7 -0
  79. package/scripts/deployments/utils/DeployMockERC20.s.sol +24 -0
  80. package/scripts/deployments/utils/DeployMockERC721A.s.sol +45 -0
  81. package/scripts/deployments/utils/DeployMockLegacyMembership.s.sol +29 -0
  82. package/scripts/deployments/utils/DeployMockMessenger.s.sol +42 -0
  83. package/scripts/deployments/utils/DeployMockNFT.s.sol +86 -0
  84. package/scripts/deployments/utils/DeployPoapEntitlement.s.sol +16 -0
  85. package/scripts/deployments/utils/DeployProxyBatchDelegation.s.sol +112 -0
  86. package/scripts/deployments/utils/DeploySpaceProxyInitializer.s.sol +28 -0
  87. package/scripts/deployments/utils/DeployTieredLogPricingV2.s.sol +23 -0
  88. package/scripts/deployments/utils/DeployTieredLogPricingV3.s.sol +23 -0
  89. package/scripts/deployments/utils/DeployTownsBase.s.sol +95 -0
  90. package/scripts/deployments/utils/DeployTownsMainnet.s.sol +66 -0
  91. package/scripts/deployments/utils/DeployTownsMulti.s.sol +53 -0
  92. package/scripts/deployments/utils/DeployWrappedTowns.s.sol +52 -0
  93. package/scripts/deployments/utils/LibLayerZeroValues.sol +34 -0
  94. package/scripts/deployments/utils/pricing/TieredLogPricing.s.sol +45 -0
  95. package/scripts/interactions/InteractAirdrop.s.sol +57 -0
  96. package/scripts/interactions/InteractAlphaPost.s.sol +32 -0
  97. package/scripts/interactions/InteractAlphaSparse.s.sol +173 -0
  98. package/scripts/interactions/InteractBaseAlpha.s.sol +84 -0
  99. package/scripts/interactions/InteractBaseBridge.s.sol +48 -0
  100. package/scripts/interactions/InteractBridgeLayerZero.s.sol +102 -0
  101. package/scripts/interactions/InteractClaimCondition.s.sol +56 -0
  102. package/scripts/interactions/InteractCreateSpace.s.sol +50 -0
  103. package/scripts/interactions/InteractDiamondCut.s.sol +47 -0
  104. package/scripts/interactions/InteractDropFacet.s.sol +32 -0
  105. package/scripts/interactions/InteractEnableNewSnapshotFormat.s.sol +27 -0
  106. package/scripts/interactions/InteractEnableNode2NodeAuth.s.sol +27 -0
  107. package/scripts/interactions/InteractMembership.s.sol +42 -0
  108. package/scripts/interactions/InteractMockERC721A.s.sol +20 -0
  109. package/scripts/interactions/InteractNodeOperators.s.sol +41 -0
  110. package/scripts/interactions/InteractPostDeploy.s.sol +59 -0
  111. package/scripts/interactions/InteractPrepay.s.sol +30 -0
  112. package/scripts/interactions/InteractRegisterApp.s.sol +61 -0
  113. package/scripts/interactions/InteractRiverAlpha.s.sol +30 -0
  114. package/scripts/interactions/InteractRiverAlphaSparse.s.sol +117 -0
  115. package/scripts/interactions/InteractRiverMainnet.s.sol +27 -0
  116. package/scripts/interactions/InteractRiverRegistry.s.sol +36 -0
  117. package/scripts/interactions/InteractRiverRegistrySetBlocklist.s.sol +30 -0
  118. package/scripts/interactions/InteractRiverRegistrySetFreq.s.sol +27 -0
  119. package/scripts/interactions/InteractRiverRegistrySetRepl.s.sol +30 -0
  120. package/scripts/interactions/InteractSetDefaultUri.s.sol +20 -0
  121. package/scripts/interactions/InteractSetDefaultUriLocalhost.s.sol +19 -0
  122. package/scripts/interactions/InteractTransferOwnership.s.sol +21 -0
  123. package/scripts/interactions/InteractUpdateMbRecencyCheck.s.sol +27 -0
  124. package/scripts/interactions/InteractUpdateMediaChunkCount.s.sol +27 -0
  125. package/scripts/interactions/InteractUpdateMediaChunkSize.s.sol +27 -0
  126. package/scripts/interactions/helpers/AlphaHelper.sol +149 -0
  127. package/scripts/interactions/helpers/RiverConfigValues.sol +22 -0
  128. package/scripts/interactions/interfaces/IL1StandardBridge.sol +35 -0
  129. package/scripts/interactions/interfaces/IL2StandardBridge.sol +69 -0
  130. package/src/airdrop/drop/DropBase.sol +210 -0
  131. package/src/airdrop/drop/DropClaim.sol +55 -0
  132. package/src/airdrop/drop/DropFacet.sol +176 -0
  133. package/src/airdrop/drop/DropGroup.sol +111 -0
  134. package/src/airdrop/drop/DropStorage.sol +23 -0
  135. package/src/airdrop/drop/IDropFacet.sol +136 -0
  136. package/src/airdrop/points/CheckIn.sol +71 -0
  137. package/src/airdrop/points/ITownsPoints.sol +64 -0
  138. package/src/airdrop/points/TownsPoints.sol +196 -0
  139. package/src/airdrop/points/TownsPointsStorage.sol +22 -0
  140. package/src/apps/BaseApp.sol +62 -0
  141. package/src/apps/ITownsApp.sol +28 -0
  142. package/src/apps/SchemaResolver.sol +170 -0
  143. package/src/apps/facets/attest/AttestationBase.sol +335 -0
  144. package/src/apps/facets/attest/AttestationLib.sol +64 -0
  145. package/src/apps/facets/attest/AttestationRegistry.sol +39 -0
  146. package/src/apps/facets/attest/AttestationStorage.sol +35 -0
  147. package/src/apps/facets/attest/IAttestationRegistry.sol +43 -0
  148. package/src/apps/facets/registry/AppRegistryBase.sol +403 -0
  149. package/src/apps/facets/registry/AppRegistryFacet.sol +173 -0
  150. package/src/apps/facets/registry/AppRegistryStorage.sol +53 -0
  151. package/src/apps/facets/registry/IAppRegistry.sol +159 -0
  152. package/src/apps/facets/schema/ISchema.sol +14 -0
  153. package/src/apps/facets/schema/SchemaBase.sol +88 -0
  154. package/src/apps/facets/schema/SchemaLib.sol +14 -0
  155. package/src/apps/facets/schema/SchemaRegistry.sol +51 -0
  156. package/src/apps/facets/schema/SchemaStorage.sol +34 -0
  157. package/src/apps/helpers/ISimpleApp.sol +51 -0
  158. package/src/apps/helpers/SimpleApp.sol +97 -0
  159. package/src/apps/helpers/SimpleAppStorage.sol +27 -0
  160. package/src/base/registry/facets/checker/EntitlementChecker.sol +237 -0
  161. package/src/base/registry/facets/checker/EntitlementCheckerStorage.sol +28 -0
  162. package/src/base/registry/facets/checker/IEntitlementChecker.sol +95 -0
  163. package/src/base/registry/facets/delegation/ISpaceDelegation.sol +69 -0
  164. package/src/base/registry/facets/delegation/SpaceDelegationFacet.sol +250 -0
  165. package/src/base/registry/facets/delegation/SpaceDelegationStorage.sol +35 -0
  166. package/src/base/registry/facets/distribution/v1/IRewardsDistribution.sol +51 -0
  167. package/src/base/registry/facets/distribution/v1/RewardsDistribution.sol +439 -0
  168. package/src/base/registry/facets/distribution/v1/RewardsDistributionStorage.sol +32 -0
  169. package/src/base/registry/facets/distribution/v2/DelegationProxy.sol +53 -0
  170. package/src/base/registry/facets/distribution/v2/IRewardsDistribution.sol +372 -0
  171. package/src/base/registry/facets/distribution/v2/RewardsDistributionBase.sol +299 -0
  172. package/src/base/registry/facets/distribution/v2/RewardsDistributionStorage.sol +37 -0
  173. package/src/base/registry/facets/distribution/v2/RewardsDistributionV2.sol +392 -0
  174. package/src/base/registry/facets/distribution/v2/StakingRewards.sol +466 -0
  175. package/src/base/registry/facets/mainnet/ICrossDomainMessenger.sol +58 -0
  176. package/src/base/registry/facets/mainnet/IMainnetDelegation.sol +127 -0
  177. package/src/base/registry/facets/mainnet/MainnetDelegation.sol +119 -0
  178. package/src/base/registry/facets/mainnet/MainnetDelegationBase.sol +274 -0
  179. package/src/base/registry/facets/mainnet/MainnetDelegationStorage.sol +36 -0
  180. package/src/base/registry/facets/operator/INodeOperator.sol +91 -0
  181. package/src/base/registry/facets/operator/NodeOperatorFacet.sol +189 -0
  182. package/src/base/registry/facets/operator/NodeOperatorStorage.sol +39 -0
  183. package/src/base/registry/facets/xchain/IXChain.sol +54 -0
  184. package/src/base/registry/facets/xchain/XChain.sol +158 -0
  185. package/src/base/registry/facets/xchain/XChainCheckLib.sol +105 -0
  186. package/src/base/registry/facets/xchain/XChainLib.sol +46 -0
  187. package/src/diamond/facets/beacon/UpgradeableBeacon.sol +38 -0
  188. package/src/diamond/facets/beacon/UpgradeableBeaconFacet.sol +34 -0
  189. package/src/diamond/facets/governance/votes/Checkpoints.sol +642 -0
  190. package/src/diamond/facets/governance/votes/Votes.sol +63 -0
  191. package/src/diamond/facets/governance/votes/VotesBase.sol +274 -0
  192. package/src/diamond/facets/governance/votes/VotesStorage.sol +21 -0
  193. package/src/diamond/facets/governance/votes/enumerable/IVotesEnumerable.sol +38 -0
  194. package/src/diamond/facets/governance/votes/enumerable/VotesEnumerable.sol +39 -0
  195. package/src/diamond/facets/governance/votes/enumerable/VotesEnumerableLib.sol +102 -0
  196. package/src/diamond/facets/metadata/IMetadata.sol +27 -0
  197. package/src/diamond/facets/metadata/MetadataFacet.sol +71 -0
  198. package/src/diamond/facets/token/ERC5643/ERC5643.sol +51 -0
  199. package/src/diamond/facets/token/ERC5643/ERC5643Base.sol +48 -0
  200. package/src/diamond/facets/token/ERC5643/ERC5643Storage.sol +26 -0
  201. package/src/diamond/facets/token/ERC5643/IERC5643.sol +44 -0
  202. package/src/diamond/facets/token/ERC721A/ERC721A.sol +270 -0
  203. package/src/diamond/facets/token/ERC721A/ERC721ABase.sol +829 -0
  204. package/src/diamond/facets/token/ERC721A/ERC721ANonTransferable.sol +21 -0
  205. package/src/diamond/facets/token/ERC721A/ERC721AStorage.sol +115 -0
  206. package/src/diamond/facets/token/ERC721A/IERC721A.sol +283 -0
  207. package/src/diamond/facets/token/ERC721A/extensions/ERC721AQueryable.sol +134 -0
  208. package/src/diamond/facets/token/ERC721A/extensions/IERC721AQueryable.sol +83 -0
  209. package/src/diamond/utils/Context.sol +19 -0
  210. package/src/factory/SpaceFactoryInit.sol +17 -0
  211. package/src/factory/facets/architect/Architect.sol +98 -0
  212. package/src/factory/facets/architect/ArchitectBase.sol +95 -0
  213. package/src/factory/facets/architect/ArchitectStorage.sol +28 -0
  214. package/src/factory/facets/architect/IArchitect.sol +155 -0
  215. package/src/factory/facets/architect/ImplementationStorage.sol +42 -0
  216. package/src/factory/facets/architect/pricing/IPricingModules.sol +41 -0
  217. package/src/factory/facets/architect/pricing/PricingModulesBase.sol +89 -0
  218. package/src/factory/facets/architect/pricing/PricingModulesFacet.sol +40 -0
  219. package/src/factory/facets/architect/pricing/PricingModulesStorage.sol +30 -0
  220. package/src/factory/facets/create/CreateSpace.sol +107 -0
  221. package/src/factory/facets/create/CreateSpaceLib.sol +335 -0
  222. package/src/factory/facets/create/ICreateSpace.sol +70 -0
  223. package/src/factory/facets/feature/FeatureConditionLib.sol +53 -0
  224. package/src/factory/facets/feature/FeatureManagerFacet.sol +66 -0
  225. package/src/factory/facets/feature/FeatureManagerLib.sol +168 -0
  226. package/src/factory/facets/feature/IFeatureManagerFacet.sol +73 -0
  227. package/src/factory/facets/partner/IPartnerRegistry.sol +56 -0
  228. package/src/factory/facets/partner/PartnerRegistry.sol +57 -0
  229. package/src/factory/facets/partner/PartnerRegistryBase.sol +132 -0
  230. package/src/factory/facets/partner/PartnerRegistryStorage.sol +40 -0
  231. package/src/factory/facets/platform/requirements/IPlatformRequirements.sol +143 -0
  232. package/src/factory/facets/platform/requirements/PlatformRequirementsBase.sol +124 -0
  233. package/src/factory/facets/platform/requirements/PlatformRequirementsFacet.sol +122 -0
  234. package/src/factory/facets/platform/requirements/PlatformRequirementsStorage.sol +41 -0
  235. package/src/factory/facets/registry/IImplementationRegistry.sol +46 -0
  236. package/src/factory/facets/registry/ImplementationRegistry.sol +64 -0
  237. package/src/factory/facets/registry/ImplementationRegistryStorage.sol +28 -0
  238. package/src/factory/facets/wallet-link/IWalletLink.sol +218 -0
  239. package/src/factory/facets/wallet-link/WalletLink.sol +108 -0
  240. package/src/factory/facets/wallet-link/WalletLinkBase.sol +492 -0
  241. package/src/factory/facets/wallet-link/interfaces/IDelegateRegistry.sol +63 -0
  242. package/src/factory/facets/wallet-link/interfaces/IDelegateRegistryV1.sol +35 -0
  243. package/src/factory/facets/wallet-link/interfaces/ISCL_EIP6565.sol +24 -0
  244. package/src/factory/facets/wallet-link/libraries/SolanaUtils.sol +161 -0
  245. package/src/factory/facets/wallet-link/libraries/WalletLib.sol +62 -0
  246. package/src/river/registry/facets/config/IRiverConfig.sol +117 -0
  247. package/src/river/registry/facets/config/RiverConfig.sol +174 -0
  248. package/src/river/registry/facets/node/INodeRegistry.sol +69 -0
  249. package/src/river/registry/facets/node/NodeRegistry.sol +143 -0
  250. package/src/river/registry/facets/operator/IOperatorRegistry.sol +28 -0
  251. package/src/river/registry/facets/operator/OperatorRegistry.sol +86 -0
  252. package/src/river/registry/facets/stream/IStreamRegistry.sol +184 -0
  253. package/src/river/registry/facets/stream/StreamRegistry.sol +396 -0
  254. package/src/river/registry/libraries/RegistryErrors.sol +24 -0
  255. package/src/river/registry/libraries/RegistryStorage.sol +181 -0
  256. package/src/router/ISwapRouter.sol +226 -0
  257. package/src/router/Permit2Hash.sol +92 -0
  258. package/src/router/SwapRouter.sol +463 -0
  259. package/src/router/SwapRouterStorage.sol +21 -0
  260. package/src/spaces/entitlements/ICrossChainEntitlement.sol +22 -0
  261. package/src/spaces/entitlements/IEntitlement.sol +61 -0
  262. package/src/spaces/entitlements/PolymarketEntitlement.sol +79 -0
  263. package/src/spaces/entitlements/poap/IPOAP.sol +26 -0
  264. package/src/spaces/entitlements/poap/PoapEntitlement.sol +56 -0
  265. package/src/spaces/entitlements/rule/IRuleEntitlement.sol +174 -0
  266. package/src/spaces/entitlements/rule/RuleEntitlement.sol +183 -0
  267. package/src/spaces/entitlements/rule/RuleEntitlementV2.sol +219 -0
  268. package/src/spaces/entitlements/user/IUserEntitlement.sol +24 -0
  269. package/src/spaces/entitlements/user/UserEntitlement.sol +273 -0
  270. package/src/spaces/facets/DependencyLib.sol +60 -0
  271. package/src/spaces/facets/Entitled.sol +172 -0
  272. package/src/spaces/facets/Permissions.sol +21 -0
  273. package/src/spaces/facets/account/AppAccount.sol +93 -0
  274. package/src/spaces/facets/account/AppAccountBase.sol +275 -0
  275. package/src/spaces/facets/account/AppAccountStorage.sol +63 -0
  276. package/src/spaces/facets/account/IAppAccount.sol +71 -0
  277. package/src/spaces/facets/account/SignerFacet.sol +26 -0
  278. package/src/spaces/facets/banning/Banning.sol +41 -0
  279. package/src/spaces/facets/banning/BanningBase.sol +33 -0
  280. package/src/spaces/facets/banning/BanningStorage.sol +23 -0
  281. package/src/spaces/facets/banning/IBanning.sol +35 -0
  282. package/src/spaces/facets/channels/ChannelBase.sol +87 -0
  283. package/src/spaces/facets/channels/ChannelService.sol +177 -0
  284. package/src/spaces/facets/channels/ChannelStorage.sol +34 -0
  285. package/src/spaces/facets/channels/Channels.sol +80 -0
  286. package/src/spaces/facets/channels/IChannel.sol +98 -0
  287. package/src/spaces/facets/dispatcher/DispatcherBase.sol +86 -0
  288. package/src/spaces/facets/dispatcher/DispatcherStorage.sol +21 -0
  289. package/src/spaces/facets/dispatcher/IDispatcher.sol +6 -0
  290. package/src/spaces/facets/entitlements/EntitlementsManager.sol +49 -0
  291. package/src/spaces/facets/entitlements/EntitlementsManagerBase.sol +87 -0
  292. package/src/spaces/facets/entitlements/EntitlementsManagerService.sol +142 -0
  293. package/src/spaces/facets/entitlements/EntitlementsManagerStorage.sol +34 -0
  294. package/src/spaces/facets/entitlements/IEntitlementsManager.sol +67 -0
  295. package/src/spaces/facets/entitlements/extensions/EntitlementDataQueryable.sol +153 -0
  296. package/src/spaces/facets/entitlements/extensions/IEntitlementDataQueryable.sol +32 -0
  297. package/src/spaces/facets/executor/ExecutorBase.sol +564 -0
  298. package/src/spaces/facets/executor/ExecutorFacet.sol +178 -0
  299. package/src/spaces/facets/executor/ExecutorStorage.sol +99 -0
  300. package/src/spaces/facets/executor/GroupLib.sol +128 -0
  301. package/src/spaces/facets/executor/IExecutor.sol +287 -0
  302. package/src/spaces/facets/executor/hooks/HookBase.sol +172 -0
  303. package/src/spaces/facets/executor/hooks/HookLib.sol +38 -0
  304. package/src/spaces/facets/executor/hooks/IHookBase.sol +48 -0
  305. package/src/spaces/facets/gated/EntitlementGated.sol +59 -0
  306. package/src/spaces/facets/gated/EntitlementGatedBase.sol +324 -0
  307. package/src/spaces/facets/gated/EntitlementGatedStorage.sol +29 -0
  308. package/src/spaces/facets/gated/IEntitlementGated.sol +55 -0
  309. package/src/spaces/facets/guardian/GuardianBase.sol +80 -0
  310. package/src/spaces/facets/guardian/GuardianFacet.sol +43 -0
  311. package/src/spaces/facets/guardian/GuardianStorage.sol +27 -0
  312. package/src/spaces/facets/guardian/IGuardian.sol +54 -0
  313. package/src/spaces/facets/membership/IMembership.sol +216 -0
  314. package/src/spaces/facets/membership/MembershipBase.sol +272 -0
  315. package/src/spaces/facets/membership/MembershipFacet.sol +191 -0
  316. package/src/spaces/facets/membership/MembershipStorage.sol +40 -0
  317. package/src/spaces/facets/membership/join/MembershipJoin.sol +547 -0
  318. package/src/spaces/facets/membership/metadata/IMembershipMetadata.sol +9 -0
  319. package/src/spaces/facets/membership/metadata/MembershipMetadata.sol +32 -0
  320. package/src/spaces/facets/membership/pricing/IMembershipPricing.sol +18 -0
  321. package/src/spaces/facets/membership/pricing/fixed/FixedPricing.sol +29 -0
  322. package/src/spaces/facets/membership/pricing/fixed/FixedPricingStorage.sol +27 -0
  323. package/src/spaces/facets/membership/pricing/tiered/TieredLogPricingOracleV2.sol +148 -0
  324. package/src/spaces/facets/membership/pricing/tiered/TieredLogPricingOracleV3.sol +137 -0
  325. package/src/spaces/facets/membership/token/MembershipToken.sol +25 -0
  326. package/src/spaces/facets/owner/ISpaceOwner.sol +85 -0
  327. package/src/spaces/facets/owner/SpaceOwner.sol +174 -0
  328. package/src/spaces/facets/owner/SpaceOwnerBase.sol +121 -0
  329. package/src/spaces/facets/owner/SpaceOwnerStorage.sol +41 -0
  330. package/src/spaces/facets/owner/SpaceOwnerUriBase.sol +54 -0
  331. package/src/spaces/facets/points/PointsBase.sol +35 -0
  332. package/src/spaces/facets/prepay/IPrepay.sol +43 -0
  333. package/src/spaces/facets/prepay/PrepayBase.sol +27 -0
  334. package/src/spaces/facets/prepay/PrepayFacet.sol +59 -0
  335. package/src/spaces/facets/prepay/PrepayStorage.sol +26 -0
  336. package/src/spaces/facets/proxy/ISpaceProxyInitializer.sol +21 -0
  337. package/src/spaces/facets/proxy/SpaceProxy.sol +15 -0
  338. package/src/spaces/facets/proxy/SpaceProxyInitializer.sol +55 -0
  339. package/src/spaces/facets/referrals/IReferrals.sol +98 -0
  340. package/src/spaces/facets/referrals/ReferralsBase.sol +81 -0
  341. package/src/spaces/facets/referrals/ReferralsFacet.sol +65 -0
  342. package/src/spaces/facets/referrals/ReferralsStorage.sol +36 -0
  343. package/src/spaces/facets/review/IReview.sol +50 -0
  344. package/src/spaces/facets/review/ReviewFacet.sol +105 -0
  345. package/src/spaces/facets/review/ReviewStorage.sol +29 -0
  346. package/src/spaces/facets/roles/IRoles.sol +197 -0
  347. package/src/spaces/facets/roles/Roles.sol +123 -0
  348. package/src/spaces/facets/roles/RolesBase.sol +420 -0
  349. package/src/spaces/facets/roles/RolesStorage.sol +132 -0
  350. package/src/spaces/facets/swap/ISwapFacet.sol +91 -0
  351. package/src/spaces/facets/swap/SwapFacet.sol +290 -0
  352. package/src/spaces/facets/swap/SwapFacetStorage.sol +24 -0
  353. package/src/spaces/facets/tipping/ITipping.sol +80 -0
  354. package/src/spaces/facets/tipping/TippingBase.sol +73 -0
  355. package/src/spaces/facets/tipping/TippingFacet.sol +123 -0
  356. package/src/spaces/facets/treasury/ITreasury.sol +64 -0
  357. package/src/spaces/facets/treasury/Treasury.sol +82 -0
  358. package/src/spaces/facets/xchain/SpaceEntitlementGated.sol +62 -0
  359. package/src/tokens/Member.sol +246 -0
  360. package/src/tokens/lock/ILock.sol +42 -0
  361. package/src/tokens/lock/LockBase.sol +64 -0
  362. package/src/tokens/lock/LockFacet.sol +44 -0
  363. package/src/tokens/lock/LockStorage.sol +26 -0
  364. package/src/tokens/mainnet/claimer/AuthorizedClaimerStorage.sol +26 -0
  365. package/src/tokens/mainnet/claimer/AuthorizedClaimers.sol +84 -0
  366. package/src/tokens/mainnet/claimer/IAuthorizedClaimers.sol +36 -0
  367. package/src/tokens/mainnet/delegation/ProxyBatchDelegation.sol +86 -0
  368. package/src/tokens/migration/ITokenMigration.sol +35 -0
  369. package/src/tokens/migration/TokenMigrationFacet.sol +86 -0
  370. package/src/tokens/migration/TokenMigrationStorage.sol +27 -0
  371. package/src/tokens/towns/base/IERC7802.sol +30 -0
  372. package/src/tokens/towns/base/IOptimismMintableERC20.sol +31 -0
  373. package/src/tokens/towns/base/ISemver.sol +13 -0
  374. package/src/tokens/towns/base/Towns.sol +283 -0
  375. package/src/tokens/towns/base/TownsDeployer.sol +32 -0
  376. package/src/tokens/towns/base/TownsLib.sol +31 -0
  377. package/src/tokens/towns/base/versions/TownsV2.sol +15 -0
  378. package/src/tokens/towns/mainnet/ITowns.sol +56 -0
  379. package/src/tokens/towns/mainnet/Towns.sol +220 -0
  380. package/src/tokens/towns/mainnet/libs/TokenInflationLib.sol +89 -0
  381. package/src/tokens/towns/multichain/Towns.sol +19 -0
  382. package/src/tokens/towns/multichain/wTowns.sol +18 -0
  383. package/src/utils/Airdrop.sol +156 -0
  384. package/src/utils/airdrop/merkle/IMerkleAirdrop.sol +55 -0
  385. package/src/utils/airdrop/merkle/MerkleAirdrop.sol +118 -0
  386. package/src/utils/airdrop/merkle/MerkleAirdropStorage.sol +29 -0
  387. package/src/utils/interfaces/AggregatorV3Interface.sol +37 -0
  388. package/src/utils/interfaces/IMulticall.sol +10 -0
  389. package/src/utils/interfaces/IWETH.sol +10 -0
  390. package/src/utils/libraries/BasisPoints.sol +24 -0
  391. package/src/utils/libraries/Create2Utils.sol +74 -0
  392. package/src/utils/libraries/CurrencyTransfer.sol +99 -0
  393. package/src/utils/libraries/CustomRevert.sol +49 -0
  394. package/src/utils/libraries/Factory.sol +66 -0
  395. package/src/utils/libraries/StringSet.sol +190 -0
  396. package/src/utils/libraries/Validator.sol +31 -0
@@ -0,0 +1,273 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.24;
3
+
4
+ // interfaces
5
+ import {IEntitlement} from "../IEntitlement.sol";
6
+
7
+ import {IChannel} from "src/spaces/facets/channels/IChannel.sol";
8
+ import {IRoles} from "src/spaces/facets/roles/IRoles.sol";
9
+
10
+ // libraries
11
+ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
12
+
13
+ // contracts
14
+
15
+ import {IUserEntitlement} from "./IUserEntitlement.sol";
16
+ import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
17
+ import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
18
+ import {ContextUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
19
+ import {ERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol";
20
+
21
+ contract UserEntitlement is
22
+ Initializable,
23
+ ERC165Upgradeable,
24
+ ContextUpgradeable,
25
+ UUPSUpgradeable,
26
+ IUserEntitlement
27
+ {
28
+ using EnumerableSet for EnumerableSet.UintSet;
29
+
30
+ address constant EVERYONE_ADDRESS = address(1);
31
+ address public SPACE_ADDRESS;
32
+
33
+ struct Entitlement {
34
+ address grantedBy;
35
+ uint256 grantedTime;
36
+ address[] users;
37
+ }
38
+
39
+ /// @notice mapping holding all the entitlements by RoleId added to Entitlement
40
+ mapping(uint256 => Entitlement) internal entitlementsByRoleId;
41
+ mapping(address => uint256[]) internal roleIdsByUser;
42
+ EnumerableSet.UintSet allEntitlementRoleIds;
43
+
44
+ string public constant name = "User Entitlement";
45
+ string public constant description = "Entitlement for users";
46
+ string public constant moduleType = "UserEntitlement";
47
+
48
+ modifier onlySpace() {
49
+ if (_msgSender() != SPACE_ADDRESS) {
50
+ revert Entitlement__NotAllowed();
51
+ }
52
+ _;
53
+ }
54
+
55
+ /// @custom:oz-upgrades-unsafe-allow constructor
56
+ constructor() {
57
+ _disableInitializers();
58
+ }
59
+
60
+ function initialize(address _space) public initializer {
61
+ __UUPSUpgradeable_init();
62
+ __ERC165_init();
63
+ __Context_init();
64
+
65
+ SPACE_ADDRESS = _space;
66
+ }
67
+
68
+ /// @notice allow the contract to be upgraded while retaining state
69
+ /// @param newImplementation address of the new implementation
70
+ function _authorizeUpgrade(address newImplementation) internal override onlySpace {}
71
+
72
+ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
73
+ return
74
+ interfaceId == type(IEntitlement).interfaceId || super.supportsInterface(interfaceId);
75
+ }
76
+
77
+ // @inheritdoc IEntitlement
78
+ function isCrosschain() external pure override returns (bool) {
79
+ return false;
80
+ }
81
+
82
+ // @inheritdoc IEntitlement
83
+ function isEntitled(
84
+ bytes32 channelId,
85
+ address[] memory wallets,
86
+ bytes32 permission
87
+ ) external view returns (bool) {
88
+ // Check if channelId is not equal to the zero value for bytes32
89
+ if (channelId != bytes32(0)) {
90
+ return _isEntitledToChannel(channelId, wallets, permission);
91
+ } else {
92
+ return _isEntitledToSpace(wallets, permission);
93
+ }
94
+ }
95
+
96
+ // @inheritdoc IEntitlement
97
+ function setEntitlement(uint256 roleId, bytes calldata entitlementData) external onlySpace {
98
+ address[] memory users = abi.decode(entitlementData, (address[]));
99
+
100
+ for (uint256 i = 0; i < users.length; i++) {
101
+ address user = users[i];
102
+ if (user == address(0)) {
103
+ revert Entitlement__InvalidValue();
104
+ }
105
+ }
106
+
107
+ // First remove any prior values
108
+ while (entitlementsByRoleId[roleId].users.length > 0) {
109
+ address user = entitlementsByRoleId[roleId].users[
110
+ entitlementsByRoleId[roleId].users.length - 1
111
+ ];
112
+ _removeRoleIdFromUser(user, roleId);
113
+ entitlementsByRoleId[roleId].users.pop();
114
+ }
115
+ delete entitlementsByRoleId[roleId];
116
+
117
+ entitlementsByRoleId[roleId] = Entitlement({
118
+ grantedBy: _msgSender(),
119
+ grantedTime: block.timestamp,
120
+ users: users
121
+ });
122
+ for (uint256 i = 0; i < users.length; i++) {
123
+ roleIdsByUser[users[i]].push(roleId);
124
+ }
125
+ }
126
+
127
+ // @inheritdoc IEntitlement
128
+ function removeEntitlement(uint256 roleId) external onlySpace {
129
+ if (entitlementsByRoleId[roleId].grantedBy == address(0)) {
130
+ revert Entitlement__InvalidValue();
131
+ }
132
+
133
+ // First remove any prior values
134
+ while (entitlementsByRoleId[roleId].users.length > 0) {
135
+ address user = entitlementsByRoleId[roleId].users[
136
+ entitlementsByRoleId[roleId].users.length - 1
137
+ ];
138
+ _removeRoleIdFromUser(user, roleId);
139
+ entitlementsByRoleId[roleId].users.pop();
140
+ }
141
+ delete entitlementsByRoleId[roleId];
142
+ }
143
+
144
+ // @inheritdoc IEntitlement
145
+ function getEntitlementDataByRoleId(uint256 roleId) external view returns (bytes memory) {
146
+ return abi.encode(entitlementsByRoleId[roleId].users);
147
+ }
148
+
149
+ /// @notice checks is a user is entitled to a specific channel
150
+ /// @param channelId the channel id
151
+ /// @param wallets the user address who we are checking for
152
+ /// @param permission the permission we are checking for
153
+ /// @return _entitled true if the user is entitled to the channel
154
+ function _isEntitledToChannel(
155
+ bytes32 channelId,
156
+ address[] memory wallets,
157
+ bytes32 permission
158
+ ) internal view returns (bool _entitled) {
159
+ IChannel.Channel memory channel = IChannel(SPACE_ADDRESS).getChannel(channelId);
160
+
161
+ // get all the roleids for the user
162
+ uint256[] memory rolesIds = _getRoleIdsByUser(wallets);
163
+
164
+ // loop over all role ids in a channel
165
+ for (uint256 i = 0; i < channel.roleIds.length; i++) {
166
+ // get each role id
167
+ uint256 roleId = channel.roleIds[i];
168
+
169
+ // loop over all the valid entitlements
170
+ for (uint256 j = 0; j < rolesIds.length; j++) {
171
+ // check if the role id for that channel matches the entitlement role id
172
+ // and if the permission matches the role permission
173
+ if (rolesIds[j] == roleId && _validateRolePermission(rolesIds[j], permission)) {
174
+ _entitled = true;
175
+ }
176
+ }
177
+ }
178
+ }
179
+
180
+ /// @notice gets all the roles given to specific users
181
+ /// @param wallets the array of user addresses
182
+ /// @return roles the array of roles these users have, may include duplicates
183
+ function _getRoleIdsByUser(address[] memory wallets) internal view returns (uint256[] memory) {
184
+ uint256 totalLength = 0;
185
+
186
+ // Calculate total length
187
+ for (uint256 i = 0; i < wallets.length; i++) {
188
+ totalLength += roleIdsByUser[wallets[i]].length;
189
+ }
190
+
191
+ totalLength += roleIdsByUser[EVERYONE_ADDRESS].length;
192
+
193
+ // Create an array to hold all roles
194
+ uint256[] memory roles = new uint256[](totalLength);
195
+ uint256 currentIndex = 0;
196
+
197
+ // Populate the roles array
198
+ for (uint256 i = 0; i < wallets.length; i++) {
199
+ uint256[] memory rolesForWallet = roleIdsByUser[wallets[i]];
200
+ for (uint256 j = 0; j < rolesForWallet.length; j++) {
201
+ roles[currentIndex++] = rolesForWallet[j];
202
+ }
203
+ }
204
+
205
+ uint256[] memory rolesForEveryone = roleIdsByUser[EVERYONE_ADDRESS];
206
+ for (uint256 j = 0; j < rolesForEveryone.length; j++) {
207
+ roles[currentIndex++] = rolesForEveryone[j];
208
+ }
209
+
210
+ return roles;
211
+ }
212
+
213
+ /// @notice checks if a user is entitled to a specific space
214
+ /// @param wallets the user address
215
+ /// @param permission the permission we are checking for
216
+ /// @return _entitled true if the user is entitled to the space
217
+ function _isEntitledToSpace(
218
+ address[] memory wallets,
219
+ bytes32 permission
220
+ ) internal view returns (bool) {
221
+ // get all the roleids for the user
222
+ uint256[] memory rolesIds = _getRoleIdsByUser(wallets);
223
+
224
+ for (uint256 i = 0; i < rolesIds.length; i++) {
225
+ if (_validateRolePermission(rolesIds[i], permission)) {
226
+ return true;
227
+ }
228
+ }
229
+
230
+ return false;
231
+ }
232
+
233
+ /// @notice checks if a role has a specific permission
234
+ /// @param roleId the role id
235
+ /// @param permission the permission we are checking for
236
+ /// @return _hasPermission true if the role has the permission
237
+ function _validateRolePermission(
238
+ uint256 roleId,
239
+ bytes32 permission
240
+ ) internal view returns (bool) {
241
+ string[] memory permissions = IRoles(SPACE_ADDRESS).getPermissionsByRoleId(roleId);
242
+ uint256 permissionLen = permissions.length;
243
+
244
+ for (uint256 i = 0; i < permissionLen; i++) {
245
+ bytes32 permissionBytes = bytes32(abi.encodePacked(permissions[i]));
246
+ if (permissionBytes == permission) {
247
+ return true;
248
+ }
249
+ }
250
+
251
+ return false;
252
+ }
253
+
254
+ function _removeRoleIdFromUser(address user, uint256 roleId) internal {
255
+ uint256[] storage roles = roleIdsByUser[user];
256
+ for (uint256 i = 0; i < roles.length; i++) {
257
+ if (roles[i] == roleId) {
258
+ roles[i] = roles[roles.length - 1];
259
+ roles.pop();
260
+ return;
261
+ }
262
+ }
263
+
264
+ // Optional: Revert if the roleId is not found
265
+ revert("Role ID not found for the user");
266
+ }
267
+
268
+ /**
269
+ * @dev Added to allow future versions to add new variables in case this contract becomes
270
+ * inherited. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
271
+ */
272
+ uint256[49] private __gap;
273
+ }
@@ -0,0 +1,60 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.23;
3
+
4
+ // interfaces
5
+ import {IAppRegistry} from "../../apps/facets/registry/IAppRegistry.sol";
6
+ import {IImplementationRegistry} from "../../factory/facets/registry/IImplementationRegistry.sol";
7
+
8
+ // libraries
9
+ import {MembershipStorage} from "./membership/MembershipStorage.sol";
10
+
11
+ // contracts
12
+
13
+ /// @title DependencyLib
14
+ /// @dev Library for resolving contract dependencies via the Implementation Registry. Used for
15
+ /// retrieving the latest implementation addresses for named dependencies within a space.
16
+ library DependencyLib {
17
+ // Constants for dependency names
18
+ bytes32 internal constant RIVER_AIRDROP = bytes32("RiverAirdrop");
19
+ bytes32 internal constant SPACE_OPERATOR = bytes32("SpaceOperator"); // BaseRegistry
20
+ bytes32 internal constant SPACE_OWNER = bytes32("Space Owner");
21
+ bytes32 internal constant APP_REGISTRY = bytes32("AppRegistry");
22
+ bytes32 internal constant SWAP_ROUTER = bytes32("SwapRouter");
23
+
24
+ /// @notice Retrieves the latest implementation address for a given dependency name.
25
+ /// @dev Looks up the dependency in the Implementation Registry associated with the space factory.
26
+ /// @param ms The MembershipStorage layout containing the spaceFactory address.
27
+ /// @param dependencyName The keccak256 hash of the dependency name to resolve.
28
+ /// @return The address of the latest implementation for the specified dependency.
29
+ function getDependency(
30
+ MembershipStorage.Layout storage ms,
31
+ bytes32 dependencyName
32
+ ) internal view returns (address) {
33
+ IImplementationRegistry registry = IImplementationRegistry(ms.spaceFactory);
34
+ return registry.getLatestImplementation(dependencyName);
35
+ }
36
+
37
+ /// @notice Retrieves the latest implementation addresses for multiple dependency names.
38
+ /// @dev Batch resolves dependencies using the Implementation Registry associated with the space factory.
39
+ /// @param ms The MembershipStorage layout containing the spaceFactory address.
40
+ /// @param deps An array of keccak256 hashes of dependency names to resolve.
41
+ /// @return dependencies An array of addresses corresponding to the latest implementations for each dependency.
42
+ function getDependencies(
43
+ MembershipStorage.Layout storage ms,
44
+ bytes32[] memory deps
45
+ ) internal view returns (address[] memory dependencies) {
46
+ uint256 length = deps.length;
47
+ dependencies = new address[](length);
48
+ IImplementationRegistry registry = IImplementationRegistry(ms.spaceFactory);
49
+ for (uint256 i; i < length; ++i) {
50
+ dependencies[i] = registry.getLatestImplementation(deps[i]);
51
+ }
52
+ }
53
+
54
+ /// @notice Retrieves the latest implementation address for the App Registry dependency.
55
+ /// @dev Convenience method to get the App Registry implementation from the registry.
56
+ /// @return The address of the latest App Registry implementation.
57
+ function getAppRegistry() internal view returns (IAppRegistry) {
58
+ return IAppRegistry(getDependency(MembershipStorage.layout(), APP_REGISTRY));
59
+ }
60
+ }
@@ -0,0 +1,172 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.23;
3
+
4
+ // interfaces
5
+ import {IWalletLink} from "../../factory/facets/wallet-link/IWalletLink.sol";
6
+ import {IEntitlement, IEntitlementBase} from "../entitlements/IEntitlement.sol";
7
+
8
+ // libraries
9
+ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
10
+ import {PausableStorage} from "@towns-protocol/diamond/src/facets/pausable/PausableStorage.sol";
11
+ import {LibSort} from "solady/utils/LibSort.sol";
12
+ import {ERC721AStorage} from "../../diamond/facets/token/ERC721A/ERC721AStorage.sol";
13
+ import {CustomRevert} from "../../utils/libraries/CustomRevert.sol";
14
+ import {EntitlementsManagerStorage} from "./entitlements/EntitlementsManagerStorage.sol";
15
+ import {MembershipStorage} from "./membership/MembershipStorage.sol";
16
+ import {BanningStorage} from "./banning/BanningStorage.sol";
17
+ import {AppAccountStorage} from "./account/AppAccountStorage.sol";
18
+ import {DependencyLib} from "./DependencyLib.sol";
19
+
20
+ // contracts
21
+ import {TokenOwnableBase} from "@towns-protocol/diamond/src/facets/ownable/token/TokenOwnableBase.sol";
22
+
23
+ abstract contract Entitled is IEntitlementBase, TokenOwnableBase {
24
+ using EnumerableSet for EnumerableSet.AddressSet;
25
+ using EnumerableSet for EnumerableSet.UintSet;
26
+ using CustomRevert for bytes4;
27
+
28
+ bytes32 internal constant IN_TOWN = 0x0;
29
+ uint256 internal constant MEMBERSHIP_START_TOKEN_ID = 0;
30
+
31
+ function _isEntitledToSpace(
32
+ address user,
33
+ string memory permission
34
+ ) internal view returns (bool) {
35
+ return _isEntitledToChannel(IN_TOWN, user, bytes32(bytes(permission)));
36
+ }
37
+
38
+ function _isEntitledToChannel(
39
+ bytes32 channelId,
40
+ address user,
41
+ bytes32 permission
42
+ ) internal view returns (bool) {
43
+ address[] memory wallets = _getLinkedWalletsWithUser(user);
44
+ if (wallets.length == 0) return false;
45
+
46
+ // Check owner first (cheapest check)
47
+ address owner = _owner();
48
+ for (uint256 i; i < wallets.length; ++i) if (wallets[i] == owner) return true;
49
+
50
+ // Check if any wallet is banned using optimized O(n log n + m) approach
51
+ if (_hasAnyBannedWallet(wallets)) return false;
52
+
53
+ // Entitlement checks for members
54
+ EntitlementsManagerStorage.Layout storage ds = EntitlementsManagerStorage.layout();
55
+ address[] memory entitlements = ds.entitlements.values();
56
+ uint256 entitlementsLength = entitlements.length;
57
+
58
+ for (uint256 i; i < entitlementsLength; ++i) {
59
+ IEntitlement entitlement = ds.entitlementByAddress[entitlements[i]].entitlement;
60
+ if (
61
+ !entitlement.isCrosschain() &&
62
+ entitlement.isEntitled(channelId, wallets, permission)
63
+ ) return true;
64
+ }
65
+
66
+ return false;
67
+ }
68
+
69
+ function _validatePermission(string memory permission) internal view {
70
+ // Owner always has permission
71
+ if (_owner() == msg.sender) return;
72
+
73
+ // Check if not paused and user has permission
74
+ if (!PausableStorage.layout().paused) {
75
+ bytes32 permissionHash = bytes32(bytes(permission));
76
+
77
+ // Check space entitlements
78
+ if (_isEntitledToSpace(msg.sender, permission)) return;
79
+
80
+ // Check bot entitlements
81
+ if (_isBotEntitled(msg.sender, permissionHash)) return;
82
+ }
83
+
84
+ Entitlement__NotAllowed.selector.revertWith();
85
+ }
86
+
87
+ function _isMember(address user) internal view returns (bool member) {
88
+ member = ERC721AStorage.balanceOf(user) > 0;
89
+ }
90
+
91
+ function _validateMembership(address user) internal view {
92
+ // return if the user is a member or the owner
93
+ if (_isMember(user)) return;
94
+ address owner = _owner();
95
+ if (user == owner) return;
96
+
97
+ // otherwise, check if the user is a linked wallet
98
+ address[] memory wallets = _getLinkedWalletsWithUser(user);
99
+ uint256 length = wallets.length;
100
+ for (uint256 i; i < length; ++i) {
101
+ if (_isMember(wallets[i]) || wallets[i] == owner) return;
102
+ }
103
+ Entitlement__NotMember.selector.revertWith();
104
+ }
105
+
106
+ function _getLinkedWalletsWithUser(
107
+ address rootKey
108
+ ) internal view returns (address[] memory wallets) {
109
+ IWalletLink wl = IWalletLink(MembershipStorage.layout().spaceFactory);
110
+ address[] memory linkedWallets = wl.getWalletsByRootKey(rootKey);
111
+
112
+ // Allow for the possibility that the user is not a root key, but a linked wallet.
113
+ if (linkedWallets.length == 0) {
114
+ address alternateRootKey = wl.getRootKeyForWallet(rootKey);
115
+ if (alternateRootKey != address(0)) {
116
+ rootKey = alternateRootKey;
117
+ linkedWallets = wl.getWalletsByRootKey(rootKey);
118
+ }
119
+ }
120
+
121
+ wallets = LibSort.copy(linkedWallets);
122
+ assembly ("memory-safe") {
123
+ // Increment the size of the array by 1 and add the root key
124
+ mstore(wallets, add(mload(wallets), 1))
125
+ // LibSort.copy assigns the free memory pointer to the end of the array
126
+ mstore(mload(0x40), rootKey)
127
+ mstore(0x40, add(mload(0x40), 0x20))
128
+ }
129
+ }
130
+
131
+ function _isBotEntitled(address client, bytes32 permission) internal view returns (bool) {
132
+ // Early return if client is zero address
133
+ if (client == address(0)) return false;
134
+
135
+ address app = DependencyLib.getAppRegistry().getAppByClient(client);
136
+ if (app == address(0)) return false;
137
+
138
+ return AppAccountStorage.isAppEntitled(app, client, permission);
139
+ }
140
+
141
+ function _hasAnyBannedWallet(address[] memory wallets) internal view returns (bool) {
142
+ BanningStorage.Layout storage ds = BanningStorage.layout();
143
+ uint256[] memory bannedTokens = ds.bannedIds.values();
144
+
145
+ if (bannedTokens.length == 0) return false;
146
+
147
+ // Step 1: Collect banned token owners - O(n)
148
+ address[] memory bannedOwners = new address[](bannedTokens.length);
149
+ for (uint256 i; i < bannedTokens.length; ++i) {
150
+ bannedOwners[i] = ERC721AStorage.ownerAt(MEMBERSHIP_START_TOKEN_ID, bannedTokens[i]);
151
+ }
152
+
153
+ // Step 2: Sort and deduplicate banned owners - O(n log n)
154
+ LibSort.sort(bannedOwners);
155
+ LibSort.uniquifySorted(bannedOwners);
156
+
157
+ unchecked {
158
+ // Step 3: Combine wallets with unique banned owners - O(m + n)
159
+ address[] memory combined = new address[](wallets.length + bannedOwners.length);
160
+ for (uint256 i; i < wallets.length; ++i) {
161
+ combined[i] = wallets[i];
162
+ }
163
+ for (uint256 i; i < bannedOwners.length; ++i) {
164
+ combined[wallets.length + i] = bannedOwners[i];
165
+ }
166
+
167
+ // Step 4: Check for duplicates - O(m + n)
168
+ // any duplicate found is an intersection between wallets and banned owners
169
+ return LibSort.hasDuplicate(combined);
170
+ }
171
+ }
172
+ }
@@ -0,0 +1,21 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.23;
3
+
4
+ // interfaces
5
+
6
+ // libraries
7
+
8
+ // contracts
9
+
10
+ library Permissions {
11
+ string public constant ModifyChannel = "ModifyChannel";
12
+ string public constant AddRemoveChannels = "AddRemoveChannels";
13
+ string public constant ModifySpaceSettings = "ModifySpaceSettings";
14
+ string public constant ModifyRoles = "ModifyRoles";
15
+ string public constant JoinSpace = "JoinSpace";
16
+ string public constant ModifyBanning = "ModifyBanning";
17
+ string public constant Read = "Read";
18
+ string public constant Write = "Write";
19
+ string public constant React = "React";
20
+ string public constant Ping = "Ping";
21
+ }
@@ -0,0 +1,93 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.23;
3
+
4
+ // interfaces
5
+ import {IAppAccount} from "./IAppAccount.sol";
6
+
7
+ // libraries
8
+ import {AppAccountBase} from "./AppAccountBase.sol";
9
+
10
+ // contracts
11
+
12
+ import {Facet} from "@towns-protocol/diamond/src/facets/Facet.sol";
13
+ import {ReentrancyGuard} from "solady/utils/ReentrancyGuard.sol";
14
+
15
+ /**
16
+ * @title AppAccount
17
+ * @notice A lightweight modular erc6900 semi-compatible account
18
+ * @dev This account is used to execute transactions on behalf of a Space
19
+ */
20
+ contract AppAccount is IAppAccount, AppAccountBase, ReentrancyGuard, Facet {
21
+ /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
22
+ /* Execution */
23
+ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
24
+
25
+ function execute(
26
+ address target,
27
+ uint256 value,
28
+ bytes calldata data
29
+ ) external payable nonReentrant returns (bytes memory result) {
30
+ result = _onExecute(target, value, data);
31
+ }
32
+
33
+ /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
34
+ /* App Management */
35
+ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
36
+
37
+ /// @inheritdoc IAppAccount
38
+ function onInstallApp(bytes32 appId, bytes calldata data) external nonReentrant {
39
+ _onlyRegistry();
40
+ _installApp(appId, data);
41
+ }
42
+
43
+ /// @inheritdoc IAppAccount
44
+ function onUninstallApp(bytes32 appId, bytes calldata data) external {
45
+ _onlyRegistry();
46
+ _uninstallApp(appId, data);
47
+ }
48
+
49
+ /// @inheritdoc IAppAccount
50
+ function onRenewApp(bytes32 appId, bytes calldata data) external nonReentrant {
51
+ _onlyRegistry();
52
+ _onRenewApp(appId, data);
53
+ }
54
+
55
+ /// @inheritdoc IAppAccount
56
+ function enableApp(address app) external onlyOwner {
57
+ _enableApp(app);
58
+ }
59
+
60
+ /// @inheritdoc IAppAccount
61
+ function disableApp(address app) external onlyOwner {
62
+ _disableApp(app);
63
+ }
64
+
65
+ /// @inheritdoc IAppAccount
66
+ function getInstalledApps() external view returns (address[] memory) {
67
+ return _getApps();
68
+ }
69
+
70
+ /// @inheritdoc IAppAccount
71
+ function isAppInstalled(address app) external view returns (bool) {
72
+ return _isAppInstalled(app);
73
+ }
74
+
75
+ /// @inheritdoc IAppAccount
76
+ function getAppId(address app) external view returns (bytes32) {
77
+ return _getInstalledAppId(app);
78
+ }
79
+
80
+ /// @inheritdoc IAppAccount
81
+ function getAppExpiration(address app) external view returns (uint48) {
82
+ return _getGroupExpiration(_getInstalledAppId(app));
83
+ }
84
+
85
+ /// @inheritdoc IAppAccount
86
+ function isAppEntitled(
87
+ address app,
88
+ address publicKey,
89
+ bytes32 permission
90
+ ) external view returns (bool) {
91
+ return _isAppEntitled(app, publicKey, permission);
92
+ }
93
+ }