@towns-protocol/contracts 0.0.302
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +21 -0
- package/README.md +206 -0
- package/docs/permitAndStake_integration_guide.md +266 -0
- package/docs/swap_integration_guide.md +591 -0
- package/package.json +57 -0
- package/scripts/common/DeployBase.s.sol +26 -0
- package/scripts/common/DeployFacet.s.sol +7 -0
- package/scripts/common/Deployer.s.sol +33 -0
- package/scripts/common/Interaction.s.sol +51 -0
- package/scripts/deployments/diamonds/DeployAppRegistry.s.sol +168 -0
- package/scripts/deployments/diamonds/DeployBaseRegistry.s.sol +263 -0
- package/scripts/deployments/diamonds/DeployRiverAirdrop.s.sol +203 -0
- package/scripts/deployments/diamonds/DeployRiverMigration.s.sol +129 -0
- package/scripts/deployments/diamonds/DeployRiverRegistry.s.sol +175 -0
- package/scripts/deployments/diamonds/DeploySpace.s.sol +285 -0
- package/scripts/deployments/diamonds/DeploySpaceFactory.s.sol +416 -0
- package/scripts/deployments/diamonds/DeploySpaceOwner.s.sol +183 -0
- package/scripts/deployments/diamonds/DeploySwapRouter.s.sol +176 -0
- package/scripts/deployments/diamonds/IDiamondInitHelper.sol +11 -0
- package/scripts/deployments/facets/DeployAppAccount.s.sol +51 -0
- package/scripts/deployments/facets/DeployAppRegistryFacet.s.sol +69 -0
- package/scripts/deployments/facets/DeployArchitect.s.sol +51 -0
- package/scripts/deployments/facets/DeployAttestationRegistry.s.sol +36 -0
- package/scripts/deployments/facets/DeployBanning.s.sol +30 -0
- package/scripts/deployments/facets/DeployChannels.s.sol +35 -0
- package/scripts/deployments/facets/DeployCreateSpace.s.sol +42 -0
- package/scripts/deployments/facets/DeployDropFacet.s.sol +49 -0
- package/scripts/deployments/facets/DeployERC721A.s.sol +48 -0
- package/scripts/deployments/facets/DeployERC721ANonTransferable.s.sol +49 -0
- package/scripts/deployments/facets/DeployERC721AQueryable.s.sol +30 -0
- package/scripts/deployments/facets/DeployEntitlementChecker.s.sol +49 -0
- package/scripts/deployments/facets/DeployEntitlementDataQueryable.s.sol +29 -0
- package/scripts/deployments/facets/DeployEntitlementsManager.s.sol +33 -0
- package/scripts/deployments/facets/DeployExecutorFacet.s.sol +60 -0
- package/scripts/deployments/facets/DeployFeatureManager.s.sol +38 -0
- package/scripts/deployments/facets/DeployGuardianFacet.s.sol +39 -0
- package/scripts/deployments/facets/DeployImplementationRegistry.s.sol +36 -0
- package/scripts/deployments/facets/DeployMainnetDelegation.s.sol +43 -0
- package/scripts/deployments/facets/DeployMembership.s.sol +77 -0
- package/scripts/deployments/facets/DeployMembershipMetadata.s.sol +30 -0
- package/scripts/deployments/facets/DeployMembershipToken.s.sol +47 -0
- package/scripts/deployments/facets/DeployMerkleAirdrop.s.sol +37 -0
- package/scripts/deployments/facets/DeployMetadata.s.sol +39 -0
- package/scripts/deployments/facets/DeployMockLegacyArchitect.s.sol +33 -0
- package/scripts/deployments/facets/DeployNodeOperator.s.sol +49 -0
- package/scripts/deployments/facets/DeployNodeRegistry.s.sol +37 -0
- package/scripts/deployments/facets/DeployOperatorRegistry.s.sol +36 -0
- package/scripts/deployments/facets/DeployPartnerRegistry.s.sol +41 -0
- package/scripts/deployments/facets/DeployPlatformRequirements.s.sol +75 -0
- package/scripts/deployments/facets/DeployPrepayFacet.s.sol +31 -0
- package/scripts/deployments/facets/DeployPricingModules.s.sol +36 -0
- package/scripts/deployments/facets/DeployReferrals.s.sol +34 -0
- package/scripts/deployments/facets/DeployReviewFacet.s.sol +31 -0
- package/scripts/deployments/facets/DeployRewardsDistributionV2.s.sol +76 -0
- package/scripts/deployments/facets/DeployRiverConfig.s.sol +41 -0
- package/scripts/deployments/facets/DeployRoles.s.sol +48 -0
- package/scripts/deployments/facets/DeploySchemaRegistry.s.sol +35 -0
- package/scripts/deployments/facets/DeploySignerFacet.s.sol +47 -0
- package/scripts/deployments/facets/DeploySimpleApp.s.sol +10 -0
- package/scripts/deployments/facets/DeploySpaceDelegation.s.sol +43 -0
- package/scripts/deployments/facets/DeploySpaceEntitlementGated.s.sol +31 -0
- package/scripts/deployments/facets/DeploySpaceFactoryInit.s.sol +33 -0
- package/scripts/deployments/facets/DeploySpaceOwnerFacet.s.sol +71 -0
- package/scripts/deployments/facets/DeployStreamRegistry.s.sol +50 -0
- package/scripts/deployments/facets/DeploySwapFacet.s.sol +33 -0
- package/scripts/deployments/facets/DeploySwapRouterFacet.s.sol +38 -0
- package/scripts/deployments/facets/DeployTipping.s.sol +31 -0
- package/scripts/deployments/facets/DeployTokenMigration.s.sol +40 -0
- package/scripts/deployments/facets/DeployTownsPoints.s.sol +53 -0
- package/scripts/deployments/facets/DeployTreasury.s.sol +30 -0
- package/scripts/deployments/facets/DeployUpgradeableBeacon.s.sol +34 -0
- package/scripts/deployments/facets/DeployWalletLink.s.sol +56 -0
- package/scripts/deployments/facets/DeployXChain.s.sol +35 -0
- package/scripts/deployments/utils/DeployAccountFactory.s.sol +40 -0
- package/scripts/deployments/utils/DeployEntitlementGatedExample.s.sol +23 -0
- package/scripts/deployments/utils/DeployEntrypoint.s.sol +28 -0
- package/scripts/deployments/utils/DeployMember.s.sol +95 -0
- package/scripts/deployments/utils/DeployMockDiamond.s.sol +7 -0
- package/scripts/deployments/utils/DeployMockERC20.s.sol +24 -0
- package/scripts/deployments/utils/DeployMockERC721A.s.sol +45 -0
- package/scripts/deployments/utils/DeployMockLegacyMembership.s.sol +29 -0
- package/scripts/deployments/utils/DeployMockMessenger.s.sol +42 -0
- package/scripts/deployments/utils/DeployMockNFT.s.sol +86 -0
- package/scripts/deployments/utils/DeployPoapEntitlement.s.sol +16 -0
- package/scripts/deployments/utils/DeployProxyBatchDelegation.s.sol +112 -0
- package/scripts/deployments/utils/DeploySpaceProxyInitializer.s.sol +28 -0
- package/scripts/deployments/utils/DeployTieredLogPricingV2.s.sol +23 -0
- package/scripts/deployments/utils/DeployTieredLogPricingV3.s.sol +23 -0
- package/scripts/deployments/utils/DeployTownsBase.s.sol +95 -0
- package/scripts/deployments/utils/DeployTownsMainnet.s.sol +66 -0
- package/scripts/deployments/utils/DeployTownsMulti.s.sol +53 -0
- package/scripts/deployments/utils/DeployWrappedTowns.s.sol +52 -0
- package/scripts/deployments/utils/LibLayerZeroValues.sol +34 -0
- package/scripts/deployments/utils/pricing/TieredLogPricing.s.sol +45 -0
- package/scripts/interactions/InteractAirdrop.s.sol +57 -0
- package/scripts/interactions/InteractAlphaPost.s.sol +32 -0
- package/scripts/interactions/InteractAlphaSparse.s.sol +173 -0
- package/scripts/interactions/InteractBaseAlpha.s.sol +84 -0
- package/scripts/interactions/InteractBaseBridge.s.sol +48 -0
- package/scripts/interactions/InteractBridgeLayerZero.s.sol +102 -0
- package/scripts/interactions/InteractClaimCondition.s.sol +56 -0
- package/scripts/interactions/InteractCreateSpace.s.sol +50 -0
- package/scripts/interactions/InteractDiamondCut.s.sol +47 -0
- package/scripts/interactions/InteractDropFacet.s.sol +32 -0
- package/scripts/interactions/InteractEnableNewSnapshotFormat.s.sol +27 -0
- package/scripts/interactions/InteractEnableNode2NodeAuth.s.sol +27 -0
- package/scripts/interactions/InteractMembership.s.sol +42 -0
- package/scripts/interactions/InteractMockERC721A.s.sol +20 -0
- package/scripts/interactions/InteractNodeOperators.s.sol +41 -0
- package/scripts/interactions/InteractPostDeploy.s.sol +59 -0
- package/scripts/interactions/InteractPrepay.s.sol +30 -0
- package/scripts/interactions/InteractRegisterApp.s.sol +61 -0
- package/scripts/interactions/InteractRiverAlpha.s.sol +30 -0
- package/scripts/interactions/InteractRiverAlphaSparse.s.sol +117 -0
- package/scripts/interactions/InteractRiverMainnet.s.sol +27 -0
- package/scripts/interactions/InteractRiverRegistry.s.sol +36 -0
- package/scripts/interactions/InteractRiverRegistrySetBlocklist.s.sol +30 -0
- package/scripts/interactions/InteractRiverRegistrySetFreq.s.sol +27 -0
- package/scripts/interactions/InteractRiverRegistrySetRepl.s.sol +30 -0
- package/scripts/interactions/InteractSetDefaultUri.s.sol +20 -0
- package/scripts/interactions/InteractSetDefaultUriLocalhost.s.sol +19 -0
- package/scripts/interactions/InteractTransferOwnership.s.sol +21 -0
- package/scripts/interactions/InteractUpdateMbRecencyCheck.s.sol +27 -0
- package/scripts/interactions/InteractUpdateMediaChunkCount.s.sol +27 -0
- package/scripts/interactions/InteractUpdateMediaChunkSize.s.sol +27 -0
- package/scripts/interactions/helpers/AlphaHelper.sol +149 -0
- package/scripts/interactions/helpers/RiverConfigValues.sol +22 -0
- package/scripts/interactions/interfaces/IL1StandardBridge.sol +35 -0
- package/scripts/interactions/interfaces/IL2StandardBridge.sol +69 -0
- package/src/airdrop/drop/DropBase.sol +210 -0
- package/src/airdrop/drop/DropClaim.sol +55 -0
- package/src/airdrop/drop/DropFacet.sol +176 -0
- package/src/airdrop/drop/DropGroup.sol +111 -0
- package/src/airdrop/drop/DropStorage.sol +23 -0
- package/src/airdrop/drop/IDropFacet.sol +136 -0
- package/src/airdrop/points/CheckIn.sol +71 -0
- package/src/airdrop/points/ITownsPoints.sol +64 -0
- package/src/airdrop/points/TownsPoints.sol +196 -0
- package/src/airdrop/points/TownsPointsStorage.sol +22 -0
- package/src/apps/BaseApp.sol +62 -0
- package/src/apps/ITownsApp.sol +28 -0
- package/src/apps/SchemaResolver.sol +170 -0
- package/src/apps/facets/attest/AttestationBase.sol +335 -0
- package/src/apps/facets/attest/AttestationLib.sol +64 -0
- package/src/apps/facets/attest/AttestationRegistry.sol +39 -0
- package/src/apps/facets/attest/AttestationStorage.sol +35 -0
- package/src/apps/facets/attest/IAttestationRegistry.sol +43 -0
- package/src/apps/facets/registry/AppRegistryBase.sol +403 -0
- package/src/apps/facets/registry/AppRegistryFacet.sol +173 -0
- package/src/apps/facets/registry/AppRegistryStorage.sol +53 -0
- package/src/apps/facets/registry/IAppRegistry.sol +159 -0
- package/src/apps/facets/schema/ISchema.sol +14 -0
- package/src/apps/facets/schema/SchemaBase.sol +88 -0
- package/src/apps/facets/schema/SchemaLib.sol +14 -0
- package/src/apps/facets/schema/SchemaRegistry.sol +51 -0
- package/src/apps/facets/schema/SchemaStorage.sol +34 -0
- package/src/apps/helpers/ISimpleApp.sol +51 -0
- package/src/apps/helpers/SimpleApp.sol +97 -0
- package/src/apps/helpers/SimpleAppStorage.sol +27 -0
- package/src/base/registry/facets/checker/EntitlementChecker.sol +237 -0
- package/src/base/registry/facets/checker/EntitlementCheckerStorage.sol +28 -0
- package/src/base/registry/facets/checker/IEntitlementChecker.sol +95 -0
- package/src/base/registry/facets/delegation/ISpaceDelegation.sol +69 -0
- package/src/base/registry/facets/delegation/SpaceDelegationFacet.sol +250 -0
- package/src/base/registry/facets/delegation/SpaceDelegationStorage.sol +35 -0
- package/src/base/registry/facets/distribution/v1/IRewardsDistribution.sol +51 -0
- package/src/base/registry/facets/distribution/v1/RewardsDistribution.sol +439 -0
- package/src/base/registry/facets/distribution/v1/RewardsDistributionStorage.sol +32 -0
- package/src/base/registry/facets/distribution/v2/DelegationProxy.sol +53 -0
- package/src/base/registry/facets/distribution/v2/IRewardsDistribution.sol +372 -0
- package/src/base/registry/facets/distribution/v2/RewardsDistributionBase.sol +299 -0
- package/src/base/registry/facets/distribution/v2/RewardsDistributionStorage.sol +37 -0
- package/src/base/registry/facets/distribution/v2/RewardsDistributionV2.sol +392 -0
- package/src/base/registry/facets/distribution/v2/StakingRewards.sol +466 -0
- package/src/base/registry/facets/mainnet/ICrossDomainMessenger.sol +58 -0
- package/src/base/registry/facets/mainnet/IMainnetDelegation.sol +127 -0
- package/src/base/registry/facets/mainnet/MainnetDelegation.sol +119 -0
- package/src/base/registry/facets/mainnet/MainnetDelegationBase.sol +274 -0
- package/src/base/registry/facets/mainnet/MainnetDelegationStorage.sol +36 -0
- package/src/base/registry/facets/operator/INodeOperator.sol +91 -0
- package/src/base/registry/facets/operator/NodeOperatorFacet.sol +189 -0
- package/src/base/registry/facets/operator/NodeOperatorStorage.sol +39 -0
- package/src/base/registry/facets/xchain/IXChain.sol +54 -0
- package/src/base/registry/facets/xchain/XChain.sol +158 -0
- package/src/base/registry/facets/xchain/XChainCheckLib.sol +105 -0
- package/src/base/registry/facets/xchain/XChainLib.sol +46 -0
- package/src/diamond/facets/beacon/UpgradeableBeacon.sol +38 -0
- package/src/diamond/facets/beacon/UpgradeableBeaconFacet.sol +34 -0
- package/src/diamond/facets/governance/votes/Checkpoints.sol +642 -0
- package/src/diamond/facets/governance/votes/Votes.sol +63 -0
- package/src/diamond/facets/governance/votes/VotesBase.sol +274 -0
- package/src/diamond/facets/governance/votes/VotesStorage.sol +21 -0
- package/src/diamond/facets/governance/votes/enumerable/IVotesEnumerable.sol +38 -0
- package/src/diamond/facets/governance/votes/enumerable/VotesEnumerable.sol +39 -0
- package/src/diamond/facets/governance/votes/enumerable/VotesEnumerableLib.sol +102 -0
- package/src/diamond/facets/metadata/IMetadata.sol +27 -0
- package/src/diamond/facets/metadata/MetadataFacet.sol +71 -0
- package/src/diamond/facets/token/ERC5643/ERC5643.sol +51 -0
- package/src/diamond/facets/token/ERC5643/ERC5643Base.sol +48 -0
- package/src/diamond/facets/token/ERC5643/ERC5643Storage.sol +26 -0
- package/src/diamond/facets/token/ERC5643/IERC5643.sol +44 -0
- package/src/diamond/facets/token/ERC721A/ERC721A.sol +270 -0
- package/src/diamond/facets/token/ERC721A/ERC721ABase.sol +829 -0
- package/src/diamond/facets/token/ERC721A/ERC721ANonTransferable.sol +21 -0
- package/src/diamond/facets/token/ERC721A/ERC721AStorage.sol +115 -0
- package/src/diamond/facets/token/ERC721A/IERC721A.sol +283 -0
- package/src/diamond/facets/token/ERC721A/extensions/ERC721AQueryable.sol +134 -0
- package/src/diamond/facets/token/ERC721A/extensions/IERC721AQueryable.sol +83 -0
- package/src/diamond/utils/Context.sol +19 -0
- package/src/factory/SpaceFactoryInit.sol +17 -0
- package/src/factory/facets/architect/Architect.sol +98 -0
- package/src/factory/facets/architect/ArchitectBase.sol +95 -0
- package/src/factory/facets/architect/ArchitectStorage.sol +28 -0
- package/src/factory/facets/architect/IArchitect.sol +155 -0
- package/src/factory/facets/architect/ImplementationStorage.sol +42 -0
- package/src/factory/facets/architect/pricing/IPricingModules.sol +41 -0
- package/src/factory/facets/architect/pricing/PricingModulesBase.sol +89 -0
- package/src/factory/facets/architect/pricing/PricingModulesFacet.sol +40 -0
- package/src/factory/facets/architect/pricing/PricingModulesStorage.sol +30 -0
- package/src/factory/facets/create/CreateSpace.sol +107 -0
- package/src/factory/facets/create/CreateSpaceLib.sol +335 -0
- package/src/factory/facets/create/ICreateSpace.sol +70 -0
- package/src/factory/facets/feature/FeatureConditionLib.sol +53 -0
- package/src/factory/facets/feature/FeatureManagerFacet.sol +66 -0
- package/src/factory/facets/feature/FeatureManagerLib.sol +168 -0
- package/src/factory/facets/feature/IFeatureManagerFacet.sol +73 -0
- package/src/factory/facets/partner/IPartnerRegistry.sol +56 -0
- package/src/factory/facets/partner/PartnerRegistry.sol +57 -0
- package/src/factory/facets/partner/PartnerRegistryBase.sol +132 -0
- package/src/factory/facets/partner/PartnerRegistryStorage.sol +40 -0
- package/src/factory/facets/platform/requirements/IPlatformRequirements.sol +143 -0
- package/src/factory/facets/platform/requirements/PlatformRequirementsBase.sol +124 -0
- package/src/factory/facets/platform/requirements/PlatformRequirementsFacet.sol +122 -0
- package/src/factory/facets/platform/requirements/PlatformRequirementsStorage.sol +41 -0
- package/src/factory/facets/registry/IImplementationRegistry.sol +46 -0
- package/src/factory/facets/registry/ImplementationRegistry.sol +64 -0
- package/src/factory/facets/registry/ImplementationRegistryStorage.sol +28 -0
- package/src/factory/facets/wallet-link/IWalletLink.sol +218 -0
- package/src/factory/facets/wallet-link/WalletLink.sol +108 -0
- package/src/factory/facets/wallet-link/WalletLinkBase.sol +492 -0
- package/src/factory/facets/wallet-link/interfaces/IDelegateRegistry.sol +63 -0
- package/src/factory/facets/wallet-link/interfaces/IDelegateRegistryV1.sol +35 -0
- package/src/factory/facets/wallet-link/interfaces/ISCL_EIP6565.sol +24 -0
- package/src/factory/facets/wallet-link/libraries/SolanaUtils.sol +161 -0
- package/src/factory/facets/wallet-link/libraries/WalletLib.sol +62 -0
- package/src/river/registry/facets/config/IRiverConfig.sol +117 -0
- package/src/river/registry/facets/config/RiverConfig.sol +174 -0
- package/src/river/registry/facets/node/INodeRegistry.sol +69 -0
- package/src/river/registry/facets/node/NodeRegistry.sol +143 -0
- package/src/river/registry/facets/operator/IOperatorRegistry.sol +28 -0
- package/src/river/registry/facets/operator/OperatorRegistry.sol +86 -0
- package/src/river/registry/facets/stream/IStreamRegistry.sol +184 -0
- package/src/river/registry/facets/stream/StreamRegistry.sol +396 -0
- package/src/river/registry/libraries/RegistryErrors.sol +24 -0
- package/src/river/registry/libraries/RegistryStorage.sol +181 -0
- package/src/router/ISwapRouter.sol +226 -0
- package/src/router/Permit2Hash.sol +92 -0
- package/src/router/SwapRouter.sol +463 -0
- package/src/router/SwapRouterStorage.sol +21 -0
- package/src/spaces/entitlements/ICrossChainEntitlement.sol +22 -0
- package/src/spaces/entitlements/IEntitlement.sol +61 -0
- package/src/spaces/entitlements/PolymarketEntitlement.sol +79 -0
- package/src/spaces/entitlements/poap/IPOAP.sol +26 -0
- package/src/spaces/entitlements/poap/PoapEntitlement.sol +56 -0
- package/src/spaces/entitlements/rule/IRuleEntitlement.sol +174 -0
- package/src/spaces/entitlements/rule/RuleEntitlement.sol +183 -0
- package/src/spaces/entitlements/rule/RuleEntitlementV2.sol +219 -0
- package/src/spaces/entitlements/user/IUserEntitlement.sol +24 -0
- package/src/spaces/entitlements/user/UserEntitlement.sol +273 -0
- package/src/spaces/facets/DependencyLib.sol +60 -0
- package/src/spaces/facets/Entitled.sol +172 -0
- package/src/spaces/facets/Permissions.sol +21 -0
- package/src/spaces/facets/account/AppAccount.sol +93 -0
- package/src/spaces/facets/account/AppAccountBase.sol +275 -0
- package/src/spaces/facets/account/AppAccountStorage.sol +63 -0
- package/src/spaces/facets/account/IAppAccount.sol +71 -0
- package/src/spaces/facets/account/SignerFacet.sol +26 -0
- package/src/spaces/facets/banning/Banning.sol +41 -0
- package/src/spaces/facets/banning/BanningBase.sol +33 -0
- package/src/spaces/facets/banning/BanningStorage.sol +23 -0
- package/src/spaces/facets/banning/IBanning.sol +35 -0
- package/src/spaces/facets/channels/ChannelBase.sol +87 -0
- package/src/spaces/facets/channels/ChannelService.sol +177 -0
- package/src/spaces/facets/channels/ChannelStorage.sol +34 -0
- package/src/spaces/facets/channels/Channels.sol +80 -0
- package/src/spaces/facets/channels/IChannel.sol +98 -0
- package/src/spaces/facets/dispatcher/DispatcherBase.sol +86 -0
- package/src/spaces/facets/dispatcher/DispatcherStorage.sol +21 -0
- package/src/spaces/facets/dispatcher/IDispatcher.sol +6 -0
- package/src/spaces/facets/entitlements/EntitlementsManager.sol +49 -0
- package/src/spaces/facets/entitlements/EntitlementsManagerBase.sol +87 -0
- package/src/spaces/facets/entitlements/EntitlementsManagerService.sol +142 -0
- package/src/spaces/facets/entitlements/EntitlementsManagerStorage.sol +34 -0
- package/src/spaces/facets/entitlements/IEntitlementsManager.sol +67 -0
- package/src/spaces/facets/entitlements/extensions/EntitlementDataQueryable.sol +153 -0
- package/src/spaces/facets/entitlements/extensions/IEntitlementDataQueryable.sol +32 -0
- package/src/spaces/facets/executor/ExecutorBase.sol +564 -0
- package/src/spaces/facets/executor/ExecutorFacet.sol +178 -0
- package/src/spaces/facets/executor/ExecutorStorage.sol +99 -0
- package/src/spaces/facets/executor/GroupLib.sol +128 -0
- package/src/spaces/facets/executor/IExecutor.sol +287 -0
- package/src/spaces/facets/executor/hooks/HookBase.sol +172 -0
- package/src/spaces/facets/executor/hooks/HookLib.sol +38 -0
- package/src/spaces/facets/executor/hooks/IHookBase.sol +48 -0
- package/src/spaces/facets/gated/EntitlementGated.sol +59 -0
- package/src/spaces/facets/gated/EntitlementGatedBase.sol +324 -0
- package/src/spaces/facets/gated/EntitlementGatedStorage.sol +29 -0
- package/src/spaces/facets/gated/IEntitlementGated.sol +55 -0
- package/src/spaces/facets/guardian/GuardianBase.sol +80 -0
- package/src/spaces/facets/guardian/GuardianFacet.sol +43 -0
- package/src/spaces/facets/guardian/GuardianStorage.sol +27 -0
- package/src/spaces/facets/guardian/IGuardian.sol +54 -0
- package/src/spaces/facets/membership/IMembership.sol +216 -0
- package/src/spaces/facets/membership/MembershipBase.sol +272 -0
- package/src/spaces/facets/membership/MembershipFacet.sol +191 -0
- package/src/spaces/facets/membership/MembershipStorage.sol +40 -0
- package/src/spaces/facets/membership/join/MembershipJoin.sol +547 -0
- package/src/spaces/facets/membership/metadata/IMembershipMetadata.sol +9 -0
- package/src/spaces/facets/membership/metadata/MembershipMetadata.sol +32 -0
- package/src/spaces/facets/membership/pricing/IMembershipPricing.sol +18 -0
- package/src/spaces/facets/membership/pricing/fixed/FixedPricing.sol +29 -0
- package/src/spaces/facets/membership/pricing/fixed/FixedPricingStorage.sol +27 -0
- package/src/spaces/facets/membership/pricing/tiered/TieredLogPricingOracleV2.sol +148 -0
- package/src/spaces/facets/membership/pricing/tiered/TieredLogPricingOracleV3.sol +137 -0
- package/src/spaces/facets/membership/token/MembershipToken.sol +25 -0
- package/src/spaces/facets/owner/ISpaceOwner.sol +85 -0
- package/src/spaces/facets/owner/SpaceOwner.sol +174 -0
- package/src/spaces/facets/owner/SpaceOwnerBase.sol +121 -0
- package/src/spaces/facets/owner/SpaceOwnerStorage.sol +41 -0
- package/src/spaces/facets/owner/SpaceOwnerUriBase.sol +54 -0
- package/src/spaces/facets/points/PointsBase.sol +35 -0
- package/src/spaces/facets/prepay/IPrepay.sol +43 -0
- package/src/spaces/facets/prepay/PrepayBase.sol +27 -0
- package/src/spaces/facets/prepay/PrepayFacet.sol +59 -0
- package/src/spaces/facets/prepay/PrepayStorage.sol +26 -0
- package/src/spaces/facets/proxy/ISpaceProxyInitializer.sol +21 -0
- package/src/spaces/facets/proxy/SpaceProxy.sol +15 -0
- package/src/spaces/facets/proxy/SpaceProxyInitializer.sol +55 -0
- package/src/spaces/facets/referrals/IReferrals.sol +98 -0
- package/src/spaces/facets/referrals/ReferralsBase.sol +81 -0
- package/src/spaces/facets/referrals/ReferralsFacet.sol +65 -0
- package/src/spaces/facets/referrals/ReferralsStorage.sol +36 -0
- package/src/spaces/facets/review/IReview.sol +50 -0
- package/src/spaces/facets/review/ReviewFacet.sol +105 -0
- package/src/spaces/facets/review/ReviewStorage.sol +29 -0
- package/src/spaces/facets/roles/IRoles.sol +197 -0
- package/src/spaces/facets/roles/Roles.sol +123 -0
- package/src/spaces/facets/roles/RolesBase.sol +420 -0
- package/src/spaces/facets/roles/RolesStorage.sol +132 -0
- package/src/spaces/facets/swap/ISwapFacet.sol +91 -0
- package/src/spaces/facets/swap/SwapFacet.sol +290 -0
- package/src/spaces/facets/swap/SwapFacetStorage.sol +24 -0
- package/src/spaces/facets/tipping/ITipping.sol +80 -0
- package/src/spaces/facets/tipping/TippingBase.sol +73 -0
- package/src/spaces/facets/tipping/TippingFacet.sol +123 -0
- package/src/spaces/facets/treasury/ITreasury.sol +64 -0
- package/src/spaces/facets/treasury/Treasury.sol +82 -0
- package/src/spaces/facets/xchain/SpaceEntitlementGated.sol +62 -0
- package/src/tokens/Member.sol +246 -0
- package/src/tokens/lock/ILock.sol +42 -0
- package/src/tokens/lock/LockBase.sol +64 -0
- package/src/tokens/lock/LockFacet.sol +44 -0
- package/src/tokens/lock/LockStorage.sol +26 -0
- package/src/tokens/mainnet/claimer/AuthorizedClaimerStorage.sol +26 -0
- package/src/tokens/mainnet/claimer/AuthorizedClaimers.sol +84 -0
- package/src/tokens/mainnet/claimer/IAuthorizedClaimers.sol +36 -0
- package/src/tokens/mainnet/delegation/ProxyBatchDelegation.sol +86 -0
- package/src/tokens/migration/ITokenMigration.sol +35 -0
- package/src/tokens/migration/TokenMigrationFacet.sol +86 -0
- package/src/tokens/migration/TokenMigrationStorage.sol +27 -0
- package/src/tokens/towns/base/IERC7802.sol +30 -0
- package/src/tokens/towns/base/IOptimismMintableERC20.sol +31 -0
- package/src/tokens/towns/base/ISemver.sol +13 -0
- package/src/tokens/towns/base/Towns.sol +283 -0
- package/src/tokens/towns/base/TownsDeployer.sol +32 -0
- package/src/tokens/towns/base/TownsLib.sol +31 -0
- package/src/tokens/towns/base/versions/TownsV2.sol +15 -0
- package/src/tokens/towns/mainnet/ITowns.sol +56 -0
- package/src/tokens/towns/mainnet/Towns.sol +220 -0
- package/src/tokens/towns/mainnet/libs/TokenInflationLib.sol +89 -0
- package/src/tokens/towns/multichain/Towns.sol +19 -0
- package/src/tokens/towns/multichain/wTowns.sol +18 -0
- package/src/utils/Airdrop.sol +156 -0
- package/src/utils/airdrop/merkle/IMerkleAirdrop.sol +55 -0
- package/src/utils/airdrop/merkle/MerkleAirdrop.sol +118 -0
- package/src/utils/airdrop/merkle/MerkleAirdropStorage.sol +29 -0
- package/src/utils/interfaces/AggregatorV3Interface.sol +37 -0
- package/src/utils/interfaces/IMulticall.sol +10 -0
- package/src/utils/interfaces/IWETH.sol +10 -0
- package/src/utils/libraries/BasisPoints.sol +24 -0
- package/src/utils/libraries/Create2Utils.sol +74 -0
- package/src/utils/libraries/CurrencyTransfer.sol +99 -0
- package/src/utils/libraries/CustomRevert.sol +49 -0
- package/src/utils/libraries/Factory.sol +66 -0
- package/src/utils/libraries/StringSet.sol +190 -0
- package/src/utils/libraries/Validator.sol +31 -0
|
@@ -0,0 +1,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 {}
|