@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,170 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.23;
3
+
4
+ // interfaces
5
+
6
+ import {Attestation} from "@ethereum-attestation-service/eas-contracts/Common.sol";
7
+ import {ISchemaResolver} from "@ethereum-attestation-service/eas-contracts/resolver/ISchemaResolver.sol";
8
+
9
+ // errors
10
+ import {AccessDenied, InvalidEAS, InvalidLength} from "@ethereum-attestation-service/eas-contracts/Common.sol";
11
+
12
+ // contracts
13
+ abstract contract SchemaResolver is ISchemaResolver {
14
+ error InsufficientValue();
15
+ error NotPayable();
16
+
17
+ function __SchemaResolver_init(address registry) internal {
18
+ SchemaResolverStorage.Layout storage l = SchemaResolverStorage.getLayout();
19
+ l.registry = registry;
20
+ }
21
+
22
+ modifier onlyRegistry() {
23
+ if (msg.sender != SchemaResolverStorage.getLayout().registry) {
24
+ revert AccessDenied();
25
+ }
26
+ _;
27
+ }
28
+
29
+ receive() external payable virtual {
30
+ if (!isPayable()) {
31
+ revert NotPayable();
32
+ }
33
+ }
34
+
35
+ /// @inheritdoc ISchemaResolver
36
+ function isPayable() public pure virtual returns (bool) {
37
+ return false;
38
+ }
39
+
40
+ /// @inheritdoc ISchemaResolver
41
+ function attest(Attestation calldata attestation) external payable onlyRegistry returns (bool) {
42
+ return onAttest(attestation, msg.value);
43
+ }
44
+
45
+ /// @inheritdoc ISchemaResolver
46
+ function multiAttest(
47
+ Attestation[] calldata attestations,
48
+ uint256[] calldata values
49
+ ) external payable onlyRegistry returns (bool) {
50
+ uint256 length = attestations.length;
51
+ if (length != values.length) {
52
+ revert InvalidLength();
53
+ }
54
+
55
+ // We are keeping track of the remaining ETH amount that can be sent to resolvers and will
56
+ // keep deducting
57
+ // from it to verify that there isn't any attempt to send too much ETH to resolvers. Please
58
+ // note that unless
59
+ // some ETH was stuck in the contract by accident (which shouldn't happen in normal
60
+ // conditions), it won't be
61
+ // possible to send too much ETH anyway.
62
+ uint256 remainingValue = msg.value;
63
+
64
+ for (uint256 i = 0; i < length; ++i) {
65
+ // Ensure that the attester/revoker doesn't try to spend more than available.
66
+ uint256 value = values[i];
67
+ if (value > remainingValue) {
68
+ revert InsufficientValue();
69
+ }
70
+
71
+ unchecked {
72
+ // Subtract the ETH amount, that was provided to this attestation, from the global
73
+ // remaining ETH amount.
74
+ remainingValue -= value;
75
+ }
76
+
77
+ // Forward the attestation to the underlying resolver and return false in case it isn't
78
+ // approved.
79
+ if (!onAttest(attestations[i], value)) {
80
+ return false;
81
+ }
82
+ }
83
+
84
+ return true;
85
+ }
86
+
87
+ /// @inheritdoc ISchemaResolver
88
+ function revoke(Attestation calldata attestation) external payable onlyRegistry returns (bool) {
89
+ return onRevoke(attestation, msg.value);
90
+ }
91
+
92
+ /// @inheritdoc ISchemaResolver
93
+ function multiRevoke(
94
+ Attestation[] calldata attestations,
95
+ uint256[] calldata values
96
+ ) external payable onlyRegistry returns (bool) {
97
+ uint256 length = attestations.length;
98
+ if (length != values.length) {
99
+ revert InvalidLength();
100
+ }
101
+
102
+ // We are keeping track of the remaining ETH amount that can be sent to resolvers and will
103
+ // keep deducting
104
+ // from it to verify that there isn't any attempt to send too much ETH to resolvers. Please
105
+ // note that unless
106
+ // some ETH was stuck in the contract by accident (which shouldn't happen in normal
107
+ // conditions), it won't be
108
+ // possible to send too much ETH anyway.
109
+ uint256 remainingValue = msg.value;
110
+
111
+ for (uint256 i = 0; i < length; ++i) {
112
+ // Ensure that the attester/revoker doesn't try to spend more than available.
113
+ uint256 value = values[i];
114
+
115
+ if (value > remainingValue) {
116
+ revert InsufficientValue();
117
+ }
118
+
119
+ unchecked {
120
+ // Subtract the ETH amount, that was provided to this attestation, from the global
121
+ // remaining ETH amount.
122
+ remainingValue -= value;
123
+ }
124
+
125
+ // Forward the revocation to the underlying resolver and return false in case it isn't
126
+ // approved.
127
+ if (!onRevoke(attestations[i], value)) {
128
+ return false;
129
+ }
130
+ }
131
+
132
+ return true;
133
+ }
134
+
135
+ /// @notice Hook that is called before an attestation is created
136
+ /// @param attestation The attestation data
137
+ /// @param value The amount of ETH sent with the attestation
138
+ /// @return Whether the attestation is valid
139
+ function onAttest(
140
+ Attestation calldata attestation,
141
+ uint256 value
142
+ ) internal virtual returns (bool);
143
+
144
+ /// @notice Hook that is called before an attestation is revoked
145
+ /// @param attestation The attestation data
146
+ /// @param value The amount of ETH sent with the revocation
147
+ /// @return Whether the attestation can be revoked
148
+ function onRevoke(
149
+ Attestation calldata attestation,
150
+ uint256 value
151
+ ) internal virtual returns (bool);
152
+ }
153
+
154
+ library SchemaResolverStorage {
155
+ // keccak256(abi.encode(uint256(keccak256("towns.schema.resolver.storage")) - 1)) &
156
+ // ~bytes32(uint256(0xff))
157
+ bytes32 internal constant STORAGE_SLOT =
158
+ 0x3a14026143f063e5ed064cce80cc75f6ea25b68d1ad3a3261a9ae5e3f526fa00;
159
+
160
+ struct Layout {
161
+ address registry;
162
+ }
163
+
164
+ function getLayout() internal pure returns (Layout storage l) {
165
+ bytes32 slot = STORAGE_SLOT;
166
+ assembly {
167
+ l.slot := slot
168
+ }
169
+ }
170
+ }
@@ -0,0 +1,335 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.23;
3
+
4
+ // interfaces
5
+ import {ISchemaResolver} from "@ethereum-attestation-service/eas-contracts/resolver/ISchemaResolver.sol";
6
+ import {IAttestationRegistryBase} from "./IAttestationRegistry.sol";
7
+ import {ISchemaBase} from "../schema/ISchema.sol";
8
+
9
+ // libraries
10
+ import {CustomRevert} from "src/utils/libraries/CustomRevert.sol";
11
+ import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol";
12
+ import {AttestationLib} from "./AttestationLib.sol";
13
+ import {AttestationStorage} from "./AttestationStorage.sol";
14
+
15
+ // types
16
+ import {SchemaStorage} from "../schema/SchemaStorage.sol";
17
+ import {Attestation, EMPTY_UID, NO_EXPIRATION_TIME, NotFound} from "@ethereum-attestation-service/eas-contracts/Common.sol";
18
+ import {AttestationRequest, AttestationRequestData, IEAS, RevocationRequestData} from "@ethereum-attestation-service/eas-contracts/IEAS.sol";
19
+ import {SchemaRecord} from "@ethereum-attestation-service/eas-contracts/ISchemaRegistry.sol";
20
+
21
+ // contracts
22
+
23
+ abstract contract AttestationBase is IAttestationRegistryBase {
24
+ using CustomRevert for bytes4;
25
+ using AttestationLib for Attestation;
26
+
27
+ /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
28
+ /* Internal Functions */
29
+ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
30
+
31
+ /// @notice Creates a new attestation
32
+ /// @param attester The address creating the attestation
33
+ /// @param value The ETH value to send with the attestation
34
+ /// @param request The attestation request data
35
+ /// @return attestation The created attestation
36
+ function _attest(
37
+ address attester,
38
+ uint256 value,
39
+ AttestationRequest memory request
40
+ ) internal returns (Attestation memory attestation) {
41
+ AttestationRequestData[] memory data = new AttestationRequestData[](1);
42
+ data[0] = request.data;
43
+ (, bytes32[] memory uids) = _attestMultiple(request.schema, data, attester, value, true);
44
+ return _getAttestation(uids[0]);
45
+ }
46
+
47
+ /// @notice Revokes an existing attestation
48
+ /// @param schemaId The schema ID of the attestation to revoke
49
+ /// @param request The revocation request data
50
+ /// @param revoker The address revoking the attestation
51
+ /// @param availableValue The available ETH value for the revocation
52
+ /// @param last Whether this is the last revocation in a batch
53
+ function _revoke(
54
+ bytes32 schemaId,
55
+ RevocationRequestData memory request,
56
+ address revoker,
57
+ uint256 availableValue,
58
+ bool last
59
+ ) internal {
60
+ RevocationRequestData[] memory requests = new RevocationRequestData[](1);
61
+ requests[0] = request;
62
+ _revokeMultiple(schemaId, requests, revoker, availableValue, last);
63
+ }
64
+
65
+ /// @notice Retrieves an attestation by its UID
66
+ /// @param uid The unique identifier of the attestation
67
+ /// @return The attestation data
68
+ function _getAttestation(bytes32 uid) internal view returns (Attestation memory) {
69
+ return AttestationStorage.getAttestation(uid);
70
+ }
71
+
72
+ /// @notice Resolves a new attestation or revocation through its resolver
73
+ /// @param schema The schema record of the attestation
74
+ /// @param attestation The attestation data
75
+ /// @param value The ETH value to send to the resolver
76
+ /// @param isRevocation Whether this is a revocation
77
+ /// @param availableValue The total available ETH value
78
+ /// @param last Whether this is the last attestation/revocation in a batch
79
+ /// @return The amount of ETH value used
80
+ function _resolveAttestation(
81
+ SchemaRecord memory schema,
82
+ Attestation memory attestation,
83
+ uint256 value,
84
+ bool isRevocation,
85
+ uint256 availableValue,
86
+ bool last
87
+ ) private returns (uint256) {
88
+ ISchemaResolver resolver = ISchemaResolver(schema.resolver);
89
+
90
+ if (schema.uid == EMPTY_UID) {
91
+ InvalidAttestationSchema.selector.revertWith();
92
+ }
93
+
94
+ if (address(resolver) == address(0)) {
95
+ if (value != 0) NotPayable.selector.revertWith();
96
+ if (last) _refund(availableValue);
97
+ return 0;
98
+ }
99
+
100
+ if (value != 0) {
101
+ if (!resolver.isPayable()) NotPayable.selector.revertWith();
102
+ if (value > availableValue) {
103
+ InsufficientBalance.selector.revertWith();
104
+ }
105
+
106
+ unchecked {
107
+ availableValue -= value;
108
+ }
109
+ }
110
+
111
+ if (isRevocation) {
112
+ if (!resolver.revoke{value: value}(attestation)) {
113
+ InvalidRevocation.selector.revertWith();
114
+ }
115
+ } else if (!resolver.attest{value: value}(attestation)) {
116
+ InvalidAttestation.selector.revertWith();
117
+ }
118
+
119
+ if (last) _refund(availableValue);
120
+
121
+ return value;
122
+ }
123
+
124
+ /// @notice Resolves multiple attestations or revocations through their resolver
125
+ /// @param schema The schema record
126
+ /// @param attestations Array of attestations to resolve
127
+ /// @param values Array of ETH values for each attestation
128
+ /// @param isRevocation Whether these are revocations
129
+ /// @param availableValue Total available ETH value
130
+ /// @param last Whether this is the last batch
131
+ /// @return totalUsedValue Total ETH value used in the resolution
132
+ function _resolveAttestations(
133
+ SchemaRecord memory schema,
134
+ Attestation[] memory attestations,
135
+ uint256[] memory values,
136
+ bool isRevocation,
137
+ uint256 availableValue,
138
+ bool last
139
+ ) private returns (uint256 totalUsedValue) {
140
+ // Get the total number of attestations to process
141
+ uint256 len = attestations.length;
142
+ // Optimization: If only one attestation, use the single attestation resolver
143
+ if (len == 1) {
144
+ return
145
+ _resolveAttestation(
146
+ schema,
147
+ attestations[0],
148
+ values[0],
149
+ isRevocation,
150
+ availableValue,
151
+ last
152
+ );
153
+ }
154
+
155
+ // Get the resolver contract for this schema
156
+ ISchemaResolver resolver = ISchemaResolver(schema.resolver);
157
+ // If no resolver is set, handle zero-value case and refund if this is the last batch
158
+ if (address(resolver) == address(0)) {
159
+ _refundIfZeroValue(values, availableValue, last);
160
+ return 0;
161
+ }
162
+
163
+ // Check if the resolver accepts ETH payments
164
+ bool isPayable = resolver.isPayable();
165
+
166
+ // Calculate total value needed and validate each attestation's value
167
+ for (uint256 i; i < len; ++i) {
168
+ uint256 val = values[i];
169
+ if (val == 0) continue; // Skip zero-value attestations
170
+ // Ensure resolver accepts payments if value is non-zero
171
+ if (!isPayable) NotPayable.selector.revertWith();
172
+ // Ensure sufficient balance for this attestation
173
+ if (val > availableValue) InsufficientBalance.selector.revertWith();
174
+ // Safe arithmetic: subtract from available and add to total
175
+ unchecked {
176
+ availableValue -= val;
177
+ totalUsedValue += val;
178
+ }
179
+ }
180
+
181
+ // The 'last' parameter indicates this is the final batch in a sequence of operations.
182
+ // When true, any remaining ETH should be refunded to the sender.
183
+ // This is important because:
184
+ // 1. Multiple batches might be processed in sequence
185
+ // 2. We want to refund unused ETH only after all batches are complete
186
+ // 3. Prevents unnecessary gas costs from multiple refunds
187
+ if (last) _refund(availableValue);
188
+
189
+ // Process either revocation or attestation for multiple items
190
+ if (isRevocation) {
191
+ if (!resolver.multiRevoke{value: totalUsedValue}(attestations, values)) {
192
+ InvalidRevocation.selector.revertWith();
193
+ }
194
+ } else if (!resolver.multiAttest{value: totalUsedValue}(attestations, values)) {
195
+ InvalidAttestation.selector.revertWith();
196
+ }
197
+ }
198
+
199
+ /// @notice Refunds any remaining ETH value if no value was used
200
+ /// @param values Array of values to check
201
+ /// @param availableValue Total available ETH value
202
+ /// @param last Whether this is the last operation
203
+ function _refundIfZeroValue(
204
+ uint256[] memory values,
205
+ uint256 availableValue,
206
+ bool last
207
+ ) private {
208
+ uint256 len = values.length;
209
+ for (uint256 i; i < len; ++i) {
210
+ if (values[i] != 0) NotPayable.selector.revertWith();
211
+ }
212
+ if (last) _refund(availableValue);
213
+ }
214
+
215
+ /// @notice Creates multiple attestations
216
+ /// @param schemaId The schema ID for the attestations
217
+ /// @param requests Array of attestation requests
218
+ /// @param attester The address creating the attestations
219
+ /// @param availableValue Total available ETH value
220
+ /// @param last Whether this is the last batch
221
+ /// @return usedValue Amount of ETH value used
222
+ /// @return uids Array of created attestation UIDs
223
+ function _attestMultiple(
224
+ bytes32 schemaId,
225
+ AttestationRequestData[] memory requests,
226
+ address attester,
227
+ uint256 availableValue,
228
+ bool last
229
+ ) private returns (uint256 usedValue, bytes32[] memory uids) {
230
+ SchemaRecord memory schema = SchemaStorage.getSchema(schemaId);
231
+ if (schema.uid == EMPTY_UID) InvalidAttestationSchema.selector.revertWith();
232
+
233
+ uint64 timeNow = uint64(block.timestamp);
234
+ uint256 len = requests.length;
235
+ uids = new bytes32[](len);
236
+
237
+ Attestation[] memory attestations = new Attestation[](len);
238
+ uint256[] memory values = new uint256[](len);
239
+
240
+ AttestationStorage.Layout storage db = AttestationStorage.getLayout();
241
+
242
+ for (uint256 i; i < len; ++i) {
243
+ AttestationRequestData memory request = requests[i];
244
+ // Ensure that either no expiration time was set or that it was set in the future.
245
+ if (request.expirationTime != NO_EXPIRATION_TIME && request.expirationTime <= timeNow) {
246
+ InvalidExpirationTime.selector.revertWith();
247
+ }
248
+
249
+ if (!schema.revocable && request.revocable) {
250
+ Irrevocable.selector.revertWith();
251
+ }
252
+
253
+ Attestation memory attestation;
254
+ attestation.schema = schemaId;
255
+ attestation.refUID = request.refUID;
256
+ attestation.time = timeNow;
257
+ attestation.expirationTime = request.expirationTime;
258
+ attestation.revocable = request.revocable;
259
+ attestation.recipient = request.recipient;
260
+ attestation.attester = attester;
261
+ attestation.data = request.data;
262
+
263
+ bytes32 attestationUID;
264
+ uint32 bump;
265
+ while (true) {
266
+ attestationUID = attestation.getUID(bump);
267
+ if (db.attestations[attestationUID].uid == EMPTY_UID) {
268
+ break;
269
+ }
270
+ unchecked {
271
+ ++bump;
272
+ }
273
+ }
274
+
275
+ attestation.uid = attestationUID;
276
+ db.attestations[attestationUID] = attestation;
277
+
278
+ AttestationLib.checkRefUID(db.attestations[request.refUID], request.refUID);
279
+
280
+ attestations[i] = attestation;
281
+ values[i] = request.value;
282
+ uids[i] = attestationUID;
283
+
284
+ emit IEAS.Attested(
285
+ attestation.recipient,
286
+ attestation.attester,
287
+ attestation.uid,
288
+ attestation.schema
289
+ );
290
+ }
291
+
292
+ usedValue = _resolveAttestations(schema, attestations, values, false, availableValue, last);
293
+ }
294
+
295
+ /// @notice Revokes multiple attestations
296
+ /// @param schemaId The schema ID of the attestations
297
+ /// @param requests Array of revocation requests
298
+ /// @param revoker The address performing the revocations
299
+ /// @param availableValue Total available ETH value
300
+ /// @param last Whether this is the last batch
301
+ /// @return Returns the total ETH value used
302
+ function _revokeMultiple(
303
+ bytes32 schemaId,
304
+ RevocationRequestData[] memory requests,
305
+ address revoker,
306
+ uint256 availableValue,
307
+ bool last
308
+ ) private returns (uint256) {
309
+ SchemaRecord memory schema = SchemaStorage.getSchema(schemaId);
310
+ if (schema.uid == EMPTY_UID) InvalidAttestationSchema.selector.revertWith();
311
+
312
+ uint256 len = requests.length;
313
+ Attestation[] memory attestations = new Attestation[](len);
314
+ uint256[] memory values = new uint256[](len);
315
+
316
+ AttestationStorage.Layout storage db = AttestationStorage.getLayout();
317
+
318
+ for (uint256 i; i < len; ++i) {
319
+ Attestation storage attestation = db.attestations[requests[i].uid];
320
+ attestation.revoke(schemaId, revoker);
321
+ attestations[i] = attestation;
322
+ values[i] = requests[i].value;
323
+ }
324
+
325
+ return _resolveAttestations(schema, attestations, values, true, availableValue, last);
326
+ }
327
+
328
+ /// @notice Refunds any remaining ETH value to the sender
329
+ /// @param value The amount to refund
330
+ function _refund(uint256 value) private {
331
+ if (value > 0) {
332
+ SafeTransferLib.safeTransferETH(msg.sender, value);
333
+ }
334
+ }
335
+ }
@@ -0,0 +1,64 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.23;
3
+
4
+ // interfaces
5
+ import {IAttestationRegistryBase} from "./IAttestationRegistry.sol";
6
+
7
+ // types
8
+ import {Attestation, EMPTY_UID} from "@ethereum-attestation-service/eas-contracts/Common.sol";
9
+ import {IEAS} from "@ethereum-attestation-service/eas-contracts/IEAS.sol";
10
+
11
+ // libraries
12
+ import {CustomRevert} from "src/utils/libraries/CustomRevert.sol";
13
+
14
+ // contracts
15
+
16
+ library AttestationLib {
17
+ using CustomRevert for bytes4;
18
+ using AttestationLib for Attestation;
19
+
20
+ function revoke(Attestation storage self, bytes32 schemaId, address revoker) internal {
21
+ if (self.uid == EMPTY_UID)
22
+ IAttestationRegistryBase.InvalidAttestation.selector.revertWith();
23
+ if (self.schema != schemaId)
24
+ IAttestationRegistryBase.InvalidAttestationSchema.selector.revertWith();
25
+ if (self.attester != revoker) IAttestationRegistryBase.InvalidRevoker.selector.revertWith();
26
+ if (!self.revocable) IAttestationRegistryBase.Irrevocable.selector.revertWith();
27
+ if (self.revocationTime != 0)
28
+ IAttestationRegistryBase.InvalidRevocation.selector.revertWith();
29
+
30
+ self.revocationTime = uint64(block.timestamp);
31
+
32
+ emit IEAS.Revoked(self.recipient, self.attester, self.uid, self.schema);
33
+ }
34
+
35
+ /// @notice Validates that a referenced attestation UID exists
36
+ /// @param self The attestation to check
37
+ /// @param refUID The reference UID to check
38
+ function checkRefUID(Attestation storage self, bytes32 refUID) internal view {
39
+ if (refUID != EMPTY_UID && self.uid == EMPTY_UID) {
40
+ IAttestationRegistryBase.InvalidAttestation.selector.revertWith();
41
+ }
42
+ }
43
+
44
+ /// @notice Generates a unique hash for an attestation
45
+ /// @param self The attestation to hash
46
+ /// @param nonce The nonce to handle hash collisions
47
+ /// @return The unique hash for the attestation
48
+ function getUID(Attestation memory self, uint32 nonce) internal pure returns (bytes32) {
49
+ return
50
+ keccak256(
51
+ abi.encodePacked(
52
+ self.schema,
53
+ self.recipient,
54
+ self.attester,
55
+ self.time,
56
+ self.expirationTime,
57
+ self.revocable,
58
+ self.refUID,
59
+ self.data,
60
+ nonce
61
+ )
62
+ );
63
+ }
64
+ }
@@ -0,0 +1,39 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.23;
3
+
4
+ // interfaces
5
+ import {IAttestationRegistry} from "./IAttestationRegistry.sol";
6
+
7
+ // libraries
8
+ import {AttestationBase} from "./AttestationBase.sol";
9
+
10
+ // contracts
11
+
12
+ import {Attestation} from "@ethereum-attestation-service/eas-contracts/Common.sol";
13
+ import {AttestationRequest, RevocationRequest} from "@ethereum-attestation-service/eas-contracts/IEAS.sol";
14
+ import {Facet} from "@towns-protocol/diamond/src/facets/Facet.sol";
15
+
16
+ /// @title Attestation Registry
17
+ /// @notice A registry for attestation requests
18
+ /// @dev This contract is used for implementation reference purposes
19
+ contract AttestationRegistry is IAttestationRegistry, AttestationBase, Facet {
20
+ /// @notice Create a new attestation
21
+ /// @param request The attestation request data
22
+ /// @return The UID of the created attestation
23
+ function attest(AttestationRequest calldata request) external payable returns (bytes32) {
24
+ return _attest(msg.sender, msg.value, request).uid;
25
+ }
26
+
27
+ /// @notice Revoke an existing attestation
28
+ /// @param request The revocation request data
29
+ function revoke(RevocationRequest calldata request) external payable {
30
+ _revoke(request.schema, request.data, msg.sender, msg.value, true);
31
+ }
32
+
33
+ /// @notice Get an attestation by its UID
34
+ /// @param uid The attestation UID
35
+ /// @return The attestation data
36
+ function getAttestation(bytes32 uid) external view returns (Attestation memory) {
37
+ return _getAttestation(uid);
38
+ }
39
+ }
@@ -0,0 +1,35 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.23;
3
+
4
+ // interfaces
5
+
6
+ // libraries
7
+
8
+ // contracts
9
+ import {Attestation} from "@ethereum-attestation-service/eas-contracts/Common.sol";
10
+
11
+ library AttestationStorage {
12
+ // keccak256(abi.encode(uint256(keccak256("attestations.module.attestation.storage")) - 1)) & ~bytes32(uint256(0xff))
13
+ bytes32 internal constant STORAGE_SLOT =
14
+ 0xb3faa0ced44596f3bee5bed62671ce37f7e9245f810f19748a1d69616f8f2b00;
15
+
16
+ struct Layout {
17
+ mapping(bytes32 uid => Attestation attestation) attestations;
18
+ }
19
+
20
+ /// @notice Returns the storage layout for the attestation module
21
+ /// @return ds The storage layout struct
22
+ function getLayout() internal pure returns (Layout storage ds) {
23
+ assembly {
24
+ ds.slot := STORAGE_SLOT
25
+ }
26
+ }
27
+
28
+ function getAttestation(bytes32 uid) internal view returns (Attestation memory) {
29
+ return getLayout().attestations[uid];
30
+ }
31
+
32
+ function setAttestation(bytes32 uid, Attestation memory attestation) internal {
33
+ getLayout().attestations[uid] = attestation;
34
+ }
35
+ }
@@ -0,0 +1,43 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.23;
3
+
4
+ // interfaces
5
+
6
+ import {Attestation} from "@ethereum-attestation-service/eas-contracts/Common.sol";
7
+ import {AttestationRequest, RevocationRequest} from "@ethereum-attestation-service/eas-contracts/IEAS.sol";
8
+ // libraries
9
+
10
+ // contracts
11
+
12
+ interface IAttestationRegistryBase {
13
+ /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
14
+ /* ERRORS */
15
+ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
16
+
17
+ error NotPayable();
18
+ error InsufficientBalance();
19
+ error InvalidRevocation();
20
+ error InvalidAttestation();
21
+ error InvalidAttestationSchema();
22
+ error InvalidExpirationTime();
23
+ error Irrevocable();
24
+ error InvalidRevoker();
25
+ }
26
+
27
+ /// @title IAttestationRegistry Interface
28
+ /// @notice Interface for managing attestations in the registry
29
+ interface IAttestationRegistry is IAttestationRegistryBase {
30
+ /// @notice Creates a new attestation
31
+ /// @param request The attestation request containing schema ID and attestation data
32
+ /// @return The UID of the created attestation
33
+ function attest(AttestationRequest calldata request) external payable returns (bytes32);
34
+
35
+ /// @notice Revokes an existing attestation
36
+ /// @param request The revocation request containing schema ID and attestation data
37
+ function revoke(RevocationRequest calldata request) external payable;
38
+
39
+ /// @notice Retrieves an attestation by its UID
40
+ /// @param uid The unique identifier of the attestation
41
+ /// @return The attestation data structure
42
+ function getAttestation(bytes32 uid) external view returns (Attestation memory);
43
+ }