grc721 source pure
View source
GRC: Gno.land Request for Comments
GRCs are the Gnoland's equivalent of Ethereum's ERCs and EIPs, or Bitcoin's BIPs.
This folder contains interfaces, examples, and implementations of standard smart-contracts and patterns.
Acknowledgment
Based and adapted from the work and discussions with people from:
- https://ethereum.org/en/developers/docs/standards/
- https://www.openzeppelin.com/
- https://github.com/transmissions11/solmate
- https://github.com/bitcoin/bips
2
1
var ErrInvalidTokenId, ErrInvalidAddress, ErrTokenIdNotHasApproved, ErrApprovalToCurrentOwner, ErrCallerIsNotOwner, ErrCallerNotApprovedForAll, ErrCannotTransferToSelf, ErrTransferFromIncorrectOwner, ErrTransferToNonGRC721Receiver, ErrCallerIsNotOwnerOrApproved, ErrTokenIdAlreadyExists, ErrSpoofedRealm, ErrNotRealm, ErrInvalidName, ErrInvalidSymbol, ErrInvalidRoyaltyPercentage, ErrInvalidRoyaltyPaymentAddress, ErrCannotCalculateRoyaltyAmount
1var (
2 ErrInvalidTokenId = errors.New("invalid token id")
3 ErrInvalidAddress = errors.New("invalid address")
4 ErrTokenIdNotHasApproved = errors.New("token id not approved for anyone")
5 ErrApprovalToCurrentOwner = errors.New("approval to current owner")
6 ErrCallerIsNotOwner = errors.New("caller is not token owner")
7 ErrCallerNotApprovedForAll = errors.New("caller is not approved for all")
8 ErrCannotTransferToSelf = errors.New("cannot send transfer to self")
9 ErrTransferFromIncorrectOwner = errors.New("transfer from incorrect owner")
10 ErrTransferToNonGRC721Receiver = errors.New("transfer to non GRC721Receiver implementer")
11 ErrCallerIsNotOwnerOrApproved = errors.New("caller is not token owner or approved")
12 ErrTokenIdAlreadyExists = errors.New("token id already exists")
13
14 // NewBasicNFT realm binding
15 ErrSpoofedRealm = errors.New("rlm does not match the current crossing frame")
16 ErrNotRealm = errors.New("rlm must be a realm (got EOA/origin)")
17 ErrInvalidName = errors.New("invalid token name (empty, too long, or contains control chars)")
18 ErrInvalidSymbol = errors.New("invalid token symbol (empty, too long, or contains chars outside [A-Za-z0-9_-])")
19
20 // ERC721Royalty
21 ErrInvalidRoyaltyPercentage = errors.New("invalid royalty percentage")
22 ErrInvalidRoyaltyPaymentAddress = errors.New("invalid royalty paymentAddress")
23 ErrCannotCalculateRoyaltyAmount = errors.New("cannot calculate royalty amount")
24)3
func NewBasicNFT
func NewNFTWithMetadata
NewNFTWithMetadata creates a new basic NFT with metadata extensions.
func NewNFTWithRoyalty
NewNFTWithRoyalty creates a new royalty NFT with the specified name, symbol, and royalty calculator.
12
type BasicNFT
struct 1type BasicNFT struct {
2 name string
3 symbol string
4 origRealm string // owning realm's package path
5 owners avl.Tree // tokenId -> OwnerAddress
6 balances avl.Tree // OwnerAddress -> TokenCount
7 tokenApprovals avl.Tree // TokenId -> ApprovedAddress
8 tokenURIs avl.Tree // TokenId -> URIs
9 operatorApprovals avl.Tree // "OwnerAddress:OperatorAddress" -> bool
10}Methods on BasicNFT
func Approve
method on BasicNFTApprove approves the input address for a particular token. caller must be the owner OR an operator approved for all on owner's behalf. The owning realm's wrapper validates IsCurrent and derives caller from rlm.Previous().Address() before calling.
func BalanceOf
method on BasicNFTBalanceOf returns balance of input address
func Burn
method on BasicNFTfunc GetApproved
method on BasicNFTGetApproved return the approved address for token
func Getter
method on BasicNFTGetter returns an NFTGetter that yields a reader-only view of the NFT. Safe to register with cross-realm aggregators like tokenhub — readers only, no rlm-typed methods, so no cur can be captured via this surface.
func ID
method on BasicNFTfunc IsApprovedForAll
method on BasicNFTIsApprovedForAll returns true if operator is approved for all by the owner. Otherwise, returns false
func Mint
method on BasicNFTMints `tokenId` and transfers it to `to`.
func Name
method on BasicNFTfunc OwnerOf
method on BasicNFTOwnerOf returns owner of input token id
func RenderHome
method on BasicNFTfunc SafeMint
method on BasicNFTMints `tokenId` and transfers it to `to`. Also checks that contract recipients are using GRC721 protocol
func SafeTransferFrom
method on BasicNFTSafeTransferFrom transfers a token from `from` to `to`, checking that contract recipients are aware of the GRC721 protocol to prevent tokens from being forever locked. caller must be the owner or an approved operator. The owning realm's wrapper derives caller from rlm.Previous().Address() under an IsCurrent() guard.
func SetApprovalForAll
method on BasicNFTSetApprovalForAll grants/revokes operator permission across all of the caller's tokens. caller is the owner whose approvals are mutated; the owning realm's wrapper derives it from rlm.Previous().Address() under an IsCurrent() guard.
func SetTokenURI
method on BasicNFTSetTokenURI sets the URI of a token. caller must equal the token's owner. The owning realm's public wrapper is responsible for deriving caller from rlm.Previous().Address() under an rlm.IsCurrent() guard before invoking this method; this method trusts the supplied caller.
func Symbol
method on BasicNFTfunc TokenCount
method on BasicNFTfunc TokenURI
method on BasicNFTTokenURI returns the URI of input token id
func TransferFrom
method on BasicNFTTransferFrom transfers a token from `from` to `to`. Same caller contract as SafeTransferFrom.
type IGRC2981
interfaceIGRC2981 follows the Ethereum standard
type IGRC721CollectionMetadata
interfaceIGRC721CollectionMetadata describes basic information about an NFT collection.
type IGRC721Metadata
interfaceIGRC721Metadata follows the Ethereum standard
type IGRC721MetadataOnchain
interfaceIGRC721Metadata follows the OpenSea metadata standard
type IGRC721Reader
interfaceIGRC721Reader is the read-only view of an NFT. Safe to receive across realm boundaries — has no rlm-typed methods, so a malicious impl can only lie about read results (data-integrity issue), not capture cur.
Writes are concrete methods on *BasicNFT / *metadataNFT / *royaltyNFT only — there is no IGRC721 writer interface. The owning realm should hold the concrete *BasicNFT in an unexported package var and expose public rlm-validating wrappers like:
Example
1func TransferFrom(cur realm, from, to address, tid TokenID) error {
2 caller := cur.Previous().Address()
3 return nft.TransferFrom(caller, from, to, tid)
4}
This is the Reader/Writer split — stronger than the Authority-pattern because the writer interface doesn't exist at all, so no realm author can accidentally expose it. See `r/demo/foo721` for the canonical wrapper pattern.
type Metadata
struct 1type Metadata struct {
2 Image string // URL to the image of the item. Can be any type of image (including SVGs, which will be cached into PNGs by OpenSea), IPFS or Arweave URLs or paths. We recommend using a minimum 3000 x 3000 image.
3 ImageData string // Raw SVG image data, if you want to generate images on the fly (not recommended). Only use this if you're not including the image parameter.
4 ExternalURL string // URL that will appear below the asset's image on OpenSea and will allow users to leave OpenSea and view the item on your site.
5 Description string // Human-readable description of the item. Markdown is supported.
6 Name string // Name of the item.
7 Attributes []Trait // Attributes for the item, which will show up on the OpenSea page for the item.
8 BackgroundColor string // Background color of the item on OpenSea. Must be a six-character hexadecimal without a pre-pended #
9 AnimationURL string // URL to a multimedia attachment for the item. Supported file extensions: GLTF, GLB, WEBM, MP4, M4V, OGV, OGG, MP3, WAV, OGA, HTML (for rich experiences and interactive NFTs using JavaScript canvas, WebGL, etc.). Scripts and relative paths within the HTML page are now supported. Access to browser extensions is not supported.
10 YoutubeURL string // URL to a YouTube video (only used if animation_url is not provided).
11}type NFTGetter
funcNFTGetter returns a reader-only view of an NFT. Aggregators (such as tokenhub) register and dispatch NFTGetters; the reader-only return type means even a malicious aggregator can't be used to leak cur.
type RoyaltyInfo
structRoyaltyInfo represents royalty information for a token.
type TokenID
identtype TokenURI
identtype Trait
struct6
- chain stdlib
- errors stdlib
- gno.land/p/nt/avl/v0 package
- gno.land/p/nt/ufmt/v0 package
- math/overflow stdlib
- strconv stdlib