Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
129 commits
Select commit Hold shift + click to select a range
be423e1
first pass at extension interfaces
Sep 14, 2022
d7818f5
forge updates
Sep 23, 2022
0d1f4ca
merge main -> this
Sep 23, 2022
2d37c82
DirectListings extension WIP
Sep 23, 2022
7347fb0
english auction
kumaryash90 Sep 28, 2022
e1fb0c1
wip Offers.sol
kumaryash90 Sep 29, 2022
76c9b3e
getOffers
kumaryash90 Sep 29, 2022
866fc8c
getOffers update
kumaryash90 Sep 30, 2022
548abbe
update DirectListings
kumaryash90 Oct 3, 2022
f30fcad
update interfaces
kumaryash90 Oct 3, 2022
dbf23e6
optimize
kumaryash90 Oct 3, 2022
0602c52
optimize
kumaryash90 Oct 3, 2022
be48cdf
Format DirectListings in library storage code pattern
Oct 3, 2022
3d3f2ae
DirectListings timestamps
kumaryash90 Oct 4, 2022
908e7cd
Offers: library storage pattern
kumaryash90 Oct 4, 2022
6153b22
EnglishAuctions: library storage pattern
kumaryash90 Oct 4, 2022
6192e70
marketplace implementation
kumaryash90 Oct 6, 2022
1ea472f
forge update
Oct 10, 2022
cbb25c6
pull from origin
Oct 10, 2022
bd0bbaf
WIP Marketplace entrypoint
Oct 10, 2022
a0cf1f0
Inherit relevant extensions in entrypoint
Oct 11, 2022
d5b83cd
Add fallback logic to entrypoint
Oct 11, 2022
914de3d
rename extensions -> extension
Oct 11, 2022
b801545
Write funcSig -> ext address Map contract
Oct 11, 2022
2b695d5
Fix compilation errors
Oct 11, 2022
84985ef
run prettier
Oct 11, 2022
60875e9
merge origin main -> this
Oct 11, 2022
938031a
remove unused Context
Oct 11, 2022
5070163
Cleanup extensions inherited by entrypoint
Oct 11, 2022
bc98bf6
replace IContext with ERC2771ContextConsumer
Oct 11, 2022
274621f
Fix typos lisiting -> listing
Oct 12, 2022
8de8c93
use platform fee extension in DirectListings
Oct 12, 2022
4ec3113
add totalListings to IDirectListings
Oct 12, 2022
0e79cf6
Create DirectListings test
Oct 12, 2022
949aea6
Add totalAuctions view fn to EnglishAuctions
Oct 12, 2022
5274d76
remove redundant native token from Offers
Oct 12, 2022
67c69a3
remove PlatformFee from marketplace extensions storage
Oct 13, 2022
429677f
Marketplace tests scaffolding
Oct 13, 2022
d5ebcc0
DirectListings: add createListing tests
Oct 13, 2022
678533d
DirectListings: add updateListing tests
Oct 13, 2022
1820b26
DirectListings: add cancelListing tests
Oct 13, 2022
67060cf
Use modifier in approveCurrencyForListing
Oct 13, 2022
2299d5e
DirectListings: add approveBuyerForListing tests
Oct 14, 2022
444d14a
DirectListings: add view fns for mappings in state
Oct 14, 2022
9b01fd2
DirectListings: add approveCurrencyForListing tests
Oct 14, 2022
4fdb548
DirectListings fix: provide expected currency and total price in buyF…
Oct 14, 2022
f8b1895
DirectListings fix: startTimestamps are inclusive
Oct 14, 2022
9b46f92
DirectListings: add buyFromListing tests
Oct 14, 2022
7a02c7c
cannot fuzz view fns quick enough
Oct 14, 2022
3620200
EnglishAuctions: add createAuction tests
kumaryash90 Oct 17, 2022
7363462
EnglishAuctions: cancel auctions only when no bids
kumaryash90 Oct 17, 2022
fedf0dd
EnglishAuctions: correct timestamps
kumaryash90 Oct 17, 2022
e188a7e
EnglishAuctions: add tests for cancelAuction
kumaryash90 Oct 17, 2022
0c46890
EnglishAuctions: add tests for bidInAuction
kumaryash90 Oct 17, 2022
0964e5a
EnglishAuctions: add tests for collectAuctionPayout and collectAuctio…
kumaryash90 Oct 17, 2022
d067ba8
EnglishAuctions: tests for view functions
kumaryash90 Oct 17, 2022
f04d47a
Offers: tests for makeOffer
kumaryash90 Oct 18, 2022
c3336ef
Offers: tests for cancelOffer
kumaryash90 Oct 18, 2022
11fa7dc
Offers: change payout to currencyTransferWithWrapper
kumaryash90 Oct 18, 2022
a9feee3
Offers: tests for acceptOffer
kumaryash90 Oct 18, 2022
f823485
correct timestamps
kumaryash90 Oct 18, 2022
9ac14ea
Offers: tests for view functions
kumaryash90 Oct 18, 2022
360b228
remove regular implementations of extensions
Oct 18, 2022
5042716
Update require statement
Oct 19, 2022
f928941
Give startTimestamp a 1 hour buffer
Oct 19, 2022
34e9045
Cleanup: createListing related logic
Oct 19, 2022
8b72d3c
cleanup require statments
Oct 19, 2022
e7a0e66
update comments for updateListing
Oct 19, 2022
6443f9a
cleanup DirectListings
Oct 19, 2022
fa0e4ae
Cleanup directlistings file
Oct 19, 2022
9771288
Add rest of the code comments to IMarketplace
Oct 19, 2022
2ec5bbc
remove updateAuction
Oct 19, 2022
083a7b6
Cleanup EnglishAuctions
Oct 19, 2022
6ae08eb
DirectListings: use onlyExistingListing modifier in getListing
kumaryash90 Oct 19, 2022
f4c2496
consistent behavior of getAll.. functions
kumaryash90 Oct 19, 2022
16e7990
wip cleanup Offers
Oct 19, 2022
27a461f
cleanup offers
Oct 20, 2022
3094088
Fix DirectListings tests
Oct 20, 2022
8fbc1fc
Fix EnglighAuctions test
Oct 20, 2022
5464feb
Fix Offers tests
Oct 20, 2022
98002ac
re-organize marketplace files
Oct 20, 2022
38df194
docs update
Oct 20, 2022
95779df
pull from origin
Oct 20, 2022
9d238b5
docs update
Oct 20, 2022
e86184d
pkg bump
Oct 20, 2022
3549c8c
pkg release
Oct 21, 2022
965ce0b
merge main -> this
nkrishang Nov 7, 2022
c12591c
Fix: (C-1) Marketplace funds can be drained due to lack of auction pa…
nkrishang Nov 7, 2022
ac92985
Fix: (C-4) Auction token collection not tracked enables stealing ERC-…
nkrishang Nov 7, 2022
f27e825
Already fixed: (C-3) Auction creator collecting payout causes buyer t…
nkrishang Nov 7, 2022
85bb739
Fix: (C-2) Unsafe listing update allows seller front-run to buyer pur…
nkrishang Nov 7, 2022
56b288a
patch tests
nkrishang Nov 7, 2022
4f65acb
update forge
kumaryash90 Nov 15, 2022
2a7f026
(M-1) setExtension allows selector clashes enables incorrect select→e…
kumaryash90 Nov 15, 2022
9a61ca8
(L-1), (L-2) - fix timestamps
kumaryash90 Nov 15, 2022
552fbe2
(L-3) Buyer can overpay when using buy out option
kumaryash90 Nov 15, 2022
5e9f3bb
(L-4) Off-chain application might block itself from buying listing
kumaryash90 Nov 16, 2022
e85243a
(Q-1) _validateOwnershipAndApproval is not needed for creating auctions
kumaryash90 Nov 16, 2022
d14d82e
(Q-2) Unused state variable
kumaryash90 Nov 16, 2022
1e3fe14
Nitpicks: Validate bid amounts inside _validateNewAuction()
kumaryash90 Nov 16, 2022
0ec8694
docs
kumaryash90 Dec 1, 2022
a6bb51b
v3.3.0-1
kumaryash90 Dec 1, 2022
5d56d32
merge main
kumaryash90 Dec 1, 2022
a73e3e4
v3.3.0-2
kumaryash90 Dec 1, 2022
d473cc5
revised fix: (L-4) Off-chain application might block itself from buyi…
kumaryash90 Dec 2, 2022
8b1a95a
test for fix: (M-1) setExtension allows selector clashes enables inco…
kumaryash90 Dec 2, 2022
0f385c0
merge main
kumaryash90 Dec 25, 2022
298316f
update version
kumaryash90 Jan 2, 2023
94409ab
setup lister and asset roles in initialize
kumaryash90 Jan 3, 2023
2f01f03
merge main
kumaryash90 Jan 9, 2023
09d6d61
update marketplace-v3 with latest plugin pattern
kumaryash90 Jan 9, 2023
7a74bb1
docs
kumaryash90 Jan 10, 2023
bab7638
fix getters
kumaryash90 Jan 10, 2023
e86ad3a
v3.3.1-0
kumaryash90 Jan 10, 2023
a78a647
change contract-type to MarketplaceRouter
kumaryash90 Jan 13, 2023
299b4c8
v3.3.1-1
kumaryash90 Jan 13, 2023
c5c0bc0
forge update
kumaryash90 Jan 17, 2023
1bc7639
fix getters
kumaryash90 Jan 24, 2023
53d9871
v3.3.1-2
kumaryash90 Jan 24, 2023
0499420
add a status flag, remove deletion
kumaryash90 Jan 31, 2023
257144a
update tests, fix bugs
kumaryash90 Jan 31, 2023
53c77a4
v3.3.1-3
kumaryash90 Jan 31, 2023
d49d68c
update event params
kumaryash90 Feb 3, 2023
4c42175
merge main
kumaryash90 Feb 3, 2023
ccd7903
rename status DNE -> UNSET
kumaryash90 Feb 3, 2023
b1a313a
docs
kumaryash90 Feb 3, 2023
556ae4e
v3.3.3-0
kumaryash90 Feb 3, 2023
e2d9427
update events
kumaryash90 Feb 3, 2023
52b628a
rename to MarketplaceV3
kumaryash90 Feb 3, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions contracts/extension/plugin/ContractMetadataLogic.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import "./ContractMetadataStorage.sol";
import "../../extension/interface/IContractMetadata.sol";

