Skip to content

Commit

Permalink
Merge pull request #1 from hoanhan101/loaf
Browse files Browse the repository at this point in the history
Loaf
  • Loading branch information
ponderingdemocritus authored Aug 28, 2023
2 parents 0aefcd1 + e468c27 commit da60fb4
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 126 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
tmp.*
.env

/target
/target

account
keys
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,10 @@ starknet call --function name --address <CONTRACT_ADDRESS> --account pusscode
starknet invoke --function whitelist --address <CONTRACT_ADDRESS> --account pusscode --max_fee 1000000000000000 --input <TO_ADDR>
starknet invoke --function mint --address <CONTRACT_ADDRESS> --account pusscode --max_fee 1000000000000000 --input <TO_ADDR> 1 1 1 13104
```
```



## Test

starkli deploy 0x031356a71c184985f63f4766f9c05cb939897bdb088391c11add23fdc80d6b83 0x3481bceb5771419b69cac998eece0cbf6be21699cdfb1a736f3c28796efbd7d 0x0 0x424541535453 0x424541535453 --account ./account
2 changes: 1 addition & 1 deletion Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "leetloot"
version = "0.1.0"

[dependencies]
starknet = "2.0.1"
starknet = "2.1.1"

[scripts]
test = "scarb cairo-test"
Expand Down
2 changes: 1 addition & 1 deletion src/beast.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2038,6 +2038,6 @@ fn getBeastPixel(beast: u8) -> LongString {
content.append('AElFTkSuQmCC');
}

return content.into();
content.into()
}

33 changes: 33 additions & 0 deletions src/interfaces.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use starknet::ContractAddress;

// LeetLoot interface
#[starknet::interface]
trait ILeetLoot<T> {
// Ownership
fn owner(self: @T) -> ContractAddress;
fn transferOwnership(ref self: T, to: ContractAddress);
fn renounceOwnership(ref self: T);

// ERC721
fn name(self: @T) -> felt252;
fn symbol(self: @T) -> felt252;
fn balanceOf(self: @T, account: ContractAddress) -> u256;
fn ownerOf(self: @T, tokenID: u256) -> ContractAddress;
fn transferFrom(ref self: T, from: ContractAddress, to: ContractAddress, tokenID: u256);
fn approve(ref self: T, to: ContractAddress, tokenID: u256);
fn setApprovalForAll(ref self: T, operator: ContractAddress, approved: bool);
fn getApproved(self: @T, tokenID: u256) -> ContractAddress;
fn isApprovedForAll(self: @T, owner: ContractAddress, operator: ContractAddress) -> bool;

// ERC165
fn supportsInterface(self: @T, interfaceId: felt252) -> bool;
fn registerInterface(ref self: T, interface_id: felt252);

// Core functions
fn whitelist(ref self: T, to: ContractAddress);
fn getWhitelist(self: @T) -> ContractAddress;
fn mint(ref self: T, to: ContractAddress, beast: u8, prefix: u8, suffix: u8, level: felt252);
fn isMinted(ref self: T, beast: u8, prefix: u8, suffix: u8) -> bool;
fn tokenURI(self: @T, tokenID: u256) -> Array::<felt252>;
fn tokenSupply(self: @T) -> u256;
}
2 changes: 2 additions & 0 deletions src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod beast;
mod loot;
mod long_string;
mod tests;
mod interfaces;
25 changes: 13 additions & 12 deletions src/long_string.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use array::{ArrayTrait, SpanTrait};
use integer::{U8IntoFelt252, U32IntoFelt252, Felt252TryIntoU32};
use option::OptionTrait;
use serde::Serde;
use starknet::{SyscallResult, StorageAccess, StorageBaseAddress};
use starknet::{SyscallResult, Store, StorageBaseAddress};
use traits::{Into, TryInto};

#[derive(Copy, Drop)]
Expand Down Expand Up @@ -72,7 +72,7 @@ impl LongStringSerde of serde::Serde<LongString> {

fn deserialize(ref serialized: Span<felt252>) -> Option<LongString> {
let content = Serde::<Span<felt252>>::deserialize(ref serialized)?;
Option::Some(LongString { len: content.len(), content, })
Option::Some(LongString { len: content.len(), content, })
}
}

Expand All @@ -88,11 +88,11 @@ impl LongStringLegacyHash of hash::LegacyHash<LongString> {
}

