Skip to content

Commit

Permalink
updated version of the code to make it work with the updated Scarb.toml
Browse files Browse the repository at this point in the history
  • Loading branch information
aradix16 committed Dec 3, 2024
1 parent 56ba087 commit 1650541
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 48 deletions.
39 changes: 31 additions & 8 deletions backend-sc/src/components/certificate/certificate.cairo
Original file line number Diff line number Diff line change
@@ -1,30 +1,53 @@
#[starknet::component]
mod NFTComponent {
use starknet::ContractAddress;
// Starknet imports

use starknet::{ContractAddress, get_caller_address, get_contract_address};

// Internal imports
use carbon_locker::components::certificate::interface::INFTComponent;

// SRC5
use openzeppelin::introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait;
// use openzeppelin::introspection::src5::SRC5Component::{SRC5, SRC5Camel};
use openzeppelin::introspection::src5::SRC5Component;
use openzeppelin::introspection::interface::{ISRC5Dispatcher, ISRC5DispatcherTrait};

// ERC 721
use openzeppelin::token::erc721::interface::IERC721;
use openzeppelin::token::erc721::{
ERC721Component,
ERC721Component::ERC721Impl,
ERC721Component::InternalTrait,
ERC721Component, ERC721HooksEmptyImpl, ERC721Component::InternalTrait as ERC721InternalTrait
};

#[storage]
struct Storage {}

#[embeddable_as(NFTComponentImpl)]
impl NFTComponent<
impl NFTComponent<
TContractState,
+HasComponent<TContractState>,
+Drop<TContractState>,
+SRC5Component::HasComponent<TContractState>,
impl ERC721: ERC721Component::HasComponent<TContractState>,
+SRC5Component::HasComponent<TContractState>,
+Drop<TContractState>,
> of INFTComponent<ComponentState<TContractState>> {
fn initializer(
ref self: ComponentState<TContractState>,
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);
}

fn mint(ref self: ComponentState<TContractState>, to: ContractAddress, token_id: u256) {
let mut erc721 = get_dep_component_mut!(ref self, ERC721);
erc721._mint(to, token_id);
erc721.mint(to, token_id);
}

fn burn(ref self: ComponentState<TContractState>, token_id: u256) {
let mut erc721 = get_dep_component_mut!(ref self, ERC721);
erc721.burn(token_id);
}
}
}
4 changes: 4 additions & 0 deletions backend-sc/src/components/certificate/interface.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@ use starknet::ContractAddress;

#[starknet::interface]
trait INFTComponent<TContractState> {
fn initializer(
ref self: TContractState, name: ByteArray, symbol: ByteArray, base_uri: ByteArray
);
fn mint(ref self: TContractState, to: ContractAddress, token_id: u256);
fn burn(ref self: TContractState, token_id: u256);
}
2 changes: 0 additions & 2 deletions backend-sc/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
mod contracts {
mod locker;
mod certificate;
}

