Skip to content

Commit

Permalink
ERC721 components (dojoengine#58)
Browse files Browse the repository at this point in the history
* add erc721 component files and test templates

* Complete approval test

* - fix components
- add remaining tests

* fix tests

* scarb fmt

* remove components in lib for 0.6.0 fix

* - apply fixes
- add erc721_enumerable
- add tests
- begin migration to ByteArray

* - remove lib code apart from erc721_metdadata

* - apply fixes
- update to 0.7.0-alpha.4
- add ByteArray
- add ERC721Receiver logic
- remove enumerables for separate PR

* - begin alpha.5 rebase

* - update to 0.7.0-alpha.5
- add ByteArrays for erc20
- fmt code

* move dojo model tags

* - make initalizer assertion that world owner called
-  change _ naming convention to internal
- use initialize protection

* fmt whitespace
  • Loading branch information
starknetdev authored Jun 4, 2024
1 parent a22e5fd commit ebc3677
Show file tree
Hide file tree
Showing 28 changed files with 2,507 additions and 67 deletions.
19 changes: 18 additions & 1 deletion token/src/components/tests.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ mod mocks {
mod erc20_mintable_burnable_mock;
mod erc20_bridgeable_mock;
}

mod erc721 {
mod erc721_approval_mock;
mod erc721_balance_mock;
mod erc721_metadata_mock;
mod erc721_mintable_burnable_mock;
mod erc721_receiver_mock;
}
}

