Conversation
| // Mark as first bid | ||
| firstBid = true; | ||
| // Transfer NFT into escrow | ||
| erc721TransferHelper.transferFrom(_tokenContract, auction.seller, address(this), _tokenId); |
There was a problem hiding this comment.
I propose that this is changed to safely transfer the ERC-721 into escrow:
| erc721TransferHelper.transferFrom(_tokenContract, auction.seller, address(this), _tokenId); | |
| erc721TransferHelper.safeTransferFrom(_tokenContract, auction.seller, address(this), _tokenId); |
Context
Given the docs for transferFrom:
"Transfers the ownership of a given token ID to another address. Usage of this method is discouraged, use
safeTransferFromwhenever possible. Requires the msg.sender to be the owner, approved, or operator."
Because the smart contract takes the ERC-721 in escrow, there might also need to be some additional work for implementing IERC721Receiver.onERC721Received, which is called upon a safe transfer as noted in these docs.
Stepping back, there could be a reason that it's designed this way, and I'm keeping an open mind. I'd love to get feedback from the team: is there a specific reason/rationale for taking this approach? If there is, noting that in the annotations would improve what's already here. 💭
There was a problem hiding this comment.
good question - this is by design. safeTransferFrom is protection on the user side to prevent sending NFTs to contracts that may not be able to handle them. in our case, since we know we're the recipient and can handle them, we can use the simpler transferFrom and save gas
There was a problem hiding this comment.
Ah, that context helps! Thank you @kulkarohan.
I was mulling over proposing a follow up change including an annotation there, but I think your input is enough for someone to look at this in the future and figure out why we use the simpler function. Considering this resolved 👍
| erc721TransferHelper.transferFrom(_tokenContract, auction.seller, address(this), _tokenId); | |
| // `transferFrom` is enough to move the NFT into escrow since the contract is the recipient | |
| erc721TransferHelper.transferFrom(_tokenContract, auction.seller, address(this), _tokenId); |
| auctions.settleAuction(address(token), 0); | ||
| } | ||
|
|
||
| function test_ETHIntegration() public { |
There was a problem hiding this comment.
The assertions in this function take into account the royalties paid out to the creator and the finder respectively. However, there doesn’t seem to be an assertion that checks the balances if a protocol fee is set at the time the auction is settled:
Even if no protocol fee were actually set in these test cases (zero), would the team be open to adding one more require to show that is truly the case, or include a separate set of tests that illustrate what happens when an auction is settled with a non-zero protocol fee? 💭
There was a problem hiding this comment.
I see your 👍 @kulkarohan -- I'll take some time this week and cut a PR that introduces a test for the protocol fee. 🔪
(If there's a known, hard deadline, do let me know and I can prioritize accordingly.)
There was a problem hiding this comment.
@kulkarohan - Hi again! 👋
I opened #140 introducing tests for when the protocol fee is set to 1 basis point (1 bps or 0.01%). I'd love your evaluative review on it so we have complete test coverage for this module. Thanks in advance!
|
👋 @kulkarohan -- I see some updates being pushed 👀 Is it best to hold off from further review until those settle? 💭 |
|
hey @almndbtr sorry about that haha we found a few small tweaks earlier that we wanted to make. feel free to further review! |
| /// @notice This contract allows users to list and bid on ERC-721 tokens with timed reserve auctions | ||
| contract ReserveAuctionV1 is ReentrancyGuard, UniversalExchangeEventV1, IncomingTransferSupportV1, FeePayoutSupportV1, ModuleNamingSupportV1 { | ||
| /// @dev The indicator to pass all remaining gas when paying out royalties | ||
| uint256 private constant USE_ALL_GAS_FLAG = 0; |
There was a problem hiding this comment.
I cut a PR to replace this with a new constant for the outgoing transfer gas limit: #137
Reserve Auction v1.0: add tests when the protocol fee is non-zero
|
hey @reefloretto ! we're just restructuring a couple things that we'll push today. planning to deploy Friday! |
🙏 Hoping the deploy goes well! Godspeed, Zora team 🚀 |
| address sellerFundsRecipient; | ||
| address bidder; | ||
| address finder; | ||
| uint16 findersFeeBps; |
There was a problem hiding this comment.
One way to save 2 slots would be to limit the size of a few fields to a more reasonable number.
Duration can easily be uint32 (probably not a great idea to have an auction beyond 100 years etc).
uint32+uint16+address is still less than uint256 (one storage slot)
firstBidTime and startTime can both be uint126 to save one slot as well
address
uint16 finderFeeBps
uint32 duration
uint128 firstBidTime
uint128 startTime
saves two slots over the current configuration.
There was a problem hiding this comment.
@iainnash hahaha i have these changes in the update. pushing soon!
…reserve-auction
|
I've restructured Reserve Auction into four gas-optimized variants:
'Core' are minimal reserve auctions and 'Finders' add support for finders fee. An important note: while ETH variants are ETH-only, the ERC-20 variants are still compatible with ETH via setting So if you'd like the simplicity of interacting with a sole contract, the Finders ERC-20 variant will support all four use-cases (ETH, ERC20s, no finders fee, finders fee) as initially designed. But if you'd like to optimize per use-case, you'll now be able to do so as well. Lemme know if there are any Qs -- thanks for your patience. |
New Module Proposal
Description
This module outlines a way for any ERC-721 token holder to create a permissionless reserve auction.
Motivation and Context
ReserveAuctionV1 is an update to ZORA V2 Auction House. NFTs are taken into escrow after the reserve price is met, as well as the current highest bid. After an auction has ended, anyone can settle to payout respective parties and transfer the NFT to the winning bidder.
How has this been tested?
Relevant tests have been included via Foundry.
Checklist: