@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,591 @@
1
+ # Swap Integration Guide
2
+
3
+ This guide provides comprehensive documentation for integrating with the Towns Protocol swap system, which consists of SwapRouter (central routing) and SwapFacet (space-specific implementation).
4
+
5
+ ## Overview
6
+
7
+ The Towns Protocol swap system provides two integration options for executing token swaps:
8
+
9
+ - **SwapRouter**: Permissionless central routing contract that anyone can use directly. Handles swap execution, protocol fee collection, and integration with whitelisted DEX aggregators
10
+ - **SwapFacet**: Optional intermediary layer that adds space-specific benefits: membership validation, configurable poster fees, and points rewards
11
+
12
+ ### Key Features
13
+
14
+ - **Permissionless Access**: SwapRouter can be used by anyone without restrictions
15
+ - **Optional Space Benefits**: SwapFacet adds value-added features for space members
16
+ - **Dual Swap Methods**: Standard swaps and Permit2-based swaps (both contracts)
17
+ - **Transfer Efficiency**: Permit2 reduces token transfer hops (important for fee-on-transfer tokens)
18
+ - **Flexible Fee Structure**: Protocol fees + optional space poster fees
19
+ - **ETH Integration**: Special handling for ETH swaps with pre-calculated fees
20
+ - **Security**: Whitelisted routers, slippage protection, and anti-manipulation measures
21
+
22
+ ## Architecture Options
23
+
24
+ ### Direct SwapRouter Usage (Permissionless)
25
+ ```
26
+ User → SwapRouter → Whitelisted DEX Aggregator
27
+
28
+ Protocol Fee Collection
29
+ ```
30
+
31
+ ### SwapFacet Usage (Space Members)
32
+ ```
33
+ User → SwapFacet → SwapRouter → Whitelisted DEX Aggregator
34
+ ↓ ↓
35
+ Membership Protocol Fee
36
+ Validation Collection
37
+ Poster Fees
38
+ Points Rewards
39
+ ```
40
+
41
+ ### Token Transfer Hops
42
+
43
+ **executeSwap Method:**
44
+ - Direct SwapRouter: 1 hop (User → SwapRouter)
45
+ - Via SwapFacet: 2 hops (User → SwapFacet → SwapRouter)
46
+
47
+ **executeSwapWithPermit Method:**
48
+ - Both contracts: 1 hop (User → SwapRouter via Permit2)
49
+
50
+ ## Prerequisites
51
+
52
+ ### 1. Contract Addresses
53
+
54
+ ```typescript
55
+ // Base addresses (update for your network)
56
+ const SPACE_FACTORY_ADDRESS = "0x9978c826d93883701522d2CA645d5436e5654252"; // SpaceFactory diamond
57
+ const SWAP_ROUTER_ADDRESS = "0x95A2a333D30c8686dE8D01AC464d6034b9aA7b24"; // SwapRouter diamond
58
+ const SPACE_ADDRESS = "0x..."; // Your space with SwapFacet
59
+ const PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
60
+ ```
61
+
62
+ ### 2. Router Whitelisting
63
+
64
+ Only whitelisted routers can be used. Currently whitelisted routers:
65
+ - LiFi
66
+
67
+ Check if a router is whitelisted:
68
+ ```solidity
69
+ IPlatformRequirements(SPACE_FACTORY_ADDRESS).isRouterWhitelisted(routerAddress)
70
+ ```
71
+
72
+ ### 3. Space Membership (SwapFacet Only)
73
+
74
+ Space membership is **only required for SwapFacet** usage. SwapRouter can be used by anyone without membership.
75
+
76
+ ### 4. Token Approvals
77
+
78
+ - **SwapRouter Standard Swaps**: Approve tokens to SwapRouter
79
+ - **SwapFacet Standard Swaps**: Approve tokens to SwapFacet (2 hops)
80
+ - **Permit2 Swaps (Both)**: Approve tokens to Permit2 contract (1 hop)
81
+
82
+ ## Function Signatures
83
+
84
+ ### SwapRouter (Permissionless)
85
+
86
+ ```solidity
87
+ // SwapRouter standard swap
88
+ function executeSwap(
89
+ ExactInputParams calldata params,
90
+ RouterParams calldata routerParams,
91
+ address poster
92
+ ) external payable returns (uint256 amountOut, uint256 protocolFee);
93
+
94
+ // SwapRouter Permit2 swap
95
+ function executeSwapWithPermit(
96
+ ExactInputParams calldata params,
97
+ RouterParams calldata routerParams,
98
+ FeeConfig calldata posterFee,
99
+ Permit2Params calldata permit
100
+ ) external payable returns (uint256 amountOut, uint256 protocolFee);
101
+ ```
102
+
103
+ ### SwapFacet (Space Members Only)
104
+
105
+ ```solidity
106
+ // SwapFacet standard swap (2 hops)
107
+ function executeSwap(
108
+ ExactInputParams calldata params,
109
+ RouterParams calldata routerParams,
110
+ address poster
111
+ ) external payable returns (uint256 amountOut);
112
+
113
+ // SwapFacet Permit2 swap (1 hop)
114
+ function executeSwapWithPermit(
115
+ ExactInputParams calldata params,
116
+ RouterParams calldata routerParams,
117
+ FeeConfig calldata posterFee,
118
+ Permit2Params calldata permit
119
+ ) external payable returns (uint256 amountOut);
120
+ ```
121
+
122
+ ### Common Structs
123
+
124
+ ```solidity
125
+ struct ExactInputParams {
126
+ address tokenIn;
127
+ address tokenOut;
128
+ uint256 amountIn;
129
+ uint256 minAmountOut;
130
+ address recipient;
131
+ }
132
+
133
+ struct RouterParams {
134
+ address router; // Whitelisted router address
135
+ address approveTarget; // Address to approve tokens to
136
+ bytes swapData; // Encoded swap data for router
137
+ }
138
+
139
+ struct FeeConfig {
140
+ address recipient; // Poster address
141
+ uint16 feeBps; // Poster fee in basis points
142
+ }
143
+
144
+ struct Permit2Params {
145
+ address owner;
146
+ uint256 nonce;
147
+ uint256 deadline;
148
+ bytes signature;
149
+ }
150
+ ```
151
+
152
+ ## Choosing SwapRouter vs SwapFacet
153
+
154
+ ### When to Use SwapRouter Directly
155
+
156
+ ✅ **Use SwapRouter when:**
157
+ - User is not a space member
158
+ - You want maximum gas efficiency
159
+ - Working with fee-on-transfer tokens (avoid 2-hop penalty)
160
+ - Building a general DEX interface
161
+ - Want to avoid poster fees (pass `address(0)` as poster parameter)
162
+
163
+ ### When to Use SwapFacet
164
+
165
+ ✅ **Use SwapFacet when:**
166
+ - User is a space member
167
+ - You want poster fee rebates for the space
168
+ - You want automatic points distribution
169
+ - Building space-specific trading features
170
+ - Community benefits outweigh gas costs
171
+
172
+ ### Fee-on-Transfer Token Considerations
173
+
174
+ For tokens with transfer fees (like SAFEMOON, SHIB variants):
175
+
176
+ ```typescript
177
+ // BAD: 2 transfer taxes
178
+ SwapFacet.executeSwap()
179
+ // User → SwapFacet (tax 1) → SwapRouter (tax 2) → DEX
180
+
181
+ // GOOD: 1 transfer tax
182
+ SwapRouter.executeSwap()
183
+ // User → SwapRouter (tax 1) → DEX
184
+
185
+ // BEST: 1 transfer tax + space benefits
186
+ SwapFacet.executeSwapWithPermit()
187
+ // User → SwapRouter (tax 1, via Permit2) → DEX
188
+ ```
189
+
190
+ ## Integration Flows
191
+
192
+ ### 1. SwapRouter ETH to Token (Permissionless)
193
+
194
+ ```typescript
195
+ import { Address, createWalletClient } from 'viem';
196
+
197
+ async function swapETHToTokenDirect(
198
+ amountIn: bigint, // ETH amount in WEI
199
+ tokenOut: Address, // Output token address
200
+ slippage: number = 0.003, // 0.3% slippage tolerance
201
+ poster: Address = '0x0000000000000000000000000000000000000000' // No poster
202
+ ) {
203
+ // Step 1: Calculate fees for ETH input
204
+ const { amountInAfterFees, protocolFee, posterFee } = await publicClient.readContract({
205
+ address: SWAP_ROUTER_ADDRESS,
206
+ abi: swapRouterAbi,
207
+ functionName: 'getETHInputFees',
208
+ args: [amountIn, walletClient.account.address, poster]
209
+ });
210
+
211
+ // Step 2: Get quote from aggregator using amountInAfterFees
212
+ const quote = await fetchLiFiQuote({
213
+ fromToken: '0x0000000000000000000000000000000000000000',
214
+ toToken: tokenOut,
215
+ amount: amountInAfterFees, // Use amount after fees!
216
+ slippage: 0.15 // 15% slippage
217
+ });
218
+
219
+ // Step 3: Prepare parameters for simulation
220
+ const params = {
221
+ tokenIn: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeeeEeeeeeeeEEeE', // ETH address
222
+ tokenOut,
223
+ amountIn, // Original amount
224
+ minAmountOut: 0n, // Will be set after simulation
225
+ recipient: walletClient.account.address
226
+ };
227
+
228
+ const routerParams = {
229
+ router: LIFI_ROUTER,
230
+ approveTarget: LIFI_ROUTER,
231
+ swapData: quote.transactionRequest.data
232
+ };
233
+
234
+ // Step 4: Simulate swap to get expected output
235
+ const simulationResult = await publicClient.simulateContract({
236
+ address: SWAP_ROUTER_ADDRESS,
237
+ abi: swapRouterAbi,
238
+ functionName: 'executeSwap',
239
+ args: [params, routerParams, poster],
240
+ value: amountIn
241
+ });
242
+
243
+ const expectedAmountOut = simulationResult.result[0]; // First return value is amountOut
244
+
245
+ // Step 5: Calculate minAmountOut with slippage protection
246
+ const minAmountOut = expectedAmountOut * BigInt(Math.floor((1 - slippage) * 10000)) / 10000n;
247
+
248
+ // Step 6: Update params with calculated minAmountOut
249
+ params.minAmountOut = minAmountOut;
250
+
251
+ // Step 7: Execute swap directly on SwapRouter
252
+ const hash = await walletClient.writeContract({
253
+ address: SWAP_ROUTER_ADDRESS,
254
+ abi: swapRouterAbi,
255
+ functionName: 'executeSwap',
256
+ args: [params, routerParams, poster],
257
+ value: amountIn // Send ETH
258
+ });
259
+
260
+ return hash;
261
+ }
262
+ ```
263
+
264
+ ### 2. SwapFacet ETH to Token (Space Members + Benefits)
265
+
266
+ ```typescript
267
+ async function swapETHToTokenViaSpace(
268
+ amountIn: bigint, // ETH amount in WEI
269
+ tokenOut: Address,
270
+ slippage: number = 0.003, // 0.3% slippage tolerance
271
+ spaceAddress: Address,
272
+ poster: Address = spaceAddress // Default poster is space itself
273
+ ) {
274
+ // Step 1: Calculate fees (same as direct)
275
+ const { amountInAfterFees } = await publicClient.readContract({
276
+ address: SWAP_ROUTER_ADDRESS,
277
+ abi: swapRouterAbi,
278
+ functionName: 'getETHInputFees',
279
+ args: [amountIn, spaceAddress, poster]
280
+ });
281
+
282
+ // Step 2: Get quote using amountInAfterFees
283
+ const quote = await fetchLiFiQuote({
284
+ fromToken: '0x0000000000000000000000000000000000000000',
285
+ toToken: tokenOut,
286
+ amount: amountInAfterFees, // Use amount after fees!
287
+ slippage: 0.15 // 15% slippage
288
+ });
289
+
290
+ // Step 3: Prepare parameters for simulation
291
+ const params = {
292
+ tokenIn: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
293
+ tokenOut,
294
+ amountIn,
295
+ minAmountOut: 0n, // Will be set after simulation
296
+ recipient: walletClient.account.address
297
+ };
298
+
299
+ const routerParams = {
300
+ router: LIFI_ROUTER,
301
+ approveTarget: LIFI_ROUTER,
302
+ swapData: quote.transactionRequest.data
303
+ };
304
+
305
+ // Step 4: Simulate swap to get expected output
306
+ const simulationResult = await publicClient.simulateContract({
307
+ address: spaceAddress,
308
+ abi: swapFacetAbi,
309
+ functionName: 'executeSwap',
310
+ args: [params, routerParams, poster],
311
+ value: amountIn
312
+ });
313
+
314
+ const expectedAmountOut = simulationResult.result[0]; // First return value is amountOut
315
+
316
+ // Step 5: Calculate minAmountOut with slippage protection
317
+ const minAmountOut = expectedAmountOut * BigInt(Math.floor((1 - slippage) * 10000)) / 10000n;
318
+
319
+ // Step 6: Update params with calculated minAmountOut
320
+ params.minAmountOut = minAmountOut;
321
+
322
+ // Step 7: Execute via SwapFacet (gets points + poster fees)
323
+ const hash = await walletClient.writeContract({
324
+ address: spaceAddress,
325
+ abi: swapFacetAbi,
326
+ functionName: 'executeSwap',
327
+ args: [params, routerParams, poster],
328
+ value: amountIn
329
+ });
330
+
331
+ return hash;
332
+ }
333
+ ```
334
+
335
+ ### 3. Token Swaps with Permit2 (Token-to-Token or Token-to-ETH)
336
+
337
+ ```typescript
338
+ import { SignatureTransfer } from '@uniswap/permit2-sdk';
339
+ import { Address } from 'viem';
340
+
341
+ async function swapTokenWithPermit2(
342
+ tokenIn: Address,
343
+ tokenOut: Address,
344
+ amountIn: bigint,
345
+ slippage: number = 0.015, // 1.5% slippage tolerance
346
+ spaceAddress: Address,
347
+ posterFee: { recipient: Address, feeBps: number }
348
+ ) {
349
+ // Step 1: Ensure token is approved to Permit2
350
+ await approveToken(tokenIn, PERMIT2_ADDRESS, MAX_UINT256);
351
+
352
+ // Step 2: Get quote from aggregator
353
+ const quote = await fetchLiFiQuote({
354
+ fromToken: tokenIn,
355
+ toToken: tokenOut,
356
+ amount: amountIn,
357
+ slippage: 0.15 // 15% slippage
358
+ });
359
+
360
+ // Step 3: Prepare parameters for simulation
361
+ const params = {
362
+ tokenIn,
363
+ tokenOut,
364
+ amountIn,
365
+ minAmountOut: 0n, // Will be set after simulation
366
+ recipient: walletClient.account.address
367
+ };
368
+
369
+ const routerParams = {
370
+ router: LIFI_ROUTER,
371
+ approveTarget: LIFI_ROUTER,
372
+ swapData: quote.transactionRequest.data
373
+ };
374
+
375
+ // Step 4: Simulate swap to get expected output
376
+ const simulationResult = await publicClient.simulateContract({
377
+ address: spaceAddress,
378
+ abi: swapFacetAbi,
379
+ functionName: 'executeSwapWithPermit',
380
+ args: [params, routerParams, posterFee, { owner: walletClient.account.address, nonce: 0n, deadline: 0n, signature: '0x' }]
381
+ });
382
+
383
+ const expectedAmountOut = simulationResult.result[0]; // First return value is amountOut
384
+
385
+ // Step 5: Calculate minAmountOut with slippage protection
386
+ const minAmountOut = expectedAmountOut * BigInt(Math.floor((1 - slippage) * 10000)) / 10000n;
387
+
388
+ // Step 6: Update params with calculated minAmountOut
389
+ params.minAmountOut = minAmountOut;
390
+
391
+ // Step 7: Create witness data for Permit2
392
+ const witness = {
393
+ params,
394
+ routerParams,
395
+ posterFee
396
+ };
397
+
398
+ // Step 8: Generate permit signature
399
+ const permit = {
400
+ permitted: {
401
+ token: tokenIn,
402
+ amount: amountIn
403
+ },
404
+ spender: SWAP_ROUTER_ADDRESS,
405
+ nonce: BigInt(Date.now()),
406
+ deadline: BigInt(Math.floor(Date.now() / 1000) + 600)
407
+ };
408
+
409
+ // Step 9: Sign permit with witness
410
+ const { domain, types, values } = SignatureTransfer.getPermitData(
411
+ permit,
412
+ PERMIT2_ADDRESS,
413
+ chainId
414
+ );
415
+
416
+ const signature = await walletClient.signTypedData({
417
+ account: walletClient.account,
418
+ domain,
419
+ types: {
420
+ ...types,
421
+ SwapWitness: [
422
+ { name: 'params', type: 'ExactInputParams' },
423
+ { name: 'routerParams', type: 'RouterParams' },
424
+ { name: 'posterFee', type: 'FeeConfig' }
425
+ ]
426
+ },
427
+ primaryType: 'PermitWitnessTransferFrom',
428
+ message: {
429
+ ...values,
430
+ witness
431
+ }
432
+ });
433
+
434
+ // Step 10: Execute swap with permit
435
+ const permitParams = {
436
+ owner: walletClient.account.address,
437
+ nonce: permit.nonce,
438
+ deadline: permit.deadline,
439
+ signature
440
+ };
441
+
442
+ const hash = await walletClient.writeContract({
443
+ address: spaceAddress,
444
+ abi: swapFacetAbi,
445
+ functionName: 'executeSwapWithPermit',
446
+ args: [params, routerParams, posterFee, permitParams]
447
+ });
448
+
449
+ return hash;
450
+ }
451
+ ```
452
+
453
+ ### 4. Decision Matrix Summary
454
+
455
+ | Scenario | Best Option | Reasoning |
456
+ |----------|-------------|-----------|
457
+ | Non-space member | SwapRouter.executeSwap | Only option available |
458
+ | Standard ERC20 + want efficiency | SwapRouter.executeSwap | 1 hop, lower gas |
459
+ | Standard ERC20 + want space benefits | SwapFacet.executeSwap | 2 hops, but gets points/fees |
460
+ | Fee-on-transfer token + no space benefits | SwapRouter.executeSwap | 1 hop, avoid double tax |
461
+ | Fee-on-transfer token + want space benefits | SwapFacet.executeSwapWithPermit | 1 hop via Permit2 + benefits |
462
+ | Maximum security + space benefits | SwapFacet.executeSwapWithPermit | Permit2 + witness binding |
463
+
464
+ ## Fee Management
465
+
466
+ ### Understanding Fee Structure
467
+
468
+ 1. **Protocol Fee**: Platform-wide fee (set by protocol)
469
+ 2. **Poster Fee**: Space-configurable fee that can either:
470
+ - Go to space treasury (default)
471
+ - Be forwarded to external poster
472
+
473
+ ### Configuring Space Fees
474
+
475
+ Space owners can configure poster fees:
476
+
477
+ ```typescript
478
+ // Space owner configures fees
479
+ await spaceOwner.writeContract({
480
+ address: SPACE_ADDRESS,
481
+ abi: swapFacetAbi,
482
+ functionName: 'setSwapFeeConfig',
483
+ args: [
484
+ 50, // 0.5% poster fee (50 basis points)
485
+ false // forwardPosterFee: false = fees go to space
486
+ ]
487
+ });
488
+ ```
489
+
490
+ ### ETH Swap Fee Calculation Example
491
+
492
+ ```typescript
493
+ import { parseEther, formatEther, Address } from 'viem';
494
+
495
+ // Example: Swapping 1 ETH
496
+ const amountIn = parseEther('1'); // ETH amount in WEI
497
+
498
+ // Get fee breakdown
499
+ const fees = await publicClient.readContract({
500
+ address: SWAP_ROUTER_ADDRESS,
501
+ abi: swapRouterAbi,
502
+ functionName: 'getETHInputFees',
503
+ args: [amountIn, SPACE_ADDRESS, SPACE_ADDRESS]
504
+ });
505
+
506
+ console.log({
507
+ originalAmount: formatEther(amountIn),
508
+ amountAfterFees: formatEther(fees.amountInAfterFees),
509
+ protocolFee: formatEther(fees.protocolFee),
510
+ posterFee: formatEther(fees.posterFee)
511
+ });
512
+
513
+ // Output example:
514
+ // originalAmount: 1.0
515
+ // amountAfterFees: 0.99 (1% total fees)
516
+ // protocolFee: 0.005 (0.5%)
517
+ // posterFee: 0.005 (0.5%)
518
+ ```
519
+
520
+ ## Security Considerations
521
+
522
+ ### 1. Router Validation
523
+
524
+ Always verify routers are whitelisted before use:
525
+
526
+ ```typescript
527
+ import { Address } from 'viem';
528
+
529
+ async function isRouterValid(router: Address): Promise<boolean> {
530
+ return await publicClient.readContract({
531
+ address: SPACE_FACTORY_ADDRESS as Address,
532
+ abi: platformRequirementsAbi,
533
+ functionName: 'isRouterWhitelisted',
534
+ args: [router]
535
+ });
536
+ }
537
+ ```
538
+
539
+ ### 2. Deadline Management
540
+
541
+ For Permit2 swaps, use short deadlines:
542
+
543
+ ```typescript
544
+ const deadline = BigInt(Math.floor(Date.now() / 1000) + 300); // 5 minutes
545
+ ```
546
+
547
+ ### 3. Fee Manipulation Protection
548
+
549
+ When using Permit2, the poster fee is validated against the space configuration, preventing bait-and-switch attacks.
550
+
551
+ ## Best Practices
552
+
553
+ ### 1. Gas Optimization
554
+
555
+ - Use Permit2 to avoid separate approval transactions
556
+ - Batch multiple operations when possible
557
+
558
+ ### 2. User Experience
559
+
560
+ - Show clear fee breakdowns before swap
561
+ - Show poster fee distributions to spaces
562
+ - Provide swap history and analytics
563
+
564
+ ### 3. Monitoring
565
+
566
+ Track important metrics:
567
+ - Swap volume by token pairs
568
+ - Fee collection (protocol + poster)
569
+ - Points distribution
570
+ - Failed transaction reasons
571
+ - Slippage statistics
572
+
573
+ ## Conclusion
574
+
575
+ The Towns Protocol swap system provides flexible integration options for different use cases. Key implementation guidelines:
576
+
577
+ ### Development Best Practices
578
+ - **Always simulate swaps** before execution to calculate proper slippage protection
579
+ - **Use the Decision Matrix** (Section 5) to choose the right approach for your use case
580
+ - **Calculate ETH fees first** when swapping from ETH using `getETHInputFees`
581
+ - **Validate routers** before use to ensure they're whitelisted
582
+ - **Test thoroughly** with different token types (standard, fee-on-transfer, rebasing)
583
+
584
+ ### Integration Checklist
585
+ 1. Choose integration approach based on user membership and requirements
586
+ 2. Implement proper error handling for common failure scenarios
587
+ 3. Set reasonable deadlines for Permit2 transactions (5-10 minutes)
588
+ 4. Monitor transaction success rates and slippage performance
589
+ 5. Provide clear fee breakdowns to users before swap execution
590
+
591
+ For additional support and the latest contract addresses, consult the contract source code or reach out to the Towns Protocol development team.
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@towns-protocol/contracts",
3
+ "version": "0.0.302",
4
+ "packageManager": "yarn@3.8.0",
5
+ "scripts": {
6
+ "build": "forge build",
7
+ "clean": "forge clean",
8
+ "format": "yarn prettier:write",
9
+ "lint": "yarn solhint \"{script,src,tests}/**/*.sol\"",
10
+ "prettier:check": "prettier --check \"**/*.{sol,json,js,md,yml,ts}\" --ignore-path \".prettierignore\"",
11
+ "prettier:write": "prettier --write \"**/*.{sol,json,js,md,yml,ts}\" --ignore-path \".prettierignore\"",
12
+ "snapshot": "forge snapshot --isolate",
13
+ "test": "forge test --ffi --nmc Fork --fuzz-runs 4096",
14
+ "test:unit": "yarn test",
15
+ "typings": "wagmi generate"
16
+ },
17
+ "dependencies": {
18
+ "@erc6900/reference-implementation": "^0.8.1",
19
+ "@ethereum-attestation-service/eas-contracts": "^1.8.0",
20
+ "@layerzerolabs/oft-evm": "^3.1.4",
21
+ "@openzeppelin/contracts": "^5.4.0",
22
+ "@openzeppelin/contracts-upgradeable": "^5.4.0",
23
+ "@prb/math": "^4.1.0",
24
+ "@towns-protocol/diamond": "^0.6.1",
25
+ "@uniswap/permit2": "https://github.com/towns-protocol/permit2/archive/refs/tags/v1.0.0.tar.gz",
26
+ "crypto-lib": "https://github.com/towns-protocol/crypto-lib/archive/refs/tags/v1.0.0.tar.gz",
27
+ "solady": "^0.1.24"
28
+ },
29
+ "devDependencies": {
30
+ "@layerzerolabs/lz-evm-messagelib-v2": "^3.0.112",
31
+ "@layerzerolabs/lz-evm-protocol-v2": "^3.0.112",
32
+ "@layerzerolabs/oapp-evm": "^0.3.2",
33
+ "@openzeppelin/merkle-tree": "^1.0.8",
34
+ "@prb/test": "^0.6.4",
35
+ "@towns-protocol/prettier-config": "^0.0.302",
36
+ "@wagmi/cli": "^2.2.0",
37
+ "account-abstraction": "https://github.com/eth-infinitism/account-abstraction/archive/refs/tags/v0.7.0.tar.gz",
38
+ "forge-std": "github:foundry-rs/forge-std#v1.10.0",
39
+ "prettier": "^3.5.3",
40
+ "prettier-plugin-solidity": "^1.4.2",
41
+ "solhint": "^5.0.5",
42
+ "solidity-bytes-utils": "^0.8.4"
43
+ },
44
+ "files": [
45
+ "docs/**/*",
46
+ "src/**/*.sol",
47
+ "scripts/**/*.sol",
48
+ "README.md"
49
+ ],
50
+ "installConfig": {
51
+ "hoistingLimits": "dependencies"
52
+ },
53
+ "publishConfig": {
54
+ "access": "public"
55
+ },
56
+ "gitHead": "34c8d901987c0ecd0b2c01f1b93b5365daf11306"
57
+ }
@@ -0,0 +1,26 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ import {DeployBase as _DeployBase} from "@towns-protocol/diamond/scripts/common/DeployBase.s.sol";
5
+
6
+ abstract contract DeployBase is _DeployBase {
7
+ constructor() {
8
+ // set up chains
9
+ setChain(
10
+ "river",
11
+ ChainData({name: "river", chainId: 550, rpcUrl: "https://mainnet.rpc.river.build/http"})
12
+ );
13
+ setChain(
14
+ "river_anvil",
15
+ ChainData({name: "river_anvil", chainId: 31_338, rpcUrl: "http://localhost:8546"})
16
+ );
17
+ setChain(
18
+ "river_devnet",
19
+ ChainData({
20
+ name: "river_devnet",
21
+ chainId: 6_524_490,
22
+ rpcUrl: "https://devnet.rpc.river.build"
23
+ })
24
+ );
25
+ }
26
+ }
@@ -0,0 +1,7 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ import {DeployBase} from "./DeployBase.s.sol";
5
+ import {DeployFacet as _DeployFacet} from "@towns-protocol/diamond/scripts/common/DeployFacet.s.sol";
6
+
7
+ contract DeployFacet is DeployBase, _DeployFacet {}