Skip to content

Commit

Permalink
Format README.md
Browse files Browse the repository at this point in the history
Signed-off-by: Mike <[email protected]>
  • Loading branch information
fulltimemike authored Jul 22, 2023
1 parent c9ac26c commit 21a29db
Showing 1 changed file with 57 additions and 59 deletions.
116 changes: 57 additions & 59 deletions arc-0721/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
arc: 0721 # Add the next sequence number
title: Aleo Non-Fungible Token Standard # Title
authors: @fulltimemike, @evanmarshall, @JohnDonavon, @dagarcia7 # Add all Github usernames, emails, and/or full names
discussion: ARC-0721: Aleo Non-Fungible Token Standard # Create a 'Github Discussion' titled 'ARC-XXXX: {TITLE}`
topic: Application # Choose: Protocol, Network, or Application
arc: 0721
title: Aleo Non-Fungible Token Standard
authors: fulltimemike, evanmarshall, JohnDonavon, dagarcia7
discussion: ARC-0721 Aleo Non-Fungible Token Standard
topic: Application
status: Draft
created: 2023-7-19 # Date
created: 2023-7-19
---

## Abstract
Expand All @@ -14,41 +14,33 @@ NFTs on Aleo are uniquely positioned to provide a private minting experience, th

The ethereum NFT standard could adopted fairly closely, as we could force all operations to happen in public state, however, we would rather see Aleo NFTs provide extra functionality that only a ZK L1 can provide.

<!-- What problem does this proposal address? -->

<!-- If someone only reads this far, what do you want them to know? -->

