Skip to content

Commit

Permalink
integrate erc721 uri storage
Browse files Browse the repository at this point in the history
  • Loading branch information
Realkayzee committed Sep 13, 2024
1 parent d44fcf7 commit 04489e1
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 114 deletions.
21 changes: 18 additions & 3 deletions cairo/src/contracts/token/components/erc721_uri_storage.cairo
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#[starknet::interface]
pub trait IERC721URIStorage<TContractState> {
fn name(self: @TContractState) -> ByteArray;
fn symbol(self: @TContractState) -> ByteArray;
fn token_uri(self: @TContractState, token_id: u256) -> ByteArray;
}

#[starknet::component]
pub mod ERC721URIStorageComponent {
use openzeppelin::token::erc721::interface::IERC721Metadata;
use openzeppelin::introspection::src5::SRC5Component;
use openzeppelin::token::erc721::{
ERC721Component, ERC721Component::InternalTrait as ERC721InternalTrait,
Expand All @@ -18,7 +21,7 @@ pub mod ERC721URIStorageComponent {

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
pub enum Event {
MetadataUpdate: MetadataUpdate,
}

Expand All @@ -28,14 +31,26 @@ pub mod ERC721URIStorageComponent {
}

#[embeddable_as(ERC721URIStorageImpl)]
impl ERC721URIStorage<
pub impl ERC721URIStorage<
TContractState,
+HasComponent<TContractState>,
+Drop<TContractState>,
+SRC5Component::HasComponent<TContractState>,
+ERC721HooksTrait<TContractState>,
impl ERC721: ERC721Component::HasComponent<TContractState>,
> of super::IERC721URIStorage<ComponentState<TContractState>> {
// returns the NFT name
fn name(self: @ComponentState<TContractState>) -> ByteArray {
let erc721_component = get_dep_component!(self, ERC721);
erc721_component.name()
}

// returns the NFT symbol
fn symbol(self: @ComponentState<TContractState>) -> ByteArray {
let erc721_component = get_dep_component!(self, ERC721);
erc721_component.symbol()
}

/// Returns the URI associated with a given `token_id`.
///
/// This function retrieves the URI for an ERC721 token based on its `token_id`.
Expand Down Expand Up @@ -71,7 +86,7 @@ pub mod ERC721URIStorageComponent {
}

#[generate_trait]
impl ERC721URIStorageInternalImpl<
pub impl ERC721URIStorageInternalImpl<
TContractState,
+HasComponent<TContractState>,
+Drop<TContractState>,
Expand Down
67 changes: 6 additions & 61 deletions cairo/src/contracts/token/components/hyp_erc721_component.cairo
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use starknet::{ContractAddress, ClassHash};

#[starknet::interface]
pub trait IHypErc721<TState> {
fn initialize(ref self: TState, mint_amount: u256, name: ByteArray, symbol: ByteArray, base_uri: ByteArray);
fn initialize(ref self: TState, mint_amount: u256, name: ByteArray, symbol: ByteArray);
}

#[starknet::component]
Expand All @@ -11,7 +9,6 @@ pub mod HypErc721Component {
MailboxclientComponent, MailboxclientComponent::MailboxClientInternalImpl,
MailboxclientComponent::MailboxClient
};
use hyperlane_starknet::contracts::token::components::token_router::{ TokenRouterComponent, TokenRouterComponent::TokenRouterHooksTrait as TokenRouterHooksTraits };
use openzeppelin::access::ownable::{
OwnableComponent, OwnableComponent::InternalImpl as OwnableInternalImpl
};
Expand All @@ -23,23 +20,21 @@ pub mod HypErc721Component {
ERC721Component::InternalTrait as ERC721InternalTrait, ERC721Component::ERC721HooksTrait,
};

use starknet::{ContractAddress, ClassHash};


#[storage]
struct Storage {}

#[embeddable_as(HypErc721Impl)]
pub impl HypErc721<
#[generate_trait]
pub impl HypErc721InternalImpl<
TContractState,
+HasComponent<TContractState>,
+Drop<TContractState>,
+OwnableComponent::HasComponent<TContractState>,
+SRC5Component::HasComponent<TContractState>,
+ERC721Component::ERC721HooksTrait<TContractState>,
+ERC721HooksTrait<TContractState>,
impl Mailboxclient: MailboxclientComponent::HasComponent<TContractState>,
impl ERC721: ERC721Component::HasComponent<TContractState>,
> of super::IHypErc721<ComponentState<TContractState>> {
> of HypErc721InternalTrait<TContractState> {
/// Initializes the ERC721 token contract with a specified mint amount, name, and symbol.
///
/// This function sets the name and symbol for the ERC721 token contract and mints the specified number
Expand All @@ -56,10 +51,9 @@ pub mod HypErc721Component {
mint_amount: u256,
name: ByteArray,
symbol: ByteArray,
base_uri: ByteArray
) {
let mut erc721_comp = get_dep_component_mut!(ref self, ERC721);
erc721_comp.initializer(name, symbol, base_uri);
erc721_comp.initializer(name, symbol, "");

let caller = starknet::get_caller_address();

Expand All @@ -70,53 +64,4 @@ pub mod HypErc721Component {
};
}
}

#[generate_trait]
pub impl HypErc721InternalImpl<
TContractState,
+HasComponent<TContractState>,
+Drop<TContractState>,
+SRC5Component::HasComponent<TContractState>,
+ERC721Component::ERC721HooksTrait<TContractState>,
impl ERC721: ERC721Component::HasComponent<TContractState>,
> of InternalTrait<TContractState> {
/// Burns a token owned by the sender.
///
/// This function ensures that the sender is the owner of the specified token before burning it.
/// The token is permanently removed from the sender's balance.
///
/// # Arguments
///
/// * `token_id` - A `u256` representing the ID of the token to be burned.
///
/// # Panics
///
/// Panics if the caller is not the owner of the token.
fn transfer_from_sender(ref self: ComponentState<TContractState>, token_id: u256) {
let erc721_comp_read = get_dep_component!(@self, ERC721);
assert!(
erc721_comp_read.owner_of(token_id) == starknet::get_caller_address(),
"Caller is not owner of token"
);

let mut erc721_comp_write = get_dep_component_mut!(ref self, ERC721);
erc721_comp_write.burn(token_id);
}

/// Mints a token to a specified recipient.
///
/// This function mints the specified token to the given recipient's address. The newly minted token
/// will be transferred to the recipient.
///
/// # Arguments
///
/// * `recipient` - A `ContractAddress` representing the recipient's address.
/// * `token_id` - A `u256` representing the ID of the token to be minted.
fn transfer_to(
ref self: ComponentState<TContractState>, recipient: ContractAddress, token_id: u256
) {
let mut erc721_comp_write = get_dep_component_mut!(ref self, ERC721);
erc721_comp_write.mint(recipient, token_id);
}
}
}
88 changes: 42 additions & 46 deletions cairo/src/contracts/token/extensions/hyp_erc721_URI_storage.cairo
Original file line number Diff line number Diff line change
@@ -1,21 +1,3 @@
use starknet::ContractAddress;

#[starknet::interface]
pub trait IHypERC721URIStorage<TState> {
fn initialize(
ref self: TState,
_mint_amount: u256,
_name: ByteArray,
_symbol: ByteArray,
_hook: ContractAddress,
_interchainSecurityModule: ContractAddress,
owner: ContractAddress
);
}

#[starknet::interface]


#[starknet::contract]
pub mod HypERC721URIStorage {
use openzeppelin::access::ownable::OwnableComponent;
Expand All @@ -27,13 +9,17 @@ pub mod HypERC721URIStorage {
TokenRouterComponent::MessageRecipientInternalHookImpl,
TokenRouterTransferRemoteHookDefaultImpl
};
use hyperlane_starknet::contracts::token::components::hyp_erc721_component::HypErc721Component;
use openzeppelin::token::erc721::{ERC721Component, ERC721Component::ERC721HooksTrait};
use hyperlane_starknet::contracts::token::components::hyp_erc721_component::{
HypErc721Component
};
use openzeppelin::token::erc721::{
ERC721Component, ERC721Component::ERC721HooksTrait
};
use openzeppelin::introspection::src5::SRC5Component;
use starknet::{ ContractAddress, get_caller_address };
use core::num::traits::Zero;
use alexandria_bytes::{ Bytes, BytesTrait };
use openzeppelin::upgrades::{interface::IUpgradeable, upgradeable::UpgradeableComponent};
use hyperlane_starknet::contracts::token::components::erc721_uri_storage::ERC721URIStorageComponent;
use alexandria_bytes::{ Bytes, BytesTrait };

component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
component!(path: MailboxclientComponent, storage: mailboxclient, event: MailboxclientEvent);
Expand All @@ -44,6 +30,7 @@ pub mod HypERC721URIStorage {
component!(path: ERC721Component, storage: erc721, event: ERC721Event);
component!(path: SRC5Component, storage: src5, event: SRC5Event);
component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);
component!(path: ERC721URIStorageComponent, storage: erc721_uri_storage, event: ERC721UriStorageEvent);

// Ownable
#[abi(embed_v0)]
Expand All @@ -70,15 +57,19 @@ pub mod HypERC721URIStorage {
impl TokenRouterInternalImpl = TokenRouterComponent::TokenRouterInternalImpl<ContractState>;

//HypERC721

impl HypErc721Impl = HypErc721Component::HypErc721Impl<ContractState>;
impl HypErc721InternalImpl = HypErc721Component::HypErc721InternalImpl<ContractState>;

//ERC721
#[abi(embed_v0)]
impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl<ContractState>;
impl ERC721URIStorageImpl = ERC721URIStorageComponent::ERC721URIStorageImpl<ContractState>;
#[abi(embed_v0)]
impl ERC721Impl = ERC721Component::ERC721Impl<ContractState>;
#[abi(embed_v0)]
impl ERC721CamelOnlyImpl = ERC721Component::ERC721CamelOnlyImpl<ContractState>;
impl ERC721InternalImpl = ERC721Component::InternalImpl<ContractState>;
impl ERC721URIStorageInternalImpl = ERC721URIStorageComponent::ERC721URIStorageInternalImpl<ContractState>;

//upgradeable
impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;

#[storage]
Expand All @@ -101,6 +92,8 @@ pub mod HypERC721URIStorage {
src5: SRC5Component::Storage,
#[substorage(v0)]
upgradeable: UpgradeableComponent::Storage,
#[substorage(v0)]
erc721_uri_storage: ERC721URIStorageComponent::Storage,
}

#[event]
Expand All @@ -124,6 +117,8 @@ pub mod HypERC721URIStorage {
HypErc721Event: HypErc721Component::Event,
#[flat]
UpgradeableEvent: UpgradeableComponent::Event,
#[flat]
ERC721UriStorageEvent: ERC721URIStorageComponent::Event,
}

#[constructor]
Expand All @@ -143,8 +138,7 @@ pub mod HypERC721URIStorage {
self.hyp_erc721.initialize(
_mint_amount,
_name,
_symbol,
_base_uri
_symbol
)
}

Expand All @@ -156,24 +150,6 @@ pub mod HypERC721URIStorage {
}
}

// #[generate_trait]
// impl InternalImpl of InternalTrait {
// fn transfer_from_sender(ref self: ContractState, token_id: u256) -> u256 {
// self.hyp_erc721.transfer_from_sender(token_id);
// token_id
// }

// fn transfer_to(ref self: ContractState, recipient: ContractAddress, token_id: u256, token_uri: u256) {
// self.hyp_erc721.transfer_to(recipient, token_id);
// }

// fn before_token_transfer(
// ref self: ContractState, from: u256, to: ContractAddress, token_id: u256, batch_size: u256
// ) {
// self.erc721.before_update(to, token_id, Zero::zero());
// }
// }

// would be extended when erc721_enumerable is imported
impl ERC721HooksImpl of ERC721HooksTrait<ContractState> {
fn before_update(
Expand All @@ -191,7 +167,6 @@ pub mod HypERC721URIStorage {
) {}
}


impl TokenRouterHooksImpl of TokenRouterHooksTrait<ContractState> {
fn transfer_from_sender_hook(
ref self: TokenRouterComponent::ComponentState<ContractState>,
Expand Down Expand Up @@ -220,7 +195,28 @@ pub mod HypERC721URIStorage {
let recipient: ContractAddress = recipient_felt.try_into().unwrap();

let mut contract_state = TokenRouterComponent::HasComponent::get_contract_mut(ref self);

let metadata_byteArray = bytes_to_byte_array(metadata);
contract_state.erc721_uri_storage._set_token_uri(amount_or_id, metadata_byteArray);
contract_state.erc721.mint(recipient, amount_or_id);
}
}

// free function
fn bytes_to_byte_array(self: Bytes) -> ByteArray {
let mut res: ByteArray = Default::default();
let mut offset = 0;
while offset < self.size() {
if offset + 31 <= self.size() {
let (new_offset, value) = self.read_bytes31(offset);
res.append_word(value.into(), 31);
offset = new_offset;
} else {
let (new_offset, value) = self.read_u8(offset);
res.append_byte(value);
offset = new_offset;
}
};
res
}
}
6 changes: 2 additions & 4 deletions cairo/src/contracts/token/hyp_erc721.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ pub mod HypErc721 {
impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;

// HypERC721
#[abi(embed_v0)]
impl HypErc721Impl = HypErc721Component::HypErc721Impl<ContractState>;
impl HypErc721InternalImpl = HypErc721Component::HypErc721InternalImpl<ContractState>;

// TokenRouter
#[abi(embed_v0)]
Expand Down Expand Up @@ -140,7 +139,6 @@ pub mod HypErc721 {
mailbox: ContractAddress,
name: ByteArray,
symbol: ByteArray,
base_uri: ByteArray,
mint_amount: u256,
hook: ContractAddress,
interchain_security_module: ContractAddress,
Expand All @@ -150,7 +148,7 @@ pub mod HypErc721 {
self
.mailboxclient
.initialize(mailbox, Option::Some(hook), Option::Some(interchain_security_module));
self.hyp_erc721.initialize(mint_amount, name, symbol, base_uri);
self.hyp_erc721.initialize(mint_amount, name, symbol);
}

#[abi(embed_v0)]
Expand Down

0 comments on commit 04489e1

Please sign in to comment.