From 5a5184e2f524c810e2b75bfc020ae5c4b4e07418 Mon Sep 17 00:00:00 2001 From: Yash Date: Mon, 9 Oct 2023 20:21:56 +0530 Subject: [PATCH 1/3] sync extensions --- contracts/extension/BurnToClaim.sol | 8 ++-- contracts/extension/PlatformFee.sol | 5 +- contracts/extension/PrimarySale.sol | 3 ++ .../extension/upgradeable/PlatformFee.sol | 46 +++++++++++++++++++ 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/contracts/extension/BurnToClaim.sol b/contracts/extension/BurnToClaim.sol index cf5ae639c..72406dda7 100644 --- a/contracts/extension/BurnToClaim.sol +++ b/contracts/extension/BurnToClaim.sol @@ -17,6 +17,8 @@ abstract contract BurnToClaim is IBurnToClaim { function setBurnToClaimInfo(BurnToClaimInfo calldata _burnToClaimInfo) external virtual { require(_canSetBurnToClaim(), "Not authorized."); + require(_burnToClaimInfo.originContractAddress != address(0), "Origin contract not set."); + require(_burnToClaimInfo.currency != address(0), "Currency not set."); burnToClaimInfo = _burnToClaimInfo; } @@ -30,12 +32,12 @@ abstract contract BurnToClaim is IBurnToClaim { if (_burnToClaimInfo.tokenType == IBurnToClaim.TokenType.ERC721) { require(_quantity == 1, "Invalid amount"); - require(IERC721(_burnToClaimInfo.originContractAddress).ownerOf(_tokenId) == _tokenOwner); + require(IERC721(_burnToClaimInfo.originContractAddress).ownerOf(_tokenId) == _tokenOwner, "!Owner"); } else if (_burnToClaimInfo.tokenType == IBurnToClaim.TokenType.ERC1155) { uint256 _eligible1155TokenId = _burnToClaimInfo.tokenId; - require(_tokenId == _eligible1155TokenId || _eligible1155TokenId == type(uint256).max); - require(IERC1155(_burnToClaimInfo.originContractAddress).balanceOf(_tokenOwner, _tokenId) >= _quantity); + require(_tokenId == _eligible1155TokenId, "Invalid token Id"); + require(IERC1155(_burnToClaimInfo.originContractAddress).balanceOf(_tokenOwner, _tokenId) >= _quantity, "!Balance"); } // TODO: check if additional verification steps are required / override in main contract diff --git a/contracts/extension/PlatformFee.sol b/contracts/extension/PlatformFee.sol index d3152a7e5..5f3bdca9d 100644 --- a/contracts/extension/PlatformFee.sol +++ b/contracts/extension/PlatformFee.sol @@ -35,7 +35,7 @@ abstract contract PlatformFee is IPlatformFee { return (platformFeeRecipient, flatPlatformFee); } - /// @dev Returns the platform fee bps and recipient. + /// @dev Returns the platform fee type. function getPlatformFeeType() public view returns (PlatformFeeType) { return platformFeeType; } @@ -61,6 +61,9 @@ abstract contract PlatformFee is IPlatformFee { if (_platformFeeBps > 10_000) { revert("Exceeds max bps"); } + if (_platformFeeRecipient == address(0)) { + revert("Invalid recipient"); + } platformFeeBps = uint16(_platformFeeBps); platformFeeRecipient = _platformFeeRecipient; diff --git a/contracts/extension/PrimarySale.sol b/contracts/extension/PrimarySale.sol index 598645c93..551607e13 100644 --- a/contracts/extension/PrimarySale.sol +++ b/contracts/extension/PrimarySale.sol @@ -38,6 +38,9 @@ abstract contract PrimarySale is IPrimarySale { /// @dev Lets a contract admin set the recipient for all primary sales. function _setupPrimarySaleRecipient(address _saleRecipient) internal { + if (_saleRecipient == address(0)) { + revert("Invalid recipient"); + } recipient = _saleRecipient; emit PrimarySaleRecipientUpdated(_saleRecipient); } diff --git a/contracts/extension/upgradeable/PlatformFee.sol b/contracts/extension/upgradeable/PlatformFee.sol index 89b4fd32b..6b9e9ef21 100644 --- a/contracts/extension/upgradeable/PlatformFee.sol +++ b/contracts/extension/upgradeable/PlatformFee.sol @@ -19,6 +19,10 @@ library PlatformFeeStorage { address platformFeeRecipient; /// @dev The % of primary sales collected as platform fees. uint16 platformFeeBps; + /// @dev Fee type variants: percentage fee and flat fee + IPlatformFee.PlatformFeeType platformFeeType; + /// @dev The flat amount collected by the contract as fees on primary sales. + uint256 flatPlatformFee; } function data() internal pure returns (Data storage data_) { @@ -44,6 +48,16 @@ abstract contract PlatformFee is IPlatformFee { return (_platformFeeStorage().platformFeeRecipient, uint16(_platformFeeStorage().platformFeeBps)); } + /// @dev Returns the platform fee bps and recipient. + function getFlatPlatformFeeInfo() public view returns (address, uint256) { + return (_platformFeeStorage().platformFeeRecipient, _platformFeeStorage().flatPlatformFee); + } + + /// @dev Returns the platform fee type. + function getPlatformFeeType() public view returns (PlatformFeeType) { + return _platformFeeStorage().platformFeeType; + } + /** * @notice Updates the platform fee recipient and bps. * @dev Caller should be authorized to set platform fee info. @@ -75,6 +89,38 @@ abstract contract PlatformFee is IPlatformFee { emit PlatformFeeInfoUpdated(_platformFeeRecipient, _platformFeeBps); } + /// @notice Lets a module admin set a flat fee on primary sales. + function setFlatPlatformFeeInfo(address _platformFeeRecipient, uint256 _flatFee) external { + if (!_canSetPlatformFeeInfo()) { + revert("Not authorized"); + } + + _setupFlatPlatformFeeInfo(_platformFeeRecipient, _flatFee); + } + + /// @dev Sets a flat fee on primary sales. + function _setupFlatPlatformFeeInfo(address _platformFeeRecipient, uint256 _flatFee) internal { + _platformFeeStorage().flatPlatformFee = _flatFee; + _platformFeeStorage().platformFeeRecipient = _platformFeeRecipient; + + emit FlatPlatformFeeUpdated(_platformFeeRecipient, _flatFee); + } + + /// @notice Lets a module admin set platform fee type. + function setPlatformFeeType(PlatformFeeType _feeType) external { + if (!_canSetPlatformFeeInfo()) { + revert("Not authorized"); + } + _setupPlatformFeeType(_feeType); + } + + /// @dev Sets platform fee type. + function _setupPlatformFeeType(PlatformFeeType _feeType) internal { + _platformFeeStorage().platformFeeType = _feeType; + + emit PlatformFeeTypeUpdated(_feeType); + } + /// @dev Returns the PlatformFee storage. function _platformFeeStorage() internal pure returns (PlatformFeeStorage.Data storage data) { data = PlatformFeeStorage.data(); From c381c0bb4a0a493e41571999972249b22ee41774 Mon Sep 17 00:00:00 2001 From: Yash Date: Mon, 9 Oct 2023 20:26:55 +0530 Subject: [PATCH 2/3] prettier --- contracts/extension/BurnToClaim.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/extension/BurnToClaim.sol b/contracts/extension/BurnToClaim.sol index 72406dda7..0d1490c56 100644 --- a/contracts/extension/BurnToClaim.sol +++ b/contracts/extension/BurnToClaim.sol @@ -37,7 +37,10 @@ abstract contract BurnToClaim is IBurnToClaim { uint256 _eligible1155TokenId = _burnToClaimInfo.tokenId; require(_tokenId == _eligible1155TokenId, "Invalid token Id"); - require(IERC1155(_burnToClaimInfo.originContractAddress).balanceOf(_tokenOwner, _tokenId) >= _quantity, "!Balance"); + require( + IERC1155(_burnToClaimInfo.originContractAddress).balanceOf(_tokenOwner, _tokenId) >= _quantity, + "!Balance" + ); } // TODO: check if additional verification steps are required / override in main contract From 91234989a12ef887c059f54a0d41c21110b73ab8 Mon Sep 17 00:00:00 2001 From: Krishang Date: Tue, 17 Oct 2023 01:47:05 +0530 Subject: [PATCH 3/3] SignatureDrop uses legacy PlatformFee and PrimarySale --- .../extension/PlatformFee_V1.sol | 105 ++++++++++++++++++ .../extension/PrimarySale_V1.sol | 47 ++++++++ .../extension/interface/IPlatformFee_V1.sol | 33 ++++++ .../extension/interface/IPrimarySale_V1.sol | 21 ++++ .../signature-drop/SignatureDrop.sol | 4 +- foundry.toml | 2 +- 6 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 contracts/legacy-contracts/extension/PlatformFee_V1.sol create mode 100644 contracts/legacy-contracts/extension/PrimarySale_V1.sol create mode 100644 contracts/legacy-contracts/extension/interface/IPlatformFee_V1.sol create mode 100644 contracts/legacy-contracts/extension/interface/IPrimarySale_V1.sol diff --git a/contracts/legacy-contracts/extension/PlatformFee_V1.sol b/contracts/legacy-contracts/extension/PlatformFee_V1.sol new file mode 100644 index 000000000..9014b7dca --- /dev/null +++ b/contracts/legacy-contracts/extension/PlatformFee_V1.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +/// @author thirdweb + +import "./interface/IPlatformFee_V1.sol"; + +/** + * @title Platform Fee + * @notice Thirdweb's `PlatformFee` is a contract extension to be used with any base contract. It exposes functions for setting and reading + * the recipient of platform fee and the platform fee basis points, and lets the inheriting contract perform conditional logic + * that uses information about platform fees, if desired. + */ + +abstract contract PlatformFee is IPlatformFee { + /// @dev The address that receives all platform fees from all sales. + address private platformFeeRecipient; + + /// @dev The % of primary sales collected as platform fees. + uint16 private platformFeeBps; + + /// @dev Fee type variants: percentage fee and flat fee + PlatformFeeType private platformFeeType; + + /// @dev The flat amount collected by the contract as fees on primary sales. + uint256 private flatPlatformFee; + + /// @dev Returns the platform fee recipient and bps. + function getPlatformFeeInfo() public view override returns (address, uint16) { + return (platformFeeRecipient, uint16(platformFeeBps)); + } + + /// @dev Returns the platform fee bps and recipient. + function getFlatPlatformFeeInfo() public view returns (address, uint256) { + return (platformFeeRecipient, flatPlatformFee); + } + + /// @dev Returns the platform fee bps and recipient. + function getPlatformFeeType() public view returns (PlatformFeeType) { + return platformFeeType; + } + + /** + * @notice Updates the platform fee recipient and bps. + * @dev Caller should be authorized to set platform fee info. + * See {_canSetPlatformFeeInfo}. + * Emits {PlatformFeeInfoUpdated Event}; See {_setupPlatformFeeInfo}. + * + * @param _platformFeeRecipient Address to be set as new platformFeeRecipient. + * @param _platformFeeBps Updated platformFeeBps. + */ + function setPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) external override { + if (!_canSetPlatformFeeInfo()) { + revert("Not authorized"); + } + _setupPlatformFeeInfo(_platformFeeRecipient, _platformFeeBps); + } + + /// @dev Sets the platform fee recipient and bps + function _setupPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) internal { + if (_platformFeeBps > 10_000) { + revert("Exceeds max bps"); + } + + platformFeeBps = uint16(_platformFeeBps); + platformFeeRecipient = _platformFeeRecipient; + + emit PlatformFeeInfoUpdated(_platformFeeRecipient, _platformFeeBps); + } + + /// @notice Lets a module admin set a flat fee on primary sales. + function setFlatPlatformFeeInfo(address _platformFeeRecipient, uint256 _flatFee) external { + if (!_canSetPlatformFeeInfo()) { + revert("Not authorized"); + } + + _setupFlatPlatformFeeInfo(_platformFeeRecipient, _flatFee); + } + + /// @dev Sets a flat fee on primary sales. + function _setupFlatPlatformFeeInfo(address _platformFeeRecipient, uint256 _flatFee) internal { + flatPlatformFee = _flatFee; + platformFeeRecipient = _platformFeeRecipient; + + emit FlatPlatformFeeUpdated(_platformFeeRecipient, _flatFee); + } + + /// @notice Lets a module admin set platform fee type. + function setPlatformFeeType(PlatformFeeType _feeType) external { + if (!_canSetPlatformFeeInfo()) { + revert("Not authorized"); + } + _setupPlatformFeeType(_feeType); + } + + /// @dev Sets platform fee type. + function _setupPlatformFeeType(PlatformFeeType _feeType) internal { + platformFeeType = _feeType; + + emit PlatformFeeTypeUpdated(_feeType); + } + + /// @dev Returns whether platform fee info can be set in the given execution context. + function _canSetPlatformFeeInfo() internal view virtual returns (bool); +} diff --git a/contracts/legacy-contracts/extension/PrimarySale_V1.sol b/contracts/legacy-contracts/extension/PrimarySale_V1.sol new file mode 100644 index 000000000..8536c9724 --- /dev/null +++ b/contracts/legacy-contracts/extension/PrimarySale_V1.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +/// @author thirdweb + +import "./interface/IPrimarySale_V1.sol"; + +/** + * @title Primary Sale + * @notice Thirdweb's `PrimarySale` is a contract extension to be used with any base contract. It exposes functions for setting and reading + * the recipient of primary sales, and lets the inheriting contract perform conditional logic that uses information about + * primary sales, if desired. + */ + +abstract contract PrimarySale is IPrimarySale { + /// @dev The address that receives all primary sales value. + address private recipient; + + /// @dev Returns primary sale recipient address. + function primarySaleRecipient() public view override returns (address) { + return recipient; + } + + /** + * @notice Updates primary sale recipient. + * @dev Caller should be authorized to set primary sales info. + * See {_canSetPrimarySaleRecipient}. + * Emits {PrimarySaleRecipientUpdated Event}; See {_setupPrimarySaleRecipient}. + * + * @param _saleRecipient Address to be set as new recipient of primary sales. + */ + function setPrimarySaleRecipient(address _saleRecipient) external override { + if (!_canSetPrimarySaleRecipient()) { + revert("Not authorized"); + } + _setupPrimarySaleRecipient(_saleRecipient); + } + + /// @dev Lets a contract admin set the recipient for all primary sales. + function _setupPrimarySaleRecipient(address _saleRecipient) internal { + recipient = _saleRecipient; + emit PrimarySaleRecipientUpdated(_saleRecipient); + } + + /// @dev Returns whether primary sale recipient can be set in the given execution context. + function _canSetPrimarySaleRecipient() internal view virtual returns (bool); +} diff --git a/contracts/legacy-contracts/extension/interface/IPlatformFee_V1.sol b/contracts/legacy-contracts/extension/interface/IPlatformFee_V1.sol new file mode 100644 index 000000000..1a1fc778a --- /dev/null +++ b/contracts/legacy-contracts/extension/interface/IPlatformFee_V1.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +/// @author thirdweb + +/** + * Thirdweb's `PlatformFee` is a contract extension to be used with any base contract. It exposes functions for setting and reading + * the recipient of platform fee and the platform fee basis points, and lets the inheriting contract perform conditional logic + * that uses information about platform fees, if desired. + */ + +interface IPlatformFee { + /// @dev Fee type variants: percentage fee and flat fee + enum PlatformFeeType { + Bps, + Flat + } + + /// @dev Returns the platform fee bps and recipient. + function getPlatformFeeInfo() external view returns (address, uint16); + + /// @dev Lets a module admin update the fees on primary sales. + function setPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) external; + + /// @dev Emitted when fee on primary sales is updated. + event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps); + + /// @dev Emitted when the flat platform fee is updated. + event FlatPlatformFeeUpdated(address platformFeeRecipient, uint256 flatFee); + + /// @dev Emitted when the platform fee type is updated. + event PlatformFeeTypeUpdated(PlatformFeeType feeType); +} diff --git a/contracts/legacy-contracts/extension/interface/IPrimarySale_V1.sol b/contracts/legacy-contracts/extension/interface/IPrimarySale_V1.sol new file mode 100644 index 000000000..6ca726842 --- /dev/null +++ b/contracts/legacy-contracts/extension/interface/IPrimarySale_V1.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +/// @author thirdweb + +/** + * Thirdweb's `Primary` is a contract extension to be used with any base contract. It exposes functions for setting and reading + * the recipient of primary sales, and lets the inheriting contract perform conditional logic that uses information about + * primary sales, if desired. + */ + +interface IPrimarySale { + /// @dev The adress that receives all primary sales value. + function primarySaleRecipient() external view returns (address); + + /// @dev Lets a module admin set the default recipient of all primary sales. + function setPrimarySaleRecipient(address _saleRecipient) external; + + /// @dev Emitted when a new sale recipient is set. + event PrimarySaleRecipientUpdated(address indexed recipient); +} diff --git a/contracts/prebuilts/signature-drop/SignatureDrop.sol b/contracts/prebuilts/signature-drop/SignatureDrop.sol index 13f65fb7b..98b464fe3 100644 --- a/contracts/prebuilts/signature-drop/SignatureDrop.sol +++ b/contracts/prebuilts/signature-drop/SignatureDrop.sol @@ -28,9 +28,9 @@ import "../../lib/CurrencyTransferLib.sol"; // ========== Features ========== import "../../extension/ContractMetadata.sol"; -import "../../extension/PlatformFee.sol"; +import "../../legacy-contracts/extension/PlatformFee_V1.sol"; import "../../extension/Royalty.sol"; -import "../../extension/PrimarySale.sol"; +import "../../legacy-contracts/extension/PrimarySale_V1.sol"; import "../../extension/Ownable.sol"; import "../../extension/DelayedReveal.sol"; import "../../extension/LazyMint.sol"; diff --git a/foundry.toml b/foundry.toml index 406a17df9..8a646b446 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,7 +2,7 @@ solc-version = "0.8.12" #auto_detect_solc = false cache = true -evm_version = 'london' +evm_version = 'shanghai' force = false gas_reports = [ "DropERC721Benchmark",