This standard is meant to build on top of the foundation laid by [ERC-721](https://eips.ethereum.org/EIPS/eip-721).

## Specification

This section should outline the technical requirements and considerations for incorporating this proposal as
a new ARC standard.

<!-- Define key terminology here. -->
collection_deployer: The address that deployed the contract. This is the only address that can initialize the NFT contract.

### Required Architecture:
#### Required Structs



<!-- Describe the architecture. -->
Required Architecture:
required structs:

// The base uri struct contains 8-bit ASCII encoded text. Aleo instructions do not support strings, but NFTs need to have an accessible base uri to fetch information from.
// NFTs must have a base folder in which their data contained with jsons are stored. The base uri struct contains 8-bit ASCII encoded text. Aleo instructions do not support strings, but NFTs need to have an accessible base uri to fetch information from.
// Different NFT projects may require more text or less text as necessary, so additional data properties can be added to the BaseURI to account for needed character length.
// The data for a base uri should be padded by 0s on the end of the struct, as 0 does not correspond to a valid ASCII character.
// An example of a BaseURI struct that matches google.com/: google.com/ to 8-bit ascii, padded with 0s on the end = 01100111011011110110111101100111011011000110010100101110011000110110111101101101001011110000000000000000000000000000000000000000
// As a u128 would be BaseURI { data1: 137489088058657146712104188238903640064u128 }

```
BaseURI {
(required) data1: u128,
(optional) data2: u128,
.
.
.
(optional) dataN: u128
},
}
```

// The token id struct is used with the base uri to provide a full url to a json representing the nft data. This structure should follow the base uri example as before, with the string text being 8-bit ASCII encoded, and padded with any extra 0s on the end.

// The token id struct is used with the base uri, to provide a full url to a json representing the nft data. This structure should follow the base uri example as before, with the string text being 8-bit ASCII encoded, and padded with any extra 0s on the end.
```
TokenId {
(required) data1: u128,
(optional) data2: u128,
Expand All @@ -57,27 +49,34 @@ TokenId {
.
(optional) dataN: u128
}
```

required records
#### Required Records

// In order to display all NFTs corresponding to this standard across wallets, a standard NFT record has to be adopted. The minimum information needed for an NFT is the owner; the data, which corresponds to the TokenId that uniquely identifies that NFT's information in the base uri folder; and the edition, which is the nth copy of the NFT. For completely unique collections, all the editions should be 0. If collections have duplicates, then the editions should increment by one.

```
record NFT {
(required) owner: address,
(required) private data: TokenId,
(required) private edition: scalar,
}
```

#### Required Mappings

required mappings
// In order to hold NFTs in public state, we need a mapping between a representation of each unique NFT and the address of the NFT owner. Multiple NFTs can be owned by the same address, so address cannot be the key. The field key must be a bhp:256 commitment to a hash of the TokenId and edition scalar.

// In order to hold NFTs in public state, we need a mapping between a representation of each unique NFT and the address of the NFT owner. Multiple NFTs can be owned by the same address, so address cannot be the key. The field key can just be a bhp:256 commitment to a hash of the TokenId and edition, or it can be another way of uniquely identifying each NFT.
mapping nft_owners: field => address;
`mapping nft_owners: field => address;`

// In order to hold the base uri in public state, we need a mapping that corresponds to all of the pieces of the base uri. By having the base uri in a publicly accessible mapping, the amount of data required to be held in each individual NFT record is lessened, and the base uri is tied to the program. The base uri can be updated by the contract maintainer.
// In order to hold the base uri in public state, we need a mapping that corresponds to all of the pieces of the base uri. By having the base uri in a publicly accessible mapping, the amount of data required to be held in each individual NFT record is lessened, and the base uri is tied to the program. The base uri can be updated.
mapping base_uri: u8 => u128;

required functions
#### Required Functions

// In order to keep track of a user's public state, they must have a standard function for converting potentially private NFT records to public state. In this way, we can follow the blockchain history to associate a given TokenId and edition that went from private to public. In the following function, the input to the finalize is the owner address of the nft, as well as the unique field that identifies that NFT. This field must be calculated in a standardized way, in order for wallets and rpcs to keep track of which unique field identifier corresponds to which tokenId + edition. In other words, we need a reverse mapping off-chain to associate these fields with NFTs.
// In order to keep track of a user's public state, there must be a standard function for converting potentially private NFT records to public state. In this way, we can follow the blockchain history to associate a given TokenId and edition that went from private to public. In the following function, the input to the finalize is the owner address of the nft, as well as the unique field that identifies that NFT. This field must be calculated in a standardized way, in order for wallets and rpcs to keep track of which unique field identifier corresponds to which tokenId + edition. In other words, we need a reverse mapping off-chain to associate these fields with NFTs.

```
transition convert_private_to_public(
(required) nft: NFT
)
Expand All @@ -88,15 +87,18 @@ transition convert_private_to_public(
}
// In this finalize block, the owner address and unique identifying NFT field are necessary, and the mapping for nft_owners must be set.
finalize convert_private_to_public(
* finalize convert_private_to_public(
(required) public owner: address,
(required) public tokenEditionHash: field
)
{
(required)nft_owners.set(tokenEditionHash, owner);
}
```

// In order to keep track of which unique NFT belongs to the public state, a standard function for public transference must be adopted. The receiver address and the NFT data (tokenId + edition) are necessary inputs, so that wallets and rpcs can associate a given NFT with the finalized mapping values in nft_owners.
```
transition transfer_public(
(required) private receiver: address,
(required) private data: TokenId,
Expand All @@ -118,23 +120,37 @@ finalize transfer_public(
assert_eq(caller, nft_owners.get(tokenEditionHash));
nft_owners.set(tokenEditionHash, receiver);
}
```

// In order to prove that you own an NFT without revealing which NFT, we introduce a novel function + finalize construct. Calling this "burn" function will only work if you indeed own the record, which will allow an inclusion proof to be generated and shared off-chain without actually burning the record, as the finalize body is guaranteed to fail.
function authorize:
input r0 as NFT.record;

finalize authorize:
assert.eq 0u8 1u8;
```
transition authorize(
nft: NFT
)
{
return then finalize();
}
finalize authorize(
)
{
// fails on purpose, so that the nft is not burned.
assert_eq(0u8, 1u8);
}
```

The ERC-721 standard allows for issuing approvals to addresses to be able to control an NFT. In Aleo, this could be done by maintaining a mapping of approved addresses to the unique identifying field for an NFT. This would allow programs to manage public NFTs, which may be necessary for swaps and escrow type contracts. As a community, we should decide whether or not approval issuance is a requirement for the NFT contract standard. The self.parent ARC (https://github.com/AleoHQ/ARCs/tree/master/arc-0030) has been added, so we should consider that this is an available method to add for this ARC.

Optional:
#### Optional:
This section is a collection of ideas and features that NFT contracts meeting the above standard can provide.

NFTs can have a symbol associated with them. The privacy pride symbol is LION.
```
struct SymbolBits {
data: u128 // The sybmol's ascii text represented in bits, and the u128 value of the bitstring.
}
```

Public minting:
NFTs can be publicly minted using the concept of a whitelist that holds addresses in public state, and only allows those addresses to mint the NFT when minting is allowed. link example to privacy pride program
Expand All @@ -154,43 +170,25 @@ Public mappings that maintain setting values can be a part of the contract, and
* turning on the mint: The setting to allow the nft mint to proceed. This is a requirement that can be combined with the mint block requirement.
* sky's the limit -- you can require any number of specific records to be in possession, limit the number of NFTs minted or issued to any given address, and more.



## Reference Implementations

https://github.com/demox-labs/art-factory/blob/main/program/src/main.leo

Implementation for a public whitelist mint: https://github.com/demox-labs/art-factory/blob/v3/program/src/main.leo
Implementation for a private optional whitelist mint: https://github.com/demox-labs/art-factory/blob/v4/program/src/main.leo


<!-- Link to any relevant Github issues. -->

<!-- Link to any related Github branches and/or pull requests. -->


## Dependencies

As this is an application ARC, there are no dependencies other than what is currently available in Aleo, as well as ARC-30, if we want to include allowance issuances.

<!-- Will this affect the Aleo PM, Aleo Explorer, or Aleo Studio? -->

<!-- Will this affect Aleo, Leo, snarkOS, snarkVM, or any other repositories? -->

### Backwards Compatibility

Not necessary.

<!-- List all backwards incompatibilities and their severity. -->

<!-- How will the backwards incompatibilities be resolved? -->


## Security & Compliance

This is an application ARC standard, so this only affects the security of managing assets on-chain. As the standard NFT contract, i.e. an interface that must be implemented, there are not enough requirements to guarantee safety of NFTs for any given asset owner. Safety and compliance will be on a contract-by-contract basis.

<!-- Outline any potential security concerns. -->

<!-- Does this proposal introduce regulatory risk? -->
This is an application ARC standard, so this only affects the security of managing assets on-chain. As the standard NFT contract, i.e. a pseudo-interface that must be implemented, there are not enough requirements to guarantee safety of NFTs for any given asset owner. Safety and compliance will be on a contract-by-contract basis.


## References
Expand Down

0 comments on commit 21a29db

Please sign in to comment.