πŸ§‘β€βš–οΈAuction

EnglishAuction

Git Source

Inherits: Owned, RoyaltyEngineV1

Author: cosimo.demedici.eth (https://github.com/ninfa-labs/ninfa-contracts)

On-chain English Auction

State Variables

_dataFeed

Chainlink ETH/USDC price feed aggregator interface

Use Counters library for Counter datatype

AggregatorV3Interface private immutable _dataFeed;

_DURATION

Duration of an auction once the first bid has been received. Set to 1 day.

uint256 private constant _DURATION = 1 days;

_EXTENSION_DURATION

Window for auction extensions. Any bid placed in the final 15 minutes of an auction will reset the time remaining to 15 minutes.

_MIN_BID_RAISE

For example, _MIN_BID_RAISE = 10 is a 10% increment, 20 is 5%, 2 is 50%. I.e., 100 / _MIN_BID_RAISE.

The last highest bid is divided by this number to obtain the minimum bid increment.

_BPS_DENOMINATOR

Denominator for basis points calculation. 10,000 basis points = 100% shares sale price.

auctionCount

Counter for tracking the number of auctions

_feeRecipient

The address for receiving auction sales fees. Typically, this is a multisig address.

_feeBps

The Ninfa fee percentage on primary sales, expressed in basis points.

_auctions

This needs to be public so that it can be called by a frontend as the auction creation event only emits auction id.

Mapping from auction IDs to auction data. This is deleted when an auction is finalized or canceled.

Functions

constructor

Parameters

Name
Type
Description

feeRecipient_

address

address (multisig) controlled by Ninfa that will receive any market fees.

feeBps_

uint256

onERC721Received

Creates an auction for the given NFT. The NFT is held in escrow until the auction is finalized or canceled.

Whenever an {IERC721} tokenId token is transferred to this contract via {IERC721-safeTransferFrom} by operator from from, this function is called. It must return its Solidity selector to confirm the token transfer. If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. The selector can be obtained in Solidity with IERC721.onERC721Received.selector.

Parameters

Name
Type
Description

_operator

address

The address which called safeTransferFrom function

_from

address

The address which previously owned the token

_tokenId

uint256

The NFT identifier which is being transferred

_data

bytes

Additional data with no specified format

Returns

Name
Type
Description

<none>

bytes4

bytes4 Returns bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))

firstBid

reservePrice is the initial reserve price for the auction. Reserve price may also be 0, clearly a mistake but not strictly required, only done in order to save gas by removing the need for a condition such as if (_price == 0) revert InvalidAmount(_price) commissionReceivers address of sale commissions receiver if msg.sender is also the _commissionReceiver, e.g. if msg.sender is a gallery, they must put their own address as the _commissionReceiver, and set the _seller parameter with the artist's/collector's address. if there is no commission receiver, it must be set to address(0) it is not required for _commissionReceiver and _seller addresses to be different (in order to save gas), although it would likely be a mistake, it cannot be exploited as the total amount paid out will never exceed the price set for the order. I.e. in the worst case the same address will receive both principal sale profit and commissions.

This function is to be used only for the first bid on any auction, in order to avoid code repetition and improve gas costs for all bids.

This function integrates third party credit card payment solution, as payment gateways will use their own contracts to call this function it is not possible to rely on msg.sender. It is also possible for the buyer to use this parameter simply in order to transfer the NFT to an address other than their own, this can be useful for external contract buying NFTs.

Parameters

Name
Type
Description

_auctionId

uint256

_bidder

address

The address of the bidder

bid

Places a bid in an auction. The bid must be at least the amount defined by getMinBidAmount. If this is the first bid on the auction, the countdown will begin. If there is already an outstanding bid, the previous bidder will be refunded at this time. If the bid is placed in the final moments of the auction, the countdown may be extended.

Bids must be at least 5% higher than the previous bid. The _auctionId must exist, the auction must have begun, and must not have ended. The _bidder parameter is needed to integrate third-party credit card payment solutions.

Parameters

Name
Type
Description

_auctionId

uint256

The id of the auction to bid on.

_bidder

address

The address of the bidder.

finalize

reverts if auction doesn't exist yet;, i.e. if _auction.end == 0