mod introspection {
Expand Down Expand Up @@ -36,5 +44,14 @@ mod token {
mod test_erc20_bridgeable;
}

mod erc711 {}
mod erc721 {
#[cfg(test)]
mod test_erc721_approval;
#[cfg(test)]
mod test_erc721_balance;
#[cfg(test)]
mod test_erc721_metadata;
#[cfg(test)]
mod test_erc721_mintable_burnable;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use starknet::ContractAddress;
trait IERC20BridgeableMockInit<TState> {
fn initializer(
ref self: TState,
name: felt252,
symbol: felt252,
name: ByteArray,
symbol: ByteArray,
initial_supply: u256,
recipient: ContractAddress,
l2_bridge_address: ContractAddress,
Expand Down Expand Up @@ -108,8 +108,8 @@ mod erc20_bridgeable_mock {
impl ERC20InitializerImpl of super::IERC20BridgeableMockInit<ContractState> {
fn initializer(
ref self: ContractState,
name: felt252,
symbol: felt252,
name: ByteArray,
symbol: ByteArray,
initial_supply: u256,
recipient: ContractAddress,
l2_bridge_address: ContractAddress,
Expand Down
39 changes: 39 additions & 0 deletions token/src/components/tests/mocks/erc721/erc721_approval_mock.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#[dojo::contract]
mod erc721_approval_mock {
use token::components::token::erc721::erc721_approval::erc721_approval_component;
use token::components::token::erc721::erc721_owner::erc721_owner_component;

component!(
path: erc721_approval_component, storage: erc721_approval, event: ERC721ApprovalEvent
);
component!(path: erc721_owner_component, storage: erc721_owner, event: ERC721OwnerEvent);

#[abi(embed_v0)]
impl ERC721ApprovalImpl =
erc721_approval_component::ERC721ApprovalImpl<ContractState>;

#[abi(embed_v0)]
impl ERC721ApprovalCamelImpl =
erc721_approval_component::ERC721ApprovalCamelImpl<ContractState>;

#[abi(embed_v0)]
impl ERC721OwnerImpl = erc721_owner_component::ERC721OwnerImpl<ContractState>;

impl ERC721ApprovalInternalImpl = erc721_approval_component::InternalImpl<ContractState>;
impl ERC721OwnerInternalImpl = erc721_owner_component::InternalImpl<ContractState>;

#[storage]
struct Storage {
#[substorage(v0)]
erc721_approval: erc721_approval_component::Storage,
#[substorage(v0)]
erc721_owner: erc721_owner_component::Storage,
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
ERC721ApprovalEvent: erc721_approval_component::Event,
ERC721OwnerEvent: erc721_owner_component::Event
}
}
112 changes: 112 additions & 0 deletions token/src/components/tests/mocks/erc721/erc721_balance_mock.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use starknet::{ContractAddress, ClassHash};
use dojo::world::IWorldDispatcher;

#[starknet::interface]
trait IERC721BalanceMock<TState> {
// IERC721
fn owner_of(self: @TState, token_id: u256) -> ContractAddress;
fn balance_of(self: @TState, account: ContractAddress) -> u256;
fn get_approved(self: @TState, token_id: u256) -> ContractAddress;
fn transfer_from(ref self: TState, from: ContractAddress, to: ContractAddress, token_id: u256);
fn safe_transfer_from(
ref self: TState,
from: ContractAddress,
to: ContractAddress,
token_id: u256,
data: Span<felt252>
);
fn approve(ref self: TState, to: ContractAddress, token_id: u256);

// IERC721CamelOnly
fn balanceOf(self: @TState, account: ContractAddress) -> u256;
fn transferFrom(ref self: TState, from: ContractAddress, to: ContractAddress, token_id: u256);
fn safeTransferFrom(
ref self: TState,
from: ContractAddress,
to: ContractAddress,
token_id: u256,
data: Span<felt252>
);

// IWorldProvider
fn world(self: @TState,) -> IWorldDispatcher;

fn initializer(ref self: TState, recipient: ContractAddress, token_id: u256);
}

#[starknet::interface]
trait IERC721BalanceMockInit<TState> {
fn initializer(ref self: TState, recipient: ContractAddress, token_id: u256);
}

#[dojo::contract(allow_ref_self)]
mod erc721_balance_mock {
use starknet::ContractAddress;
use token::components::token::erc721::erc721_approval::erc721_approval_component;
use token::components::token::erc721::erc721_balance::erc721_balance_component;
use token::components::token::erc721::erc721_mintable::erc721_mintable_component;
use token::components::token::erc721::erc721_owner::erc721_owner_component;

component!(
path: erc721_approval_component, storage: erc721_approval, event: ERC721ApprovalEvent
);
component!(path: erc721_balance_component, storage: erc721_balance, event: ERC721BalanceEvent);
component!(
path: erc721_mintable_component, storage: erc721_mintable, event: ERC721MintableEvent
);
component!(path: erc721_owner_component, storage: erc721_owner, event: ERC721OwnerEvent);

#[abi(embed_v0)]
impl ERC721ApprovalImpl =
erc721_approval_component::ERC721ApprovalImpl<ContractState>;

#[abi(embed_v0)]
impl ERC721ApprovalCamelImpl =
erc721_approval_component::ERC721ApprovalCamelImpl<ContractState>;

#[abi(embed_v0)]
impl ERC721BalanceImpl =
erc721_balance_component::ERC721BalanceImpl<ContractState>;

#[abi(embed_v0)]
impl ERC721BalanceCamelImpl =
erc721_balance_component::ERC721BalanceCamelImpl<ContractState>;

#[abi(embed_v0)]
impl ERC721OwnerImpl = erc721_owner_component::ERC721OwnerImpl<ContractState>;

impl ERC721ApprovalInternalImpl = erc721_approval_component::InternalImpl<ContractState>;
impl ERC721BalanceInternalImpl = erc721_balance_component::InternalImpl<ContractState>;
impl ERC721MintableInternalImpl = erc721_mintable_component::InternalImpl<ContractState>;
impl ERC721OwnerInternalImpl = erc721_owner_component::InternalImpl<ContractState>;

#[storage]
struct Storage {
#[substorage(v0)]
erc721_approval: erc721_approval_component::Storage,
#[substorage(v0)]
erc721_balance: erc721_balance_component::Storage,
#[substorage(v0)]
erc721_mintable: erc721_mintable_component::Storage,
#[substorage(v0)]
erc721_owner: erc721_owner_component::Storage,
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
ERC721ApprovalEvent: erc721_approval_component::Event,
ERC721BalanceEvent: erc721_balance_component::Event,
ERC721MintableEvent: erc721_mintable_component::Event,
ERC721OwnerEvent: erc721_owner_component::Event,
}


#[abi(embed_v0)]
impl InitializerImpl of super::IERC721BalanceMockInit<ContractState> {
fn initializer(ref self: ContractState, recipient: ContractAddress, token_id: u256) {
// mint to recipient
self.erc721_mintable.mint(recipient, token_id);
}
}
}
54 changes: 54 additions & 0 deletions token/src/components/tests/mocks/erc721/erc721_metadata_mock.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#[dojo::contract]
mod erc721_metadata_mock {
use token::components::token::erc721::erc721_approval::erc721_approval_component;
use token::components::token::erc721::erc721_balance::erc721_balance_component;
use token::components::token::erc721::erc721_metadata::erc721_metadata_component;
use token::components::token::erc721::erc721_mintable::erc721_mintable_component;
use token::components::token::erc721::erc721_owner::erc721_owner_component;

component!(
path: erc721_approval_component, storage: erc721_approval, event: ERC721ApprovalEvent
);
component!(path: erc721_balance_component, storage: erc721_balance, event: ERC721BalanceEvent);
component!(
path: erc721_metadata_component, storage: erc721_metadata, event: ERC721MetadataEvent
);
component!(
path: erc721_mintable_component, storage: erc721_mintable, event: ERC721MintableEvent
);
component!(path: erc721_owner_component, storage: erc721_owner, event: ERC721OwnerEvent);

#[abi(embed_v0)]
impl ERC721MetadataImpl =
erc721_metadata_component::ERC721MetadataImpl<ContractState>;

impl ERC721ApprovalInternalImpl = erc721_approval_component::InternalImpl<ContractState>;
impl ERC721BalanceInternalImpl = erc721_balance_component::InternalImpl<ContractState>;
impl ERC721MetadataInternalImpl = erc721_metadata_component::InternalImpl<ContractState>;
impl ERC721MintableInternalImpl = erc721_mintable_component::InternalImpl<ContractState>;
impl ERC721OwnerInternalImpl = erc721_owner_component::InternalImpl<ContractState>;

#[storage]
struct Storage {
#[substorage(v0)]
erc721_approval: erc721_approval_component::Storage,
#[substorage(v0)]
erc721_balance: erc721_balance_component::Storage,
#[substorage(v0)]
erc721_metadata: erc721_metadata_component::Storage,
#[substorage(v0)]
erc721_mintable: erc721_mintable_component::Storage,
#[substorage(v0)]
erc721_owner: erc721_owner_component::Storage,
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
ERC721ApprovalEvent: erc721_approval_component::Event,
ERC721BalanceEvent: erc721_balance_component::Event,
ERC721MetadataEvent: erc721_metadata_component::Event,
ERC721MintableEvent: erc721_mintable_component::Event,
ERC721OwnerEvent: erc721_owner_component::Event
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#[dojo::contract]
mod erc721_mintable_burnable_mock {
use token::components::token::erc721::erc721_approval::erc721_approval_component;
use token::components::token::erc721::erc721_balance::erc721_balance_component;
use token::components::token::erc721::erc721_metadata::erc721_metadata_component;
use token::components::token::erc721::erc721_mintable::erc721_mintable_component;
use token::components::token::erc721::erc721_burnable::erc721_burnable_component;
use token::components::token::erc721::erc721_owner::erc721_owner_component;

component!(
path: erc721_approval_component, storage: erc721_approval, event: ERC721ApprovalEvent
);
component!(path: erc721_balance_component, storage: erc721_balance, event: ERC721BalanceEvent);
component!(
path: erc721_metadata_component, storage: erc721_metadata, event: ERC721MetadataEvent
);
component!(
path: erc721_mintable_component, storage: erc721_mintable, event: ERC721MintableEvent
);
component!(
path: erc721_burnable_component, storage: erc721_burnable, event: ERC721BurnableEvent
);
component!(path: erc721_owner_component, storage: erc721_owner, event: ERC721OwnerEvent);

impl ERC721ApprovalInternalImpl = erc721_approval_component::InternalImpl<ContractState>;
impl ERC721BalanceInternalImpl = erc721_balance_component::InternalImpl<ContractState>;
impl ERC721MetadataInternalImpl = erc721_metadata_component::InternalImpl<ContractState>;
impl ERC721MintableInternalImpl = erc721_mintable_component::InternalImpl<ContractState>;
impl ERC721BurnableInternalImpl = erc721_burnable_component::InternalImpl<ContractState>;
impl ERC721OwnerInternalImpl = erc721_owner_component::InternalImpl<ContractState>;

#[storage]
struct Storage {
#[substorage(v0)]
erc721_approval: erc721_approval_component::Storage,
#[substorage(v0)]
erc721_balance: erc721_balance_component::Storage,
#[substorage(v0)]
erc721_metadata: erc721_metadata_component::Storage,
#[substorage(v0)]
erc721_mintable: erc721_mintable_component::Storage,
#[substorage(v0)]
erc721_burnable: erc721_burnable_component::Storage,
#[substorage(v0)]
erc721_owner: erc721_owner_component::Storage,
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
ERC721ApprovalEvent: erc721_approval_component::Event,
ERC721BalanceEvent: erc721_balance_component::Event,
ERC721MetadataEvent: erc721_metadata_component::Event,
ERC721MintableEvent: erc721_mintable_component::Event,
ERC721BurnableEvent: erc721_burnable_component::Event,
ERC721OwnerEvent: erc721_owner_component::Event
}
}
57 changes: 57 additions & 0 deletions token/src/components/tests/mocks/erc721/erc721_receiver_mock.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use dojo::world::IWorldDispatcher;

#[starknet::interface]
trait IERC721ReceiverMock<TState> {
fn supports_interface(self: @TState, interface_id: felt252) -> bool;
fn supportsInterface(self: @TState, interfaceId: felt252) -> bool;

fn initializer(ref self: TState);
}

#[starknet::interface]
trait IERC721ReceiverMockInit<TState> {
fn initializer(ref self: TState);
}

#[dojo::contract(allow_ref_self)]
mod erc721_receiver_mock {
use token::components::introspection::src5::src5_component;
use token::components::token::erc721::erc721_receiver::erc721_receiver_component;

component!(
path: erc721_receiver_component, storage: erc721_receiver, event: ERC721ReceiverEvent
);
component!(path: src5_component, storage: src5, event: SRC5Event);

#[abi(embed_v0)]
impl SRC5Impl = src5_component::SRC5Impl<ContractState>;

#[abi(embed_v0)]
impl ERC721ReceiverImpl =
erc721_receiver_component::ERC721ReceiverImpl<ContractState>;

impl ERC721ReceiverInternalImpl = erc721_receiver_component::InternalImpl<ContractState>;

#[storage]
struct Storage {
#[substorage(v0)]
erc721_receiver: erc721_receiver_component::Storage,
#[substorage(v0)]
src5: src5_component::Storage
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
ERC721ReceiverEvent: erc721_receiver_component::Event,
SRC5Event: src5_component::Event
}

#[abi(embed_v0)]
impl InitializerImpl of super::IERC721ReceiverMockInit<ContractState> {
fn initializer(ref self: ContractState) {
// mint to recipient
self.erc721_receiver.initializer();
}
}
}
Loading

0 comments on commit ebc3677

Please sign in to comment.