Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
scarb 2.15.1
scarb 2.18.0
rust 1.89.0
starknet-foundry 0.55.0
starknet-foundry 0.60.0
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ The Beasts are a collection of digital-native creatures, born onchain and built

### Prerequisites

- [Scarb](https://docs.swmansion.com/scarb/) 2.15.1
- [Starknet Foundry](https://foundry-rs.github.io/starknet-foundry/) 0.55.0
- [Scarb](https://docs.swmansion.com/scarb/) 2.18.0
- [Starknet Foundry](https://foundry-rs.github.io/starknet-foundry/) 0.60.0
- [Starkli](https://book.starkli.rs/) for deployment
- [Cairo Coverage](https://github.com/software-mansion/cairo-coverage) and [lcov](https://github.com/linux-test-project/lcov) for local coverage reports

Expand Down
10 changes: 6 additions & 4 deletions Scarb.lock
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,15 @@ dependencies = [

[[package]]
name = "snforge_scarb_plugin"
version = "0.55.0"
source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.55.0#8891212a4fe99f1787298042f828ebd4e4abe9a3"
version = "0.60.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:924358bf316e502923f6733b50e239ea37585a05dc24c5fc8dd9e45f88cf7339"

[[package]]
name = "snforge_std"
version = "0.55.0"
source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.55.0#8891212a4fe99f1787298042f828ebd4e4abe9a3"
version = "0.60.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:32e6baabec4f9af21089bc7ca685ffea5e4164497340ecbdb99314e568029195"
dependencies = [
"snforge_scarb_plugin",
]
7 changes: 3 additions & 4 deletions Scarb.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[package]
cairo-version = "2.15.0"
cairo-version = "2.18.0"
name = "beasts_nft"
version = "0.1.0"
edition = "2024_07"

[lib]

[dependencies]
starknet = "2.15.1"
starknet = "2.18.0"
openzeppelin_interfaces = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v3.0.0" }
openzeppelin_access = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v3.0.0" }
openzeppelin_token = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v3.0.0" }
Expand All @@ -19,10 +19,9 @@ openzeppelin_utils = { git = "https://github.com/OpenZeppelin/cairo-contracts.gi
test = "snforge test"

[dev-dependencies]
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.55.0" }
snforge_std = "0.60.0"

[[target.starknet-contract]]
allowed-libfuncs-list.name = "experimental"

[profile.dev.cairo]

Expand Down
18 changes: 11 additions & 7 deletions src/metadata_generator.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -286,13 +286,17 @@ mod tests {
ContractClassTrait, DeclareResultTrait, declare, start_cheat_caller_address,
start_mock_call, stop_cheat_caller_address,
};
use starknet::{ContractAddress, contract_address_const};
use starknet::ContractAddress;
use super::super::beast_manager::BeastManagerTrait;
use super::super::interfaces::{
IBeastImageDataProviderDispatcher, IBeastImageDataProviderDispatcherTrait,
};
use super::{Attribute, BeastSvgTrait, MetadataGeneratorTrait, PackableBeast};

fn test_address(address: felt252) -> ContractAddress {
address.try_into().unwrap()
}
Comment on lines +296 to +298

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test_address helper function is duplicated across multiple test files (metadata_generator.cairo, mint_tests.cairo, and tests.cairo). To improve maintainability and adhere to the DRY (Don't Repeat Yourself) principle, consider moving this utility to a shared test helper module or an existing utility file that is accessible by all test modules.


fn find_substring(text: @ByteArray, pattern: @ByteArray) -> bool {
let text_len = text.len();
let pattern_len = pattern.len();
Expand Down Expand Up @@ -333,8 +337,8 @@ mod tests {
fn deploy_beasts_with_terminal(
terminal_ts: u64, mock_provider_addr: ContractAddress,
) -> (IBeastsDispatcher, IERC721MetadataDispatcher, ContractAddress, ContractAddress) {
let owner = contract_address_const::<'owner'>();
let royalty_receiver: ContractAddress = contract_address_const::<'royalty_receiver'>();
let owner = test_address('owner');
let royalty_receiver: ContractAddress = test_address('royalty_receiver');

let contract = declare("beasts_nft").unwrap().contract_class();

Expand Down Expand Up @@ -393,13 +397,13 @@ mod tests {
let (beasts, metadata, owner, _addr) = deploy_beasts_with_terminal(0_u64, mock_provider);

// Set minter
let minter = contract_address_const::<'minter'>();
let minter = test_address('minter');
start_cheat_caller_address(beasts.contract_address, owner);
beasts.set_dungeon_address(minter);
stop_cheat_caller_address(beasts.contract_address);

// Mint one beast
let recipient = contract_address_const::<'recipient'>();
let recipient = test_address('recipient');
start_cheat_caller_address(beasts.contract_address, minter);
let (token_id, _, _) = beasts.mint(recipient, 3, 1, 2, 10, 100, 0, 0);
stop_cheat_caller_address(beasts.contract_address);
Expand All @@ -423,13 +427,13 @@ mod tests {
let (beasts, metadata, owner, _addr) = deploy_beasts_with_terminal(1_u64, mock_provider);

// Set minter
let minter = contract_address_const::<'minter'>();
let minter = test_address('minter');
start_cheat_caller_address(beasts.contract_address, owner);
beasts.set_dungeon_address(minter);
stop_cheat_caller_address(beasts.contract_address);

// Mint a beast so token exists
let recipient = contract_address_const::<'recipient'>();
let recipient = test_address('recipient');
start_cheat_caller_address(beasts.contract_address, minter);
let (token_id, _, _) = beasts.mint(recipient, 3, 1, 2, 10, 100, 0, 0);
stop_cheat_caller_address(beasts.contract_address);
Expand Down
78 changes: 41 additions & 37 deletions src/mint_tests.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ mod mint_tests {
ContractClassTrait, DeclareResultTrait, declare, start_cheat_caller_address,
stop_cheat_caller_address,
};
use starknet::{ContractAddress, contract_address_const};
use starknet::ContractAddress;

fn test_address(address: felt252) -> ContractAddress {
address.try_into().unwrap()
}

fn deploy_contract() -> (
IBeastsDispatcher, IERC721Dispatcher, IOwnableDispatcher, ContractAddress,
) {
let owner = contract_address_const::<'owner'>();
let recipient = contract_address_const::<'recipient'>();
let royalty_receiver: ContractAddress = contract_address_const::<'royalty_receiver'>();
let owner = test_address('owner');
let recipient = test_address('recipient');
let royalty_receiver: ContractAddress = test_address('royalty_receiver');
let royalty_fraction: u128 = 500;

// Declare and deploy contract
Expand Down Expand Up @@ -68,7 +72,7 @@ mod mint_tests {
#[test]
fn test_set_dungeon_address() {
let (beasts, _, ownable, owner) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let minter = test_address('minter');

// Set minter as owner
start_cheat_caller_address(beasts.contract_address, owner);
Expand All @@ -83,8 +87,8 @@ mod mint_tests {
#[should_panic(expected: ('Caller is not the owner',))]
fn test_set_dungeon_address_not_owner() {
let (beasts, _, _, _) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let random_caller = contract_address_const::<'random'>();
let minter = test_address('minter');
let random_caller = test_address('random');

// Try to set minter as non-owner
start_cheat_caller_address(beasts.contract_address, random_caller);
Expand All @@ -95,8 +99,8 @@ mod mint_tests {
#[test]
fn test_mint_basic() {
let (beasts, erc721, _, owner) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let recipient = contract_address_const::<'recipient'>();
let minter = test_address('minter');
let recipient = test_address('recipient');

// Set minter
start_cheat_caller_address(beasts.contract_address, owner);
Expand Down Expand Up @@ -136,8 +140,8 @@ mod mint_tests {
#[should_panic(expected: ('Not authorized to mint',))]
fn test_mint_not_authorized() {
let (beasts, _, _, owner) = deploy_contract();
let random_caller = contract_address_const::<'random'>();
let recipient = contract_address_const::<'recipient'>();
let random_caller = test_address('random');
let recipient = test_address('recipient');

// Try to mint without being minter
start_cheat_caller_address(beasts.contract_address, random_caller);
Expand All @@ -149,7 +153,7 @@ mod mint_tests {
#[should_panic(expected: ('Invalid beast ID',))]
fn test_mint_invalid_beast_id_zero() {
let (beasts, _, _, owner) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let minter = test_address('minter');

// Set minter
start_cheat_caller_address(beasts.contract_address, owner);
Expand All @@ -166,7 +170,7 @@ mod mint_tests {
#[should_panic(expected: ('Invalid beast ID',))]
fn test_mint_invalid_beast_id_too_high() {
let (beasts, _, _, owner) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let minter = test_address('minter');

// Set minter
start_cheat_caller_address(beasts.contract_address, owner);
Expand All @@ -183,8 +187,8 @@ mod mint_tests {
#[should_panic(expected: ('Beast already minted',))]
fn test_mint_duplicate() {
let (beasts, _, _, owner) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let recipient = contract_address_const::<'recipient'>();
let minter = test_address('minter');
let recipient = test_address('recipient');

// Set minter
start_cheat_caller_address(beasts.contract_address, owner);
Expand All @@ -203,8 +207,8 @@ mod mint_tests {
#[test]
fn test_mint_same_beast_different_attributes() {
let (beasts, erc721, _, owner) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let recipient = contract_address_const::<'recipient'>();
let minter = test_address('minter');
let recipient = test_address('recipient');

// Set minter
start_cheat_caller_address(beasts.contract_address, owner);
Expand All @@ -231,7 +235,7 @@ mod mint_tests {
#[test]
fn test_mint_genesis_beasts() {
let (beasts, erc721, _, owner) = deploy_contract();
let recipient = contract_address_const::<'recipient'>();
let recipient = test_address('recipient');

// Mint genesis beasts as owner
start_cheat_caller_address(beasts.contract_address, owner);
Expand Down Expand Up @@ -261,7 +265,7 @@ mod mint_tests {
#[should_panic(expected: ('Caller is not the owner',))]
fn test_mint_genesis_beasts_not_owner() {
let (beasts, _, _, _) = deploy_contract();
let random_caller = contract_address_const::<'random'>();
let random_caller = test_address('random');

// Try to mint genesis beasts as non-owner
start_cheat_caller_address(beasts.contract_address, random_caller);
Expand All @@ -272,7 +276,7 @@ mod mint_tests {
#[test]
fn test_total_supply() {
let (beasts, _, _, owner) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let minter = test_address('minter');

// Initial supply should be 0
assert(beasts.total_supply() == 0, 'Initial supply should be 0');
Expand All @@ -298,8 +302,8 @@ mod mint_tests {
#[test]
fn test_token_uri_with_minted_data() {
let (beasts, _, _, owner) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let recipient = contract_address_const::<'recipient'>();
let minter = test_address('minter');
let recipient = test_address('recipient');

// Set minter
start_cheat_caller_address(beasts.contract_address, owner);
Expand Down Expand Up @@ -378,8 +382,8 @@ mod mint_tests {
#[test]
fn test_king_beast_basic_functionality() {
let (beasts, _, _, owner) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let recipient = contract_address_const::<'recipient'>();
let minter = test_address('minter');
let recipient = test_address('recipient');

// Set minter
start_cheat_caller_address(beasts.contract_address, owner);
Expand All @@ -405,9 +409,9 @@ mod mint_tests {
#[test]
fn test_king_beast_higher_power_replaces_king() {
let (beasts, _, _, owner) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let recipient = contract_address_const::<'recipient'>();
let recipient2 = contract_address_const::<'recipient2'>();
let minter = test_address('minter');
let recipient = test_address('recipient');
let recipient2 = test_address('recipient2');

// Set minter
start_cheat_caller_address(beasts.contract_address, owner);
Expand All @@ -434,9 +438,9 @@ mod mint_tests {
#[test]
fn test_king_beast_lower_power_does_not_replace() {
let (beasts, _, _, owner) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let recipient = contract_address_const::<'recipient'>();
let recipient2 = contract_address_const::<'recipient2'>();
let minter = test_address('minter');
let recipient = test_address('recipient');
let recipient2 = test_address('recipient2');

// Set minter
start_cheat_caller_address(beasts.contract_address, owner);
Expand All @@ -463,8 +467,8 @@ mod mint_tests {
#[test]
fn test_king_beast_different_tiers() {
let (beasts, _, _, owner) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let recipient = contract_address_const::<'recipient'>();
let minter = test_address('minter');
let recipient = test_address('recipient');

// Set minter
start_cheat_caller_address(beasts.contract_address, owner);
Expand Down Expand Up @@ -502,9 +506,9 @@ mod mint_tests {
#[test]
fn test_king_beast_same_power_keeps_existing() {
let (beasts, _, _, owner) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let recipient = contract_address_const::<'recipient'>();
let recipient2 = contract_address_const::<'recipient2'>();
let minter = test_address('minter');
let recipient = test_address('recipient');
let recipient2 = test_address('recipient2');

// Set minter
start_cheat_caller_address(beasts.contract_address, owner);
Expand All @@ -531,8 +535,8 @@ mod mint_tests {
#[test]
fn test_king_beast_edge_cases() {
let (beasts, _, _, owner) = deploy_contract();
let minter = contract_address_const::<'minter'>();
let recipient = contract_address_const::<'recipient'>();
let minter = test_address('minter');
let recipient = test_address('recipient');

// Set minter
start_cheat_caller_address(beasts.contract_address, owner);
Expand Down
9 changes: 7 additions & 2 deletions src/tests.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ mod tests {
IERC721MetadataDispatcher, IERC721MetadataDispatcherTrait,
};
use snforge_std::{ContractClassTrait, DeclareResultTrait, declare};
use starknet::ContractAddress;

fn test_address(address: felt252) -> ContractAddress {
address.try_into().unwrap()
}

#[test]
fn test_beast_names() {
Expand Down Expand Up @@ -50,8 +55,8 @@ mod tests {
#[test]
fn test_token_uri_returns_proper_strings() {
// Deploy contract
let owner = contract_address_const::<'owner'>();
let recipient = contract_address_const::<'recipient'>();
let owner = test_address('owner');
let recipient = test_address('recipient');

// Declare and deploy contract
let contract = declare("beasts_nft").unwrap().contract_class();
Expand Down
Loading