mod components {
mod locker {
mod interface;
mod locker_handler;
}

mod certificate {
mod interface;
mod certificate;
Expand Down
11 changes: 6 additions & 5 deletions backend-sc/tests/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod tests_locker;
<<<<<<< HEAD
mod tests_utils;
=======
>>>>>>> 70ee68c (Draft: Implement basic ERC721 logic for certificates)
//mod tests_locker;
//mod tests_utils;
mod tests_certificate;
mod mocks {
mod erc721;
}
51 changes: 51 additions & 0 deletions backend-sc/tests/mocks/erc721.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use starknet::ContractAddress;

#[starknet::contract]
mod ERC721 {
use starknet::ContractAddress;

// SRC5
use openzeppelin_introspection::src5::SRC5Component;
// ERC721
use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl};
// NFTComponent
use carbon_locker::components::certificate::certificate::NFTComponent;

component!(path: NFTComponent, storage: nft_component, event: NFTComponentEvent);
component!(path: ERC721Component, storage: erc721, event: ERC721Event);
component!(path: SRC5Component, storage: src5, event: SRC5Event);

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

#[abi(embed_v0)]
impl NFTComponentImpl = NFTComponent::NFTComponentImpl<ContractState>;

#[storage]
struct Storage {
#[substorage(v0)]
nft_component: NFTComponent::Storage,
#[substorage(v0)]
erc721: ERC721Component::Storage,
#[substorage(v0)]
src5: SRC5Component::Storage
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
NFTComponentEvent: NFTComponent::Event,
#[flat]
ERC721Event: ERC721Component::Event,
#[flat]
SRC5Event: SRC5Component::Event
}

#[constructor]
fn constructor(ref self: ContractState) {
self.initializer("Certificate", "CERT", "");
}
}
78 changes: 45 additions & 33 deletions backend-sc/tests/tests_certificate.cairo
Original file line number Diff line number Diff line change
@@ -1,65 +1,77 @@
use starknet::{ContractAddress, contract_address_const, get_caller_address};
// Starknet deps

use openzeppelin::token::erc721::interface::IERC721;
//use openzeppelin::token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait};
use starknet::{ContractAddress, contract_address_const, get_caller_address, get_block_timestamp};

use openzeppelin::token::erc721::interface::{
IERC721Dispatcher,
IERC721DispatcherTrait,
IERC721Metadata,
IERC721MetadataDispatcher,
IERC721MetadataDispatcherTrait
};
// External deps

use snforge_std as snf;
use snforge_std::{
ContractClassTrait, EventSpy, start_cheat_caller_address, stop_cheat_caller_address, spy_events,
cheatcodes::events::{EventSpyAssertionsTrait, EventSpyTrait, EventsFilterTrait}
ContractClassTrait, DeclareResultTrait, EventSpy, spy_events, EventSpyTrait,
EventSpyAssertionsTrait, start_cheat_caller_address, stop_cheat_caller_address
};

// Components

use carbon_locker::components::certificate::interface::{
INFTComponent, INFTComponentDispatcher, INFTComponentDispatcherTrait
};

use carbon_locker::contracts::certificate::Certificate;
// Components

use openzeppelin::token::erc721::interface::{
IERC721Dispatcher, IERC721DispatcherTrait, IERC721Metadata, IERC721MetadataDispatcher,
IERC721MetadataDispatcherTrait
};

// Contracts
use super::mocks::erc721::ERC721;

fn deploy_nft_certificate() -> ContractAddress {
let contract = snf::declare("Certificate").expect('Declaration failed');
fn deploy_certificate() -> ContractAddress {
let contract_class = snf::declare("ERC721").expect('Declaration failed').contract_class();

let mut calldata: Array<felt252> = array![];
let deploy_result = contract_class.deploy(@calldata);

let (contract_address, _) = deploy_result.expect('Certificate deployment failed');

let (contract_address, _) = contract.deploy(@calldata).expect('NFT deployment failed');
contract_address
}

#[test]
fn test_proper_initialization() {
let certificate_address = deploy_nft_certificate();
let certificate_address = deploy_certificate();
let user_address: ContractAddress = contract_address_const::<'USER'>();
start_cheat_caller_address(certificate_address, user_address);
let erc721 = IERC721Dispatcher { contract_address: certificate_address };
let erc721_metadata = IERC721MetadataDispatcher { contract_address: certificate_address };

let name = erc721_metadata.name();
assert(name == "Certificate", 'Name should be Certificate');
let symbol = erc721_metadata.symbol();
assert(symbol == "CERT", 'Symbol should be CERT');

let balance = erc721.balance_of(user_address);
let mut balance = erc721.balance_of(user_address);
assert(balance == 0, 'Balance should be 0');

let name = erc721_metadata.name();
assert(name == "Certificate", 'Token name mismatch');
}

#[test]
fn test_mint() {
let certificate_address = deploy_nft_certificate();
let erc721 = IERC721Dispatcher { contract_address: certificate_address };
fn test_mint_function() {
let certificate_address = deploy_certificate();
let certificate = INFTComponentDispatcher { contract_address: certificate_address };
let user_address: ContractAddress = contract_address_const::<'USER'>();
start_cheat_caller_address(certificate_address, user_address);

let nft_component = INFTComponentDispatcher { contract_address: certificate_address };
let nft_id = 1;
nft_component.mint(user_address, nft_id);
let erc721 = IERC721Dispatcher { contract_address: certificate_address };

let balance = erc721.balance_of(user_address);
certificate.mint(user_address, 1);
let mut balance = erc721.balance_of(user_address);
assert(balance == 1, 'Balance should be 1');
}

#[test]
fn test_burn_function() {
let certificate_address = deploy_certificate();
let certificate = INFTComponentDispatcher { contract_address: certificate_address };
let user_address: ContractAddress = contract_address_const::<'USER'>();
let erc721 = IERC721Dispatcher { contract_address: certificate_address };

certificate.mint(user_address, 1);
certificate.burn(1);
let mut balance = erc721.balance_of(user_address);
assert(balance == 0, 'Balance should be 0');
}

0 comments on commit 1650541

Please sign in to comment.