@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,290 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
import {ITownsPointsBase} from "../../../airdrop/points/ITownsPoints.sol";
|
|
6
|
+
import {IPlatformRequirements} from "../../../factory/facets/platform/requirements/IPlatformRequirements.sol";
|
|
7
|
+
import {ISwapRouter} from "../../../router/ISwapRouter.sol";
|
|
8
|
+
import {ISwapFacet} from "./ISwapFacet.sol";
|
|
9
|
+
|
|
10
|
+
// libraries
|
|
11
|
+
import {BasisPoints} from "../../../utils/libraries/BasisPoints.sol";
|
|
12
|
+
import {CurrencyTransfer} from "../../../utils/libraries/CurrencyTransfer.sol";
|
|
13
|
+
import {CustomRevert} from "../../../utils/libraries/CustomRevert.sol";
|
|
14
|
+
import {DependencyLib} from "../DependencyLib.sol";
|
|
15
|
+
import {MembershipStorage} from "../membership/MembershipStorage.sol";
|
|
16
|
+
import {SwapFacetStorage} from "./SwapFacetStorage.sol";
|
|
17
|
+
import {FixedPointMathLib} from "solady/utils/FixedPointMathLib.sol";
|
|
18
|
+
import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol";
|
|
19
|
+
|
|
20
|
+
// contracts
|
|
21
|
+
import {Entitled} from "../Entitled.sol";
|
|
22
|
+
import {PointsBase} from "../points/PointsBase.sol";
|
|
23
|
+
import {Facet} from "@towns-protocol/diamond/src/facets/Facet.sol";
|
|
24
|
+
import {ReentrancyGuardTransient} from "solady/utils/ReentrancyGuardTransient.sol";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @title SwapFacet
|
|
28
|
+
* @notice Diamond facet for executing swaps within a space with configurable fees and poster handling
|
|
29
|
+
* @dev This facet extends SwapRouter functionality with space-specific features:
|
|
30
|
+
*
|
|
31
|
+
* Standard Swaps (`executeSwap`):
|
|
32
|
+
* - Space membership validation required for all callers
|
|
33
|
+
* - Configurable poster fees (to space treasury or forwarded to poster)
|
|
34
|
+
* - Smart ETH refund logic accounts for poster fees when poster is space
|
|
35
|
+
* - Points minting for ETH-involved swaps
|
|
36
|
+
*
|
|
37
|
+
* Permit2 Swaps (`executeSwapWithPermit`):
|
|
38
|
+
* - All standard swap features plus Permit2 security enhancements
|
|
39
|
+
* - Cryptographic binding prevents fee manipulation attacks
|
|
40
|
+
*
|
|
41
|
+
* Space-Specific Features:
|
|
42
|
+
* - Owner-configurable poster fee rates and forwarding behavior via `setSwapFeeConfig`
|
|
43
|
+
* - Automatic fee collection to space treasury when poster equals space address
|
|
44
|
+
* - Smart refund logic preserves space fees during partial ETH swaps
|
|
45
|
+
* - Integration with space entitlement and membership validation systems
|
|
46
|
+
* - Diamond pattern integration for upgradeable space functionality
|
|
47
|
+
*/
|
|
48
|
+
contract SwapFacet is ISwapFacet, ReentrancyGuardTransient, Entitled, PointsBase, Facet {
|
|
49
|
+
using CustomRevert for bytes4;
|
|
50
|
+
using SafeTransferLib for address;
|
|
51
|
+
|
|
52
|
+
/// @notice Maximum fee in basis points (2%)
|
|
53
|
+
uint16 internal constant MAX_FEE_BPS = 200;
|
|
54
|
+
|
|
55
|
+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
|
|
56
|
+
/* ADMIN FUNCTIONS */
|
|
57
|
+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
|
|
58
|
+
|
|
59
|
+
/// @inheritdoc ISwapFacet
|
|
60
|
+
function setSwapFeeConfig(uint16 posterFeeBps, bool forwardPosterFee) external onlyOwner {
|
|
61
|
+
// get protocol fee for validation
|
|
62
|
+
IPlatformRequirements platform = _getPlatformRequirements();
|
|
63
|
+
(uint16 protocolBps, ) = platform.getSwapFees();
|
|
64
|
+
|
|
65
|
+
// ensure total fee is reasonable
|
|
66
|
+
if (protocolBps + posterFeeBps > MAX_FEE_BPS) {
|
|
67
|
+
SwapFacet__TotalFeeTooHigh.selector.revertWith();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
SwapFacetStorage.Layout storage ds = SwapFacetStorage.layout();
|
|
71
|
+
(ds.posterFeeBps, ds.forwardPosterFee) = (posterFeeBps, forwardPosterFee);
|
|
72
|
+
|
|
73
|
+
emit SwapFeeConfigUpdated(posterFeeBps, forwardPosterFee);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
|
|
77
|
+
/* SWAP */
|
|
78
|
+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
|
|
79
|
+
|
|
80
|
+
/// @inheritdoc ISwapFacet
|
|
81
|
+
function executeSwap(
|
|
82
|
+
ExactInputParams calldata params,
|
|
83
|
+
RouterParams calldata routerParams,
|
|
84
|
+
address poster
|
|
85
|
+
) external payable nonReentrant returns (uint256 amountOut) {
|
|
86
|
+
address swapRouter = _validateSwapPrerequisites(poster);
|
|
87
|
+
|
|
88
|
+
// create mutable copy in memory to modify amountIn for fee-on-transfer tokens
|
|
89
|
+
ExactInputParams memory paramsMemory = params;
|
|
90
|
+
|
|
91
|
+
// handle ERC20 transfers before calling SwapRouter
|
|
92
|
+
bool isNativeToken = params.tokenIn == CurrencyTransfer.NATIVE_TOKEN;
|
|
93
|
+
|
|
94
|
+
// take snapshot of balance BEFORE receiving user tokens for refund calculation
|
|
95
|
+
uint256 tokenInBalanceBefore;
|
|
96
|
+
if (!isNativeToken) {
|
|
97
|
+
// use the actual received amount to handle fee-on-transfer tokens
|
|
98
|
+
tokenInBalanceBefore = params.tokenIn.balanceOf(address(this));
|
|
99
|
+
params.tokenIn.safeTransferFrom(msg.sender, address(this), params.amountIn);
|
|
100
|
+
// update amountIn based on the actual balance after transfer
|
|
101
|
+
paramsMemory.amountIn = params.tokenIn.balanceOf(address(this)) - tokenInBalanceBefore;
|
|
102
|
+
|
|
103
|
+
// approve SwapRouter to spend the tokens
|
|
104
|
+
params.tokenIn.safeApprove(swapRouter, paramsMemory.amountIn);
|
|
105
|
+
} else {
|
|
106
|
+
// for ETH, msg.value is already included in balance, so subtract it
|
|
107
|
+
tokenInBalanceBefore = address(this).balance - msg.value;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// execute swap through the router
|
|
111
|
+
// forwarding `msg.value` may introduce double-spending if used with `multicall`
|
|
112
|
+
// which has been handled by Solady Multicallable
|
|
113
|
+
uint256 protocolFee;
|
|
114
|
+
(amountOut, protocolFee) = ISwapRouter(swapRouter).executeSwap{value: msg.value}(
|
|
115
|
+
paramsMemory,
|
|
116
|
+
routerParams,
|
|
117
|
+
poster
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
// handle refunds of unconsumed input tokens
|
|
121
|
+
_handleRefunds(params.tokenIn, tokenInBalanceBefore, poster);
|
|
122
|
+
|
|
123
|
+
// reset approval for ERC20 tokens
|
|
124
|
+
if (!isNativeToken) params.tokenIn.safeApprove(swapRouter, 0);
|
|
125
|
+
|
|
126
|
+
_mintPointsAndEmitSwapEvent(params, amountOut, protocolFee, poster, msg.sender);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/// @inheritdoc ISwapFacet
|
|
130
|
+
/// @dev Permit is forwarded directly to SwapRouter which handles all token operations,
|
|
131
|
+
/// e.g. Permit2 transfers, approvals, refunds
|
|
132
|
+
function executeSwapWithPermit(
|
|
133
|
+
ExactInputParams calldata params,
|
|
134
|
+
RouterParams calldata routerParams,
|
|
135
|
+
FeeConfig calldata posterFee,
|
|
136
|
+
Permit2Params calldata permit
|
|
137
|
+
) external payable nonReentrant returns (uint256 amountOut) {
|
|
138
|
+
// Permit2 swaps do not support ETH
|
|
139
|
+
if (msg.value != 0) SwapFacet__UnexpectedETH.selector.revertWith();
|
|
140
|
+
|
|
141
|
+
address swapRouter = _validateSwapPrerequisites(posterFee.recipient);
|
|
142
|
+
|
|
143
|
+
// execute swap through the router with permit
|
|
144
|
+
uint256 protocolFee;
|
|
145
|
+
(amountOut, protocolFee) = ISwapRouter(swapRouter).executeSwapWithPermit(
|
|
146
|
+
params,
|
|
147
|
+
routerParams,
|
|
148
|
+
posterFee,
|
|
149
|
+
permit
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
_mintPointsAndEmitSwapEvent(
|
|
153
|
+
params,
|
|
154
|
+
amountOut,
|
|
155
|
+
protocolFee,
|
|
156
|
+
posterFee.recipient,
|
|
157
|
+
permit.owner
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
|
|
162
|
+
/* GETTERS */
|
|
163
|
+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
|
|
164
|
+
|
|
165
|
+
/// @inheritdoc ISwapFacet
|
|
166
|
+
function getSwapRouter() public view returns (address) {
|
|
167
|
+
return DependencyLib.getDependency(MembershipStorage.layout(), DependencyLib.SWAP_ROUTER);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/// @inheritdoc ISwapFacet
|
|
171
|
+
function getSwapFees()
|
|
172
|
+
public
|
|
173
|
+
view
|
|
174
|
+
returns (uint16 protocolBps, uint16 posterBps, bool forwardPosterFee)
|
|
175
|
+
{
|
|
176
|
+
SwapFacetStorage.Layout storage ds = SwapFacetStorage.layout();
|
|
177
|
+
|
|
178
|
+
// get protocolBps and posterBps from protocol config
|
|
179
|
+
IPlatformRequirements platform = _getPlatformRequirements();
|
|
180
|
+
(protocolBps, posterBps) = platform.getSwapFees();
|
|
181
|
+
|
|
182
|
+
uint16 spacePosterBps;
|
|
183
|
+
(spacePosterBps, forwardPosterFee) = (ds.posterFeeBps, ds.forwardPosterFee);
|
|
184
|
+
|
|
185
|
+
// if poster fee is forwarded or spacePosterBps is set, use spacePosterBps
|
|
186
|
+
if (forwardPosterFee || spacePosterBps != 0) posterBps = spacePosterBps;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
|
|
190
|
+
/* INTERNAL */
|
|
191
|
+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
|
|
192
|
+
|
|
193
|
+
/// @notice Mint points for ETH swaps and emit swap events
|
|
194
|
+
/// @param params The swap parameters for event emission
|
|
195
|
+
/// @param amountOut The amount of output tokens received
|
|
196
|
+
/// @param protocolFee The protocol fee collected for points calculation
|
|
197
|
+
/// @param poster The swap poster address
|
|
198
|
+
/// @param payer The address that should receive the points
|
|
199
|
+
function _mintPointsAndEmitSwapEvent(
|
|
200
|
+
ExactInputParams calldata params,
|
|
201
|
+
uint256 amountOut,
|
|
202
|
+
uint256 protocolFee,
|
|
203
|
+
address poster,
|
|
204
|
+
address payer
|
|
205
|
+
) internal {
|
|
206
|
+
// mint points based on the protocol fee if ETH is involved
|
|
207
|
+
if (
|
|
208
|
+
params.tokenIn == CurrencyTransfer.NATIVE_TOKEN ||
|
|
209
|
+
params.tokenOut == CurrencyTransfer.NATIVE_TOKEN
|
|
210
|
+
) {
|
|
211
|
+
address airdropDiamond = _getAirdropDiamond();
|
|
212
|
+
uint256 points = _getPoints(
|
|
213
|
+
airdropDiamond,
|
|
214
|
+
ITownsPointsBase.Action.Swap,
|
|
215
|
+
abi.encode(protocolFee)
|
|
216
|
+
);
|
|
217
|
+
_mintPoints(airdropDiamond, payer, points);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
emit SwapExecuted(
|
|
221
|
+
params.recipient,
|
|
222
|
+
params.tokenIn,
|
|
223
|
+
params.tokenOut,
|
|
224
|
+
params.amountIn,
|
|
225
|
+
amountOut,
|
|
226
|
+
poster
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/// @notice Handles refunds of unconsumed input tokens back to the caller
|
|
231
|
+
/// @param tokenIn The input token address
|
|
232
|
+
/// @param tokenInBalanceBefore The balance before receiving tokens from user
|
|
233
|
+
/// @param poster The poster address for this swap
|
|
234
|
+
function _handleRefunds(
|
|
235
|
+
address tokenIn,
|
|
236
|
+
uint256 tokenInBalanceBefore,
|
|
237
|
+
address poster
|
|
238
|
+
) internal {
|
|
239
|
+
uint256 currentBalance = _getBalance(tokenIn);
|
|
240
|
+
|
|
241
|
+
// calculate base refund amount
|
|
242
|
+
uint256 refundAmount = FixedPointMathLib.zeroFloorSub(currentBalance, tokenInBalanceBefore);
|
|
243
|
+
|
|
244
|
+
// for ETH, subtract poster fee if it was collected to space
|
|
245
|
+
// this happens when poster is the space itself (regardless of forwardPosterFee setting)
|
|
246
|
+
if (tokenIn == CurrencyTransfer.NATIVE_TOKEN && poster == address(this)) {
|
|
247
|
+
// get the poster fee that was collected to space
|
|
248
|
+
(, uint16 posterBps, ) = getSwapFees();
|
|
249
|
+
uint256 posterFee = BasisPoints.calculate(msg.value, posterBps);
|
|
250
|
+
|
|
251
|
+
// subtract poster fee from refund since it should stay in space
|
|
252
|
+
refundAmount = FixedPointMathLib.zeroFloorSub(refundAmount, posterFee);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
CurrencyTransfer.transferCurrency(tokenIn, address(this), msg.sender, refundAmount);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/// @notice Validates swap prerequisites (membership, SwapRouter availability, and poster address)
|
|
259
|
+
/// @param poster The poster address to validate
|
|
260
|
+
/// @return swapRouter The address of the SwapRouter to use
|
|
261
|
+
function _validateSwapPrerequisites(address poster) internal view returns (address swapRouter) {
|
|
262
|
+
_validateMembership(msg.sender);
|
|
263
|
+
|
|
264
|
+
swapRouter = getSwapRouter();
|
|
265
|
+
if (swapRouter == address(0)) SwapFacet__SwapRouterNotSet.selector.revertWith();
|
|
266
|
+
|
|
267
|
+
// validate poster address based on fee configuration
|
|
268
|
+
if (!(_isForwardPosterFee() || poster == address(this))) {
|
|
269
|
+
SwapFacet__InvalidPosterInput.selector.revertWith();
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function _getPlatformRequirements() internal view returns (IPlatformRequirements) {
|
|
274
|
+
return IPlatformRequirements(MembershipStorage.layout().spaceFactory);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/// @notice Gets the balance of a token for this contract
|
|
278
|
+
/// @param token The token to check
|
|
279
|
+
/// @return uint256 The balance
|
|
280
|
+
function _getBalance(address token) internal view returns (uint256) {
|
|
281
|
+
if (token == CurrencyTransfer.NATIVE_TOKEN) return address(this).balance;
|
|
282
|
+
return token.balanceOf(address(this));
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/// @notice Checks if poster fees should be forwarded to the poster
|
|
286
|
+
/// @return bool True if poster fees are forwarded, false if they go to the space
|
|
287
|
+
function _isForwardPosterFee() internal view returns (bool) {
|
|
288
|
+
return SwapFacetStorage.layout().forwardPosterFee;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
/// @title SwapFacetStorage
|
|
5
|
+
/// @notice Storage layout for the SwapFacet contract
|
|
6
|
+
library SwapFacetStorage {
|
|
7
|
+
// keccak256(abi.encode(uint256(keccak256("spaces.facets.swap.storage")) - 1)) &
|
|
8
|
+
// ~bytes32(uint256(0xff))
|
|
9
|
+
bytes32 internal constant STORAGE_SLOT =
|
|
10
|
+
0xf363e6f383c163fac4382e7bd60c54a795a129059b7601463644e52990dfaf00;
|
|
11
|
+
|
|
12
|
+
struct Layout {
|
|
13
|
+
/// @notice Poster fee in basis points (space-specific)
|
|
14
|
+
uint16 posterFeeBps;
|
|
15
|
+
/// @notice Whether to forward the poster fee to the poster (default: false, fees go to space)
|
|
16
|
+
bool forwardPosterFee;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function layout() internal pure returns (Layout storage l) {
|
|
20
|
+
assembly {
|
|
21
|
+
l.slot := STORAGE_SLOT
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
|
|
6
|
+
// libraries
|
|
7
|
+
|
|
8
|
+
// contracts
|
|
9
|
+
|
|
10
|
+
interface ITippingBase {
|
|
11
|
+
// =============================================================
|
|
12
|
+
// Structs
|
|
13
|
+
// =============================================================
|
|
14
|
+
|
|
15
|
+
struct TipRequest {
|
|
16
|
+
address receiver;
|
|
17
|
+
uint256 tokenId;
|
|
18
|
+
address currency;
|
|
19
|
+
uint256 amount;
|
|
20
|
+
bytes32 messageId;
|
|
21
|
+
bytes32 channelId;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// =============================================================
|
|
25
|
+
// Events
|
|
26
|
+
// =============================================================
|
|
27
|
+
|
|
28
|
+
event Tip(
|
|
29
|
+
uint256 indexed tokenId,
|
|
30
|
+
address indexed currency,
|
|
31
|
+
address sender,
|
|
32
|
+
address receiver,
|
|
33
|
+
uint256 amount,
|
|
34
|
+
bytes32 messageId,
|
|
35
|
+
bytes32 channelId
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// =============================================================
|
|
39
|
+
// Errors
|
|
40
|
+
// =============================================================
|
|
41
|
+
|
|
42
|
+
error TokenDoesNotExist();
|
|
43
|
+
error ReceiverIsNotMember();
|
|
44
|
+
error CannotTipSelf();
|
|
45
|
+
error AmountIsZero();
|
|
46
|
+
error CurrencyIsZero();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface ITipping is ITippingBase {
|
|
50
|
+
/// @notice Sends a tip to a space member
|
|
51
|
+
/// @param tipRequest The tip request containing token ID, currency, amount, message ID and
|
|
52
|
+
/// channel ID
|
|
53
|
+
/// @dev Requires sender and receiver to be members of the space
|
|
54
|
+
/// @dev Requires amount > 0 and valid currency address
|
|
55
|
+
/// @dev Emits Tip event
|
|
56
|
+
function tip(TipRequest calldata tipRequest) external payable;
|
|
57
|
+
|
|
58
|
+
/// @notice Gets the total tips received for a token ID in a specific currency
|
|
59
|
+
/// @param tokenId The token ID to get tips for
|
|
60
|
+
/// @param currency The currency address to get tips in
|
|
61
|
+
/// @return The total amount of tips received in the specified currency
|
|
62
|
+
function tipsByCurrencyAndTokenId(
|
|
63
|
+
uint256 tokenId,
|
|
64
|
+
address currency
|
|
65
|
+
) external view returns (uint256);
|
|
66
|
+
|
|
67
|
+
/// @notice Gets the list of currencies that have been tipped to the space
|
|
68
|
+
/// @return An array of currency addresses
|
|
69
|
+
function tippingCurrencies() external view returns (address[] memory);
|
|
70
|
+
|
|
71
|
+
/// @notice Gets the total number of tips received in a specific currency
|
|
72
|
+
/// @param currency The currency address to get tips for
|
|
73
|
+
/// @return The total number of tips received in the specified currency
|
|
74
|
+
function totalTipsByCurrency(address currency) external view returns (uint256);
|
|
75
|
+
|
|
76
|
+
/// @notice Gets the total amount of tips received in a specific currency
|
|
77
|
+
/// @param currency The currency address to get tips for
|
|
78
|
+
/// @return The total amount of tips received in the specified currency
|
|
79
|
+
function tipAmountByCurrency(address currency) external view returns (uint256);
|
|
80
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
|
|
6
|
+
// libraries
|
|
7
|
+
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
|
|
8
|
+
import {CurrencyTransfer} from "src/utils/libraries/CurrencyTransfer.sol";
|
|
9
|
+
// contracts
|
|
10
|
+
|
|
11
|
+
library TippingBase {
|
|
12
|
+
using EnumerableSet for EnumerableSet.AddressSet;
|
|
13
|
+
|
|
14
|
+
// keccak256(abi.encode(uint256(keccak256("spaces.facets.tipping.storage")) - 1)) &
|
|
15
|
+
// ~bytes32(uint256(0xff))
|
|
16
|
+
bytes32 internal constant STORAGE_SLOT =
|
|
17
|
+
0xb6cb334a9eea0cca2581db4520b45ac6f03de8e3927292302206bb82168be300;
|
|
18
|
+
|
|
19
|
+
struct TippingStats {
|
|
20
|
+
uint256 totalTips;
|
|
21
|
+
uint256 tipAmount;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
struct Layout {
|
|
25
|
+
EnumerableSet.AddressSet currencies;
|
|
26
|
+
mapping(uint256 tokenId => mapping(address currency => uint256 amount)) tipsByCurrencyByTokenId;
|
|
27
|
+
mapping(address currency => TippingStats) tippingStatsByCurrency;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function layout() internal pure returns (Layout storage l) {
|
|
31
|
+
assembly {
|
|
32
|
+
l.slot := STORAGE_SLOT
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function tip(
|
|
37
|
+
address sender,
|
|
38
|
+
address receiver,
|
|
39
|
+
uint256 tokenId,
|
|
40
|
+
address currency,
|
|
41
|
+
uint256 amount
|
|
42
|
+
) internal {
|
|
43
|
+
Layout storage ds = layout();
|
|
44
|
+
|
|
45
|
+
ds.currencies.add(currency);
|
|
46
|
+
ds.tipsByCurrencyByTokenId[tokenId][currency] += amount;
|
|
47
|
+
|
|
48
|
+
TippingStats storage stats = ds.tippingStatsByCurrency[currency];
|
|
49
|
+
stats.tipAmount += amount;
|
|
50
|
+
stats.totalTips += 1;
|
|
51
|
+
|
|
52
|
+
CurrencyTransfer.transferCurrency(currency, sender, receiver, amount);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function totalTipsByCurrency(address currency) internal view returns (uint256) {
|
|
56
|
+
return layout().tippingStatsByCurrency[currency].totalTips;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function tipAmountByCurrency(address currency) internal view returns (uint256) {
|
|
60
|
+
return layout().tippingStatsByCurrency[currency].tipAmount;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function tipsByCurrencyByTokenId(
|
|
64
|
+
uint256 tokenId,
|
|
65
|
+
address currency
|
|
66
|
+
) internal view returns (uint256) {
|
|
67
|
+
return layout().tipsByCurrencyByTokenId[tokenId][currency];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function tippingCurrencies() internal view returns (address[] memory) {
|
|
71
|
+
return layout().currencies.values();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
import {ITipping} from "./ITipping.sol";
|
|
6
|
+
import {ITownsPointsBase} from "src/airdrop/points/ITownsPoints.sol";
|
|
7
|
+
import {IPlatformRequirements} from "src/factory/facets/platform/requirements/IPlatformRequirements.sol";
|
|
8
|
+
|
|
9
|
+
// libraries
|
|
10
|
+
import {TippingBase} from "./TippingBase.sol";
|
|
11
|
+
import {MembershipStorage} from "src/spaces/facets/membership/MembershipStorage.sol";
|
|
12
|
+
import {BasisPoints} from "src/utils/libraries/BasisPoints.sol";
|
|
13
|
+
import {CurrencyTransfer} from "src/utils/libraries/CurrencyTransfer.sol";
|
|
14
|
+
import {CustomRevert} from "src/utils/libraries/CustomRevert.sol";
|
|
15
|
+
|
|
16
|
+
// contracts
|
|
17
|
+
import {Facet} from "@towns-protocol/diamond/src/facets/Facet.sol";
|
|
18
|
+
import {ReentrancyGuard} from "solady/utils/ReentrancyGuard.sol";
|
|
19
|
+
import {ERC721ABase} from "src/diamond/facets/token/ERC721A/ERC721ABase.sol";
|
|
20
|
+
import {PointsBase} from "../points/PointsBase.sol";
|
|
21
|
+
|
|
22
|
+
contract TippingFacet is ITipping, ERC721ABase, PointsBase, Facet, ReentrancyGuard {
|
|
23
|
+
function __Tipping_init() external onlyInitializing {
|
|
24
|
+
_addInterface(type(ITipping).interfaceId);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/// @inheritdoc ITipping
|
|
28
|
+
function tip(TipRequest calldata tipRequest) external payable nonReentrant {
|
|
29
|
+
_validateTipRequest(
|
|
30
|
+
msg.sender,
|
|
31
|
+
tipRequest.receiver,
|
|
32
|
+
tipRequest.currency,
|
|
33
|
+
tipRequest.amount
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
uint256 tipAmount = tipRequest.amount;
|
|
37
|
+
|
|
38
|
+
if (tipRequest.currency == CurrencyTransfer.NATIVE_TOKEN) {
|
|
39
|
+
uint256 protocolFee = _payProtocol(msg.sender, tipRequest.amount);
|
|
40
|
+
tipAmount = tipRequest.amount - protocolFee;
|
|
41
|
+
|
|
42
|
+
address airdropDiamond = _getAirdropDiamond();
|
|
43
|
+
uint256 points = _getPoints(
|
|
44
|
+
airdropDiamond,
|
|
45
|
+
ITownsPointsBase.Action.Tip,
|
|
46
|
+
abi.encode(protocolFee)
|
|
47
|
+
);
|
|
48
|
+
_mintPoints(airdropDiamond, msg.sender, points);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
TippingBase.tip(
|
|
52
|
+
msg.sender,
|
|
53
|
+
tipRequest.receiver,
|
|
54
|
+
tipRequest.tokenId,
|
|
55
|
+
tipRequest.currency,
|
|
56
|
+
tipAmount
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
emit Tip(
|
|
60
|
+
tipRequest.tokenId,
|
|
61
|
+
tipRequest.currency,
|
|
62
|
+
msg.sender,
|
|
63
|
+
tipRequest.receiver,
|
|
64
|
+
tipRequest.amount,
|
|
65
|
+
tipRequest.messageId,
|
|
66
|
+
tipRequest.channelId
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/// @inheritdoc ITipping
|
|
71
|
+
function tippingCurrencies() external view returns (address[] memory) {
|
|
72
|
+
return TippingBase.tippingCurrencies();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// @inheritdoc ITipping
|
|
76
|
+
function tipsByCurrencyAndTokenId(
|
|
77
|
+
uint256 tokenId,
|
|
78
|
+
address currency
|
|
79
|
+
) external view returns (uint256) {
|
|
80
|
+
return TippingBase.tipsByCurrencyByTokenId(tokenId, currency);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/// @inheritdoc ITipping
|
|
84
|
+
function totalTipsByCurrency(address currency) external view returns (uint256) {
|
|
85
|
+
return TippingBase.totalTipsByCurrency(currency);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/// @inheritdoc ITipping
|
|
89
|
+
function tipAmountByCurrency(address currency) external view returns (uint256) {
|
|
90
|
+
return TippingBase.tipAmountByCurrency(currency);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
|
|
94
|
+
/* Internal */
|
|
95
|
+
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
|
|
96
|
+
|
|
97
|
+
function _validateTipRequest(
|
|
98
|
+
address sender,
|
|
99
|
+
address receiver,
|
|
100
|
+
address currency,
|
|
101
|
+
uint256 amount
|
|
102
|
+
) internal pure {
|
|
103
|
+
if (currency == address(0)) {
|
|
104
|
+
CustomRevert.revertWith(CurrencyIsZero.selector);
|
|
105
|
+
}
|
|
106
|
+
if (sender == receiver) CustomRevert.revertWith(CannotTipSelf.selector);
|
|
107
|
+
if (amount == 0) CustomRevert.revertWith(AmountIsZero.selector);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function _payProtocol(address sender, uint256 amount) internal returns (uint256 protocolFee) {
|
|
111
|
+
MembershipStorage.Layout storage ds = MembershipStorage.layout();
|
|
112
|
+
IPlatformRequirements platform = IPlatformRequirements(ds.spaceFactory);
|
|
113
|
+
|
|
114
|
+
protocolFee = BasisPoints.calculate(amount, 50); // 0.5%
|
|
115
|
+
|
|
116
|
+
CurrencyTransfer.transferCurrency(
|
|
117
|
+
CurrencyTransfer.NATIVE_TOKEN,
|
|
118
|
+
sender,
|
|
119
|
+
platform.getFeeRecipient(),
|
|
120
|
+
protocolFee
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
// interfaces
|
|
5
|
+
|
|
6
|
+
// libraries
|
|
7
|
+
|
|
8
|
+
// contracts
|
|
9
|
+
|
|
10
|
+
interface ITreasury {
|
|
11
|
+
/// @notice Withdraw funds from the treasury to a specified account
|
|
12
|
+
/// @dev Can only be called by the owner of the contract. Will revert if account is zero address
|
|
13
|
+
/// or if balance is 0
|
|
14
|
+
/// @param account The address to withdraw funds to
|
|
15
|
+
function withdraw(address account) external;
|
|
16
|
+
|
|
17
|
+
/// @notice Handle the receipt of a single ERC721 token
|
|
18
|
+
/// @dev Implements the IERC721Receiver interface to safely receive ERC721 tokens
|
|
19
|
+
/// @param operator The address which called `safeTransferFrom` function
|
|
20
|
+
/// @param from The address which previously owned the token
|
|
21
|
+
/// @param tokenId The NFT identifier which is being transferred
|
|
22
|
+
/// @param data Additional data with no specified format
|
|
23
|
+
/// @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
|
|
24
|
+
function onERC721Received(
|
|
25
|
+
address operator,
|
|
26
|
+
address from,
|
|
27
|
+
uint256 tokenId,
|
|
28
|
+
bytes calldata data
|
|
29
|
+
) external returns (bytes4);
|
|
30
|
+
|
|
31
|
+
/// @notice Handle the receipt of a single ERC1155 token
|
|
32
|
+
/// @dev Implements the IERC1155Receiver interface to safely receive ERC1155 tokens
|
|
33
|
+
/// @param operator The address which called the `safeTransferFrom` function
|
|
34
|
+
/// @param from The address which previously owned the token
|
|
35
|
+
/// @param id The ID of the token being transferred
|
|
36
|
+
/// @param value The amount of tokens being transferred
|
|
37
|
+
/// @param data Additional data with no specified format
|
|
38
|
+
/// @return bytes4
|
|
39
|
+
/// `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
|
|
40
|
+
function onERC1155Received(
|
|
41
|
+
address operator,
|
|
42
|
+
address from,
|
|
43
|
+
uint256 id,
|
|
44
|
+
uint256 value,
|
|
45
|
+
bytes calldata data
|
|
46
|
+
) external returns (bytes4);
|
|
47
|
+
|
|
48
|
+
/// @notice Handle the receipt of multiple ERC1155 tokens
|
|
49
|
+
/// @dev Implements the IERC1155Receiver interface to safely receive multiple ERC1155 tokens
|
|
50
|
+
/// @param operator The address which called the `safeBatchTransferFrom` function
|
|
51
|
+
/// @param from The address which previously owned the tokens
|
|
52
|
+
/// @param ids An array containing ids of each token being transferred
|
|
53
|
+
/// @param values An array containing amounts of each token being transferred
|
|
54
|
+
/// @param data Additional data with no specified format
|
|
55
|
+
/// @return bytes4
|
|
56
|
+
/// `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
|
|
57
|
+
function onERC1155BatchReceived(
|
|
58
|
+
address operator,
|
|
59
|
+
address from,
|
|
60
|
+
uint256[] calldata ids,
|
|
61
|
+
uint256[] calldata values,
|
|
62
|
+
bytes calldata data
|
|
63
|
+
) external returns (bytes4);
|
|
64
|
+
}
|