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: token erc721 uristorage #109

Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ 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 Down Expand Up @@ -59,7 +60,7 @@ pub mod HypErc721Component {
}

#[generate_trait]
impl HypErc721InternalImpl<
pub impl HypErc721InternalImpl<
TContractState,
+HasComponent<TContractState>,
+Drop<TContractState>,
Expand Down
207 changes: 186 additions & 21 deletions cairo/src/contracts/token/extensions/hyp_erc721_URI_storage.cairo
Realkayzee marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,48 +1,213 @@
use starknet::ContractAddress;

#[starknet::interface]
pub trait IHypERC721URIStorage<TState> {
fn initialize(ref self: TState);
fn balance_of(self: @TState, account: u256) -> u256;
fn token_uri(self: @TState, token_id: u256) -> u256;
fn supports_interface(self: @TState, interface_id: u256) -> bool;
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;
use hyperlane_starknet::contracts::client::mailboxclient_component::MailboxclientComponent;
use hyperlane_starknet::contracts::client::router_component::RouterComponent;
use hyperlane_starknet::contracts::client::gas_router_component::GasRouterComponent;
use hyperlane_starknet::contracts::token::components::token_router::{ TokenRouterComponent, TokenRouterComponent::TokenRouterHooksTrait };
use hyperlane_starknet::contracts::token::components::hyp_erc721_component::HypErc721Component;
use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl};
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};

component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
component!(path: MailboxclientComponent, storage: mailboxclient, event: MailboxclientEvent);
component!(path: RouterComponent, storage: router, event: RouterEvent);
component!(path: GasRouterComponent, storage: gas_router, event: GasRouterEvent);
component!(path: TokenRouterComponent, storage: token_router, event: TokenRouterEvent);
component!(path: HypErc721Component, storage: hyp_erc721, event: HypErc721Event);
component!(path: ERC721Component, storage: erc721, event: ERC721Event);
component!(path: SRC5Component, storage: src5, event: SRC5Event);
component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);

// Ownable
#[abi(embed_v0)]
impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;
impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;

// MailboxClient
#[abi(embed_v0)]
impl MailboxClientImpl = MailboxclientComponent::MailboxClientImpl<ContractState>;
impl MailboxClientInternalImpl = MailboxclientComponent::MailboxClientInternalImpl<ContractState>;

//Router
#[abi(embed_v0)]
impl RouterImpl = RouterComponent::RouterImpl<ContractState>;

// GasRouter
#[abi(embed_v0)]
impl GasRouterImpl = GasRouterComponent::GasRouterImpl<ContractState>;

// TokenRouter
#[abi(embed_v0)]
impl TokenRouterImpl = TokenRouterComponent::TokenRouterImpl<ContractState>;
impl TokenRouterInternalImpl = TokenRouterComponent::TokenRouterInternalImpl<ContractState>;

//HypERC721

Realkayzee marked this conversation as resolved.
Show resolved Hide resolved
impl HypErc721Impl = HypErc721Component::HypErc721Impl<ContractState>;
impl HypErc721InternalImpl = HypErc721Component::HypErc721InternalImpl<ContractState>;

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

impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;

#[storage]
struct Storage {
mailbox: u256,
#[substorage(v0)]
ownable: OwnableComponent::Storage,
#[substorage(v0)]
mailboxclient: MailboxclientComponent::Storage,
#[substorage(v0)]
router: RouterComponent::Storage,
#[substorage(v0)]
gas_router: GasRouterComponent::Storage,
#[substorage(v0)]
token_router: TokenRouterComponent::Storage,
#[substorage(v0)]
hyp_erc721: HypErc721Component::Storage,
#[substorage(v0)]
erc721: ERC721Component::Storage,
#[substorage(v0)]
src5: SRC5Component::Storage,
#[substorage(v0)]
upgradeable: UpgradeableComponent::Storage,
}

fn constructor() {}