/**
* @title Contract Metadata
* @notice Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI
* for you contract.
* Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea.
*/

abstract contract ContractMetadataLogic is IContractMetadata {
/// @dev Returns the metadata URI of the contract.
function contractURI() public view returns (string memory) {
ContractMetadataStorage.Data storage data = ContractMetadataStorage.contractMetadataStorage();
return data.contractURI;
}

/**
* @notice Lets a contract admin set the URI for contract-level metadata.
* @dev Caller should be authorized to setup contractURI, e.g. contract admin.
* See {_canSetContractURI}.
* Emits {ContractURIUpdated Event}.
*
* @param _uri keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
*/
function setContractURI(string memory _uri) external override {
if (!_canSetContractURI()) {
revert("Not authorized");
}

_setupContractURI(_uri);
}

/// @dev Lets a contract admin set the URI for contract-level metadata.
function _setupContractURI(string memory _uri) internal {
ContractMetadataStorage.Data storage data = ContractMetadataStorage.contractMetadataStorage();
string memory prevURI = data.contractURI;
data.contractURI = _uri;

emit ContractURIUpdated(prevURI, _uri);
}

/// @dev Returns whether contract metadata can be set in the given execution context.
function _canSetContractURI() internal view virtual returns (bool);
}
17 changes: 17 additions & 0 deletions contracts/extension/plugin/ContractMetadataStorage.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