reverts if auction has been created but no one has called firstBid() yet. i.e. if _auction.end == 0

reverts if auction has ended, i.e. if block.timestamp > _auction.end

Reverts if raise is less than minimum raise pct required, i.e. bids Delta must be greater than or equal to the old bid value divided by _MIN_BID_RAISE.

Does not follow check-effects-interactions pattern in order to avoid storing previous bidder and amount in memory variables. No reentrancy exploit is possible in practice however; _auction.bidPrice and _auction.bidder are not used by any other function that may be reentered, namely onERC721Received() and firstBid().

finalize

Finalizes an auction. The NFT is held in escrow until the auction is finalized or canceled.

reverts if auction has started but not ended yet, i.e. block.timestamp < auction.end

reverts if auction does not exist or was already finalized/deleted, i.e. auction.end == 0

The reserve price may also be 0.

Parameters

Name
Type
Description

_auctionIds

uint256[]

The ids of the auctions to finalize.

updateReservePrice

If an auction has been created but has not yet received bids, the reservePrice may be edited by the seller.

reverts if auction has started but not ended yet, i.e. block.timestamp < auction.end

reverts if auction does not exist or was already finalized/deleted, i.e. auction.end == 0

_newReservePrice may be equal to old price (_auctions[_auctionId].price); although this doesn't make much sense it isn't a security requirement, hence require(_auction.bidPrice != _price) it has been omitted in order to save the user some gas

_newReservePrice may also be 0, clearly a mistake but not a security requirement, hence require(_price > 0) has been omitted in order to save the user some gas

Parameters

Name
Type
Description

_auctionId

uint256

The id of the auction to change.

_newReservePrice

uint256

The new reserve price for this auction, may be higher or lower than the previoius price.

updateCommissionBps

If an auction has been created but has not yet received bids, the commissionBps may be edited by the seller.

Parameters

Name
Type
Description

_auctionId

uint256

The id of the auction to change.

_commissionBps

uint256[]

The new commission basis points for this auction.

_commissionReceivers

address[]

The new commission receivers for this auction.

cancelAuction

If an auction has been created but has not yet received bids, it may be canceled by the seller.

The NFT is transferred back to the owner unless there is still a buy price set.

Parameters

Name
Type
Description

_auctionId

uint256

The id of the auction to cancel.

setFeeRecipient

Setter function only callable by contract admin used to change the address to which fees are paid.

Parameters

Name
Type
Description

_newFeeRecipient

address

is the address owned by NINFA that will collect sales fees.

setFeeBps

Setter function only callable by contract admin used to change the fee percentage on primary sales.

Parameters

Name
Type
Description

_newFeeBps

uint256

is the new fee percentage in basis points.

getAuction

Returns the minimum bid amount for an auction.

Parameters

Name
Type
Description

_auctionId

uint256

The id of the auction to get the minimum bid amount for.

Returns

Name
Type
Description

<none>

Auction

The minimum bid amount.

supportsInterface

See IERC165-supportsInterface. A wallet/broker/auction application MUST implement the wallet interface if it will accept safe transfers.

Events

AuctionCreated

Emitted when an auction is created. All auction data is stored in db by reading Auction struct after events are emitted, therefore information can be retrieved even after an AuctionFinalized event has been emitted and the corresponding auction struct deleted from storage.

AuctionCanceled

Emitted when an auction is canceled.

AuctionUpdated

Emitted when an auction is updated.

AuctionFinalized

Emitted when an auction is finalized.

Bid

Emitted when a bid is placed in an auction.

Structs

Auction

This struct stores the auction configuration for a specific NFT.

Properties

Name
Type
Description

operator

address

The address of the operator. This is necessary because if the order creator is a gallery (i.e., the commission receiver), they wouldn't be able to cancel or update the order without knowing whether the order creator was the seller or the commissionReceiver.

seller

address

collection

address

bidder

address

The address of the highest bidder. This address must be payable to receive a refund in case of being outbid.

tokenId

uint256

bidPrice

uint256

end

uint256

The time at which this auction will stop accepting any new bids. This is 0 until the first bid is placed.

commissionBps

uint256[]

commissionReceivers

address[]

Last updated