-
Notifications
You must be signed in to change notification settings - Fork 342
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
Add ERC6909 #1040
base: main
Are you sure you want to change the base?
Add ERC6909 #1040
Conversation
Removed much of the logic for these extensions from the `ERC6909Component`. Now these are different components. Reason for this was to keep the original code as small as possible as metadata, supply and uri are not part of the EIP, but are just optional extensions
Thanks for opening this PR @swan-of-bodom! It may take some time to review this since it's quite big, but we'll get to it as soon as we can |
No worries, thank 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.
Good start on this! I still have to review tests, but I think it's worth giving feedback now on design choices, implementations, and styling
src/token/erc6909/dual6909.cairo
Outdated
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.
We include dual dispatchers to provide a means of supporting camelCase entrypoints from the (inconsistent) Cairo v0 convention. Since ERC6909 is a new standard to this lib and it's not backwards compatible with the existing token standards, we don't need to include the dual dispatcher for it
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.
Removed the dual dispatcher in a27fe02.
Thanks!
src/token/erc6909/erc6909.cairo
Outdated
fn supports_interface( | ||
self: @ComponentState<TContractState>, interface_id: felt252 | ||
) -> bool { | ||
interface_id == interface::IERC6909_ID || interface_id == ISRC5_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.
Shouldn't this component have SRC5 as a dependency? If a contract implemented this and access control, for example, supports_interface
would clash when exposing them. SRC5 stores a contract's supported interfaces in storage, so I think the IERC6909 should be set in SRC5's storage during construction (in the initializer)
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.
Definitely, you are right, implementing this with access control would clash. Will set it in storage
src/token/erc6909/erc6909.cairo
Outdated
#[embeddable_as(ERC6909CamelOnlyImpl)] | ||
impl ERC6909CamelOnly< | ||
TContractState, +HasComponent<TContractState>, +ERC6909HooksTrait<TContractState> | ||
> of interface::IERC6909CamelOnly<ComponentState<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.
We can remove these. See the comment in the dual dispatchers module
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.
Removed in a27fe02
src/token/erc6909/erc6909.cairo
Outdated
/// @notice The event emitted when a transfer occurs. | ||
/// @param caller The caller of the transfer. | ||
/// @param sender The address of the sender. | ||
/// @param receiver The address of the receiver. | ||
/// @param id The id of the token. | ||
/// @param amount The amount of the token. |
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 code is well-documented! Though, we don't follow natspec. We use a rust-like style. Would you mind updating the documentation to be consistent with our style (see our other components)?
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 updated the comments to match as close as possible to the other components. 03e577e
src/token/erc6909/erc6909.cairo
Outdated
/// @dev Thrown when owner balance for id is insufficient. | ||
pub const INSUFFICIENT_BALANCE: felt252 = 'ERC6909: insufficient balance'; | ||
/// @dev Thrown when spender allowance for id is insufficient. | ||
pub const INSUFFICIENT_ALLOWANCE: felt252 = 'ERC6909: insufficient allowance'; | ||
/// @dev Thrown when transferring from the zero address | ||
pub const TRANSFER_FROM_ZERO: felt252 = 'ERC6909: transfer from 0'; | ||
/// @dev Thrown when transferring to the zero address | ||
pub const TRANSFER_TO_ZERO: felt252 = 'ERC6909: transfer to 0'; | ||
/// @dev Thrown when minting to the zero address | ||
pub const MINT_TO_ZERO: felt252 = 'ERC6909: mint to 0'; | ||
/// @dev Thrown when burning from the zero address | ||
pub const BURN_FROM_ZERO: felt252 = 'ERC6909: burn from 0'; | ||
/// @dev Thrown when approving from the zero address | ||
pub const APPROVE_FROM_ZERO: felt252 = 'ERC6909: approve from 0'; | ||
/// @dev Thrown when approving to the zero 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.
Again, I know this is directly from the reference in the EIP, but we can omit these comments. The const name conveys enough IMO. (We should also be using panics
instead of thrown
in cairoland)
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.
Same as above, updated comments on 03e577e
* xref:#ERC6909Component-_set_operator[`++_set_operator(self, owner, spender, approved)++`] | ||
* xref:#ERC6909Component-_spend_allowance[`++_spend_allowance(self, sender, spender, id, amount)++`] | ||
* xref:#ERC6909Component-_approve[`++_approve(self, owner, spender, id, amount)++`] | ||
* xref:#ERC6909Component-_transfer[`++_approve(self, caller, sender, receiver, id, amount)++`] |
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.
* xref:#ERC6909Component-_transfer[`++_approve(self, caller, sender, receiver, id, amount)++`] | |
* xref:#ERC6909Component-_transfer[`++_transfer(self, caller, sender, receiver, id, amount)++`] |
|
||
[.contract-item] | ||
[[ERC6909Component-Approval]] | ||
==== `[.contract-item-name]#++Approval++#++(owner: ContractAddress, spender: ContractAddress, value: u256)++` [.item-kind]#event# |
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.
==== `[.contract-item-name]#++Approval++#++(owner: ContractAddress, spender: ContractAddress, value: u256)++` [.item-kind]#event# | |
==== `[.contract-item-name]#++Approval++#++(owner: ContractAddress, spender: ContractAddress, id: u256, amount: u256)++` [.item-kind]#event# |
|
||
NOTE: Implementing xref:#ERC6909Component[ERC6909Component] is a requirement for this component to be implemented. | ||
|
||
This extension allows to set the contract URI (ideally) in the constructor via `initializer(uri: ByteArray)`. |
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.
This extension allows to set the contract URI (ideally) in the constructor via `initializer(uri: ByteArray)`. | |
This extension allows contracts to set the contract URI in the constructor via `initializer`. |
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.
And this may include setting the base_uri
depending on the design discussion
|
||
NOTE: Implementing xref:#ERC6909Component[ERC6909Component] is a requirement for this component to be implemented. | ||
|
||
WARNING: To individual token metadata, this extension requires that the |
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.
Not sure what you mean by "To individual token metadata"
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.
We're missing the ERC6909TokenSupply section and the actual API for ERC6909Metadata
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.
Thanks for your efforts! I've left several suggestions. Please note that to approve the implementation we'll have to wait till the EIP-6909 is finalized, since atm it's still in the draft state
src/token/erc6909/erc6909.cairo
Outdated
// SPDX-License-Identifier: MIT | ||
// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc6909/erc6909.cairo) | ||
|
||
use core::starknet::{ContractAddress}; |
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 core::starknet::{ContractAddress}; | |
use starknet::ContractAddress; |
src/token/erc6909/erc6909.cairo
Outdated
use starknet::ContractAddress; | ||
use starknet::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.
use starknet::ContractAddress; | |
use starknet::get_caller_address; | |
use starknet::{ContractAddress, 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.
Updated in 56570aa
src/token/erc6909/erc6909.cairo
Outdated
|
||
let zero_address = Zero::zero(); | ||
|
||
if (sender != zero_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.
if (sender != zero_address) { | |
if (sender.is_non_zero()) { |
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.
Fixed in 40538f6
src/token/erc6909/erc6909.cairo
Outdated
self.ERC6909_balances.write((sender, id), sender_balance - amount); | ||
} | ||
|
||
if (receiver != zero_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.
if (receiver != zero_address) { | |
if (receiver.is_non_zero()) { |
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.
Fixed in 40538f6
src/token/erc6909/erc6909.cairo
Outdated
/// Does not update the allowance value in case of infinite allowance or if spender is operator. | ||
fn _spend_allowance( | ||
ref self: ComponentState<TContractState>, | ||
sender: ContractAddress, |
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.
Should this parameter be named owner
as in 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.
Renamed it to owner
in 40538f6 to match ERC20!
src/token/erc6909/erc6909.cairo
Outdated
caller: ContractAddress, // For the `Transfer` event | ||
sender: ContractAddress, // from | ||
receiver: ContractAddress, // to |
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.
+1
I think getting caller
by calling get_caller_address
in the function makes total sense and can reduce the amount of parameters
let zero_address = Zero::zero(); | ||
|
||
// In case of new ID mints update the token metadata | ||
if (sender == zero_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.
if (sender == zero_address) { | |
if (sender.is_zero()) { |
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.
Fixed in 40538f6
let zero_address = Zero::zero(); | ||
|
||
// In case of mints we increase the total supply of this token ID | ||
if (sender == zero_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.
if (sender == zero_address) { | |
if (sender.is_zero()) { |
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.
Fixed in 40538f6.
} | ||
|
||
// In case of burns we decrease the total supply of this token ID | ||
if (receiver == zero_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.
if (receiver == zero_address) { | |
if (receiver.is_zero()) { |
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.
Fixed in 40538f6 thank you!
Thanks, happy to contribute to this great library :) |
Adding the new multi-token standard ERC6909 written in Cairo. This token standard will most likely be used by UniswapV4 so might be interesting to have one for Cairo too as discussed with @andrew-fleming
Deploy transaction:
0x004297aadb57195520d58b6de3db91c14bb30284080c78b7f3d65407d2d06e79
Mint transaction:
0x008debb59434cc64f432110c118d8ba64725545764a71529c7226d127d46df5a
Thanks!