Hi NEAR Community,
We wanted to share some technical specifics on the Few and Far NFT Specification, a fully backwards-compatible extension of NEP-171. The below information can also be found on Medium here.
At Few and Far, we want to provide the best NFT experience possible for creators, collectors and traders. This means giving creators control over their NFT businesses , with the ability to enforce sale rules such as royalty payouts. For collectors and traders, this means creator transparency and fast NFT sales .
Currently, with NEAR’s NEP-199 Approvals standard, the NFT contract is responsible for transferring NFTs to a new owner, but the actual sale transaction — the flow of funds — is always processed via a 3rd party (e.g. a marketplace contract). On a sale, at a request from a 3rd party contract approved by the seller, the NFT contract transfers the NFT to the new owner, and specifies the royalty amounts that should be paid out.
However, the 3rd party contract has no obligation to pay out these royalties , and as we have seen recently on Solana, we cannot rely on marketplaces to “do the right thing” by paying out the royalty holders. Marketplaces are businesses, and once one marketplace stops paying out royalties thereby offering larger payouts to sellers, other marketplaces will start to lose market share, and it becomes a slippery slope and a race to the bottom.
The Few and Far NFT Specification (an extension of NEAR’s NEP-171 Standard) solves this problem as follows:
- The NFT contract can manage listings and sales itself (“native” listings), without the need for a trusted 3rd party
- If the creator (contract owner) chooses, legacy 3rd party approvals can be enabled, providing full compatibility with the existing NEP-199 Approvals standard.
- If the creator chooses to enable legacy approvals, they can further specify allowed &/or denied marketplace accounts that are permitted to process NFT sales, enabling them to allow specific marketplaces of their choosing or deny marketplaces that don’t play nice.
Importantly, NFT sales via the proposed “native” listings are at least 3x faster than the legacy equivalent, because they always complete in a single block. The legacy approvals standard takes a minimum of 3 blocks, and could take longer if block space is in high demand! Native listings and sales have important implications when it comes to high-speed use cases like gaming, but also will result in a noticeable performance improvement for regular collectors and traders.
Long story short: we believe this specification is a necessary and important step forward for the NFT community.
Let’s dig in and see how it works!
LISTING
pub struct Listing {
pub amount: U128,
}
An NFT owner can list their NFT natively on the NFT contract by calling the list()
method. This creates and stores a Listing
for the specified amount, and broadcasts this listing via an nft_listing
event. By natively listing their NFT, the seller is guaranteed that they will receive the amount specified in the listing, minus any royalties.
This standard supports one native listing per NFT. To update the native listing for their NFT, the owner calls the list()
method; this will replace any existing listing with the updated listing.
To remove a native listing, the owner should call the remove_listing()
method. This will remove an existing listing and broadcast this via an nft_remove_listing
event.
NB: Support for non-NEAR tokens (e.g. an ft_token_id) will be added in a future version of this specification.
list():
fn list(
&mut self,
token_id: String,
amount: U128,
) -> Listing;
The list() method acts as follows:
- Can only be called by owner of specified NFT
- Verifies that caller has attached exactly 1 yoctoNEAR for security purposes
- Adds a
Listing
for this NFT (remember — only one listing is allowed per NFT, so this method will override any existing listing for this NFT. This means that it doubles as an “update” method!) - Emits
nft_listing
event (see below) - Returns new
Listing
// nft_listing event
{
"standard": “fnf007”,
"version": "1.0.0",
"event": "nft_listing",
"data": { owner_id, token_id, amount }
}
remove_listing():
fn remove_listing(
&mut self,
token_id: TokenId,
) -> Listing;
The remove_listing() method acts as follows:
- Can only be called by owner of specified NFT
- Verifies that caller has attached exactly 1 yoctoNEAR for security purposes
- If listing exists for this NFT, removes it and emits
nft_listing_remove
event (see below)
// nft_listing_remove event
{
"standard": “fnf007”,
"version": "1.0.0",
"event": "nft_listing_remove",
"data": { owner_id, token_id }
}
BUYING
Anyone can buy an NFT that has been listed natively by calling the buy()
method.
In order to allow marketplaces to add a platform fee on top of an NFT’s listing price, an optional referrer
parameter can be included that specifies an id
of an account that facilitated the sale, and an amount
that this account should receive. This amount is added on top of the listing price at the time of purchase , and the deposit sent with the transaction should cover the listing price plus any specified referrer amount.
pub struct Referrer {
amount: U128,
id: AccountId,
}
An optional receiver_id
parameter can be included if the NFT should be transferred to a different account than the method caller.
buy():
fn buy(
&mut self,
token_id: TokenId,
referrer: Option<Referrer>,
receiver_id: Option<AccountId>,
);
The buy() method acts as follows:
- Verifies that a
Listing
exists for this NFT, and that the attached deposit is greater than (or equal to) the listing amount - If no receiver_id is specified, receiver of NFT will be
env::predecessor_account_id()
- Transfers NFT to new owner
- Sends payouts to royalty holders and seller (seller is guaranteed to receive listing amount minus royalties)
- If
referrer
is specified and deposit includes funds for referrer, sends the referreramount
to the referrerid
- Returns any remaining funds to method caller
- Removes
Listing
- Emits
nft_listing_remove
event (see above) - Emits
nft_transfer
event (as per NEP-171’sNftTransferLog
) - Emits nft_sale event (see below)
// nft_sale event
{
"standard": “fnf007”,
"version": "1.0.0",
"event": "nft_sale",
"data": { token_id, amount, seller_id, buyer_id }
}
And that’s it for the native listing functionality! The Few and Far NFT Specification contains other exciting updates, such as providing a utility promise directly on the NFT collection and allowing NFT holders to rate the collection on-chain, and we look forward to sharing these details in upcoming posts!
We look forward to hearing your feedback here. Additionally, our DMs are always open. Follow us on Twitter &/or jump into our Discord - we’d love to hear from you!