library ContractMetadataStorage {
bytes32 public constant CONTRACT_METADATA_STORAGE_POSITION = keccak256("contract.metadata.storage");

struct Data {
string contractURI;
}

function contractMetadataStorage() internal pure returns (Data storage contractMetadataData) {
bytes32 position = CONTRACT_METADATA_STORAGE_POSITION;
assembly {
contractMetadataData.slot := position
}
}
}
45 changes: 45 additions & 0 deletions contracts/extension/plugin/ERC2771ContextUpgradeableLogic.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import "./ERC2771ContextStorage.sol";

/**
* @dev Context variant with ERC2771 support.
*/
abstract contract ERC2771ContextUpgradeableLogic {
function __ERC2771Context_init(address[] memory trustedForwarder) internal {
__ERC2771Context_init_unchained(trustedForwarder);
}

function __ERC2771Context_init_unchained(address[] memory trustedForwarder) internal {
ERC2771ContextStorage.Data storage data = ERC2771ContextStorage.erc2771ContextStorage();

for (uint256 i = 0; i < trustedForwarder.length; i++) {
data._trustedForwarder[trustedForwarder[i]] = true;
}
}

function isTrustedForwarder(address forwarder) public view virtual returns (bool) {
ERC2771ContextStorage.Data storage data = ERC2771ContextStorage.erc2771ContextStorage();
return data._trustedForwarder[forwarder];
}

function _msgSender() internal view virtual returns (address sender) {
if (isTrustedForwarder(msg.sender)) {
// The assembly code is more direct than the Solidity version using `abi.decode`.
assembly {
sender := shr(96, calldataload(sub(calldatasize(), 20)))
}
} else {
return msg.sender;
}
}

function _msgData() internal view virtual returns (bytes calldata) {
if (isTrustedForwarder(msg.sender)) {
return msg.data[:msg.data.length - 20];
} else {
return msg.data;
}
}
}
18 changes: 18 additions & 0 deletions contracts/extension/plugin/ERC2771ContextUpgradeableStorage.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