impl HypERC721URIStorageImpl of super::IHypERC721URIStorage<ContractState> {
fn initialize(ref self: ContractState) {}
#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
OwnableEvent: OwnableComponent::Event,
#[flat]
MailboxclientEvent: MailboxclientComponent::Event,
#[flat]
RouterEvent: RouterComponent::Event,
#[flat]
GasRouterEvent: GasRouterComponent::Event,
#[flat]
TokenRouterEvent: TokenRouterComponent::Event,
#[flat]
ERC721Event: ERC721Component::Event,
#[flat]
SRC5Event: SRC5Component::Event,
#[flat]
HypErc721Event: HypErc721Component::Event,
#[flat]
UpgradeableEvent: UpgradeableComponent::Event,
}

fn balance_of(self: @ContractState, account: u256) -> u256 {
0
}
#[constructor]
fn constructor(
ref self: ContractState,
owner: ContractAddress,
mailbox: ContractAddress
) {
self.ownable._transfer_ownership(owner);
self.mailboxclient.initialize(mailbox, Option::None, Option::None);
}

fn token_uri(self: @ContractState, token_id: u256) -> u256 {
0
#[abi(embed_v0)]
impl HypERC721URIStorageImpl of super::IHypERC721URIStorage<ContractState> {
fn initialize(
Realkayzee marked this conversation as resolved.
Show resolved Hide resolved
ref self: ContractState,
_mint_amount: u256,
_name: ByteArray,
_symbol: ByteArray,
_hook: ContractAddress,
_interchainSecurityModule: ContractAddress,
owner: ContractAddress
) {
self.ownable.initializer(owner);
let mailbox = self.mailboxclient.mailbox.read();
self.mailboxclient.initialize(mailbox.contract_address, Option::Some(_hook), Option::Some(_interchainSecurityModule));
self.hyp_erc721.initialize(
_mint_amount,
_name,
_symbol
);
}
}

fn supports_interface(self: @ContractState, interface_id: u256) -> bool {
false
#[abi(embed_v0)]
impl HypErc721Upgradeable of IUpgradeable<ContractState> {
fn upgrade(ref self: ContractState, new_class_hash: starknet::ClassHash) {
self.ownable.assert_only_owner();
self.upgradeable.upgrade(new_class_hash);
}
}

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

fn transfer_to(ref self: ContractState, recipient: u256, token_id: u256, token_uri: u256) {}
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(
Realkayzee marked this conversation as resolved.
Show resolved Hide resolved
ref self: ContractState, from: u256, to: u256, token_id: u256, batch_size: u256
) {}
ref self: ContractState, from: u256, to: ContractAddress, token_id: u256, batch_size: u256
) {
self.erc721.before_update(to, token_id, Zero::zero());
}
}

impl TokenRouterHooksImpl of TokenRouterHooksTrait<ContractState> {
fn transfer_from_sender_hook(
Realkayzee marked this conversation as resolved.
Show resolved Hide resolved
ref self: TokenRouterComponent::ComponentState<ContractState>,
amount_or_id: u256
) -> Bytes {
let contract_state = TokenRouterComponent::HasComponent::get_contract(@self);
let token_owner = contract_state.erc721.owner_of(amount_or_id);
assert!(
token_owner == get_caller_address(),
"Caller is not owner of token"
);

fn burn(ref self: ContractState, token_id: u256) {}
let mut contract_state = TokenRouterComponent::HasComponent::get_contract_mut(ref self);
contract_state.erc721.burn(amount_or_id);

BytesTrait::new_empty()
}

fn transfer_to_hook(
Realkayzee marked this conversation as resolved.
Show resolved Hide resolved
ref self: TokenRouterComponent::ComponentState<ContractState>,
recipient: u256,
amount_or_id: u256,
metadata: Bytes
) {
let recipient_felt: felt252 = recipient.try_into().expect('u256 to felt failed');
let recipient: ContractAddress = recipient_felt.try_into().unwrap();

let mut contract_state = TokenRouterComponent::HasComponent::get_contract_mut(ref self);
contract_state.erc721.mint(recipient, amount_or_id);
}
}
}