Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added an ERC721 NFT Contract #214

Closed
wants to merge 15 commits into from

Conversation

raizo07
Copy link
Contributor

@raizo07 raizo07 commented Jun 4, 2024

Issue(s): #197

Description

Implemented a simple ERC721 Non-Fungible Token (NFT) contract

Checklist

  • Contract Tests: Added tests to cover the changes

Copy link
Contributor

@julio4 julio4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to add a md page in src, detailing each methods of the interface as well.

@raizo07
Copy link
Contributor Author

raizo07 commented Jun 5, 2024

You need to add a md page in src, detailing each methods of the interface as well.

Alright I'll submit a PR for that along side the test today.

@0xNeshi
Copy link
Contributor

0xNeshi commented Jun 7, 2024

@raizo07 need any help with this?

@raizo07
Copy link
Contributor Author

raizo07 commented Jun 7, 2024

@raizo07 need any help with this?

I'm on it already, when I'm done I'll make it a draft PR so you can help review before the main review if that's okay with you.

Copy link
Contributor

@julio4 julio4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some changes!

listings/applications/ERC721/ERC721.cairo Outdated Show resolved Hide resolved
listings/applications/ERC721/ERC721.cairo Outdated Show resolved Hide resolved
listings/applications/ERC721/ERC721.cairo Outdated Show resolved Hide resolved
@raizo07
Copy link
Contributor Author

raizo07 commented Jun 18, 2024

@julio4 Kindly review this.

@raizo07
Copy link
Contributor Author

raizo07 commented Jun 20, 2024

Hello @julio4 @misicnenad Any chance of you reviewing this soon?

Copy link
Contributor