library ERC2771ContextUpgradeableStorage {
bytes32 public constant ERC2771_CONTEXT_UPGRADEABLE_STORAGE_POSITION =
keccak256("erc2771.context.upgradeable.storage");

struct Data {
mapping(address => bool) _trustedForwarder;
}

function erc2771ContextUpgradeableStorage() internal pure returns (Data storage erc2771ContextData) {
bytes32 position = ERC2771_CONTEXT_UPGRADEABLE_STORAGE_POSITION;
assembly {
erc2771ContextData.slot := position
}
}
}
52 changes: 52 additions & 0 deletions contracts/extension/plugin/PlatformFeeLogic.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import "./PlatformFeeStorage.sol";
import "../../extension/interface/IPlatformFee.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 PlatformFeeLogic is IPlatformFee {
/// @dev Returns the platform fee recipient and bps.
function getPlatformFeeInfo() public view override returns (address, uint16) {
PlatformFeeStorage.Data storage data = PlatformFeeStorage.platformFeeStorage();
return (data.platformFeeRecipient, uint16(data.platformFeeBps));
}

/**
* @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 Lets a contract admin update the platform fee recipient and bps
function _setupPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) internal {
PlatformFeeStorage.Data storage data = PlatformFeeStorage.platformFeeStorage();
if (_platformFeeBps > 10_000) {
revert("Exceeds max bps");
}

data.platformFeeBps = uint16(_platformFeeBps);
data.platformFeeRecipient = _platformFeeRecipient;

emit PlatformFeeInfoUpdated(_platformFeeRecipient, _platformFeeBps);
}

/// @dev Returns whether platform fee info can be set in the given execution context.
function _canSetPlatformFeeInfo() internal view virtual returns (bool);
}
20 changes: 20 additions & 0 deletions contracts/extension/plugin/PlatformFeeStorage.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

library PlatformFeeStorage {
bytes32 public constant PLATFORM_FEE_STORAGE_POSITION = keccak256("platform.fee.storage");

struct Data {
/// @dev The address that receives all platform fees from all sales.
address platformFeeRecipient;
/// @dev The % of primary sales collected as platform fees.
uint16 platformFeeBps;
}

function platformFeeStorage() internal pure returns (Data storage platformFeeData) {
bytes32 position = PLATFORM_FEE_STORAGE_POSITION;
assembly {
platformFeeData.slot := position
}
}
}
68 changes: 68 additions & 0 deletions contracts/extension/plugin/ReentrancyGuardLogic.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;

import "./ReentrancyGuardStorage.sol";

/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardLogic {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.

// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;

function __ReentrancyGuard_init() internal {
__ReentrancyGuard_init_unchained();
}

function __ReentrancyGuard_init_unchained() internal {
ReentrancyGuardStorage.Data storage data = ReentrancyGuardStorage.reentrancyGuardStorage();
data._status = _NOT_ENTERED;
}

/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
ReentrancyGuardStorage.Data storage data = ReentrancyGuardStorage.reentrancyGuardStorage();
// On the first call to nonReentrant, _notEntered will be true
require(data._status != _ENTERED, "ReentrancyGuard: reentrant call");

// Any calls to nonReentrant after this point will fail
data._status = _ENTERED;

_;

// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
data._status = _NOT_ENTERED;
}
}
17 changes: 17 additions & 0 deletions contracts/extension/plugin/ReentrancyGuardStorage.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

library ReentrancyGuardStorage {
bytes32 public constant REENTRANCY_GUARD_STORAGE_POSITION = keccak256("reentrancy.guard.storage");

struct Data {
uint256 _status;
}

function reentrancyGuardStorage() internal pure returns (Data storage reentrancyGuardData) {
bytes32 position = REENTRANCY_GUARD_STORAGE_POSITION;
assembly {
reentrancyGuardData.slot := position
}
}
}
Loading