@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,463 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
import {IPlatformRequirements} from "../factory/facets/platform/requirements/IPlatformRequirements.sol";
|
|
6
|
+
import {IArchitect} from "../factory/facets/architect/IArchitect.sol";
|
|
7
|
+
import {ISwapFacet} from "../spaces/facets/swap/ISwapFacet.sol";
|
|
8
|
+
import {ISwapRouter} from "./ISwapRouter.sol";
|
|
9
|
+
import {ISignatureTransfer} from "@uniswap/permit2/src/interfaces/ISignatureTransfer.sol";
|
|
10
|
+
|
|
11
|
+
// libraries
|
|
12
|
+
import {BasisPoints} from "../utils/libraries/BasisPoints.sol";
|
|
13
|
+
import {CurrencyTransfer} from "../utils/libraries/CurrencyTransfer.sol";
|
|
14
|
+
import {CustomRevert} from "../utils/libraries/CustomRevert.sol";
|
|
15
|
+
import {Permit2Hash} from "./Permit2Hash.sol";
|
|
16
|
+
import {SwapRouterStorage} from "./SwapRouterStorage.sol";
|
|
17
|
+
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
|
|
18
|
+
import {PermitHash} from "@uniswap/permit2/src/libraries/PermitHash.sol";
|
|
19
|
+
import {LibBit} from "solady/utils/LibBit.sol";
|
|
20
|
+
import {LibCall} from "solady/utils/LibCall.sol";
|
|
21
|
+
import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol";
|
|
22
|
+
|
|
23
|
+
// contracts
|
|
24
|
+
import {Facet} from "@towns-protocol/diamond/src/facets/Facet.sol";
|
|
25
|
+
import {PausableBase} from "@towns-protocol/diamond/src/facets/pausable/PausableBase.sol";
|
|
26
|
+
import {ReentrancyGuardTransient} from "solady/utils/ReentrancyGuardTransient.sol";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @title SwapRouter
|
|
30
|
+
* @notice Handles swaps through whitelisted routers with fee collection
|
|
31
|
+
* @dev This contract provides two swap execution methods:
|
|
32
|
+
*
|
|
33
|
+
* Standard Swaps (`executeSwap`):
|
|
34
|
+
* - User transfers tokens to contract, then swap executes
|
|
35
|
+
* - Supports both ERC20 tokens and native ETH
|
|
36
|
+
* - Traditional approve/transferFrom flow
|
|
37
|
+
*
|
|
38
|
+
* Permit2 Swaps (`executeSwapWithPermit`):
|
|
39
|
+
* - Enhanced security using Uniswap's Permit2 protocol with witness data
|
|
40
|
+
* - Direct token transfer: User → SwapRouter → DEX (skips intermediate approvals)
|
|
41
|
+
* - ERC20 tokens only (native ETH not supported)
|
|
42
|
+
* - Cryptographically binds permit signatures to exact swap parameters
|
|
43
|
+
* - Prevents front-running attacks through witness data binding
|
|
44
|
+
* - Uses EIP-712 witness containing ExactInputParams, RouterParams, and FeeConfig
|
|
45
|
+
* - Requires pre-approval of tokens to Permit2 contract
|
|
46
|
+
* - Provides nonce-based replay protection and deadline-based time bounds
|
|
47
|
+
*/
|
|
48
|
+
contract SwapRouter is PausableBase, ReentrancyGuardTransient, ISwapRouter, Facet {
|
|
49
|
+
using CustomRevert for bytes4;
|
|
50
|
+
using SafeTransferLib for address;
|
|
51
|
+
|
|
52
|
+
/// @notice Universal Permit2 contract address
|
|
53
|
+
/// @dev This contract implements Uniswap's Permit2 protocol for signature-based token transfers
|
|
54
|
+
address internal constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
|
|
55
|
+
|
|
56
|
+
/// @notice EIP-712 domain separator for Permit2
|
|
57
|
+
bytes32 internal immutable PERMIT2_DOMAIN_SEPARATOR =
|
|
58
|
+
ISignatureTransfer(PERMIT2).DOMAIN_SEPARATOR();
|
|
59
|
+
|
|
60
|
+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
|
|
61
|
+
/* ADMIN FUNCTIONS */
|
|
62
|
+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
|
|
63
|
+
|
|
64
|
+
/// @notice Initializes the SwapRouter with the space factory address
|
|
65
|
+
/// @param spaceFactory The address of the space factory
|
|
66
|
+
function __SwapRouter_init(address spaceFactory) external onlyInitializing {
|
|
67
|
+
SwapRouterStorage.layout().spaceFactory = spaceFactory;
|
|
68
|
+
emit SwapRouterInitialized(spaceFactory);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
|
|
72
|
+
/* SWAP */
|
|
73
|
+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
|
|
74
|
+
|
|
75
|
+
/// @inheritdoc ISwapRouter
|
|
76
|
+
/// @dev Handles refunds of unconsumed input tokens. For ERC20s, calculates actual received amount
|
|
77
|
+
/// to support fee-on-transfer tokens. For ETH, tracks original balance and refunds any unconsumed
|
|
78
|
+
/// ETH after the external router call. Refunds are sent back to msg.sender.
|
|
79
|
+
function executeSwap(
|
|
80
|
+
ExactInputParams calldata params,
|
|
81
|
+
RouterParams calldata routerParams,
|
|
82
|
+
address poster
|
|
83
|
+
) external payable nonReentrant whenNotPaused returns (uint256 amountOut, uint256 protocolFee) {
|
|
84
|
+
// validate parameters before any transfers
|
|
85
|
+
_validateSwapParams(params, routerParams);
|
|
86
|
+
|
|
87
|
+
// for standard swaps, handle token transfer with balance check for fee-on-transfer tokens
|
|
88
|
+
uint256 tokenInBalanceBefore;
|
|
89
|
+
|
|
90
|
+
if (params.tokenIn != CurrencyTransfer.NATIVE_TOKEN) {
|
|
91
|
+
// ensure no ETH is sent when tokenIn is not native
|
|
92
|
+
if (msg.value != 0) SwapRouter__UnexpectedETH.selector.revertWith();
|
|
93
|
+
|
|
94
|
+
// use the actual received amount to handle fee-on-transfer tokens
|
|
95
|
+
tokenInBalanceBefore = params.tokenIn.balanceOf(address(this));
|
|
96
|
+
params.tokenIn.safeTransferFrom(msg.sender, address(this), params.amountIn);
|
|
97
|
+
} else {
|
|
98
|
+
// for native token, the value should be sent with the transaction
|
|
99
|
+
if (msg.value != params.amountIn) SwapRouter__InvalidAmount.selector.revertWith();
|
|
100
|
+
|
|
101
|
+
// store original balance before router call for ETH refunds
|
|
102
|
+
unchecked {
|
|
103
|
+
tokenInBalanceBefore = address(this).balance - msg.value;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return _executeSwap(params, routerParams, poster, tokenInBalanceBefore, msg.sender);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/// @inheritdoc ISwapRouter
|
|
111
|
+
/// @dev Uses Permit2 with witness data to bind permit signatures to exact swap parameters,
|
|
112
|
+
/// preventing front-running attacks. Requires user to pre-approve tokens to Permit2 contract.
|
|
113
|
+
/// Handles refunds of unconsumed ERC20 tokens back to the permit owner (not msg.sender).
|
|
114
|
+
function executeSwapWithPermit(
|
|
115
|
+
ExactInputParams calldata params,
|
|
116
|
+
RouterParams calldata routerParams,
|
|
117
|
+
FeeConfig calldata posterFee,
|
|
118
|
+
Permit2Params calldata permit
|
|
119
|
+
) external payable nonReentrant whenNotPaused returns (uint256 amountOut, uint256 protocolFee) {
|
|
120
|
+
// validate parameters before any transfers
|
|
121
|
+
_validateSwapParams(params, routerParams);
|
|
122
|
+
|
|
123
|
+
// ensure no ETH is sent
|
|
124
|
+
if (msg.value != 0) SwapRouter__UnexpectedETH.selector.revertWith();
|
|
125
|
+
|
|
126
|
+
// Permit2 only works with ERC20 tokens, not native ETH
|
|
127
|
+
if (params.tokenIn == CurrencyTransfer.NATIVE_TOKEN) {
|
|
128
|
+
SwapRouter__NativeTokenNotSupportedWithPermit.selector.revertWith();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// validate that the poster fee in permit matches the actual configured fee
|
|
132
|
+
(, uint16 actualPosterBps) = _getSwapFees(_getSpaceFactory(), msg.sender);
|
|
133
|
+
if (actualPosterBps != posterFee.feeBps) {
|
|
134
|
+
SwapRouter__PosterFeeMismatch.selector.revertWith();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// take balance snapshot before Permit2 transfer to handle fee-on-transfer tokens
|
|
138
|
+
uint256 tokenInBalanceBefore = params.tokenIn.balanceOf(address(this));
|
|
139
|
+
|
|
140
|
+
// execute permit transfer from owner to this contract via Permit2
|
|
141
|
+
ISignatureTransfer(PERMIT2).permitWitnessTransferFrom(
|
|
142
|
+
ISignatureTransfer.PermitTransferFrom(
|
|
143
|
+
ISignatureTransfer.TokenPermissions(params.tokenIn, params.amountIn),
|
|
144
|
+
permit.nonce,
|
|
145
|
+
permit.deadline
|
|
146
|
+
),
|
|
147
|
+
ISignatureTransfer.SignatureTransferDetails({
|
|
148
|
+
to: address(this),
|
|
149
|
+
requestedAmount: params.amountIn
|
|
150
|
+
}),
|
|
151
|
+
permit.owner, // owner who signed the permit
|
|
152
|
+
Permit2Hash.hash(SwapWitness(params, routerParams, posterFee)),
|
|
153
|
+
Permit2Hash.WITNESS_TYPE_STRING,
|
|
154
|
+
permit.signature
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// execute the swap with the balance before transfer
|
|
158
|
+
return
|
|
159
|
+
_executeSwap(
|
|
160
|
+
params,
|
|
161
|
+
routerParams,
|
|
162
|
+
posterFee.recipient,
|
|
163
|
+
tokenInBalanceBefore,
|
|
164
|
+
permit.owner
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
|
|
169
|
+
/* GETTERS */
|
|
170
|
+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
|
|
171
|
+
|
|
172
|
+
/// @inheritdoc ISwapRouter
|
|
173
|
+
function getETHInputFees(
|
|
174
|
+
uint256 amountIn,
|
|
175
|
+
address caller,
|
|
176
|
+
address poster
|
|
177
|
+
) external view returns (uint256 amountInAfterFees, uint256 protocolFee, uint256 posterFee) {
|
|
178
|
+
address spaceFactory = _getSpaceFactory();
|
|
179
|
+
|
|
180
|
+
// get fee rates based on whether the caller is a space
|
|
181
|
+
(uint16 protocolBps, uint16 posterBps) = _getSwapFees(spaceFactory, caller);
|
|
182
|
+
|
|
183
|
+
// calculate fees and amount after fees
|
|
184
|
+
return _calculateSwapFees(amountIn, protocolBps, posterBps, poster);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
|
|
188
|
+
/* PERMIT2 UTILS */
|
|
189
|
+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
|
|
190
|
+
|
|
191
|
+
/// @inheritdoc ISwapRouter
|
|
192
|
+
function getPermit2Nonce(
|
|
193
|
+
address owner,
|
|
194
|
+
uint256 startNonce
|
|
195
|
+
) external view returns (uint256 nonce) {
|
|
196
|
+
unchecked {
|
|
197
|
+
uint256 bitPos = startNonce & 0xff;
|
|
198
|
+
|
|
199
|
+
for (uint256 wordPos = startNonce >> 8; wordPos <= type(uint248).max; ++wordPos) {
|
|
200
|
+
uint256 bitmap = ISignatureTransfer(PERMIT2).nonceBitmap(owner, uint248(wordPos));
|
|
201
|
+
|
|
202
|
+
// create mask to ignore bits below bitPos (set bits below bitPos to 1)
|
|
203
|
+
uint256 mask = (1 << bitPos) - 1;
|
|
204
|
+
uint256 availableBits = ~(bitmap | mask);
|
|
205
|
+
|
|
206
|
+
// if there are available bits in this word, find the first one
|
|
207
|
+
if (availableBits != 0) {
|
|
208
|
+
// find first set bit in availableBits (which represents available nonces)
|
|
209
|
+
uint256 firstZeroBit = LibBit.ffs(availableBits);
|
|
210
|
+
return (wordPos << 8) | firstZeroBit;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
bitPos = 0; // reset for next word
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// no available nonces found
|
|
217
|
+
return type(uint256).max;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/// @inheritdoc ISwapRouter
|
|
222
|
+
function getPermit2MessageHash(
|
|
223
|
+
ExactInputParams calldata params,
|
|
224
|
+
RouterParams calldata routerParams,
|
|
225
|
+
FeeConfig calldata posterFee,
|
|
226
|
+
uint256 amount,
|
|
227
|
+
uint256 nonce,
|
|
228
|
+
uint256 deadline
|
|
229
|
+
) external view returns (bytes32 messageHash) {
|
|
230
|
+
bytes32 witnessHash = Permit2Hash.hash(SwapWitness(params, routerParams, posterFee));
|
|
231
|
+
bytes32 tokenPermissions = keccak256(
|
|
232
|
+
abi.encode(PermitHash._TOKEN_PERMISSIONS_TYPEHASH, params.tokenIn, amount)
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
bytes32 structHash = keccak256(
|
|
236
|
+
abi.encode(
|
|
237
|
+
Permit2Hash.PERMIT_WITNESS_TRANSFER_FROM_TYPEHASH,
|
|
238
|
+
tokenPermissions,
|
|
239
|
+
address(this), // spender
|
|
240
|
+
nonce,
|
|
241
|
+
deadline,
|
|
242
|
+
witnessHash
|
|
243
|
+
)
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
return MessageHashUtils.toTypedDataHash(PERMIT2_DOMAIN_SEPARATOR, structHash);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
|
|
250
|
+
/* INTERNAL */
|
|
251
|
+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
|
|
252
|
+
|
|
253
|
+
/// @notice Validates swap parameters before any transfers occur
|
|
254
|
+
/// @param params The parameters for the swap
|
|
255
|
+
/// @param routerParams The router parameters for the swap
|
|
256
|
+
function _validateSwapParams(
|
|
257
|
+
ExactInputParams calldata params,
|
|
258
|
+
RouterParams calldata routerParams
|
|
259
|
+
) internal view {
|
|
260
|
+
// require explicit recipient
|
|
261
|
+
if (params.recipient == address(0)) SwapRouter__RecipientRequired.selector.revertWith();
|
|
262
|
+
|
|
263
|
+
// prevent swaps where tokenIn and tokenOut are the same
|
|
264
|
+
if (params.tokenIn == params.tokenOut) SwapRouter__SameToken.selector.revertWith();
|
|
265
|
+
|
|
266
|
+
// only allow whitelisted routers
|
|
267
|
+
if (!_isRouterWhitelisted(routerParams.router)) {
|
|
268
|
+
SwapRouter__InvalidRouter.selector.revertWith();
|
|
269
|
+
}
|
|
270
|
+
if (!_isRouterWhitelisted(routerParams.approveTarget)) {
|
|
271
|
+
SwapRouter__InvalidRouter.selector.revertWith();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/// @notice Internal function to execute a swap with tokens already in the contract
|
|
276
|
+
/// @param params The parameters for the swap
|
|
277
|
+
/// @param routerParams The router parameters for the swap
|
|
278
|
+
/// @param poster The address that posted this swap opportunity
|
|
279
|
+
/// @param tokenInBalanceBefore The balance of input token before any transfers (0 for ETH)
|
|
280
|
+
/// @param payer The address that should receive any refund of unconsumed input tokens
|
|
281
|
+
/// @return amountOut The amount of tokenOut received
|
|
282
|
+
/// @return protocolFee The protocol fee amount
|
|
283
|
+
function _executeSwap(
|
|
284
|
+
ExactInputParams calldata params,
|
|
285
|
+
RouterParams calldata routerParams,
|
|
286
|
+
address poster,
|
|
287
|
+
uint256 tokenInBalanceBefore,
|
|
288
|
+
address payer
|
|
289
|
+
) internal returns (uint256 amountOut, uint256 protocolFee) {
|
|
290
|
+
// snapshot the balance of tokenOut before the swap
|
|
291
|
+
uint256 balanceBefore = _getBalance(params.tokenOut);
|
|
292
|
+
|
|
293
|
+
bool isNativeToken = params.tokenIn == CurrencyTransfer.NATIVE_TOKEN;
|
|
294
|
+
{
|
|
295
|
+
uint256 value;
|
|
296
|
+
|
|
297
|
+
if (!isNativeToken) {
|
|
298
|
+
// calculate actualAmountIn for ERC20
|
|
299
|
+
uint256 actualAmountIn = params.tokenIn.balanceOf(address(this)) -
|
|
300
|
+
tokenInBalanceBefore;
|
|
301
|
+
|
|
302
|
+
// tokens are already in the contract, just approve the router
|
|
303
|
+
params.tokenIn.safeApprove(routerParams.approveTarget, actualAmountIn);
|
|
304
|
+
} else {
|
|
305
|
+
// calculate and collect fees before the swap for ETH input
|
|
306
|
+
(value, protocolFee, ) = _collectFees(
|
|
307
|
+
CurrencyTransfer.NATIVE_TOKEN,
|
|
308
|
+
msg.value,
|
|
309
|
+
poster
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// execute swap with the router
|
|
314
|
+
LibCall.callContract(routerParams.router, value, routerParams.swapData);
|
|
315
|
+
|
|
316
|
+
// reset approval for tokenIn
|
|
317
|
+
if (!isNativeToken) params.tokenIn.safeApprove(routerParams.approveTarget, 0);
|
|
318
|
+
|
|
319
|
+
// refund any unconsumed input tokens to the payer
|
|
320
|
+
uint256 refundAmount = _getBalance(params.tokenIn) - tokenInBalanceBefore;
|
|
321
|
+
CurrencyTransfer.transferCurrency(params.tokenIn, address(this), payer, refundAmount);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// use the actual received amount to handle fee-on-transfer tokens
|
|
325
|
+
amountOut = _getBalance(params.tokenOut) - balanceBefore;
|
|
326
|
+
|
|
327
|
+
// calculate and distribute fees only for non-ETH inputs
|
|
328
|
+
// for ETH inputs, fees were already collected before the swap
|
|
329
|
+
if (!isNativeToken) {
|
|
330
|
+
(amountOut, protocolFee, ) = _collectFees(params.tokenOut, amountOut, poster);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// slippage check after fees
|
|
334
|
+
if (amountOut < params.minAmountOut) SwapRouter__InsufficientOutput.selector.revertWith();
|
|
335
|
+
|
|
336
|
+
// transfer remaining tokens to the recipient
|
|
337
|
+
CurrencyTransfer.transferCurrency(
|
|
338
|
+
params.tokenOut,
|
|
339
|
+
address(this),
|
|
340
|
+
params.recipient,
|
|
341
|
+
amountOut
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
emit Swap(
|
|
345
|
+
routerParams.router,
|
|
346
|
+
msg.sender,
|
|
347
|
+
params.tokenIn,
|
|
348
|
+
params.tokenOut,
|
|
349
|
+
params.amountIn,
|
|
350
|
+
amountOut,
|
|
351
|
+
params.recipient
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/// @notice Collects and distributes both protocol and poster fees
|
|
356
|
+
/// @param token The token to collect fees in
|
|
357
|
+
/// @param amount The amount to calculate fees from
|
|
358
|
+
/// @param poster The address that posted this swap opportunity
|
|
359
|
+
/// @return amountAfterFees The amount after deducting protocol and poster fees
|
|
360
|
+
/// @return protocolFee The protocol fee amount collected
|
|
361
|
+
/// @return posterFee The poster fee amount collected
|
|
362
|
+
function _collectFees(
|
|
363
|
+
address token,
|
|
364
|
+
uint256 amount,
|
|
365
|
+
address poster
|
|
366
|
+
) internal returns (uint256 amountAfterFees, uint256 protocolFee, uint256 posterFee) {
|
|
367
|
+
address spaceFactory = _getSpaceFactory();
|
|
368
|
+
(uint16 protocolBps, uint16 posterBps) = _getSwapFees(spaceFactory, msg.sender);
|
|
369
|
+
|
|
370
|
+
// calculate fees
|
|
371
|
+
(amountAfterFees, protocolFee, posterFee) = _calculateSwapFees(
|
|
372
|
+
amount,
|
|
373
|
+
protocolBps,
|
|
374
|
+
posterBps,
|
|
375
|
+
poster
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
// transfer fees
|
|
379
|
+
address feeRecipient = IPlatformRequirements(spaceFactory).getFeeRecipient();
|
|
380
|
+
CurrencyTransfer.transferCurrency(token, address(this), feeRecipient, protocolFee);
|
|
381
|
+
|
|
382
|
+
if (posterFee > 0) {
|
|
383
|
+
CurrencyTransfer.transferCurrency(token, address(this), poster, posterFee);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
emit FeeDistribution(token, feeRecipient, poster, protocolFee, posterFee);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function _getSwapFees(
|
|
390
|
+
address spaceFactory,
|
|
391
|
+
address caller
|
|
392
|
+
) internal view returns (uint16 protocolBps, uint16 posterBps) {
|
|
393
|
+
// check if caller is a space
|
|
394
|
+
bool isSpace = IArchitect(spaceFactory).getTokenIdBySpace(caller) != 0;
|
|
395
|
+
|
|
396
|
+
// get fee configuration based on whether caller is a space
|
|
397
|
+
if (isSpace) {
|
|
398
|
+
try ISwapFacet(caller).getSwapFees() returns (
|
|
399
|
+
uint16 spaceTreasuryBps,
|
|
400
|
+
uint16 spacePosterBps,
|
|
401
|
+
bool
|
|
402
|
+
) {
|
|
403
|
+
return (spaceTreasuryBps, spacePosterBps);
|
|
404
|
+
} catch {}
|
|
405
|
+
// fallback to platform fees if the space doesn't implement getSwapFees
|
|
406
|
+
}
|
|
407
|
+
IPlatformRequirements platform = IPlatformRequirements(spaceFactory);
|
|
408
|
+
return platform.getSwapFees();
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function _getSpaceFactory() internal view returns (address) {
|
|
412
|
+
return SwapRouterStorage.layout().spaceFactory;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function _getPlatformRequirements() internal view returns (IPlatformRequirements) {
|
|
416
|
+
return IPlatformRequirements(_getSpaceFactory());
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/// @notice Checks if a router is whitelisted
|
|
420
|
+
/// @param router The address to check
|
|
421
|
+
/// @return bool True if the router is whitelisted
|
|
422
|
+
function _isRouterWhitelisted(address router) internal view returns (bool) {
|
|
423
|
+
return _getPlatformRequirements().isRouterWhitelisted(router);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/// @notice Gets the balance of a token for this contract
|
|
427
|
+
/// @param token The token to check
|
|
428
|
+
/// @return uint256 The balance
|
|
429
|
+
function _getBalance(address token) internal view returns (uint256) {
|
|
430
|
+
if (token != CurrencyTransfer.NATIVE_TOKEN) return token.balanceOf(address(this));
|
|
431
|
+
return address(this).balance;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/// @notice Calculates swap fees and the amount after fees
|
|
435
|
+
/// @param amount The original amount to calculate fees from
|
|
436
|
+
/// @param protocolBps Protocol fee in basis points
|
|
437
|
+
/// @param posterBps Poster fee in basis points
|
|
438
|
+
/// @param poster The address that posted this swap opportunity
|
|
439
|
+
/// @return amountAfterFees The amount after deducting protocol and poster fees
|
|
440
|
+
/// @return protocolFee The protocol fee amount computed
|
|
441
|
+
/// @return posterFee The poster fee amount computed
|
|
442
|
+
function _calculateSwapFees(
|
|
443
|
+
uint256 amount,
|
|
444
|
+
uint16 protocolBps,
|
|
445
|
+
uint16 posterBps,
|
|
446
|
+
address poster
|
|
447
|
+
) internal pure returns (uint256 amountAfterFees, uint256 protocolFee, uint256 posterFee) {
|
|
448
|
+
if (protocolBps + posterBps > BasisPoints.MAX_BPS) {
|
|
449
|
+
SwapRouter__InvalidBps.selector.revertWith();
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// calculate protocol fee
|
|
453
|
+
protocolFee = BasisPoints.calculate(amount, protocolBps);
|
|
454
|
+
|
|
455
|
+
// only calculate poster fee if the address is not zero
|
|
456
|
+
if (poster != address(0)) posterFee = BasisPoints.calculate(amount, posterBps);
|
|
457
|
+
|
|
458
|
+
// calculate amount after fees
|
|
459
|
+
unchecked {
|
|
460
|
+
amountAfterFees = amount - protocolFee - posterFee;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
/// @title SwapRouterStorage
|
|
5
|
+
/// @notice Storage layout for the SwapRouter contract
|
|
6
|
+
library SwapRouterStorage {
|
|
7
|
+
// keccak256(abi.encode(uint256(keccak256("router.swap.storage")) - 1)) &
|
|
8
|
+
// ~bytes32(uint256(0xff))
|
|
9
|
+
bytes32 internal constant STORAGE_SLOT =
|
|
10
|
+
0xbaabbaf01fc4f6195bfdcefdfc41afc4577058a099d6e5a21edcf605dd045400;
|
|
11
|
+
|
|
12
|
+
struct Layout {
|
|
13
|
+
address spaceFactory;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function layout() internal pure returns (Layout storage l) {
|
|
17
|
+
assembly {
|
|
18
|
+
l.slot := STORAGE_SLOT
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
|
|
6
|
+
// libraries
|
|
7
|
+
|
|
8
|
+
// contracts
|
|
9
|
+
interface ICrossChainEntitlement {
|
|
10
|
+
struct Parameter {
|
|
11
|
+
string name;
|
|
12
|
+
string primitive;
|
|
13
|
+
string description;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function isEntitled(
|
|
17
|
+
address[] calldata users,
|
|
18
|
+
bytes calldata parameters
|
|
19
|
+
) external view returns (bool);
|
|
20
|
+
|
|
21
|
+
function parameters() external view returns (Parameter[] memory);
|
|
22
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
//SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
interface IEntitlementBase {
|
|
5
|
+
// Caller is not allowed to perform this action
|
|
6
|
+
error Entitlement__NotAllowed();
|
|
7
|
+
|
|
8
|
+
// Caller has passed an invalid value
|
|
9
|
+
error Entitlement__InvalidValue();
|
|
10
|
+
|
|
11
|
+
// Caller has passed a value that already exists
|
|
12
|
+
error Entitlement__ValueAlreadyExists();
|
|
13
|
+
|
|
14
|
+
// Caller is not a member
|
|
15
|
+
error Entitlement__NotMember();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface IEntitlement is IEntitlementBase {
|
|
19
|
+
/// @notice initializes the entitlement module
|
|
20
|
+
function initialize(address space) external;
|
|
21
|
+
|
|
22
|
+
/// @notice The name of the entitlement module
|
|
23
|
+
function name() external view returns (string memory);
|
|
24
|
+
|
|
25
|
+
/// @notice The type of the entitlement module
|
|
26
|
+
function moduleType() external view returns (string memory);
|
|
27
|
+
|
|
28
|
+
/// @notice The description of the entitlement module
|
|
29
|
+
function description() external view returns (string memory);
|
|
30
|
+
|
|
31
|
+
/// @notice sets a new entitlement
|
|
32
|
+
/// @param roleId id of the role to gate
|
|
33
|
+
/// @param entitlementData abi encoded array of data necessary to set the entitlement
|
|
34
|
+
function setEntitlement(uint256 roleId, bytes calldata entitlementData) external;
|
|
35
|
+
|
|
36
|
+
/// @notice removes an entitlement
|
|
37
|
+
/// @param roleId id of the role to remove
|
|
38
|
+
function removeEntitlement(uint256 roleId) external;
|
|
39
|
+
|
|
40
|
+
/// @notice fetches the entitlement data for a roleId
|
|
41
|
+
/// @param roleId the roleId to fetch the entitlement data for
|
|
42
|
+
/// @return entitlementData array for the role
|
|
43
|
+
function getEntitlementDataByRoleId(uint256 roleId) external view returns (bytes memory);
|
|
44
|
+
|
|
45
|
+
/// @notice some entitlements require cross chain evaluation and may not be executed directly
|
|
46
|
+
/// from
|
|
47
|
+
/// other contracts
|
|
48
|
+
/// @return whether this entitlement will require crosschain evaluation
|
|
49
|
+
function isCrosschain() external view returns (bool);
|
|
50
|
+
|
|
51
|
+
/// @notice checks whether a user is has a given permission for a channel or a space
|
|
52
|
+
/// @param channelId id of the channel to check, if empty, checks space
|
|
53
|
+
/// @param user address of the user to check
|
|
54
|
+
/// @param permission the permission to check
|
|
55
|
+
/// @return whether the user is entitled to the permission
|
|
56
|
+
function isEntitled(
|
|
57
|
+
bytes32 channelId,
|
|
58
|
+
address[] memory user,
|
|
59
|
+
bytes32 permission
|
|
60
|
+
) external view returns (bool);
|
|
61
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
|
|
5
|
+
import {ICrossChainEntitlement} from "src/spaces/entitlements/ICrossChainEntitlement.sol";
|
|
6
|
+
|
|
7
|
+
interface IGnosisSafeProxyFactory {
|
|
8
|
+
function computeProxyAddress(address user) external view returns (address);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
contract PolymarketEntitlement is ICrossChainEntitlement {
|
|
12
|
+
IGnosisSafeProxyFactory public proxyFactory;
|
|
13
|
+
IERC1155 public tokenContract;
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
// Set the proxyFactory and token contract addresses
|
|
17
|
+
proxyFactory = IGnosisSafeProxyFactory(address(0xaacFeEa03eb1561C4e67d661e40682Bd20E3541b));
|
|
18
|
+
tokenContract = IERC1155(address(0x4D97DCd97eC945f40cF65F87097ACe5EA0476045));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isEntitled(
|
|
22
|
+
address[] calldata users,
|
|
23
|
+
bytes calldata paramData
|
|
24
|
+
) external view override returns (bool) {
|
|
25
|
+
(uint256 tokenId, uint256 requiredBalance, bool aggregate) = abi.decode(
|
|
26
|
+
paramData,
|
|
27
|
+
(uint256, uint256, bool)
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
uint256 totalBalance = 0;
|
|
31
|
+
|
|
32
|
+
for (uint256 i = 0; i < users.length; i++) {
|
|
33
|
+
address userAddress = users[i];
|
|
34
|
+
address proxyAddress = proxyFactory.computeProxyAddress(userAddress);
|
|
35
|
+
|
|
36
|
+
// Check balance for both the user and the proxy
|
|
37
|
+
uint256 userBalance = tokenContract.balanceOf(userAddress, tokenId);
|
|
38
|
+
uint256 proxyBalance = tokenContract.balanceOf(proxyAddress, tokenId);
|
|
39
|
+
|
|
40
|
+
if (aggregate) {
|
|
41
|
+
// Add both user and proxy balance to the total
|
|
42
|
+
totalBalance += userBalance + proxyBalance;
|
|
43
|
+
} else {
|
|
44
|
+
// If not aggregating, return true if any address meets the threshold
|
|
45
|
+
if (userBalance >= requiredBalance || proxyBalance >= requiredBalance) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// If aggregating, check if the total balance meets the threshold
|
|
52
|
+
if (aggregate) {
|
|
53
|
+
return totalBalance >= requiredBalance;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// If not aggregating, and no address met the threshold, return false
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function parameters() external pure override returns (Parameter[] memory) {
|
|
61
|
+
Parameter[] memory params = new Parameter[](3);
|
|
62
|
+
params[0] = Parameter({
|
|
63
|
+
name: "tokenId",
|
|
64
|
+
primitive: "uint256",
|
|
65
|
+
description: "The token ID of the ERC-1155 token."
|
|
66
|
+
});
|
|
67
|
+
params[1] = Parameter({
|
|
68
|
+
name: "requiredBalance",
|
|
69
|
+
primitive: "uint256",
|
|
70
|
+
description: "The minimum balance required for entitlement."
|
|
71
|
+
});
|
|
72
|
+
params[2] = Parameter({
|
|
73
|
+
name: "aggregate",
|
|
74
|
+
primitive: "bool",
|
|
75
|
+
description: "Whether to aggregate balances across all wallets."
|
|
76
|
+
});
|
|
77
|
+
return params;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
|
|
6
|
+
// libraries
|
|
7
|
+
|
|
8
|
+
// contracts
|
|
9
|
+
|
|
10
|
+
interface IPOAP {
|
|
11
|
+
/// @notice Get the POAP token balance of an owner
|
|
12
|
+
/// @param owner The address to query the balance of
|
|
13
|
+
/// @return The number of POAP tokens owned by the given address
|
|
14
|
+
function balanceOf(address owner) external view returns (uint256);
|
|
15
|
+
|
|
16
|
+
/// @dev Gets the Token Id and Event Id for a given index of the tokens list of the requested
|
|
17
|
+
/// owner
|
|
18
|
+
/// @param owner ( address ) Owner address of the token list to be queried
|
|
19
|
+
/// @param index ( uint256 ) Index to be accessed of the requested tokens list
|
|
20
|
+
/// @return tokenId The unique identifier of the POAP token
|
|
21
|
+
/// @return eventId The ID of the event associated with the POAP token
|
|
22
|
+
function tokenDetailsOfOwnerByIndex(
|
|
23
|
+
address owner,
|
|
24
|
+
uint256 index
|
|
25
|
+
) external view returns (uint256 tokenId, uint256 eventId);
|
|
26
|
+
}
|