// StorageAccess implementation with a max length of 256.
impl LongStringStorageAccess of starknet::StorageAccess<LongString> {
impl LongStringStorageAccess of starknet::Store<LongString> {
fn read(
address_domain: u32, base: starknet::StorageBaseAddress
) -> SyscallResult::<LongString> {
let len = StorageAccess::<u32>::read(address_domain, base)?;
let len = Store::<u32>::read(address_domain, base)?;

let mut content: Array<felt252> = ArrayTrait::new();
let mut offset: u8 = 1;
Expand All @@ -111,15 +111,15 @@ impl LongStringStorageAccess of starknet::StorageAccess<LongString> {
offset += 1;
};

SyscallResult::Ok(LongString { len, content: content.span(), })
SyscallResult::Ok(LongString { len, content: content.span(), })
}

fn write(
address_domain: u32, base: StorageBaseAddress, value: LongString
) -> SyscallResult::<()> {
assert(value.len < 255, 'Max length');

StorageAccess::<u32>::write(address_domain, base, value.len)?;
Store::<u32>::write(address_domain, base, value.len)?;

let mut offset: u8 = 1;

Expand All @@ -144,19 +144,20 @@ impl LongStringStorageAccess of starknet::StorageAccess<LongString> {
SyscallResult::Ok(())
}

fn read_at_offset_internal(
fn read_at_offset(
address_domain: u32, base: StorageBaseAddress, offset: u8
) -> SyscallResult<LongString> {
LongStringStorageAccess::read_at_offset_internal(address_domain, base, offset)
LongStringStorageAccess::read_at_offset(address_domain, base, offset)
}

fn write_at_offset_internal(
fn write_at_offset(
address_domain: u32, base: StorageBaseAddress, offset: u8, value: LongString
) -> SyscallResult<()> {
LongStringStorageAccess::write_at_offset_internal(address_domain, base, offset, value)
LongStringStorageAccess::write_at_offset(address_domain, base, offset, value)
}

fn size_internal(value: LongString) -> u8 {
value.len.try_into().unwrap() + 1_u8
fn size() -> u8 {
// this is wrong, but it's not used anywhere
0
}
}
121 changes: 11 additions & 110 deletions src/loot.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,16 @@
// By hoanh.eth
//

use starknet::ContractAddress;
use super::long_string::LongString;
use super::beast;

// LeetLoot interface
#[starknet::interface]
trait ILeetLoot<T> {
// Ownership
fn owner(self: @T) -> ContractAddress;
fn transferOwnership(ref self: T, to: ContractAddress);
fn renounceOwnership(ref self: T);

// ERC721
fn name(self: @T) -> felt252;
fn symbol(self: @T) -> felt252;
fn balanceOf(self: @T, account: ContractAddress) -> u256;
fn ownerOf(self: @T, tokenID: u256) -> ContractAddress;
fn transferFrom(ref self: T, from: ContractAddress, to: ContractAddress, tokenID: u256);
fn approve(ref self: T, to: ContractAddress, tokenID: u256);
fn setApprovalForAll(ref self: T, operator: ContractAddress, approved: bool);
fn getApproved(self: @T, tokenID: u256) -> ContractAddress;
fn isApprovedForAll(self: @T, owner: ContractAddress, operator: ContractAddress) -> bool;

// ERC165
fn supportsInterface(self: @T, interfaceId: felt252) -> bool;
fn registerInterface(ref self: T, interface_id: felt252);

// Core functions
fn whitelist(ref self: T, to: ContractAddress);
fn getWhitelist(self: @T) -> ContractAddress;
fn mint(ref self: T, to: ContractAddress, beast: u8, prefix: u8, suffix: u8, level: felt252);
fn isMinted(ref self: T, beast: u8, prefix: u8, suffix: u8) -> bool;
fn tokenURI(self: @T, tokenID: u256) -> Array::<felt252>;
fn tokenSupply(self: @T) -> u256;
}

// LeetLoot contract
#[starknet::contract]
mod LeetLoot {
use array::{ArrayTrait};
use core::traits::{Into};
use super::{ILeetLoot, LongString};
use super::{LongString};
use leetloot::interfaces::{ILeetLoot};
use starknet::get_caller_address;
use starknet::ContractAddress;
use zeroable::Zeroable;
Expand Down Expand Up @@ -239,7 +207,7 @@ mod LeetLoot {
content.append(getBeastName(beast));
content.append(getBeastNamePrefix(prefix));
content.append(getBeastNameSuffix(suffix));
return poseidon_hash_span(content.span());
poseidon_hash_span(content.span())
}
}

Expand Down Expand Up @@ -381,11 +349,11 @@ mod LeetLoot {
content.append('isp-edges;image-rendering:pixel');
content.append('ated;}</style></svg>"}');

return content;
content
}

fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool {
return self._supportsInterface(interfaceId);
self._supportsInterface(interfaceId)
}

fn registerInterface(ref self: ContractState, interface_id: felt252) {
Expand All @@ -402,7 +370,7 @@ mod LeetLoot {
}

fn isMinted(ref self: ContractState, beast: u8, prefix: u8, suffix: u8) -> bool {
return self._minted.read(self._getBeastHash(beast, prefix, suffix));
self._minted.read(self._getBeastHash(beast, prefix, suffix))
}

fn mint(
Expand All @@ -414,10 +382,10 @@ mod LeetLoot {
level: felt252
) {
assert(!to.is_zero(), 'Invalid receiver');
// let caller: ContractAddress = get_caller_address();
// assert(
// caller == self.owner() || caller == self.getWhitelist(), 'Not owner or whitelist'
// );
let caller: ContractAddress = get_caller_address();
assert(
caller == self.owner() || caller == self.getWhitelist(), 'Not owner or whitelist'
);
assert(!self.isMinted(beast, prefix, suffix), 'Already minted');
let current: u256 = self._tokenIndex.read();
self._beasts.write(current, beast);
Expand All @@ -430,75 +398,8 @@ mod LeetLoot {


fn tokenSupply(self: @ContractState) -> u256 {
return self._tokenIndex.read();
self._tokenIndex.read()
}
}
}

#[cfg(test)]
mod tests {
use starknet::contract_address_const;
use starknet::ContractAddress;
use serde::Serde;
use array::{ArrayTrait, SpanTrait};
use traits::{TryInto, Into};
use option::OptionTrait;
use result::ResultTrait;
use super::{LongString};
use super::{LeetLoot, ILeetLootDispatcher, ILeetLootDispatcherTrait};
use debug::PrintTrait;

const DEPLOYER_CONTRACT: felt252 =
0x168893664220f03a74a9bce84228b009df46040c08bb308783dcf130790335f;

fn deploy() -> ILeetLootDispatcher {
let mut calldata: Array<felt252> = array::ArrayTrait::new();
calldata.append(DEPLOYER_CONTRACT);
calldata.append(DEPLOYER_CONTRACT);
calldata.append('LeetLoot');
calldata.append('LEETLOOT');

let (addr, _) = starknet::deploy_syscall(
LeetLoot::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false
)
.expect('Fail to deploy_syscall');

ILeetLootDispatcher { contract_address: addr }
}

#[test]
#[available_gas(1000000000000000)]
fn test_basics() {
let contract = deploy();
let owner = contract.owner();
assert(contract.name() == 'LeetLoot', 'Wrong name');
assert(contract.symbol() == 'LEETLOOT', 'Wrong symbol');
assert(contract.tokenSupply() == 0, 'Wrong supply');
assert(contract.supportsInterface(0x80ac58cd), 'No support interface');
assert(!contract.supportsInterface(0x150b7a02), 'No support interface');
contract.registerInterface(0x150b7a02);
assert(contract.supportsInterface(0x150b7a02), 'No support interface');
// // Comment out because there's no good way to mock caller address yet
// // Also, felt252 13104 is string 30
// assert(!contract.isMinted(1, 1, 1), 'Already minted');
// contract.mint(owner, 1, 1, 1, 13104);
// // contract.mint(owner, 1, 1, 1, 13104); // should panic here
// assert(contract.isMinted(1, 1, 1), 'Already minted');
// assert(contract.isMinted(1, 1, 1), 'Already minted');
// assert(contract.tokenSupply() == 1, 'Wrong supply');
// let uri = contract.tokenURI(0);
// let mut i = 0_usize;
// loop {
// if i == uri.len() {
// break;
// }

// (*uri[i]).print();
// i += 1;
// };

// assert(!contract.isMinted(2, 2, 2), 'Already minted');
// contract.mint(owner, 2, 2, 2, 13104);
// assert(contract.tokenSupply() == 2, 'Wrong supply');
}
}
1 change: 1 addition & 0 deletions src/tests.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod deploy;
Loading

0 comments on commit da60fb4

Please sign in to comment.