-
Notifications
You must be signed in to change notification settings - Fork 86
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
Conversation
There was a problem hiding this 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.
Alright I'll submit a PR for that along side the test today. |
@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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some changes!
@julio4 Kindly review this. |
Hello @julio4 @misicnenad Any chance of you reviewing this soon? |
There was a problem hiding this 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:
- You forgot to address Jules change request related to
mod errors
. - You are missing Scarb.toml file.
- 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 thescarb new <project-name>
command (see The Cairo Book for more details). - The
IERC721
interface in the PR does not match the conventional one:- different function names
- should use
u256
instead of felts andu128
, as Jules said at the end of his original comment IERC721
does not contain functions to getname
,symbol
andtoken_uri
(those are part ofIERC721Metadata
).
- 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.
Yes, this are all valid concerns outlined by @misicnenad |
Hello @julio4 @misicnenad can you review? |
Have you been able to take a look at this? @misicnenad |
There was a problem hiding this 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.
|
||
// 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'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should address Jules's change request related to mod errors
use starknet::ContractAddress; | ||
|
||
#[starknet::interface] | ||
pub trait IERC721<TContractState> { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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::*; |
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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
command as requested and it passed as can be seen from the attached image.
There was a problem hiding this comment.
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()); |
There was a problem hiding this comment.
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:
- testing events in plain Cairo: https://starknet-by-example.voyager.online/getting-started/testing/contract-testing.html#testing-events
- testing events with Foundry: https://foundry-rs.github.io/starknet-foundry/testing/testing-events.html
use starknet::ContractAddress; | ||
|
||
#[starknet::interface] | ||
pub trait IERC721<TContractState> { |
There was a problem hiding this comment.
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!
|
||
let new_owner = contract.owner_of(nft_id); | ||
assert(new_owner == user, 'wrong new OWNER'); | ||
} |
There was a problem hiding this comment.
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.
Hello @julio4 I've implemented all the necessary changes. Kindly review. |
#[test] | ||
#[available_gas(2000000)] | ||
fn test_erc721_burn() { |
There was a problem hiding this comment.
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> { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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::*; |
There was a problem hiding this comment.
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.
There was a problem hiding this 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:
-
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:- Implement the IERC721Metadata trait (see feat: added an ERC721 NFT Contract #214 (comment) and feat: added an ERC721 NFT Contract #214 (comment))
- Implement event emission checks in your tests (see feat: added an ERC721 NFT Contract #214 (comment))
- Set up the tests correctly for Cairo, not for Rust (related feat: added an ERC721 NFT Contract #214 (comment))
Only once you have addressed all of the change requests should you ping the reviewers to review your code.
-
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}; |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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>, |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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"] |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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.
@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. |
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. |
Issue(s): #197
Description
Implemented a simple ERC721 Non-Fungible Token (NFT) contract
Checklist