From f228eea13152fa140ffab9151a727c55bd98bc28 Mon Sep 17 00:00:00 2001 From: george-openformat Date: Wed, 7 Aug 2024 10:47:52 +0100 Subject: [PATCH 01/11] refactor: remove application fee extension --- .../applicationFee/ApplicationFee.sol | 31 ---------- .../applicationFee/ApplicationFeeInternal.sol | 50 --------------- .../applicationFee/ApplicationFeeMock.sol | 61 ------------------- .../applicationFee/ApplicationFeeStorage.sol | 21 ------- .../applicationFee/IApplicationFee.sol | 18 ------ 5 files changed, 181 deletions(-) delete mode 100644 src/extensions/applicationFee/ApplicationFee.sol delete mode 100644 src/extensions/applicationFee/ApplicationFeeInternal.sol delete mode 100644 src/extensions/applicationFee/ApplicationFeeMock.sol delete mode 100644 src/extensions/applicationFee/ApplicationFeeStorage.sol delete mode 100644 src/extensions/applicationFee/IApplicationFee.sol diff --git a/src/extensions/applicationFee/ApplicationFee.sol b/src/extensions/applicationFee/ApplicationFee.sol deleted file mode 100644 index f68dfad..0000000 --- a/src/extensions/applicationFee/ApplicationFee.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.16; - -import {IApplicationFee} from "./IApplicationFee.sol"; -import {ApplicationFeeInternal} from "./ApplicationFeeInternal.sol"; - -/** - * @dev The application fee extension can be used by facets to set and pay a percentage fee. - * - * inheriting contracts can use the internal function _applicationFeeInfo to get the amount - * and recipient to pay. - * - * See payApplicationFee in ApplicationFeeMock.sol for an implementation example. - */ - -abstract contract ApplicationFee is IApplicationFee, ApplicationFeeInternal { - modifier onlyAcceptedCurrencies(address _currency) { - if (!_isCurrencyAccepted(_currency)) { - revert ApplicationFee_currencyNotAccepted(); - } - _; - } - - /** - * @inheritdoc IApplicationFee - */ - - function applicationFeeInfo(uint256 _price) external view returns (address recipient, uint256 amount) { - return _applicationFeeInfo(_price); - } -} diff --git a/src/extensions/applicationFee/ApplicationFeeInternal.sol b/src/extensions/applicationFee/ApplicationFeeInternal.sol deleted file mode 100644 index ad4b5af..0000000 --- a/src/extensions/applicationFee/ApplicationFeeInternal.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.16; - -import {IERC20, SafeERC20} from "@solidstate/contracts/utils/SafeERC20.sol"; - -import {IApplicationFee} from "./IApplicationFee.sol"; -import {ApplicationFeeStorage} from "./ApplicationFeeStorage.sol"; - -abstract contract ApplicationFeeInternal is IApplicationFee { - /** - * @dev gets applicationFeeInfo for a given price based on percentBPS - * inspired by eip-2981 NFT royalty standard - */ - function _applicationFeeInfo(uint256 _price) internal view returns (address recipient, uint256 amount) { - ApplicationFeeStorage.Layout storage l = ApplicationFeeStorage.layout(); - - recipient = l.recipient; - amount = _price == 0 ? 0 : (_price * l.percentageBPS) / 10_000; - } - - /** - * @dev sets applicationFeeInfo. reverts if percent exceeds 100% (10_000 BPS) - */ - function _setApplicationFee(uint16 _percentBPS, address _recipient) internal virtual { - ApplicationFeeStorage.Layout storage l = ApplicationFeeStorage.layout(); - - if (_percentBPS > 10_000) { - revert ApplicationFee_exceedsMaxPercentBPS(); - } - - l.percentageBPS = _percentBPS; - l.recipient = _recipient; - } - - function _setAcceptedCurrencies(address[] memory _currencies, bool[] memory _approvals) internal virtual { - ApplicationFeeStorage.Layout storage l = ApplicationFeeStorage.layout(); - - if (_currencies.length != _approvals.length) { - revert ApplicationFee_currenciesAndApprovalsMustBeTheSameLength(); - } - - for (uint256 i = 0; i < _currencies.length; i++) { - l.acceptedCurrencies[_currencies[i]] = _approvals[i]; - } - } - - function _isCurrencyAccepted(address _currency) internal virtual returns (bool) { - return ApplicationFeeStorage.layout().acceptedCurrencies[_currency]; - } -} diff --git a/src/extensions/applicationFee/ApplicationFeeMock.sol b/src/extensions/applicationFee/ApplicationFeeMock.sol deleted file mode 100644 index 9895201..0000000 --- a/src/extensions/applicationFee/ApplicationFeeMock.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.16; - -import {ApplicationFee, IApplicationFee} from "./ApplicationFee.sol"; -import {ApplicationFeeStorage} from "./ApplicationFeeStorage.sol"; - -import {CurrencyTransferLib} from "src/lib/CurrencyTransferLib.sol"; - -contract ApplicationFeeMock is ApplicationFee { - /* INTERNAL HELPERS */ - - function setApplicationFee(uint16 _percentBPS, address _recipient) external { - _setApplicationFee(_percentBPS, _recipient); - } - - function setAcceptedCurrencies(address[] memory _currencies, bool[] memory _approvals) external { - _setAcceptedCurrencies(_currencies, _approvals); - } - - /* STORAGE HELPERS */ - - function percentBPS() external view returns (uint16) { - return ApplicationFeeStorage.layout().percentageBPS; - } - - function recipient() external view returns (address) { - return ApplicationFeeStorage.layout().recipient; - } - - function isCurrencyAccepted(address _currency) external view returns (bool) { - return ApplicationFeeStorage.layout().acceptedCurrencies[_currency]; - } - - /* IMPLEMENTATION EXAMPLE */ - - /** - * @dev pays application fee in ether or erc20 token, to be used in payable functions - * @param _currency the address of the currency, use address(0) for native token - * @param _price used to calculate application fee, can be set to 0 for none priced functions - * @return remaining is the remaining balance after the application fee has been paid - */ - - function payApplicationFee(address _currency, uint256 _price) - external - payable - onlyAcceptedCurrencies(_currency) - returns (uint256 remaining) - { - (address to, uint256 amount) = _applicationFeeInfo(_price); - - if ((_currency == address(0)) && (amount > msg.value)) { - revert CurrencyTransferLib.CurrencyTransferLib_insufficientValue(); - } - - CurrencyTransferLib.transferCurrency(_currency, msg.sender, to, amount); - - emit PaidApplicationFee(_currency, amount); - - remaining = _price - amount; - } -} diff --git a/src/extensions/applicationFee/ApplicationFeeStorage.sol b/src/extensions/applicationFee/ApplicationFeeStorage.sol deleted file mode 100644 index f1efb63..0000000 --- a/src/extensions/applicationFee/ApplicationFeeStorage.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.16; - -library ApplicationFeeStorage { - struct Layout { - uint16 percentageBPS; - address recipient; - mapping(address => bool) acceptedCurrencies; - } - - bytes32 internal constant STORAGE_SLOT = keccak256("openformat.contracts.storage.ApplicationFee"); - - function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; - - // slither-disable-next-line assembly - assembly { - l.slot := slot - } - } -} diff --git a/src/extensions/applicationFee/IApplicationFee.sol b/src/extensions/applicationFee/IApplicationFee.sol deleted file mode 100644 index 8d50920..0000000 --- a/src/extensions/applicationFee/IApplicationFee.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.16; - -interface IApplicationFee { - error ApplicationFee_currenciesAndApprovalsMustBeTheSameLength(); - error ApplicationFee_currencyNotAccepted(); - error ApplicationFee_exceedsMaxPercentBPS(); - - event PaidApplicationFee(address currency, uint256 amount); - - /** - * @notice gets the application fee for a given price - * @param _price the given price of a transaction - * @return recipient the address to pay the application fee to - * @return amount the fee amount - */ - function applicationFeeInfo(uint256 _price) external view returns (address recipient, uint256 amount); -} From bfe488caf7eef396efa283f46850341562ee539b Mon Sep 17 00:00:00 2001 From: george-openformat Date: Wed, 7 Aug 2024 10:48:38 +0100 Subject: [PATCH 02/11] refactor: remove platform fee extension --- src/extensions/platformFee/IPlatformFee.sol | 14 -------------- src/extensions/platformFee/PlatformFee.sol | 14 -------------- .../platformFee/PlatformFeeInternal.sol | 15 --------------- 3 files changed, 43 deletions(-) delete mode 100644 src/extensions/platformFee/IPlatformFee.sol delete mode 100644 src/extensions/platformFee/PlatformFee.sol delete mode 100644 src/extensions/platformFee/PlatformFeeInternal.sol diff --git a/src/extensions/platformFee/IPlatformFee.sol b/src/extensions/platformFee/IPlatformFee.sol deleted file mode 100644 index 6bd380a..0000000 --- a/src/extensions/platformFee/IPlatformFee.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.16; - -interface IPlatformFee { - event PaidPlatformFee(address currency, uint256 amount); - - /** - * @notice gets the platform fee for a given price - * @param _price the given price of a transaction - * @return recipient the address to pay the platform fee to - * @return amount the fee amount - */ - function platformFeeInfo(uint256 _price) external view returns (address recipient, uint256 amount); -} diff --git a/src/extensions/platformFee/PlatformFee.sol b/src/extensions/platformFee/PlatformFee.sol deleted file mode 100644 index c89f3e3..0000000 --- a/src/extensions/platformFee/PlatformFee.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.16; - -import {IPlatformFee} from "./IPlatformFee.sol"; -import {PlatformFeeInternal} from "./PlatformFeeInternal.sol"; - -abstract contract PlatformFee is IPlatformFee, PlatformFeeInternal { - /** - * @inheritdoc IPlatformFee - */ - function platformFeeInfo(uint256 _price) external view returns (address recipient, uint256 amount) { - (recipient, amount) = _platformFeeInfo(_price); - } -} diff --git a/src/extensions/platformFee/PlatformFeeInternal.sol b/src/extensions/platformFee/PlatformFeeInternal.sol deleted file mode 100644 index fd0f1bd..0000000 --- a/src/extensions/platformFee/PlatformFeeInternal.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.16; - -import {Global} from "../global/Global.sol"; -import {IPlatformFee} from "./IPlatformFee.sol"; - -abstract contract PlatformFeeInternal is IPlatformFee, Global { - /** - * @dev wrapper that calls platformFeeInfo from globals contract - * inspired by eip-2981 NFT royalty standard - */ - function _platformFeeInfo(uint256 _price) internal view returns (address recipient, uint256 amount) { - (recipient, amount) = _getGlobals().platformFeeInfo(_price); - } -} From e2dd998f6279d059f6a264860a03199e05ad9bdd Mon Sep 17 00:00:00 2001 From: george-openformat Date: Wed, 7 Aug 2024 10:56:11 +0100 Subject: [PATCH 03/11] refactor: remove fee logic from facets --- src/facet/ERC20FactoryFacet.sol | 30 ++------------ src/facet/ERC721FactoryFacet.sol | 30 ++------------ src/facet/ERC721LazyDropFacet.sol | 68 ++----------------------------- src/facet/RewardsFacet.sol | 2 - src/facet/SettingsFacet.sol | 28 ++----------- 5 files changed, 14 insertions(+), 144 deletions(-) diff --git a/src/facet/ERC20FactoryFacet.sol b/src/facet/ERC20FactoryFacet.sol index fa6ba09..a0bd10a 100644 --- a/src/facet/ERC20FactoryFacet.sol +++ b/src/facet/ERC20FactoryFacet.sol @@ -4,44 +4,20 @@ pragma solidity ^0.8.16; import {Ownable} from "@solidstate/contracts/access/ownable/Ownable.sol"; import {CurrencyTransferLib} from "src/lib/CurrencyTransferLib.sol"; import {ERC20Factory} from "../extensions/ERC20Factory/ERC20Factory.sol"; -import {PlatformFee} from "../extensions/platformFee/PlatformFee.sol"; import {ApplicationAccess} from "../extensions/applicationAccess/ApplicationAccess.sol"; /** * @title "ERC20Factory Facet" * @notice A facet of the ERC20Factory contract that provides functionality for creating new ERC20 tokens. - * This contract also includes extensions for Ownable, PlatformFee, and ApplicationAccess, which allow for ownership management, - * platform fee collection, and restricted access to contract creation, respectively. - * Before creating a new contract, a platform fee is added, which must be paid in ether. + * This contract also includes extensions for Ownable and ApplicationAccess, which allow for ownership management + * and restricted access to contract creation, respectively. */ -contract ERC20FactoryFacet is ERC20Factory, Ownable, PlatformFee, ApplicationAccess { +contract ERC20FactoryFacet is ERC20Factory, Ownable, ApplicationAccess { /** * @dev uses applicationAccess extension for create access for new erc20 contracts */ function _canCreate() internal view override returns (bool) { return _hasCreatorAccess(msg.sender); } - - /** - * @dev override before create to add platform fee - * requires msg.value to be equal or more than base platform fee - * when calling createERC20 - */ - function _beforeCreate() internal override { - (address recipient, uint256 amount) = _platformFeeInfo(0); - - if (amount == 0) { - return; - } - - // ensure the ether being sent was included in the transaction - if (msg.value < amount) { - revert CurrencyTransferLib.CurrencyTransferLib_insufficientValue(); - } - - CurrencyTransferLib.safeTransferNativeToken(recipient, amount); - - emit PaidPlatformFee(address(0), amount); - } } diff --git a/src/facet/ERC721FactoryFacet.sol b/src/facet/ERC721FactoryFacet.sol index f027d17..de8515a 100644 --- a/src/facet/ERC721FactoryFacet.sol +++ b/src/facet/ERC721FactoryFacet.sol @@ -5,43 +5,19 @@ import {Ownable} from "@solidstate/contracts/access/ownable/Ownable.sol"; import {CurrencyTransferLib} from "src/lib/CurrencyTransferLib.sol"; import {ApplicationAccess} from "../extensions/applicationAccess/ApplicationAccess.sol"; import {ERC721Factory} from "../extensions/ERC721Factory/ERC721Factory.sol"; -import {PlatformFee} from "../extensions/platformFee/PlatformFee.sol"; /** * @title "ERC721Factory Facet" * @notice A facet of the ERC721Factory contract that provides functionality for creating new ERC721 tokens. - * This contract also includes extensions for Ownable, PlatformFee, and ApplicationAccess, which allow for ownership management, - * platform fee collection, and restricted access to contract creation, respectively. - * Before creating a new contract, a platform fee is added, which must be paid in ether. + * This contract also includes extensions for Ownable, and ApplicationAccess, which allow for ownership management + * and restricted access to contract creation, respectively. */ -contract ERC721FactoryFacet is ERC721Factory, Ownable, PlatformFee, ApplicationAccess { +contract ERC721FactoryFacet is ERC721Factory, Ownable, ApplicationAccess { /** * @dev uses applicationAccess extension for create access for new erc721 contracts */ function _canCreate() internal view override returns (bool) { return _hasCreatorAccess(msg.sender); } - - /** - * @dev override before create to add platform fee - * requires msg.value to be equal or more than base platform fee - * when calling createERC721 - */ - function _beforeCreate() internal override { - (address recipient, uint256 amount) = _platformFeeInfo(0); - - if (amount == 0) { - return; - } - - // ensure the ether being sent was included in the transaction - if (msg.value < amount) { - revert CurrencyTransferLib.CurrencyTransferLib_insufficientValue(); - } - - CurrencyTransferLib.safeTransferNativeToken(recipient, amount); - - emit PaidPlatformFee(address(0), amount); - } } diff --git a/src/facet/ERC721LazyDropFacet.sol b/src/facet/ERC721LazyDropFacet.sol index dfb86f6..868c2cd 100644 --- a/src/facet/ERC721LazyDropFacet.sol +++ b/src/facet/ERC721LazyDropFacet.sol @@ -4,9 +4,6 @@ pragma solidity ^0.8.16; import {ERC721LazyDrop, IERC721LazyDrop} from "src/extensions/ERC721LazyDrop/ERC721LazyDrop.sol"; import {ICompatibleERC721} from "src/extensions/ERC721LazyDrop/ICompatibleERC721.sol"; import {ERC721LazyDropStorage} from "src/extensions/ERC721LazyDrop/ERC721LazyDropStorage.sol"; - -import {PlatformFee} from "src/extensions/platformFee/PlatformFee.sol"; -import {ApplicationFee} from "src/extensions/applicationFee/ApplicationFee.sol"; import {CurrencyTransferLib} from "src/lib/CurrencyTransferLib.sol"; import {IERC2981} from "@solidstate/contracts/interfaces/IERC2981.sol"; @@ -16,40 +13,9 @@ import {IERC2981} from "@solidstate/contracts/interfaces/IERC2981.sol"; * @notice Allows token contract admins/owners to use an app to drop lazy minted tokens for a price */ -contract ERC721LazyDropFacet is ERC721LazyDrop, PlatformFee, ApplicationFee { +contract ERC721LazyDropFacet is ERC721LazyDrop { error ERC721LazyDropFacet_EIP2981NotSupported(); error ERC721LazyDropFacet_royaltyRecipientNotFound(); - /** - * @dev override before setClaimCondition to add platform fee - * requires msg.value to be equal or more than base platform fee - * when calling ERC721LazyDrop_setClaimCondition - */ - - function _beforeSetClaimCondition(address _tokenContract, ERC721LazyDropStorage.ClaimCondition calldata _condition) - internal - override - { - // token contracts must support the royalty standard - bool supportsERC281 = ICompatibleERC721(_tokenContract).supportsInterface(0x2a55205a); - if (!supportsERC281) { - revert ERC721LazyDropFacet_EIP2981NotSupported(); - } - - (address recipient, uint256 amount) = _platformFeeInfo(0); - - if (amount == 0) { - return; - } - - // ensure the ether being sent was included in the transaction - if (amount > msg.value) { - revert CurrencyTransferLib.CurrencyTransferLib_insufficientValue(); - } - - CurrencyTransferLib.safeTransferNativeToken(recipient, amount); - - emit PaidPlatformFee(address(0), amount); - } /** * @dev override to handle minting of NFT's @@ -67,13 +33,12 @@ contract ERC721LazyDropFacet is ERC721LazyDrop, PlatformFee, ApplicationFee { } /** - * @dev override to add platform and application fees as well as paying the royalty receiver + * @dev override to pay the royalty receiver */ function _collectPriceOnClaim(address _tokenContract, uint256 _quantity, address _currency, uint256 _pricePerToken) internal override - onlyAcceptedCurrencies(_currency) { // Get recipient from royaltyInfo // We are only after an address to send funds so price and id doesn't matter @@ -84,39 +49,14 @@ contract ERC721LazyDropFacet is ERC721LazyDrop, PlatformFee, ApplicationFee { } uint256 totalPrice = _quantity * _pricePerToken; - (address platformFeeRecipient, uint256 platformFee) = _platformFeeInfo(totalPrice); - (address applicationFeeRecipient, uint256 applicationFee) = _applicationFeeInfo(totalPrice); - bool isNativeToken = _currency == CurrencyTransferLib.NATIVE_TOKEN; - uint256 fees = isNativeToken ? platformFee + applicationFee : platformFee; - - if (fees > msg.value) { - revert CurrencyTransferLib.CurrencyTransferLib_insufficientValue(); - } - - // pay platform fee - if (platformFee > 0) { - CurrencyTransferLib.safeTransferNativeToken(platformFeeRecipient, platformFee); - - emit PaidPlatformFee(address(0), platformFee); - } - - // pay application fee - if (applicationFee > 0) { - if (isNativeToken) { - CurrencyTransferLib.safeTransferNativeToken(applicationFeeRecipient, applicationFee); - } else { - CurrencyTransferLib.safeTransferERC20(_currency, msg.sender, applicationFeeRecipient, applicationFee); - } - emit PaidApplicationFee(_currency, applicationFee); - } // pay nft royalty recipient if (isNativeToken) { - CurrencyTransferLib.safeTransferNativeToken(royaltyRecipient, msg.value - fees); + CurrencyTransferLib.safeTransferNativeToken(royaltyRecipient, msg.value); } else { - CurrencyTransferLib.safeTransferERC20(_currency, msg.sender, royaltyRecipient, totalPrice - applicationFee); + CurrencyTransferLib.safeTransferERC20(_currency, msg.sender, royaltyRecipient, totalPrice); } } } diff --git a/src/facet/RewardsFacet.sol b/src/facet/RewardsFacet.sol index 6beacfa..5ccfc0f 100644 --- a/src/facet/RewardsFacet.sol +++ b/src/facet/RewardsFacet.sol @@ -2,9 +2,7 @@ pragma solidity ^0.8.16; import {SafeOwnable, OwnableInternal} from "@solidstate/contracts/access/ownable/SafeOwnable.sol"; -import {ApplicationFee} from "../extensions/applicationFee/ApplicationFee.sol"; import {ApplicationAccess, IApplicationAccess} from "../extensions/applicationAccess/ApplicationAccess.sol"; -import {PlatformFee} from "../extensions/platformFee/PlatformFee.sol"; import {Multicall} from "@solidstate/contracts/utils/Multicall.sol"; interface NFT { diff --git a/src/facet/SettingsFacet.sol b/src/facet/SettingsFacet.sol index 372bf98..13d5053 100644 --- a/src/facet/SettingsFacet.sol +++ b/src/facet/SettingsFacet.sol @@ -2,38 +2,18 @@ pragma solidity ^0.8.16; import {SafeOwnable, OwnableInternal} from "@solidstate/contracts/access/ownable/SafeOwnable.sol"; -import {ApplicationFee} from "../extensions/applicationFee/ApplicationFee.sol"; import {ApplicationAccess, IApplicationAccess} from "../extensions/applicationAccess/ApplicationAccess.sol"; -import {PlatformFee} from "../extensions/platformFee/PlatformFee.sol"; +import {Global} from "../extensions/global/Global.sol"; /** * @title "Settings Facet" * @notice A facet of the Settings contract that allows the application owner to manage application-wide settings. - * This contract includes extensions for ApplicationFee, PlatformFee, SafeOwnable, and ApplicationAccess, - * which provide functionality for managing application and platform fees, ownership management, and restricted + * This contract includes extensions for SafeOwnable, and ApplicationAccess, + * which provide functionality for ownership management, and restricted * access to contract creation. */ -contract SettingsFacet is ApplicationFee, PlatformFee, SafeOwnable, ApplicationAccess { - /** - * @notice sets the application percentage fee in BPS and the recipient wallet - * @param percentBPS The percentage used to calculate application fee - * @param recipient The wallet or contract address to send the application fee to - */ - function setApplicationFee(uint16 percentBPS, address recipient) external onlyOwner { - _setApplicationFee(percentBPS, recipient); - } - - /** - * @notice sets the accepted currencies for the application fee - * @dev the arrays of currencies and approvals must be the same length - * @param currencies the list of currencies to edit - * @param approvals the list of approvals for the given currencies - */ - function setAcceptedCurrencies(address[] memory currencies, bool[] memory approvals) external onlyOwner { - _setAcceptedCurrencies(currencies, approvals); - } - +contract SettingsFacet is SafeOwnable, Global, ApplicationAccess { /** * @notice sets the approved accounts that have access to create new token contracts, * setting the zero address will open it up to all. From 505acbe2551c7e63195a533ee27914a29b0e6b6b Mon Sep 17 00:00:00 2001 From: george-openformat Date: Wed, 7 Aug 2024 11:13:47 +0100 Subject: [PATCH 04/11] refactor: remove fee logic from tokens --- src/tokens/ERC20/ERC20Base.sol | 44 +----------------- src/tokens/ERC721/ERC721Badge.sol | 58 ++--------------------- src/tokens/ERC721/ERC721Base.sol | 48 +------------------ src/tokens/ERC721/ERC721BaseMock.sol | 6 --- src/tokens/ERC721/ERC721LazyMint.sol | 59 ++---------------------- src/tokens/ERC721/ERC721LazyMintMock.sol | 6 --- 6 files changed, 12 insertions(+), 209 deletions(-) diff --git a/src/tokens/ERC20/ERC20Base.sol b/src/tokens/ERC20/ERC20Base.sol index 3f8597b..7164d79 100644 --- a/src/tokens/ERC20/ERC20Base.sol +++ b/src/tokens/ERC20/ERC20Base.sol @@ -13,8 +13,6 @@ import {ReentrancyGuard} from "@solidstate/contracts/utils/ReentrancyGuard.sol"; import {ContractMetadata, IContractMetadata} from "@extensions/contractMetadata/ContractMetadata.sol"; import {Initializable} from "@extensions/initializable/Initializable.sol"; import {Global} from "@extensions/global/Global.sol"; -import {PlatformFee} from "@extensions/platformFee/PlatformFee.sol"; - import {CurrencyTransferLib} from "src/lib/CurrencyTransferLib.sol"; /** @@ -45,8 +43,6 @@ contract ERC20Base is ContractMetadata, Initializable, ERC165Base, - Global, - PlatformFee, ReentrancyGuard { error ERC20Base_notAuthorized(); @@ -78,16 +74,12 @@ contract ERC20Base is return; } - // decode data to app address and globals address - (address app, address globals) = abi.decode(_data, (address, address)); + // decode data to app address + (address app) = abi.decode(_data, (address)); if (app != address(0)) { _grantRole(MINTER_ROLE, app); } - - if (globals != address(0)) { - _setGlobals(globals); - } } /*////////////////////////////////////////////////////////////// @@ -110,11 +102,7 @@ contract ERC20Base is revert ERC20Base_zeroAmount(); } - (address platformFeeRecipient, uint256 platformFeeAmount) = _checkPlatformFee(); - _mint(_to, _amount); - - _payPlatformFee(platformFeeRecipient, platformFeeAmount); } /** @@ -157,34 +145,6 @@ contract ERC20Base is } } - /*////////////////////////////////////////////////////////////// - Internal (platform fee) functions - //////////////////////////////////////////////////////////////*/ - - function _checkPlatformFee() internal view returns (address recipient, uint256 amount) { - // don't charge platform fee if sender is a contract or globals address is not set - if (_isContract(msg.sender) || _getGlobalsAddress() == address(0)) { - return (address(0), 0); - } - - (recipient, amount) = _platformFeeInfo(0); - - // ensure the ether being sent was included in the transaction - if (amount > msg.value) { - revert CurrencyTransferLib.CurrencyTransferLib_insufficientValue(); - } - } - - function _payPlatformFee(address recipient, uint256 amount) internal { - if (amount == 0) { - return; - } - - CurrencyTransferLib.safeTransferNativeToken(recipient, amount); - - emit PaidPlatformFee(address(0), amount); - } - /** * @dev derived from Openzepplin's address utils * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.2/contracts/utils/Address.sol diff --git a/src/tokens/ERC721/ERC721Badge.sol b/src/tokens/ERC721/ERC721Badge.sol index d0dde57..83253a1 100644 --- a/src/tokens/ERC721/ERC721Badge.sol +++ b/src/tokens/ERC721/ERC721Badge.sol @@ -18,8 +18,6 @@ import {ERC721AUpgradeable} from "@erc721a-upgradeable/contracts/ERC721AUpgradea import {Royalty} from "@extensions/royalty/Royalty.sol"; import {BatchMintMetadata} from "@extensions/batchMintMetadata/BatchMintMetadata.sol"; import {ContractMetadata, IContractMetadata} from "@extensions/contractMetadata/ContractMetadata.sol"; -import {Global} from "@extensions/global/Global.sol"; -import {PlatformFee} from "@extensions/platformFee/PlatformFee.sol"; import {CurrencyTransferLib} from "src/lib/CurrencyTransferLib.sol"; @@ -36,8 +34,6 @@ contract ERC721Badge is BatchMintMetadata, Royalty, Multicall, - Global, - PlatformFee, ReentrancyGuard, Ownable { @@ -62,13 +58,11 @@ contract ERC721Badge is /** * @dev initialize should be called from a trusted contract and not directly by an account. - * platform fee could easily be bypassed by not properly encoding data. * * @param _data bytes encoded with the signature (address,address,string) - * the first will be granted a minter role - * the second address will be set as the globals address - * used to calculate platform fees - * The string is the baseURI for all tokens on the contract + * the first address will be granted a minter role + * the second address is not used as there is no need for globals + * the third string is the baseURI for all tokens on the contract */ function initialize( address _owner, @@ -93,16 +87,12 @@ contract ERC721Badge is } // decode data to app address and globals address - (address app, address globals, string memory baseURIForTokens) = abi.decode(_data, (address, address, string)); + (address app, , string memory baseURIForTokens) = abi.decode(_data, (address, address, string)); if (app != address(0)) { _grantRole(MINTER_ROLE, app); } - if (globals != address(0)) { - _setGlobals(globals); - } - if (bytes(baseURIForTokens).length > 0) { _batchMintMetadata(0, MAX_INT, baseURIForTokens); emit BatchMetadataUpdate(0, MAX_INT); @@ -150,8 +140,6 @@ contract ERC721Badge is revert ERC721Badge.ERC721Badge_notAuthorized(); } - (address platformFeeRecipient, uint256 platformFeeAmount) = _checkPlatformFee(); - // there will only ever be a baseURICount of zero or one if (_getBaseURICount() > 0) { _setBaseURI(MAX_INT, _baseURIForTokens); @@ -161,8 +149,6 @@ contract ERC721Badge is emit BatchMetadataUpdate(0, MAX_INT); emit UpdatedBaseURI(_baseURIForTokens); - - _payPlatformFee(platformFeeRecipient, platformFeeAmount); } /** @@ -176,15 +162,11 @@ contract ERC721Badge is revert ERC721Badge_notAuthorized(); } - (address platformFeeRecipient, uint256 platformFeeAmount) = _checkPlatformFee(); - uint256 tokenId = _nextTokenId(); _safeMint(_to, 1); emit Minted(_to, _getBaseURI(tokenId)); - - _payPlatformFee(platformFeeRecipient, platformFeeAmount); } /** @@ -199,14 +181,10 @@ contract ERC721Badge is revert ERC721Badge_notAuthorized(); } - (address platformFeeRecipient, uint256 platformFeeAmount) = _checkPlatformFee(); - string memory _baseURI = _getBaseURI(_nextTokenId()); _safeMint(_to, _quantity); emit BatchMinted(_to, _quantity, _baseURI); - - _payPlatformFee(platformFeeRecipient, platformFeeAmount * _quantity); } /** @@ -298,34 +276,6 @@ contract ERC721Badge is return _hasRole(ADMIN_ROLE, msg.sender); } - /*////////////////////////////////////////////////////////////// - Internal (platform fee) functions - //////////////////////////////////////////////////////////////*/ - - function _checkPlatformFee() internal view returns (address recipient, uint256 amount) { - // don't charge platform fee if sender is a contract or globals address is not set - if (_isContract(msg.sender) || _getGlobalsAddress() == address(0)) { - return (address(0), 0); - } - - (recipient, amount) = _platformFeeInfo(0); - - // ensure the ether being sent was included in the transaction - if (amount > msg.value) { - revert CurrencyTransferLib.CurrencyTransferLib_insufficientValue(); - } - } - - function _payPlatformFee(address recipient, uint256 amount) internal { - if (amount == 0) { - return; - } - - CurrencyTransferLib.safeTransferNativeToken(recipient, amount); - - emit PaidPlatformFee(address(0), amount); - } - /** * @dev derived from Openzepplin's address utils * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.2/contracts/utils/Address.sol diff --git a/src/tokens/ERC721/ERC721Base.sol b/src/tokens/ERC721/ERC721Base.sol index e470657..9fbaa35 100644 --- a/src/tokens/ERC721/ERC721Base.sol +++ b/src/tokens/ERC721/ERC721Base.sol @@ -17,8 +17,6 @@ import {Royalty} from "@extensions/royalty/Royalty.sol"; import {MintMetadata} from "@extensions/mintMetadata/MintMetadata.sol"; import {BatchMintMetadata} from "@extensions/batchMintMetadata/BatchMintMetadata.sol"; import {ContractMetadata, IContractMetadata} from "@extensions/contractMetadata/ContractMetadata.sol"; -import {Global} from "@extensions/global/Global.sol"; -import {PlatformFee} from "@extensions/platformFee/PlatformFee.sol"; import {CurrencyTransferLib} from "src/lib/CurrencyTransferLib.sol"; @@ -34,8 +32,6 @@ contract ERC721Base is ContractMetadata, Royalty, Multicall, - Global, - PlatformFee, ReentrancyGuard, Ownable { @@ -67,16 +63,12 @@ contract ERC721Base is return; } - // decode data to app address and globals address - (address app, address globals) = abi.decode(_data, (address, address)); + // decode data to app address + (address app) = abi.decode(_data, (address)); if (app != address(0)) { _grantRole(MINTER_ROLE, app); } - - if (globals != address(0)) { - _setGlobals(globals); - } } /*////////////////////////////////////////////////////////////// @@ -129,14 +121,10 @@ contract ERC721Base is revert ERC721Base_notAuthorized(); } - (address platformFeeRecipient, uint256 platformFeeAmount) = _checkPlatformFee(); - _mintMetadata(_nextTokenId(), _tokenURI); _safeMint(_to, 1); emit Minted(_to, _tokenURI); - - _payPlatformFee(platformFeeRecipient, platformFeeAmount); } /** @@ -153,14 +141,10 @@ contract ERC721Base is revert ERC721Base_notAuthorized(); } - (address platformFeeRecipient, uint256 platformFeeAmount) = _checkPlatformFee(); - _batchMintMetadata(_nextTokenId(), _quantity, _baseURI); _safeMint(_to, _quantity); emit BatchMinted(_to, _quantity, _baseURI); - - _payPlatformFee(platformFeeRecipient, platformFeeAmount * _quantity); } /** @@ -267,34 +251,6 @@ contract ERC721Base is return _hasRole(ADMIN_ROLE, msg.sender); } - /*////////////////////////////////////////////////////////////// - Internal (platform fee) functions - //////////////////////////////////////////////////////////////*/ - - function _checkPlatformFee() internal view returns (address recipient, uint256 amount) { - // don't charge platform fee if sender is a contract or globals address is not set - if (_isContract(msg.sender) || _getGlobalsAddress() == address(0)) { - return (address(0), 0); - } - - (recipient, amount) = _platformFeeInfo(0); - - // ensure the ether being sent was included in the transaction - if (amount > msg.value) { - revert CurrencyTransferLib.CurrencyTransferLib_insufficientValue(); - } - } - - function _payPlatformFee(address recipient, uint256 amount) internal { - if (amount == 0) { - return; - } - - CurrencyTransferLib.safeTransferNativeToken(recipient, amount); - - emit PaidPlatformFee(address(0), amount); - } - /** * @dev derived from Openzepplin's address utils * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.2/contracts/utils/Address.sol diff --git a/src/tokens/ERC721/ERC721BaseMock.sol b/src/tokens/ERC721/ERC721BaseMock.sol index d93b84b..c9485f2 100644 --- a/src/tokens/ERC721/ERC721BaseMock.sol +++ b/src/tokens/ERC721/ERC721BaseMock.sol @@ -13,10 +13,4 @@ contract ERC721BaseMock is ERC721Base { ) payable initializerERC721A { initialize(msg.sender, _name, _symbol, _royaltyReceiver, _royaltyBPS, _data); } - - /* STORAGE HELPERS */ - - function _globals() external view returns (address) { - return _getGlobalsAddress(); - } } diff --git a/src/tokens/ERC721/ERC721LazyMint.sol b/src/tokens/ERC721/ERC721LazyMint.sol index 7eb6698..8d64186 100644 --- a/src/tokens/ERC721/ERC721LazyMint.sol +++ b/src/tokens/ERC721/ERC721LazyMint.sol @@ -16,8 +16,6 @@ import {ERC721AUpgradeable} from "@erc721a-upgradeable/contracts/ERC721AUpgradea import {Royalty} from "@extensions/royalty/Royalty.sol"; import {LazyMint} from "@extensions/lazyMint/LazyMint.sol"; import {ContractMetadata, IContractMetadata} from "@extensions/contractMetadata/ContractMetadata.sol"; -import {Global} from "@extensions/global/Global.sol"; -import {PlatformFee} from "@extensions/platformFee/PlatformFee.sol"; import {CurrencyTransferLib} from "src/lib/CurrencyTransferLib.sol"; @@ -32,8 +30,6 @@ contract ERC721LazyMint is ContractMetadata, Royalty, Multicall, - Global, - PlatformFee, ReentrancyGuard, Ownable { @@ -56,12 +52,9 @@ contract ERC721LazyMint is /** * @dev initialize should be called from a trusted contract and not directly by an account. - * platform fee could easily be bypassed by not properly encoding data. * - * @param _data bytes encoded with the signature (address,address) - * the fist will be granted a minter role - * the second address will be set as the globals address - * used to calculate platform fees + * @param _data bytes encoded with the signature (address) + * the address will be granted a minter role */ function initialize( @@ -86,16 +79,12 @@ contract ERC721LazyMint is return; } - // decode data to app address and globals address - (address app, address globals) = abi.decode(_data, (address, address)); + // decode data to app address + (address app) = abi.decode(_data, (address)); if (app != address(0)) { _grantRole(MINTER_ROLE, app); } - - if (globals != address(0)) { - _setGlobals(globals); - } } /*////////////////////////////////////////////////////////////// @@ -145,11 +134,7 @@ contract ERC721LazyMint is nonReentrant returns (uint256 batchId) { - (address platformFeeRecipient, uint256 platformFeeAmount) = _checkPlatformFee(); - batchId = _lazyMint(_amount, _baseURIForTokens, _data); - - _payPlatformFee(platformFeeRecipient, platformFeeAmount); } /** @@ -164,8 +149,6 @@ contract ERC721LazyMint is revert ERC721LazyMint_notAuthorized(); } - (address platformFeeRecipient, uint256 platformFeeAmount) = _checkPlatformFee(); - uint256 tokenId = _nextTokenId(); if (tokenId >= _getNextTokenIdToLazyMint()) { @@ -175,8 +158,6 @@ contract ERC721LazyMint is _safeMint(_to, 1); emit Minted(_to, _getBaseURI(tokenId)); - - _payPlatformFee(platformFeeRecipient, platformFeeAmount); } /** @@ -192,8 +173,6 @@ contract ERC721LazyMint is revert ERC721LazyMint_notAuthorized(); } - (address platformFeeRecipient, uint256 platformFeeAmount) = _checkPlatformFee(); - if ((_nextTokenId() + _quantity) > _getNextTokenIdToLazyMint()) { revert ERC721LazyMint_insufficientLazyMintedTokens(); } @@ -202,8 +181,6 @@ contract ERC721LazyMint is _safeMint(_to, _quantity); emit BatchMinted(_to, _quantity, _baseURI); - - _payPlatformFee(platformFeeRecipient, platformFeeAmount * _quantity); } /** @@ -311,34 +288,6 @@ contract ERC721LazyMint is return _hasRole(ADMIN_ROLE, msg.sender); } - /*////////////////////////////////////////////////////////////// - Internal (platform fee) functions - //////////////////////////////////////////////////////////////*/ - - function _checkPlatformFee() internal view returns (address recipient, uint256 amount) { - // don't charge platform fee if sender is a contract or globals address is not set - if (_isContract(msg.sender) || _getGlobalsAddress() == address(0)) { - return (address(0), 0); - } - - (recipient, amount) = _platformFeeInfo(0); - - // ensure the ether being sent was included in the transaction - if (amount > msg.value) { - revert CurrencyTransferLib.CurrencyTransferLib_insufficientValue(); - } - } - - function _payPlatformFee(address recipient, uint256 amount) internal { - if (amount == 0) { - return; - } - - CurrencyTransferLib.safeTransferNativeToken(recipient, amount); - - emit PaidPlatformFee(address(0), amount); - } - /** * @dev derived from Openzepplin's address utils * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.2/contracts/utils/Address.sol diff --git a/src/tokens/ERC721/ERC721LazyMintMock.sol b/src/tokens/ERC721/ERC721LazyMintMock.sol index 99ebcc4..07ce164 100644 --- a/src/tokens/ERC721/ERC721LazyMintMock.sol +++ b/src/tokens/ERC721/ERC721LazyMintMock.sol @@ -13,10 +13,4 @@ contract ERC721LazyMintMock is ERC721LazyMint { ) ERC721LazyMint(true) { initialize(msg.sender, _name, _symbol, _royaltyReceiver, _royaltyBPS, _data); } - - /* STORAGE HELPERS */ - - function _globals() external view returns (address) { - return _getGlobalsAddress(); - } } From 61f8dc705ee6f372d8fac43df28a1d488abfcc86 Mon Sep 17 00:00:00 2001 From: george-openformat Date: Wed, 7 Aug 2024 11:46:19 +0100 Subject: [PATCH 05/11] refactor: remove application and platform fee tests --- test/extensions/ApplicationFee.t.sol | 183 --------------- test/integration/TransactionLayer.t.sol | 214 ------------------ test/integration/extensions/PlatformFee.t.sol | 175 -------------- 3 files changed, 572 deletions(-) delete mode 100644 test/extensions/ApplicationFee.t.sol delete mode 100644 test/integration/TransactionLayer.t.sol delete mode 100644 test/integration/extensions/PlatformFee.t.sol diff --git a/test/extensions/ApplicationFee.t.sol b/test/extensions/ApplicationFee.t.sol deleted file mode 100644 index 11935be..0000000 --- a/test/extensions/ApplicationFee.t.sol +++ /dev/null @@ -1,183 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.16; - -import "forge-std/Test.sol"; -import {ApplicationFeeMock, IApplicationFee} from "src/extensions/applicationFee/ApplicationFeeMock.sol"; -import {CurrencyTransferLib} from "src/lib/CurrencyTransferLib.sol"; - -import {ERC20BaseMock} from "src/tokens/ERC20/ERC20BaseMock.sol"; -import {IERC20} from "@solidstate/contracts/interfaces/IERC20.sol"; - -contract Setup is Test { - address recipient; - uint16 tenPercentBPS; - ApplicationFeeMock applicationFee; - - function setUp() public { - recipient = address(0x10); - tenPercentBPS = 1000; - applicationFee = new ApplicationFeeMock(); - - _afterSetup(); - } - - function _afterSetup() internal virtual {} -} - -contract ApplicationFee__applicationFeeInfo is Setup { - function test_returns_zero_address_and_amount_when_not_set() public { - (address recipient, uint256 amount) = applicationFee.applicationFeeInfo(100 ether); - assertEq(recipient, address(0)); - assertEq(amount, 0); - } - - function test_returns_percentage_of_price() public { - applicationFee.setApplicationFee(tenPercentBPS, recipient); - - (, uint256 amount) = applicationFee.applicationFeeInfo(100 ether); - assertEq(amount, 10 ether); - } - - function test_returns_recipient() public { - applicationFee.setApplicationFee(tenPercentBPS, recipient); - - (address recipient,) = applicationFee.applicationFeeInfo(100 ether); - assertEq(recipient, recipient); - } -} - -contract ApplicationFee__internal_setApplicationFee is Setup { - function test_sets_application_fee() public { - applicationFee.setApplicationFee(tenPercentBPS, recipient); - - assertEq(applicationFee.percentBPS(), tenPercentBPS); - assertEq(applicationFee.recipient(), recipient); - } - - function test_reverts_if_percent_exceeds_100() public { - vm.expectRevert(IApplicationFee.ApplicationFee_exceedsMaxPercentBPS.selector); - applicationFee.setApplicationFee(10_001, recipient); - } -} - -contract ApplicationFee__internal_setAcceptedCurrencies is Setup { - function test_sets_accepted_currencies() public { - address[] memory currencies = new address[](3); - currencies[0] = address(0); // native token - currencies[1] = address(0xabc); - currencies[2] = address(0xdef); - - bool[] memory approvals = new bool[](3); - approvals[0] = true; - approvals[1] = true; - approvals[2] = true; - - applicationFee.setAcceptedCurrencies(currencies, approvals); - - assertTrue(applicationFee.isCurrencyAccepted(address(0))); - assertTrue(applicationFee.isCurrencyAccepted(address(0xabc))); - assertTrue(applicationFee.isCurrencyAccepted(address(0xdef))); - } - - function test_reverts_when_currencies_and_approvals_are_different_length() public { - address[] memory currencies = new address[](1); - currencies[0] = address(0); // native token - - bool[] memory approvals = new bool[](2); - approvals[0] = true; - approvals[1] = true; - - vm.expectRevert(IApplicationFee.ApplicationFee_currenciesAndApprovalsMustBeTheSameLength.selector); - applicationFee.setAcceptedCurrencies(currencies, approvals); - } -} - -contract ApplicationFee__internal_payApplicationFee is Setup { - ERC20BaseMock erc20; - - event PaidApplicationFee(address currency, uint256 amount); - - function _afterSetup() internal override { - applicationFee.setApplicationFee(tenPercentBPS, recipient); - - // create Dummy ERC20 token - erc20 = new ERC20BaseMock("Dummy", "D", 18, 1000); - - // accept native token - address[] memory currencies = new address[](2); - currencies[0] = address(0); // native token - currencies[1] = address(erc20); - - bool[] memory approvals = new bool[](2); - approvals[0] = true; - approvals[1] = true; - - applicationFee.setAcceptedCurrencies(currencies, approvals); - } - - function test_pays_application_fee() public { - erc20.approve(address(applicationFee), 100); - - applicationFee.payApplicationFee(address(erc20), 100); - - assertEq(erc20.balanceOf(recipient), 10); - } - - function test_pays_application_fee_with_native_token() public { - applicationFee.payApplicationFee{value: 100 ether}(address(0), 100 ether); - - assertEq(recipient.balance, 10 ether); - } - - function test_returns_remaining_amount() public { - erc20.approve(address(applicationFee), 100); - uint256 remaining = applicationFee.payApplicationFee(address(erc20), 100); - - assertEq(remaining, 90); - } - - function test_returns_remaining_amount_with_native_token() public { - uint256 remaining = applicationFee.payApplicationFee{value: 100 ether}(address(0), 100 ether); - - assertEq(remaining, 90 ether); - } - - function test_returns_full_price_if_no_fee() public { - applicationFee.setApplicationFee(0, recipient); - - erc20.approve(address(applicationFee), 100); - uint256 remaining = applicationFee.payApplicationFee(address(erc20), 100); - - assertEq(remaining, 100); - } - - function test_returns_full_price_if_no_fee_with_native_token() public { - applicationFee.setApplicationFee(0, recipient); - uint256 remaining = applicationFee.payApplicationFee{value: 100 ether}(address(0), 100 ether); - - assertEq(remaining, 100 ether); - } - - function test_reverts_if_currency_not_accepted() public { - vm.expectRevert(IApplicationFee.ApplicationFee_currencyNotAccepted.selector); - applicationFee.payApplicationFee(address(0xabc), 100); - } - - function test_emits_paidApplicationFee_event() public { - erc20.approve(address(applicationFee), 100); - vm.expectEmit(true, true, true, true); - emit PaidApplicationFee(address(erc20), 10); - applicationFee.payApplicationFee(address(erc20), 100); - } - - function test_emits_paidApplicationFee_event_with_native_token() public { - vm.expectEmit(true, true, true, true); - emit PaidApplicationFee(address(0), 10 ether); - applicationFee.payApplicationFee{value: 100 ether}(address(0), 100 ether); - } - - function test_reverts_if_msg_value_less_than_fee_with_native_token() public { - vm.expectRevert(CurrencyTransferLib.CurrencyTransferLib_insufficientValue.selector); - applicationFee.payApplicationFee{value: 9 ether}(address(0), 100 ether); - } -} diff --git a/test/integration/TransactionLayer.t.sol b/test/integration/TransactionLayer.t.sol deleted file mode 100644 index bb002ef..0000000 --- a/test/integration/TransactionLayer.t.sol +++ /dev/null @@ -1,214 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.16; - -// The following tests the integration of the "transaction layer" of an application. -// The DummyDonateFacet contract inherits the platformFee and applicationFee extensions -// and demonstrates a simple implementation of a donation via the app. -// The settings facet is used to set application fee -// The globals contract is used to set the platform fee - -import "forge-std/Test.sol"; - -import { - IDiamondWritable, - IDiamondWritableInternal -} from "@solidstate/contracts/proxy/diamond/writable/IDiamondWritable.sol"; - -import {ReentrancyGuard} from "@solidstate/contracts/utils/ReentrancyGuard.sol"; -import {IERC20, SafeERC20} from "@solidstate/contracts/utils/SafeERC20.sol"; - -import {Proxy} from "src/proxy/Proxy.sol"; -import {Upgradable} from "src/proxy/upgradable/Upgradable.sol"; -import {RegistryMock} from "src/registry/RegistryMock.sol"; -import {AppFactory} from "src/factories/App.sol"; -import {Globals} from "src/globals/Globals.sol"; -import {SettingsFacet} from "src/facet/SettingsFacet.sol"; -import {ERC20BaseMock} from "src/tokens/ERC20/ERC20BaseMock.sol"; -import {ERC20Base} from "src/tokens/ERC20/ERC20Base.sol"; -import {CurrencyTransferLib} from "src/lib/CurrencyTransferLib.sol"; - -import {PlatformFee, IPlatformFee, PlatformFeeInternal} from "src/extensions/platformFee/PlatformFee.sol"; -import { - ApplicationFee, IApplicationFee, ApplicationFeeInternal -} from "src/extensions/applicationFee/ApplicationFee.sol"; - -contract DummyDonateFacet is PlatformFee, ApplicationFee, ReentrancyGuard { - function donate(address currency, uint256 price, address to) - external - payable - onlyAcceptedCurrencies(currency) - nonReentrant - { - (address platformFeeRecipient, uint256 platformFee) = _platformFeeInfo(price); - (address applicationFeeRecipient, uint256 applicationFee) = _applicationFeeInfo(price); - - if (currency == CurrencyTransferLib.NATIVE_TOKEN) { - uint256 fees = platformFee + applicationFee; - if (fees > msg.value) { - revert CurrencyTransferLib.CurrencyTransferLib_insufficientValue(); - } - - // pay platform fee - CurrencyTransferLib.safeTransferNativeToken(platformFeeRecipient, platformFee); - emit PaidPlatformFee(currency, platformFee); - - // pay application fee - CurrencyTransferLib.safeTransferNativeToken(applicationFeeRecipient, applicationFee); - emit PaidApplicationFee(currency, applicationFee); - - // send remaining - CurrencyTransferLib.safeTransferNativeToken(to, msg.value - fees); - } else { - if (platformFee > msg.value) { - revert CurrencyTransferLib.CurrencyTransferLib_insufficientValue(); - } - - // pay platform fee - CurrencyTransferLib.safeTransferNativeToken(platformFeeRecipient, platformFee); - emit PaidPlatformFee(CurrencyTransferLib.NATIVE_TOKEN, platformFee); - - // pay application fee - CurrencyTransferLib.safeTransferERC20(currency, msg.sender, applicationFeeRecipient, applicationFee); - emit PaidApplicationFee(currency, applicationFee); - - // Send remaining - // shouldn't overflow because applicationFee cannot be more than 100% - CurrencyTransferLib.safeTransferERC20(currency, msg.sender, to, price - applicationFee); - } - } -} - -abstract contract Helpers { - function prepareSingleFacetCut( - address cutAddress, - IDiamondWritableInternal.FacetCutAction cutAction, - bytes4[] memory selectors - ) public pure returns (IDiamondWritableInternal.FacetCut[] memory) { - IDiamondWritableInternal.FacetCut[] memory cuts = new IDiamondWritableInternal.FacetCut[](1); - cuts[0] = IDiamondWritableInternal.FacetCut(cutAddress, cutAction, selectors); - return cuts; - } -} - -contract Setup is Test, Helpers { - address appOwner; - address other; - address socialConscious; - - AppFactory appFactory; - Proxy template; - Proxy app; - RegistryMock registry; - Globals globals; - ERC20BaseMock erc20; - ERC20Base erc20Implementation; - - SettingsFacet settingsFacet; - DummyDonateFacet facet; - - uint16 tenPercentBPS = 1_000; - - function setUp() public { - appOwner = address(0x10); - other = address(0x11); - socialConscious = address(0x12); - - globals = new Globals(); - registry = new RegistryMock(); - template = new Proxy(true); - appFactory = new AppFactory(address(template), address(registry), address(globals)); - erc20 = new ERC20BaseMock("Dummy", "D", 18, 1000); - - erc20Implementation = new ERC20Base(); - - // Add Facets - { - settingsFacet = new SettingsFacet(); - bytes4[] memory selectors = new bytes4[](2); - selectors[0] = SettingsFacet.setApplicationFee.selector; - selectors[1] = SettingsFacet.setAcceptedCurrencies.selector; - registry.diamondCut( - prepareSingleFacetCut(address(settingsFacet), IDiamondWritableInternal.FacetCutAction.ADD, selectors), - address(0), - "" - ); - } - { - facet = new DummyDonateFacet(); - bytes4[] memory selectors = new bytes4[](1); - selectors[0] = DummyDonateFacet.donate.selector; - registry.diamondCut( - prepareSingleFacetCut(address(facet), IDiamondWritableInternal.FacetCutAction.ADD, selectors), - address(0), - "" - ); - } - - // setup platform fee to be base 0.01 ether and receiver to be social Conscious - globals.setPlatformFee(0.1 ether, 0, socialConscious); - - // create app - vm.prank(appOwner); - app = Proxy(payable(appFactory.create("ERC721LazyMintTest", appOwner))); - - // set application fee - vm.prank(appOwner); - SettingsFacet(address(app)).setApplicationFee(tenPercentBPS, appOwner); - - // set accepted tokens - address[] memory currencies = new address[](2); - currencies[0] = address(0); // native token - currencies[1] = address(erc20); - - bool[] memory approvals = new bool[](2); - approvals[0] = true; - approvals[1] = true; - - vm.prank(appOwner); - SettingsFacet(address(app)).setAcceptedCurrencies(currencies, approvals); - } -} - -contract TransactionLayer__integration is Setup { - event PaidPlatformFee(address currency, uint256 amount); - event PaidApplicationFee(address currency, uint256 amount); - - function test_pays_correct_fees() public { - erc20.approve(address(app), 100); - DummyDonateFacet(address(app)).donate{value: 0.1 ether}(address(erc20), 100, other); - - assertEq(socialConscious.balance, 0.1 ether); - assertEq(erc20.balanceOf(appOwner), 10); - assertEq(erc20.balanceOf(other), 90); - } - - function test_pays_correct_fees_with_native_token() public { - DummyDonateFacet(address(app)).donate{value: 1.1 ether}(address(0), 1 ether, other); - - assertEq(socialConscious.balance, 0.1 ether); - assertEq(appOwner.balance, 0.1 ether); - assertEq(other.balance, 0.9 ether); - } - - function test_emits_paid_events() public { - erc20.approve(address(app), 100); - - vm.expectEmit(true, true, true, true); - emit PaidPlatformFee(address(0), 0.1 ether); - - vm.expectEmit(true, true, true, true); - emit PaidApplicationFee(address(erc20), 10); - - DummyDonateFacet(address(app)).donate{value: 0.1 ether}(address(erc20), 100, other); - } - - function test_emits_paid_events_with_naitive_token() public { - vm.expectEmit(true, true, true, true); - emit PaidPlatformFee(address(0), 0.1 ether); - - vm.expectEmit(true, true, true, true); - emit PaidApplicationFee(address(0), 0.1 ether); - - DummyDonateFacet(address(app)).donate{value: 1.1 ether}(address(0), 1 ether, other); - } -} diff --git a/test/integration/extensions/PlatformFee.t.sol b/test/integration/extensions/PlatformFee.t.sol deleted file mode 100644 index 4826a6e..0000000 --- a/test/integration/extensions/PlatformFee.t.sol +++ /dev/null @@ -1,175 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.16; - -// The following tests that the platform fee extension works as intentended within the ecosystem - -import "forge-std/Test.sol"; - -import { - IDiamondWritable, - IDiamondWritableInternal -} from "@solidstate/contracts/proxy/diamond/writable/IDiamondWritable.sol"; - -import {CurrencyTransferLib} from "src/lib/CurrencyTransferLib.sol"; - -import {Proxy} from "src/proxy/Proxy.sol"; -import {Upgradable} from "src/proxy/upgradable/Upgradable.sol"; -import {RegistryMock} from "src/registry/RegistryMock.sol"; -import {AppFactory} from "src/factories/App.sol"; -import {Globals} from "src/globals/Globals.sol"; - -import {ERC20Base} from "src/tokens/ERC20/ERC20Base.sol"; - -import {PlatformFee, IPlatformFee} from "src/extensions/platformFee/PlatformFee.sol"; - -contract DummyFacet is PlatformFee { - string public message = ""; - - function purchase(uint256 _price) external payable { - _payPlatformFee(_price); - } - - function write() external payable { - _payPlatformFee(0); - } - - /** - * @dev dummy implementation of paying platform fee - */ - function _payPlatformFee(uint256 _price) internal virtual returns (uint256 remaining) { - (address recipient, uint256 amount) = _platformFeeInfo(_price); - - if (amount == 0) { - return _price; - } - - // ensure the ether being sent was included in the transaction - if (msg.value < amount) { - revert CurrencyTransferLib.CurrencyTransferLib_insufficientValue(); - } - - CurrencyTransferLib.transferCurrency(address(0), msg.sender, recipient, amount); - - emit PaidPlatformFee(address(0), amount); - - remaining = msg.value - amount; - } -} - -abstract contract Helpers { - function prepareSingleFacetCut( - address cutAddress, - IDiamondWritableInternal.FacetCutAction cutAction, - bytes4[] memory selectors - ) public pure returns (IDiamondWritableInternal.FacetCut[] memory) { - IDiamondWritableInternal.FacetCut[] memory cuts = new IDiamondWritableInternal.FacetCut[](1); - cuts[0] = IDiamondWritableInternal.FacetCut(cutAddress, cutAction, selectors); - return cuts; - } -} - -contract Setup is Test, Helpers { - address creator; - address socialConscious; - - AppFactory appFactory; - Proxy template; - Proxy app; - RegistryMock registry; - DummyFacet facet; - Globals globals; - ERC20Base erc20Implementation; - - function setUp() public { - creator = address(0x10); - socialConscious = address(0x11); - - globals = new Globals(); - registry = new RegistryMock(); - template = new Proxy(true); - appFactory = new AppFactory(address(template), address(registry), address(globals)); - facet = new DummyFacet(); - - erc20Implementation = new ERC20Base(); - - // add facet to registry - bytes4[] memory selectors = new bytes4[](2); - selectors[0] = DummyFacet.write.selector; - selectors[1] = DummyFacet.purchase.selector; - registry.diamondCut( - prepareSingleFacetCut(address(facet), IDiamondWritableInternal.FacetCutAction.ADD, selectors), - address(0), - "" - ); - - // setup platform fee to be base 0.01 ether and reciever to be social Conscious - globals.setPlatformFee(0.1 ether, 0, socialConscious); - - // create app - app = Proxy(payable(appFactory.create("platformFeeTest", address(0)))); - } -} - -contract PlatformFee__intergration is Setup { - event PaidPlatformFee(address currency, uint256 amount); - - function test_platform_fee_is_paid() public { - DummyFacet(address(app)).write{value: 0.1 ether}(); - - assertEq(socialConscious.balance, 0.1 ether); - } - - function test_exact_platform_fee_is_paid() public { - DummyFacet(address(app)).write{value: 10 ether}(); - - assertEq(socialConscious.balance, 0.1 ether); - } - - function test_platform_percentage_fee_is_paid() public { - uint16 tenPercentBPS = 1000; - globals.setPlatformFee(0, tenPercentBPS, socialConscious); - - DummyFacet(address(app)).purchase{value: 1 ether}(1 ether); - assertEq(socialConscious.balance, 0.1 ether); - } - - function test_platform_percentage_fee_is_zero_when_price_is_zero() public { - uint16 tenPercentBPS = 1000; - globals.setPlatformFee(0, tenPercentBPS, socialConscious); - - DummyFacet(address(app)).purchase{value: 0 ether}(0 ether); - assertEq(socialConscious.balance, 0 ether); - } - - function test_platform_percentage_and_base_fee_is_paid() public { - uint16 tenPercentBPS = 1000; - globals.setPlatformFee(0.1 ether, tenPercentBPS, socialConscious); - - DummyFacet(address(app)).purchase{value: 1 ether}(1 ether); - assertEq(socialConscious.balance, 0.2 ether); - } - - function test_emits_paid_platform_fee_event() public { - vm.expectEmit(true, true, true, true, address(app)); - emit PaidPlatformFee(address(0), 0.1 ether); - - DummyFacet(address(app)).write{value: 0.1 ether}(); - } - - function test_reverts_when_value_is_less_than_amount() public { - vm.expectRevert(CurrencyTransferLib.CurrencyTransferLib_insufficientValue.selector); - DummyFacet(address(app)).write{value: 0.001 ether}(); - } - - function test_reverts_when_no_value_is_sent() public { - vm.expectRevert(CurrencyTransferLib.CurrencyTransferLib_insufficientValue.selector); - DummyFacet(address(app)).write(); - } - - function test_reverts_when_value_is_less_than_amount_and_contract_has_sufficiant_balance() public { - vm.deal(address(app), 1 ether); - - vm.expectRevert(CurrencyTransferLib.CurrencyTransferLib_insufficientValue.selector); - DummyFacet(address(app)).write(); - } -} From e6427937a4245aaf375d5e916b985e45f204e169 Mon Sep 17 00:00:00 2001 From: george-openformat Date: Wed, 7 Aug 2024 12:34:39 +0100 Subject: [PATCH 06/11] refactor: remove facet tests related to fees --- .../integration/facet/ERC20FactoryFacet.t.sol | 14 -- .../facet/ERC721FactoryFacet.t.sol | 30 ---- test/integration/facet/ERC721LazyDrop.t.sol | 169 ------------------ test/integration/facet/RewardsFacet.t.sol | 18 -- test/integration/facet/SettingsFacet.t.sol | 83 +-------- 5 files changed, 5 insertions(+), 309 deletions(-) diff --git a/test/integration/facet/ERC20FactoryFacet.t.sol b/test/integration/facet/ERC20FactoryFacet.t.sol index 53f25f9..e9fadc2 100644 --- a/test/integration/facet/ERC20FactoryFacet.t.sol +++ b/test/integration/facet/ERC20FactoryFacet.t.sol @@ -152,19 +152,6 @@ contract ERC20FactoryFacet__integration_createERC20 is Setup { } } - function test_can_create_erc20_and_pay_platform_fee() public { - // set platform base fee to 1 ether - globals.setPlatformFee(1 ether, 0, socialConscious); - - // create nft and pay platform fee - vm.prank(creator); - address erc20Address = ERC20FactoryFacet(address(app)).createERC20{value: 1 ether}( - "name", "symbol", 18, 1000, erc20ImplementationId - ); - // check platform fee has been received - assertEq(socialConscious.balance, 1 ether); - } - function test_can_create_erc721_when_approved_creator() public { _approveCreatorAccess(other); @@ -188,7 +175,6 @@ contract ERC20FactoryFacet__integration_createERC20 is Setup { vm.expectEmit(false, true, true, true); emit Created(expectedAddress, creator, "name", "symbol", 18, 1000, erc20ImplementationId); - // create nft and pay platform fee vm.prank(creator); ERC20FactoryFacet(address(app)).createERC20("name", "symbol", 18, 1000, erc20ImplementationId); } diff --git a/test/integration/facet/ERC721FactoryFacet.t.sol b/test/integration/facet/ERC721FactoryFacet.t.sol index 834fdae..d2d4ac1 100644 --- a/test/integration/facet/ERC721FactoryFacet.t.sol +++ b/test/integration/facet/ERC721FactoryFacet.t.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.16; -// The following tests that the platform fee extension works as intended within the ecosystem - import "forge-std/Test.sol"; import { @@ -154,19 +152,6 @@ contract ERC721FactoryFacet__integration_createERC721 is Setup { assertTrue(ERC721Base(erc721Address).hasRole(MINTER_ROLE, address(app))); } - function test_can_create_erc721_and_pay_platform_fee() public { - // set platform base fee to 1 ether - globals.setPlatformFee(1 ether, 0, socialConscious); - - // create nft and pay platform fee - vm.prank(creator); - address erc721Address = ERC721FactoryFacet(address(app)).createERC721{value: 1 ether}( - "name", "symbol", creator, 1000, erc721ImplementationId - ); - // check platform fee has been received - assertEq(socialConscious.balance, 1 ether); - } - function test_can_create_erc721_when_approved_creator() public { _approveCreatorAccess(other); @@ -216,7 +201,6 @@ contract ERC721FactoryFacet__integration_createERC721 is Setup { vm.expectEmit(false, true, true, true); emit Created(expectedAddress, creator, "name", "symbol", creator, 1000, erc721ImplementationId); - // create nft and pay platform fee vm.prank(creator); ERC721FactoryFacet(address(app)).createERC721("name", "symbol", creator, 1000, erc721ImplementationId); } @@ -320,19 +304,6 @@ contract ERC721FactoryFacet_integration_createERC721WithTokenURI is Setup { assertTrue(ERC721Badge(erc721Address).hasRole(MINTER_ROLE, address(app))); } - function test_can_create_erc721_and_pay_platform_fee() public { - // set platform base fee to 1 ether - globals.setPlatformFee(1 ether, 0, socialConscious); - - // create nft and pay platform fee - vm.prank(creator); - address erc721Address = ERC721FactoryFacet(address(app)).createERC721WithTokenURI{value: 1 ether}( - "name", "symbol", tokenURI, creator, 1000, erc721BadgeImplementationId - ); - // check platform fee has been received - assertEq(socialConscious.balance, 1 ether); - } - function test_can_create_erc721_when_approved_creator() public { _approveCreatorAccess(other); @@ -388,7 +359,6 @@ contract ERC721FactoryFacet_integration_createERC721WithTokenURI is Setup { vm.expectEmit(false, true, true, true); emit Created(expectedAddress, creator, "name", "symbol", creator, 1000, erc721BadgeImplementationId); - // create nft and pay platform fee vm.prank(creator); ERC721FactoryFacet(address(app)).createERC721WithTokenURI( "name", "symbol", tokenURI, creator, 1000, erc721BadgeImplementationId diff --git a/test/integration/facet/ERC721LazyDrop.t.sol b/test/integration/facet/ERC721LazyDrop.t.sol index 4ffbc03..9cd6edb 100644 --- a/test/integration/facet/ERC721LazyDrop.t.sol +++ b/test/integration/facet/ERC721LazyDrop.t.sol @@ -88,21 +88,6 @@ contract Setup is Test, Helpers { erc20Implementation = new ERC20Base(); - { - settingsFacet = new SettingsFacet(); - // add facet to registry - bytes4[] memory selectors = new bytes4[](3); - selectors[0] = settingsFacet.setApplicationFee.selector; - selectors[1] = settingsFacet.setAcceptedCurrencies.selector; - selectors[2] = settingsFacet.applicationFeeInfo.selector; - - registry.diamondCut( - prepareSingleFacetCut(address(settingsFacet), IDiamondWritableInternal.FacetCutAction.ADD, selectors), - address(0), - "" - ); - } - { dropFacet = new ERC721LazyDropFacet(); @@ -128,17 +113,6 @@ contract Setup is Test, Helpers { // create app vm.prank(appOwner); app = Proxy(payable(appFactory.create("ERC721LazyMintTest", appOwner))); - // Add NATIVE_TOKEN and ERC20 to accepted currencies - { - address[] memory currencies = new address[](2); - currencies[0] = address(0); - currencies[1] = address(erc20); - bool[] memory approvals = new bool[](2); - approvals[0] = true; - approvals[1] = true; - vm.prank(appOwner); - SettingsFacet(address(app)).setAcceptedCurrencies(currencies, approvals); - } // Note: just deploy a erc721 for testing no need to do factory facet biz yet // TODO: deploy from factory @@ -347,20 +321,6 @@ contract ERC721LazyDropFacet_ERC721LazyDrop_setClaimCondition is Setup { assertEqClaimCondition(claimCondition, testClaimCondition); } - function test_pays_platform_fee() public { - // set platform fee - globals.setPlatformFee(0.1 ether, 0, socialConscienceLayer); - - vm.deal(nftOwner, 0.1 ether); - - vm.prank(nftOwner); - ERC721LazyDropFacet(address(app)).ERC721LazyDrop_setClaimCondition{value: 0.1 ether}( - address(erc721), testClaimCondition, false - ); - - assertEq(socialConscienceLayer.balance, 0.1 ether); - } - function test_only_token_contract_owner_can_set_claim_condition() public { vm.expectRevert(IERC721LazyDrop.ERC721LazyDrop_notAuthorised.selector); vm.prank(other); @@ -460,69 +420,6 @@ contract ERC721LazyDropFacet_ERC721LazyDrop_claim is Setup { assertEq(nftOwner.balance, 1 ether); } - function test_pays_application_fee_with_native_token() public { - // set application fee - vm.prank(appOwner); - SettingsFacet(address(app)).setApplicationFee(tenPercentBPS, appOwner); - - // update claim condition price per token - testClaimCondition.pricePerToken = 1 ether; - vm.prank(nftOwner); - ERC721LazyDropFacet(address(app)).ERC721LazyDrop_setClaimCondition(address(erc721), testClaimCondition, false); - - // make claim with ether - vm.prank(other); - ERC721LazyDropFacet(address(app)).ERC721LazyDrop_claim{value: 1 ether}( - address(erc721), other, 1, testClaimCondition.currency, testClaimCondition.pricePerToken - ); - - assertEq(nftOwner.balance, 0.9 ether); - assertEq(appOwner.balance, 0.1 ether); - } - - function test_pays_platform_fee_with_native_token() public { - // update claim condition price per token - testClaimCondition.pricePerToken = 1 ether; - vm.prank(nftOwner); - ERC721LazyDropFacet(address(app)).ERC721LazyDrop_setClaimCondition(address(erc721), testClaimCondition, false); - - // set platform fee - globals.setPlatformFee(0.1 ether, 0, socialConscienceLayer); - - // make claim with ether - vm.prank(other); - ERC721LazyDropFacet(address(app)).ERC721LazyDrop_claim{value: 1.1 ether}( - address(erc721), other, 1, testClaimCondition.currency, testClaimCondition.pricePerToken - ); - - assertEq(nftOwner.balance, 1 ether); - assertEq(socialConscienceLayer.balance, 0.1 ether); - } - - function test_pays_platform_and_application_fee_with_native_token() public { - // update claim condition price per token - testClaimCondition.pricePerToken = 1 ether; - vm.prank(nftOwner); - ERC721LazyDropFacet(address(app)).ERC721LazyDrop_setClaimCondition(address(erc721), testClaimCondition, false); - - // set platform fee - globals.setPlatformFee(0.1 ether, 0, socialConscienceLayer); - - // set application fee - vm.prank(appOwner); - SettingsFacet(address(app)).setApplicationFee(tenPercentBPS, appOwner); - - // make claim with ether - vm.prank(other); - ERC721LazyDropFacet(address(app)).ERC721LazyDrop_claim{value: 1.1 ether}( - address(erc721), other, 1, testClaimCondition.currency, testClaimCondition.pricePerToken - ); - - assertEq(nftOwner.balance, 0.9 ether); - assertEq(appOwner.balance, 0.1 ether); - assertEq(socialConscienceLayer.balance, 0.1 ether); - } - function test_pays_price_to_recipient() public { // update claim condition price per token and currency testClaimCondition.pricePerToken = 1 ether; @@ -539,72 +436,6 @@ contract ERC721LazyDropFacet_ERC721LazyDrop_claim is Setup { assertEq(erc20.balanceOf(nftOwner), 1 ether); } - function test_pays_application_fee() public { - // set application fee - vm.prank(appOwner); - SettingsFacet(address(app)).setApplicationFee(tenPercentBPS, appOwner); - - /// update claim condition price per token and currency - testClaimCondition.pricePerToken = 1 ether; - testClaimCondition.currency = address(erc20); - vm.prank(nftOwner); - ERC721LazyDropFacet(address(app)).ERC721LazyDrop_setClaimCondition(address(erc721), testClaimCondition, false); - - // make claim with erc20 - vm.prank(other); - ERC721LazyDropFacet(address(app)).ERC721LazyDrop_claim( - address(erc721), other, 1, testClaimCondition.currency, testClaimCondition.pricePerToken - ); - - assertEq(erc20.balanceOf(nftOwner), 0.9 ether); - assertEq(erc20.balanceOf(appOwner), 0.1 ether); - } - - function test_pays_platform_fee() public { - // update claim condition price per token - testClaimCondition.pricePerToken = 1 ether; - testClaimCondition.currency = address(erc20); - vm.prank(nftOwner); - ERC721LazyDropFacet(address(app)).ERC721LazyDrop_setClaimCondition(address(erc721), testClaimCondition, false); - - // set platform fee - globals.setPlatformFee(0.1 ether, 0, socialConscienceLayer); - - // make claim with platform fee - vm.prank(other); - ERC721LazyDropFacet(address(app)).ERC721LazyDrop_claim{value: 0.1 ether}( - address(erc721), other, 1, testClaimCondition.currency, testClaimCondition.pricePerToken - ); - - assertEq(erc20.balanceOf(nftOwner), 1 ether); - assertEq(socialConscienceLayer.balance, 0.1 ether); - } - - function test_pays_platform_and_application_fee() public { - // update claim condition price per token - testClaimCondition.pricePerToken = 1 ether; - testClaimCondition.currency = address(erc20); - vm.prank(nftOwner); - ERC721LazyDropFacet(address(app)).ERC721LazyDrop_setClaimCondition(address(erc721), testClaimCondition, false); - - // set platform fee - globals.setPlatformFee(0.1 ether, 0, socialConscienceLayer); - - // set application fee - vm.prank(appOwner); - SettingsFacet(address(app)).setApplicationFee(tenPercentBPS, appOwner); - - // make claim with ether - vm.prank(other); - ERC721LazyDropFacet(address(app)).ERC721LazyDrop_claim{value: 0.1 ether}( - address(erc721), other, 1, testClaimCondition.currency, testClaimCondition.pricePerToken - ); - - assertEq(erc20.balanceOf(nftOwner), 0.9 ether); - assertEq(erc20.balanceOf(appOwner), 0.1 ether); - assertEq(socialConscienceLayer.balance, 0.1 ether); - } - function test_reverts_when_quantity_per_wallet_limit_exceeded() public { vm.prank(other); ERC721LazyDropFacet(address(app)).ERC721LazyDrop_claim( diff --git a/test/integration/facet/RewardsFacet.t.sol b/test/integration/facet/RewardsFacet.t.sol index 00792ae..31b3fe1 100644 --- a/test/integration/facet/RewardsFacet.t.sol +++ b/test/integration/facet/RewardsFacet.t.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.16; -// The following tests ERC20Base integration with Globals ERC20FactoryFacet and platform fees - import "forge-std/Test.sol"; import { @@ -41,16 +39,6 @@ abstract contract Helpers { } } -/** - * @dev dummy contract to test platform fee is not paid when called from a contract - * must first grant MINTER_ROLE to this contract - */ -contract MinterDummy { - function mintTo(address _erc20, address _account, uint256 _amount) public { - ERC20Base(_erc20).mintTo(_account, _amount); - } -} - bytes32 constant ADMIN_ROLE = bytes32(uint256(0)); bytes32 constant MINTER_ROLE = bytes32(uint256(1)); @@ -287,7 +275,6 @@ contract RewardFacet__integration_multicall is Setup { contract ERC20Base_Setup is Setup { ERC20Base base; - MinterDummy minter; function _afterSetup() internal override { // add lazy mint implementation @@ -309,11 +296,6 @@ contract ERC20Base_Setup is Setup { ); // forgefmt: disable-end - // create contract that can mint - minter = new MinterDummy(); - // grant minter role to minter contract - vm.prank(creator); - base.grantRole(MINTER_ROLE, address(minter)); } } diff --git a/test/integration/facet/SettingsFacet.t.sol b/test/integration/facet/SettingsFacet.t.sol index c3de95c..bc3476d 100644 --- a/test/integration/facet/SettingsFacet.t.sol +++ b/test/integration/facet/SettingsFacet.t.sol @@ -60,14 +60,10 @@ contract Setup is Test, Helpers { settingsFacet = new SettingsFacet(); // add facet to registry - bytes4[] memory selectors = new bytes4[](7); - selectors[0] = settingsFacet.setApplicationFee.selector; - selectors[1] = settingsFacet.setAcceptedCurrencies.selector; - selectors[2] = settingsFacet.applicationFeeInfo.selector; - selectors[3] = settingsFacet.setCreatorAccess.selector; - selectors[4] = settingsFacet.hasCreatorAccess.selector; - selectors[5] = settingsFacet.platformFeeInfo.selector; - selectors[6] = settingsFacet.getGlobalsAddress.selector; + bytes4[] memory selectors = new bytes4[](3); + selectors[0] = settingsFacet.setCreatorAccess.selector; + selectors[1] = settingsFacet.hasCreatorAccess.selector; + selectors[2] = settingsFacet.getGlobalsAddress.selector; registry.diamondCut( prepareSingleFacetCut(address(settingsFacet), IDiamondWritableInternal.FacetCutAction.ADD, selectors), @@ -85,63 +81,6 @@ contract Setup is Test, Helpers { function _afterSetUp() internal virtual {} } -contract SettingsFacet__integration_setApplicationFee is Setup { - function test_sets_application_fee() public { - vm.prank(appOwner); - SettingsFacet(address(app)).setApplicationFee(tenPercentBPS, appOwner); - - (address recipient, uint256 amount) = SettingsFacet(address(app)).applicationFeeInfo(100); - assertEq(recipient, appOwner); - assertEq(amount, 10); - } - - function test_revert_if_not_the_owner() public { - vm.prank(other); - vm.expectRevert(); - SettingsFacet(address(app)).setApplicationFee(tenPercentBPS, other); - } -} - -contract SettingsFacet__integration_applicationFeeInfo is Setup { - function _afterSetUp() internal override { - vm.prank(appOwner); - SettingsFacet(address(app)).setApplicationFee(tenPercentBPS, appOwner); - } - - function test_returns_application_fee_info() public { - (address recipient, uint256 amount) = SettingsFacet(address(app)).applicationFeeInfo(100); - assertEq(recipient, appOwner); - assertEq(amount, 10); - } -} - -contract SettingsFacet__integration_setAcceptedCurrencies is Setup { - function test_sets_accepted_currencies() public { - (address[] memory currencies, bool[] memory approvals) = _prepareAcceptedCurrencies(); - - vm.prank(appOwner); - SettingsFacet(address(app)).setAcceptedCurrencies(currencies, approvals); - } - - function test_revert_if_not_the_owner() public { - (address[] memory currencies, bool[] memory approvals) = _prepareAcceptedCurrencies(); - - vm.prank(other); - vm.expectRevert(); - SettingsFacet(address(app)).setAcceptedCurrencies(currencies, approvals); - } - - function _prepareAcceptedCurrencies() internal returns (address[] memory currencies, bool[] memory approvals) { - currencies = new address[](2); - currencies[0] = address(0); // native token - currencies[1] = address(0xabc); - - approvals = new bool[](2); - approvals[0] = true; - approvals[1] = true; - } -} - /** * @dev because `SafeOwnable` contract is inherited in `SettingsFacet` we can use it's abi * to call the proxy(apps) safe ownable functions @@ -234,16 +173,4 @@ contract SettingsFacet__integration_getGlobalsAddress is Setup { function test_returns_globals_address() public { assertEq(SettingsFacet(address(app)).getGlobalsAddress(), address(globals)); } -} - -contract SettingsFacet__integration_platformFeeInfo is Setup { - function test_returns_platform_fee_info() public { - // set platform base fee to 1 ether - globals.setPlatformFee(1 ether, 0, other); - - (address recipient, uint256 amount) = SettingsFacet(address(app)).platformFeeInfo(0); - - assertEq(recipient, other); - assertEq(amount, 1 ether); - } -} +} \ No newline at end of file From afe529dfbcbe27c6b3286d9e7a267287befe4f0d Mon Sep 17 00:00:00 2001 From: george-openformat Date: Wed, 7 Aug 2024 12:41:50 +0100 Subject: [PATCH 07/11] refactor: remove token tests related to fees --- test/integration/tokens/ERC20Base.t.sol | 21 ---- test/integration/tokens/ERC721Base.t.sol | 63 ---------- test/integration/tokens/ERC721LazyMint.t.sol | 126 +------------------ test/tokens/ERC721/ERC721Base.t.sol | 10 +- test/tokens/ERC721/ERC721LazyMint.t.sol | 10 +- 5 files changed, 9 insertions(+), 221 deletions(-) diff --git a/test/integration/tokens/ERC20Base.t.sol b/test/integration/tokens/ERC20Base.t.sol index 3e9cc98..2591703 100644 --- a/test/integration/tokens/ERC20Base.t.sol +++ b/test/integration/tokens/ERC20Base.t.sol @@ -166,25 +166,4 @@ contract ERC20Base__integration_mintTo is ERC20Base_Setup { // check nft is minted to creator assertEq(base.balanceOf(creator), 1000); } - - function test_pays_platform_fee() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - vm.prank(creator); - base.mintTo{value: basePlatformFee}(creator, 1000); - - // check platform fee has been received - assertEq(socialConscious.balance, basePlatformFee); - } - - function test_does_not_pay_platform_fee_when_called_from_contract() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - minter.mintTo(address(base), creator, 1000); - assertEq(base.balanceOf(creator), 1000); - } } diff --git a/test/integration/tokens/ERC721Base.t.sol b/test/integration/tokens/ERC721Base.t.sol index a314049..5404ad8 100644 --- a/test/integration/tokens/ERC721Base.t.sol +++ b/test/integration/tokens/ERC721Base.t.sol @@ -171,37 +171,6 @@ contract ERC721Base__integration_mintTo is ERC721Base_Setup { // check nft is minted to creator assertEq(base.ownerOf(0), creator); } - - function test_pays_platform_fee() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - vm.prank(creator); - base.mintTo{value: basePlatformFee}(creator, "ipfs://"); - - // check platform fee has been received - assertEq(socialConscious.balance, basePlatformFee); - } - - function test_reverts_if_platform_fee_not_supplied() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - vm.expectRevert(CurrencyTransferLib.CurrencyTransferLib_insufficientValue.selector); - vm.prank(creator); - base.mintTo(creator, "ipfs://"); - } - - function test_does_not_pay_platform_fee_when_called_from_contract() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - contractDummy.mintTo(address(base), creator, "ipfs://"); - assertEq(base.ownerOf(0), creator); - } } contract ERC721Base__integration_batchMintTo is ERC721Base_Setup { @@ -214,36 +183,4 @@ contract ERC721Base__integration_batchMintTo is ERC721Base_Setup { assertEq(base.ownerOf(1), creator); assertEq(base.ownerOf(2), creator); } - - function test_pays_platform_fee() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - uint256 quantity = 3; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - vm.prank(creator); - base.batchMintTo{value: basePlatformFee * quantity}(creator, quantity, "ipfs://"); - - // check platform fee has been received - assertEq(socialConscious.balance, basePlatformFee * quantity); - } - - function test_reverts_if_platform_fee_not_supplied() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - vm.expectRevert(CurrencyTransferLib.CurrencyTransferLib_insufficientValue.selector); - vm.prank(creator); - base.batchMintTo(creator, 3, "ipfs://"); - } - - function test_does_not_pay_platform_fee_when_called_from_contract() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - contractDummy.batchMintTo(address(base), creator, 3, "ipfs://"); - assertEq(base.ownerOf(0), creator); - } } diff --git a/test/integration/tokens/ERC721LazyMint.t.sol b/test/integration/tokens/ERC721LazyMint.t.sol index c21bf98..49b9694 100644 --- a/test/integration/tokens/ERC721LazyMint.t.sol +++ b/test/integration/tokens/ERC721LazyMint.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.16; -// The following tests ERC721LazyMint integration with Globals ERC721FactoryFacet and platform fees +// The following tests ERC721LazyMint integration with ERC721FactoryFacet import "forge-std/Test.sol"; @@ -37,24 +37,6 @@ abstract contract Helpers { } } -/** - * @dev dummy contract to test platform fee is not paid when called from a contract - * must first grant ADMIN_ROLE to this contract - */ -contract ContractDummy { - function mintTo(address _erc721, address _to) public { - ERC721LazyMint(_erc721).mintTo(_to); - } - - function batchMintTo(address _erc721, address _to, uint256 _quantity) public { - ERC721LazyMint(_erc721).batchMintTo(_to, _quantity); - } - - function lazyMint(address _erc721, uint256 _amount, string memory _baseURI) public { - ERC721LazyMint(_erc721).lazyMint(_amount, _baseURI, ""); - } -} - contract Setup is Test, Helpers { address creator; address other; @@ -140,7 +122,6 @@ contract Setup is Test, Helpers { contract ERC721LazyMint_Setup is Setup { ERC721LazyMint lazyMint; - ContractDummy contractDummy; function _afterSetup() internal override { // add lazy mint implementation @@ -164,12 +145,6 @@ contract ERC721LazyMint_Setup is Setup { vm.prank(creator); lazyMint.lazyMint(3, "ipfs://", ""); - - // create contract that can mint - contractDummy = new ContractDummy(); - // grant admin role to minter contract - vm.prank(creator); - lazyMint.grantRole(ADMIN_ROLE, address(contractDummy)); } } @@ -181,37 +156,6 @@ contract ERC721LazyMint__integration_mintTo is ERC721LazyMint_Setup { // check nft is minted to creator assertEq(lazyMint.ownerOf(0), creator); } - - function test_pays_platform_fee() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - vm.prank(creator); - lazyMint.mintTo{value: basePlatformFee}(creator); - - // check platform fee has been received - assertEq(socialConscious.balance, basePlatformFee); - } - - function test_reverts_if_platform_fee_not_supplied() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - vm.expectRevert(CurrencyTransferLib.CurrencyTransferLib_insufficientValue.selector); - vm.prank(creator); - lazyMint.mintTo(creator); - } - - function test_does_not_pay_platform_fee_when_called_from_contract() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - contractDummy.mintTo(address(lazyMint), creator); - assertEq(lazyMint.ownerOf(0), creator); - } } contract ERC721LazyMint__integration_batchMintTo is ERC721LazyMint_Setup { @@ -224,72 +168,4 @@ contract ERC721LazyMint__integration_batchMintTo is ERC721LazyMint_Setup { assertEq(lazyMint.ownerOf(1), creator); assertEq(lazyMint.ownerOf(2), creator); } - - function test_pays_platform_fee() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - uint256 quantity = 3; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - vm.prank(creator); - lazyMint.batchMintTo{value: basePlatformFee * quantity}(creator, quantity); - - // check platform fee has been received - assertEq(socialConscious.balance, basePlatformFee * quantity); - } - - function test_reverts_if_platform_fee_not_supplied() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - vm.expectRevert(CurrencyTransferLib.CurrencyTransferLib_insufficientValue.selector); - vm.prank(creator); - lazyMint.batchMintTo(creator, 3); - } - - function test_does_not_pay_platform_fee_when_called_from_contract() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - contractDummy.batchMintTo(address(lazyMint), creator, 3); - assertEq(lazyMint.ownerOf(0), creator); - assertEq(lazyMint.ownerOf(1), creator); - assertEq(lazyMint.ownerOf(2), creator); - } -} - -contract ERC721LazyMint__integration_lazyMint is ERC721LazyMint_Setup { - function test_pays_platform_fee() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - vm.prank(creator); - lazyMint.lazyMint{value: basePlatformFee}(3, "ipfs://", ""); - - // check platform fee has been received - assertEq(socialConscious.balance, basePlatformFee); - } - - function test_reverts_if_platform_fee_not_supplied() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - vm.expectRevert(CurrencyTransferLib.CurrencyTransferLib_insufficientValue.selector); - vm.prank(creator); - lazyMint.lazyMint(3, "ipfs://", ""); - assertEq(lazyMint.tokenURI(2), "ipfs://"); - } - - function test_does_not_pay_platform_fee_when_called_from_contract() public { - // set platform base fee to 0.001 ether - uint256 basePlatformFee = 0.001 ether; - globals.setPlatformFee(basePlatformFee, 0, socialConscious); - - contractDummy.lazyMint(address(lazyMint), 3, "ipfs://"); - assertEq(lazyMint.tokenURI(2), "ipfs://"); - } } diff --git a/test/tokens/ERC721/ERC721Base.t.sol b/test/tokens/ERC721/ERC721Base.t.sol index a484807..535de5d 100644 --- a/test/tokens/ERC721/ERC721Base.t.sol +++ b/test/tokens/ERC721/ERC721Base.t.sol @@ -49,8 +49,8 @@ contract ERC721Base__initialize is Setup { erc721Base.initialize(creator, "Name", "Symbol", creator, uint16(tenPercentBPS), ""); } - function test_sets_minter_role_and_global_when_passed_encoded_data() public { - bytes memory data = abi.encode(other, globals); + function test_sets_minter_role_when_passed_encoded_data() public { + bytes memory data = abi.encode(other); erc721Base = new ERC721BaseMock( "Name", "Symbol", @@ -60,11 +60,10 @@ contract ERC721Base__initialize is Setup { ); assertTrue(erc721Base.hasRole(MINTER_ROLE, other)); - assertEq(erc721Base._globals(), globals); } function test_does_not_grant_minter_role_when_passed_encoded_zero_address() public { - bytes memory data = abi.encode(address(0), globals); + bytes memory data = abi.encode(address(0)); erc721Base = new ERC721BaseMock( "Name", "Symbol", @@ -76,7 +75,7 @@ contract ERC721Base__initialize is Setup { assertFalse(erc721Base.hasRole(MINTER_ROLE, address(0))); } - function test_minter_role_and_globals_are_set_with_extra_data() public { + function test_minter_role_is_set_with_extra_data() public { bytes memory data = abi.encode(other, globals, 12356789); erc721Base = new ERC721BaseMock( @@ -88,7 +87,6 @@ contract ERC721Base__initialize is Setup { ); assertTrue(erc721Base.hasRole(MINTER_ROLE, other)); - assertEq(erc721Base._globals(), globals); } } diff --git a/test/tokens/ERC721/ERC721LazyMint.t.sol b/test/tokens/ERC721/ERC721LazyMint.t.sol index da67fa0..93c3fb8 100644 --- a/test/tokens/ERC721/ERC721LazyMint.t.sol +++ b/test/tokens/ERC721/ERC721LazyMint.t.sol @@ -44,8 +44,8 @@ contract ERC721LazyMint__initialize is Setup { erc721LazyMint.initialize(creator, "Name", "Symbol", creator, uint16(tenPercentBPS), ""); } - function test_sets_minter_role_and_global_when_passed_encoded_data() public { - bytes memory data = abi.encode(other, globals); + function test_sets_minter_role_when_passed_encoded_data() public { + bytes memory data = abi.encode(other); erc721LazyMint = new ERC721LazyMintMock( "Name", "Symbol", @@ -55,11 +55,10 @@ contract ERC721LazyMint__initialize is Setup { ); assertTrue(erc721LazyMint.hasRole(MINTER_ROLE, other)); - assertEq(erc721LazyMint._globals(), globals); } function test_does_not_grant_minter_role_when_passed_encoded_zero_address() public { - bytes memory data = abi.encode(address(0), globals); + bytes memory data = abi.encode(address(0)); erc721LazyMint = new ERC721LazyMintMock( "Name", "Symbol", @@ -71,7 +70,7 @@ contract ERC721LazyMint__initialize is Setup { assertFalse(erc721LazyMint.hasRole(MINTER_ROLE, address(0))); } - function test_minter_role_and_globals_are_set_with_extra_data() public { + function test_minter_role_are_set_with_extra_data() public { bytes memory data = abi.encode(other, globals, 12356789); erc721LazyMint = new ERC721LazyMintMock( @@ -83,7 +82,6 @@ contract ERC721LazyMint__initialize is Setup { ); assertTrue(erc721LazyMint.hasRole(MINTER_ROLE, other)); - assertEq(erc721LazyMint._globals(), globals); } } From 26f21267e3b0f0159594af8955d02467c5b6f85d Mon Sep 17 00:00:00 2001 From: george-openformat Date: Tue, 13 Aug 2024 13:04:41 +0100 Subject: [PATCH 08/11] feat: add update script --- scripts/facet/ERC721LazyDropFacet.s.sol | 31 +++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/scripts/facet/ERC721LazyDropFacet.s.sol b/scripts/facet/ERC721LazyDropFacet.s.sol index 8a214d6..380c125 100644 --- a/scripts/facet/ERC721LazyDropFacet.s.sol +++ b/scripts/facet/ERC721LazyDropFacet.s.sol @@ -42,3 +42,34 @@ contract Deploy is Script, Utils { exportContractDeployment(CONTRACT_NAME, address(erc721LazyDropFacet), block.number); } } + +contract Update is Script, Utils { + function run() external { + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + + // deploy + ERC721LazyDropFacet erc721LazyDropFacet = new ERC721LazyDropFacet(); + + // construct array of function selectors + bytes4[] memory selectors = new bytes4[](5); + selectors[0] = erc721LazyDropFacet.ERC721LazyDrop_getClaimCondition.selector; + selectors[1] = erc721LazyDropFacet.ERC721LazyDrop_verifyClaim.selector; + selectors[2] = erc721LazyDropFacet.ERC721LazyDrop_claim.selector; + selectors[3] = erc721LazyDropFacet.ERC721LazyDrop_setClaimCondition.selector; + selectors[4] = erc721LazyDropFacet.ERC721LazyDrop_removeClaimCondition.selector; + + // construct and ADD facet cut + IDiamondWritableInternal.FacetCut[] memory cuts = new IDiamondWritableInternal.FacetCut[](1); + cuts[0] = IDiamondWritableInternal.FacetCut( + address(erc721LazyDropFacet), IDiamondWritableInternal.FacetCutAction.REPLACE, selectors + ); + + // add to registry + RegistryMock(payable(getContractDeploymentAddress("Registry"))).diamondCut(cuts, address(0), ""); + + vm.stopBroadcast(); + + exportContractDeployment(CONTRACT_NAME, address(erc721LazyDropFacet), block.number); + } +} From 9d14a2a6896d7404921cf865f342ce576cd21a0f Mon Sep 17 00:00:00 2001 From: george-openformat Date: Tue, 13 Aug 2024 14:28:56 +0100 Subject: [PATCH 09/11] feat: add update script to remove platform and application fees --- scripts/facet/SettingsFacet.s.sol | 62 +++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/scripts/facet/SettingsFacet.s.sol b/scripts/facet/SettingsFacet.s.sol index f31185f..210d346 100644 --- a/scripts/facet/SettingsFacet.s.sol +++ b/scripts/facet/SettingsFacet.s.sol @@ -21,14 +21,10 @@ contract Deploy is Script, Utils { SettingsFacet settingsFacet = new SettingsFacet(); // construct array of function selectors - bytes4[] memory selectors = new bytes4[](7); - selectors[0] = settingsFacet.setApplicationFee.selector; - selectors[1] = settingsFacet.setAcceptedCurrencies.selector; - selectors[2] = settingsFacet.applicationFeeInfo.selector; - selectors[3] = settingsFacet.setCreatorAccess.selector; - selectors[4] = settingsFacet.hasCreatorAccess.selector; - selectors[5] = settingsFacet.platformFeeInfo.selector; - selectors[6] = settingsFacet.getGlobalsAddress.selector; + bytes4[] memory selectors = new bytes4[](3); + selectors[0] = settingsFacet.setCreatorAccess.selector; + selectors[1] = settingsFacet.hasCreatorAccess.selector; + selectors[2] = settingsFacet.getGlobalsAddress.selector; // construct and ADD facet cut IDiamondWritableInternal.FacetCut[] memory cuts = new IDiamondWritableInternal.FacetCut[](1); @@ -82,15 +78,15 @@ contract Update_ExposeGlobals is Script, Utils { // construct array of function selectors to replace // keeping it neat having all selectors point to the latest deployment bytes4[] memory replaceSelectors = new bytes4[](5); - replaceSelectors[0] = settingsFacet.setApplicationFee.selector; - replaceSelectors[1] = settingsFacet.setAcceptedCurrencies.selector; - replaceSelectors[2] = settingsFacet.applicationFeeInfo.selector; + replaceSelectors[0] = bytes4(keccak256(bytes("setApplicationFee(uint16,address)"))); + replaceSelectors[1] = bytes4(keccak256(bytes("setAcceptedCurrencies(address[],bool[])"))); + replaceSelectors[2] = bytes4(keccak256(bytes("applicationFeeInfo(uint256)"))); replaceSelectors[3] = settingsFacet.setCreatorAccess.selector; replaceSelectors[4] = settingsFacet.hasCreatorAccess.selector; // add globals bytes4[] memory addSelectors = new bytes4[](2); - addSelectors[0] = settingsFacet.platformFeeInfo.selector; + addSelectors[0] = bytes4(keccak256(bytes("platformFeeInfo(uint256)"))); addSelectors[1] = settingsFacet.getGlobalsAddress.selector; // construct REPLACE and ADD facet cuts @@ -109,3 +105,45 @@ contract Update_ExposeGlobals is Script, Utils { exportContractDeployment(CONTRACT_NAME, address(settingsFacet), block.number); } } + +/** + * @dev updates settings facet to remove platform and application fee logic + */ +contract Update_Remove_Platform_and_Application_Fees is Script, Utils { + function run() external { + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + + // deploy + SettingsFacet settingsFacet = new SettingsFacet(); + + // construct array of function selectors to remove + bytes4[] memory removeSelectors = new bytes4[](4); + removeSelectors[0] = bytes4(keccak256(bytes("platformFeeInfo(uint256)"))); + removeSelectors[1] = bytes4(keccak256(bytes("setApplicationFee(uint16,address)"))); + removeSelectors[2] = bytes4(keccak256(bytes("applicationFeeInfo(uint256)"))); + removeSelectors[3] = bytes4(keccak256(bytes("setAcceptedCurrencies(address[],bool[])"))); + + // construct array of function selectors to replace + bytes4[] memory replaceSelectors = new bytes4[](3); + replaceSelectors[0] = settingsFacet.setCreatorAccess.selector; + replaceSelectors[1] = settingsFacet.hasCreatorAccess.selector; + replaceSelectors[2] = settingsFacet.getGlobalsAddress.selector; + + // construct and perform facet cut + IDiamondWritableInternal.FacetCut[] memory cuts = new IDiamondWritableInternal.FacetCut[](2); + cuts[0] = IDiamondWritableInternal.FacetCut( + address(0), IDiamondWritableInternal.FacetCutAction.REMOVE, removeSelectors + ); + cuts[1] = IDiamondWritableInternal.FacetCut( + address(settingsFacet), IDiamondWritableInternal.FacetCutAction.REPLACE, replaceSelectors + ); + + // add to registry + RegistryMock(payable(getContractDeploymentAddress("Registry"))).diamondCut(cuts, address(0), ""); + + vm.stopBroadcast(); + + exportContractDeployment(CONTRACT_NAME, address(settingsFacet), block.number); + } +} From 83febd43e04323d1628e1fcdf1577a39ce9863cb Mon Sep 17 00:00:00 2001 From: george-openformat Date: Tue, 13 Aug 2024 15:04:35 +0100 Subject: [PATCH 10/11] feat: script to remove application and platform fees --- Makefile | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 052415e..ef510df 100644 --- a/Makefile +++ b/Makefile @@ -184,13 +184,32 @@ update:; make \ # update update-ERC721FactoryFacet:; forge script scripts/facet/ERC721FactoryFacet.s.sol:Update --rpc-url $(rpc) --broadcast $(verbose) $(legacy) $(slow) update-ERC20FactoryFacet:; forge script scripts/facet/ERC20FactoryFacet.s.sol:Update --rpc-url $(rpc) --broadcast $(verbose) $(legacy) $(slow) +update-ERC721LazyDropFacet:; forge script scripts/facet/ERC721LazyDropFacet.s.sol:Update --rpc-url $(rpc) --broadcast $(verbose) $(legacy) $(slow) +update-RewardsFacet:; forge script scripts/facet/RewardsFacet.s.sol:Update --rpc-url $(rpc) --broadcast $(verbose) $(legacy) $(slow) + +# Remove application and platform fees +# Updates all effected facet contracts with specific script for SettingsFacet +# Redeploys Token contracts to remove fee logic from minting +# Date (not run yet) +update-removeApplicationAndPlatformFees:; make \ + update-SettingsFacet-removeAppAndPlatformFees \ + update-ERC721FactoryFacet \ + update-ERC20FactoryFacet \ + update-RewardsFacet \ + update-ERC721LazyDropFacet \ + deploy-ERC20Base \ + deploy-ERC721Base \ + deploy-ERC721Badge \ + deploy-ERC721LazyMint + +update-SettingsFacet-removeAppAndPlatformFees:; forge script scripts/facet/SettingsFacet.s.sol:Update_Remove_Platform_and_Application_Fees --rpc-url $(rpc) --broadcast $(verbose) $(legacy) $(slow) # Add badge minting functionality # Date 20.05.24 # updates ERC721RewardFacet to update mintERC721 function and add mintBadge and batchMintBadge functions # deploys and registers RewardsFacet contract # PR #126 https://github.com/open-format/contracts/pull/126 -update-RewardsFacet:; forge script scripts/facet/RewardsFacet.s.sol:Update_Add_badgeMintingFunctionality --rpc-url $(rpc) --broadcast $(verbose) $(legacy) $(slow) +update-RewardsFacet-add-badgeMintingFunctionality:; forge script scripts/facet/RewardsFacet.s.sol:Update_Add_badgeMintingFunctionality --rpc-url $(rpc) --broadcast $(verbose) $(legacy) $(slow) # Add ERC721Badge contract # Date 14.05.24 From 2819e111b489310420637b2271d6c7caa57574cc Mon Sep 17 00:00:00 2001 From: george-openformat Date: Tue, 13 Aug 2024 15:32:48 +0100 Subject: [PATCH 11/11] remove code owners --- .github/CODEOWNERS | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index 10dc254..0000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -* @tinypell3ts \ No newline at end of file