@0xNeshi 0xNeshi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of things:

  1. You forgot to address Jules change request related to mod errors.
  2. You are missing Scarb.toml file.
  3. Expanding on the previous point, you should use a valid Cairo project structure, e.g. see listings/templates/scarb.
    You can easily create the correct Cairo project structure using the scarb new <project-name> command (see The Cairo Book for more details).
  4. The IERC721 interface in the PR does not match the conventional one:
  5. To confirm you implemented everything correctly, you could run bash scripts/cairo_programs_verifier.sh from the root directory - it will pinpoint any potential issues in your code (see project's Contributing guidelines).

You can use OpenZeppelin's ERC721 implementation as inspiration for this PR, it will make it much easier to implement, see https://github.com/OpenZeppelin/cairo-contracts/blob/main/src/token/erc721.

listings/applications/ERC721/ERC721.cairo Outdated Show resolved Hide resolved
listings/applications/ERC721/ERC721.cairo Outdated Show resolved Hide resolved
listings/applications/ERC721/test_erc721.rs Outdated Show resolved Hide resolved
@julio4
Copy link
Contributor

julio4 commented Jun 21, 2024

A couple of things:

1. You forgot to address [Jules change request related to `mod errors`](https://github.com/NethermindEth/StarknetByExample/pull/214/files#r1637947087).

2. You are missing [Scarb.toml](https://book.cairo-lang.org/ch13-00-introduction-to-starknet-smart-contracts.html?highlight=scarb.toml#scarb) file.

3. Expanding on the previous point, you should use a valid Cairo project structure, e.g. see [listings/templates/scarb](https://github.com/NethermindEth/StarknetByExample/tree/main/listings/templates/scarb).
   You can easily create the correct Cairo project structure using the `scarb new <project-name>` command (see [The Cairo Book](https://book.cairo-lang.org/ch01-02-hello-world.html#creating-a-project-with-scarb) for more details).

4. The `IERC721` interface in the PR does not match the conventional one:
   
   * different function names
   * should use `u256` instead of felts and `u128`, as [Jules said at the end of his original comment](https://github.com/NethermindEth/StarknetByExample/pull/214#discussion_r1640884954)
   * `IERC721` does not contain functions to get `name`, `symbol` and `token_uri` (those are part of `IERC721Metadata`).

5. To confirm you implemented everything correctly, you could run `bash scripts/cairo_programs_verifier.sh` from the root directory - it will pinpoint any potential issues in your code (see project's [Contributing guidelines](https://github.com/NethermindEth/StarknetByExample/blob/main/CONTRIBUTING.md#verification-script)).

You can use OpenZeppelin's ERC721 implementation as inspiration for this PR, it will make it much easier to implement, see https://github.com/OpenZeppelin/cairo-contracts/blob/main/src/token/erc721.

Yes, this are all valid concerns outlined by @misicnenad

@julio4 julio4 mentioned this pull request Jun 21, 2024
@raizo07
Copy link
Contributor Author

raizo07 commented Jun 26, 2024

Hello @julio4 @misicnenad can you review?

@raizo07
Copy link
Contributor Author

raizo07 commented Jun 28, 2024

Hello @julio4 @misicnenad can you review?

Have you been able to take a look at this? @misicnenad

0xNeshi

This comment was marked as outdated.

Copy link
Contributor

@0xNeshi 0xNeshi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR is much better.

You may have missed some of the change requests though. Please make sure to address all of them, as it makes for much faster PR reviews.

listings/applications/erc721/Scarb.toml Outdated Show resolved Hide resolved
listings/applications/erc721/src/tests.cairo Outdated Show resolved Hide resolved
listings/applications/erc721/src/erc721.cairo Outdated Show resolved Hide resolved
listings/applications/erc721/src/erc721.cairo Outdated Show resolved Hide resolved

// Returns the metadata URI for a given token ID
fn get_token_uri(self: @ContractState, token_id: u256) -> felt252 {
assert(self._exists(token_id), 'ERC721: invalid token ID');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use starknet::ContractAddress;

#[starknet::interface]
pub trait IERC721<TContractState> {
Copy link
Contributor

@0xNeshi 0xNeshi Jun 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The IERC721 interface in the PR does not match the conventional one:
- IERC721 does not contain functions to get get_name, get_symbol and get_token_uri, those are part of IERC721Metadata. See the expected IERC721 interface definition here.
- The IERC721Metadata interface is missing; also, it's function names are fn name, fn symbol and fn token_uri (all without the get_ part).
- You can use OpenZeppelin's ERC721 implementation as inspiration for this PR, it will make it much easier to implement, see https://github.com/OpenZeppelin/cairo-contracts/blob/main/src/token/erc721.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a simplified version of OpenZeppelin is really enough for this!

@@ -0,0 +1,90 @@
#[cfg(test)]
mod tests {
use super::*;
Copy link
Contributor

@0xNeshi 0xNeshi Jun 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests are written in Rust, not in Cairo.

Once you rewrite them, you should run bash scripts/cairo_programs_verifier.sh from the root directory - it will pinpoint any potential issues in your code and verify all of the tests pass (see project's Contributing guidelines).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests are written in Rust, not in Cairo.

Once you rewrite them, you should run bash scripts/cairo_programs_verifier.sh from the root directory - it will pinpoint any potential issues in your code and verify all of the tests pass (see project's Contributing guidelines).

I ran the bash scripts/cairo_programs_verifier.sh
Screenshot 2024-07-16 at 11 39 27
command as requested and it passed as can be seen from the attached image.

Copy link
Contributor

@0xNeshi 0xNeshi Jul 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is because you renamed the file from tests.cairo to test_ERC721.cairo, but didn't declare the corresponding module in lib.cairo.
Please read how to properly write tests in Cairo using the official documentation and apply that.

contract._mint(to, token_id);

assert_eq!(contract.owner_of(token_id), to);
assert_eq!(contract.balance_of(to), 1.into());
Copy link
Contributor

@0xNeshi 0xNeshi Jun 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the tests that test functions that emit events should assert those events have been emitted as well.

Below are the links on how to do that depending on the testing library you use:

use starknet::ContractAddress;

#[starknet::interface]
pub trait IERC721<TContractState> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a simplified version of OpenZeppelin is really enough for this!

@raizo07 raizo07 marked this pull request as draft July 2, 2024 05:57
@raizo07 raizo07 marked this pull request as ready for review July 4, 2024 15:14

let new_owner = contract.owner_of(nft_id);
assert(new_owner == user, 'wrong new OWNER');
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still missing the newline character, please resolve the conversation only once the request is addressed.

listings/applications/erc721/src/tests.cairo Outdated Show resolved Hide resolved
listings/applications/erc721/src/tests.cairo Outdated Show resolved Hide resolved
listings/applications/erc721/src/erc721.cairo Show resolved Hide resolved
listings/applications/erc721/src/erc721.cairo Outdated Show resolved Hide resolved
listings/applications/erc721/src/erc721.cairo Show resolved Hide resolved
listings/applications/erc721/src/erc721.cairo Outdated Show resolved Hide resolved
listings/applications/erc721/src/erc721.cairo Outdated Show resolved Hide resolved
listings/applications/erc721/src/erc721.cairo Outdated Show resolved Hide resolved
listings/applications/erc721/src/erc721.cairo Outdated Show resolved Hide resolved
@raizo07 raizo07 marked this pull request as draft July 14, 2024 11:16
@raizo07 raizo07 marked this pull request as ready for review July 16, 2024 10:19
@raizo07 raizo07 requested review from 0xNeshi and julio4 July 16, 2024 10:19
@raizo07
Copy link
Contributor Author

raizo07 commented Jul 22, 2024

Hello @julio4 I've implemented all the necessary changes. Kindly review.

#[test]
#[available_gas(2000000)]
fn test_erc721_burn() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implement the test

@@ -19,9 +19,9 @@ pub trait IERC721<TContractState> {

#[starknet::interface]
pub trait IERC721Metadata<TContractState> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not resolve comments that have not been addressed.
This trait should be implemented, as per the standard.

@@ -116,20 +117,23 @@ mod ERC721 {
fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) {
let owner = self.owner_of(token_id);
assert(to != owner, Errors::APPROVAL_TO_CURRENT_OWNER);

// Split the combined assert into two separate asserts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this comment

fn set_approval_for_all(
ref self: ContractState, operator: ContractAddress, approved: bool
) {
let owner = get_caller_address();
assert(owner != operator, Errors::APPROVE_TO_CALLER);
// assert(owner != operator, Errors::APPROVE_TO_CALLER);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of commenting the unnecessary code, just remove it

@@ -0,0 +1,90 @@
#[cfg(test)]
mod tests {
use super::*;
Copy link
Contributor

@0xNeshi 0xNeshi Jul 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is because you renamed the file from tests.cairo to test_ERC721.cairo, but didn't declare the corresponding module in lib.cairo.
Please read how to properly write tests in Cairo using the official documentation and apply that.

Copy link
Contributor

@0xNeshi 0xNeshi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will give you some very frank constructive criticism:

  1. It is frustrating to have to repeat oneself when reviewing PRs, as it is a drain on the reviewer's time.
    For the last couple of PRs you've been given the same comments repeatedly:

    Only once you have addressed all of the change requests should you ping the reviewers to review your code.

  2. Related to invalid tests: read the official language documentation before you attempt to submit a PR in said language. The reviewers are giving you respect by investing their time to check your code and leave feedback - the least you could do is read the docs to be able to submit valid code for review.

@@ -0,0 +1,217 @@
use starknet::{ContractAddress, contract_address_const, get_caller_address};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert the file name to tests.cairo, see #214 (comment).
This will make all of the issues with this test file apparent to you.


#[storage]
struct Storage {
name: felt252,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name and symbol should have the type of ByteArray

balances: LegacyMap::<ContractAddress, u256>,
token_approvals: LegacyMap::<u256, ContractAddress>,
operator_approvals: LegacyMap::<(ContractAddress, ContractAddress), bool>,
token_uri: LegacyMap::<u256, felt252>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use ByteArray instead of felt252

@@ -0,0 +1 @@
mod erc721;
Copy link
Contributor

@0xNeshi 0xNeshi Jul 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the missing mod tests declaration, check out the official Cairo docs on how to write tests and have them actually picked up by the compiler. Then the bash scripts/cairo_programs_verifier.sh will work as expected (see #214 (comment)).

test.workspace = true

[[target.starknet-contract]]
build-external-contracts = ["erc20::token::erc20"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remember to address all review comments, see #214 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remember to address all review comments, see #214 (comment)

Alright thank you.

@julio4
Copy link
Contributor

julio4 commented Aug 5, 2024

@raizo07 I might have to close this PR, I understand that you put lots of effort into it and hopefully learned a lot in the process. However it is still below the quality we are expected. I hope you can understand and feel free to contribute again when you have a more solid understanding of Cairo and Starknet.

@raizo07
Copy link
Contributor Author

raizo07 commented Aug 5, 2024

Hello @julio4 I'm currently resolving all the issues @misicnenad mentioned.

@raizo07 raizo07 marked this pull request as draft August 8, 2024 04:13
@julio4
Copy link
Contributor

julio4 commented Aug 8, 2024

Hello @julio4 I'm currently resolving all the issues @misicnenad mentioned.

I'll keep it open for a while but please take into account comments by @misicnenad, which I agree with.

@0xNeshi 0xNeshi mentioned this pull request Oct 17, 2024
3 tasks
@julio4 julio4 closed this Oct 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants