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

♻️ tests refactoring #41

Merged
merged 9 commits into from
Aug 25, 2022
Merged
Show file tree
Hide file tree
Changes from 3 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
27 changes: 27 additions & 0 deletions tests/integrations/minter/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
user:
bal7hazar marked this conversation as resolved.
Show resolved Hide resolved
admin: 1000
anyone: 1001

nft:
name: Project
symbol: NFT

token:
name: Token
symbol: TOK
decimals: 6
initial_supply: 1000000

minter:
public_sale_open: 0
max_buy_per_tx: 5
unit_price: 10
max_supply_for_mint: 10
reserved_supply_for_mint: 4

whitelist:
slots: 5
merkle_root: 3236969588476960619958150604131083087415975923122021901088942336874683133579
merkle_proof:
- 1489335374474017495857579265074565262713421005832572026644103123081435719307
merkle_proof_len: 1
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,70 @@ from openzeppelin.security.safemath import SafeUint256
from interfaces.minter import ICarbonableMinter
from interfaces.CarbonableProjectNFT import IERC721, IERC721_Enumerable, ICarbonableProjectNFT

func setup{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}():
alloc_locals
local carbonable_minter
local merkle_root
%{
# Load config
import yaml
with open("./tests/integrations/minter/config.yml", 'r') as file_instance:
config = yaml.safe_load(file_instance)
for section, subconfig in config.items():
for key, value in subconfig.items():
name = f"{section.lower()}_{key.lower()}"
setattr(context, name, value)

# ERC-721 deployment
context.project_nft_contract = deploy_contract(
"./src/nft/project/CarbonableProjectNFT.cairo",
{
"name": context.nft_name,
"symbol": context.nft_symbol,
"owner": context.user_admin,
},
).contract_address

# ERC-20 deployment
context.payment_token_contract = deploy_contract(
"./tests/mocks/token/erc20.cairo",
{
"name": context.token_name,
"symbol": context.token_symbol,
"decimals": context.token_decimals,
"initial_supply": context.token_initial_supply,
"recipient": context.user_anyone
},
).contract_address

# Minter deployment
context.carbonable_minter_contract = deploy_contract(
"./src/mint/minter.cairo",
{
"owner": context.user_admin,
"project_nft_address": context.project_nft_contract,
"payment_token_address": context.payment_token_contract,
"public_sale_open": context.minter_public_sale_open,
"max_buy_per_tx": context.minter_max_buy_per_tx,
"unit_price": context.minter_unit_price,
"max_supply_for_mint": context.minter_max_supply_for_mint,
"reserved_supply_for_mint": context.minter_reserved_supply_for_mint,
},
).contract_address

# Externalize required variables
ids.carbonable_minter = context.carbonable_minter_contract
ids.merkle_root = context.whitelist_merkle_root
%}

# Transfer project nft ownershop from admin to minter
admin_instance.transferOwnership(carbonable_minter)
# Set merkle tree root to minter contract
admin_instance.set_whitelist_merkle_root(merkle_root)

return ()
end

namespace project_nft_instance:
# Internals

Expand Down Expand Up @@ -276,7 +340,7 @@ namespace admin_instance:

func get_address() -> (address : felt):
tempvar admin
%{ ids.admin = context.ADMIN %}
%{ ids.admin = context.user_admin %}
return (admin)
end

Expand Down Expand Up @@ -444,27 +508,27 @@ namespace anyone_instance:

func get_address() -> (address : felt):
tempvar anyone
%{ ids.anyone = context.ANYONE %}
%{ ids.anyone = context.user_anyone %}
return (anyone)
end

func get_slots() -> (slots : felt):
tempvar slots
%{ ids.slots = context.SLOTS %}
%{ ids.slots = context.whitelist_slots %}
return (slots)
end

func get_proof_len() -> (proof_len : felt):
tempvar proof_len
%{ ids.proof_len = context.PROOF_LEN %}
%{ ids.proof_len = context.whitelist_merkle_proof_len %}
return (proof_len)
end

func get_proof() -> (proof : felt*):
alloc_locals
let (proof : felt*) = alloc()
let (local proof : felt*) = alloc()
%{
for index, node in enumerate(context.PROOF):
for index, node in enumerate(context.whitelist_merkle_proof):
memory[ids.proof + index] = node
%}
return (proof)
Expand Down
131 changes: 131 additions & 0 deletions tests/integrations/minter/test_nominal_cases.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# SPDX-License-Identifier: MIT
# Carbonable smart contracts written in Cairo v0.1.0 (test_nominal_case.cairo)

%lang starknet

# Starkware dependencies
from starkware.cairo.common.bool import TRUE, FALSE
from starkware.cairo.common.cairo_builtins import HashBuiltin

# Project dependencies
from tests.integrations.minter.library import (
setup,
admin_instance as admin,
anyone_instance as anyone,
)

@view
func __setup__{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}():
# GIVEN a deployed user contracts
bal7hazar marked this conversation as resolved.
Show resolved Hide resolved
# AND admin with address 1000
# AND anyone with address 1001
# GIVEN a deployed project nft contact
# GIVEN a deployed payment token contact
# AND total supply set to 1,000,000
# AND anyone owns the whole supply
# GIVEN a deployed minter contact
# AND whitelist sale open
# AND public sale close
# AND max buy per tx set to 5
# AND unit price set to 10
# AND max supply set to 10
# AND reserved supply set to 4
# GIVEN a set up whitelist merkle tree
# AND whitelist includes 5 slots to anyone
return setup()
end

@view
func test_e2e_whitelisted{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}():
# GIVEN setup context
# WHEN anyone approves minter for 5 token equivalent nfts
# AND anyone makes 5 whitelist buy
# AND admin open the public sale
# AND anyone approves minter for 1 token equivalent nft
# AND anyone makes 1 public buy
# AND admin withdraw minter contract balance
# THEN no failed transactions expected

anyone.approve(quantity=5)
anyone.whitelist_buy(quantity=5)
admin.set_public_sale_open(TRUE)
anyone.approve(quantity=1)
anyone.public_buy(quantity=1)
admin.withdraw()

return ()
end

@view
func test_e2e_not_whitelisted{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}():
# GIVEN setup context
# WHEN admin set up a new whitelist merkle tree excluding anyone
# AND anyone approves minter for 1 token equivalent nft
# AND anyone makes 1 whitelist buy
# THEN 'caller address is not whitelisted' failed transaction happens
# WHEN admin open the public sale
# AND anyone approves minter for 5 token equivalent nfts
# AND anyone makes 5 public buy
# AND admin withdraw minter contract balance
# THEN no failed transactions expected

admin.set_whitelist_merkle_root(123)
anyone.approve(quantity=1)
%{ expect_revert("TRANSACTION_FAILED", "CarbonableMinter: caller address is not whitelisted") %}
anyone.whitelist_buy(quantity=1)
admin.set_public_sale_open(TRUE)
anyone.approve(quantity=5)
anyone.public_buy(quantity=5)
admin.withdraw()

return ()
end

@view
func test_e2e_airdrop{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}():
# GIVEN setup context
# WHEN anyone approves minter for 5 token equivalent nfts
# AND anyone makes 5 whitelist buy
# AND admin open the public sale
# AND anyone approves minter for 2 token equivalent nfts
# AND anyone makes 2 public buy
# THEN 'not enough available NFTs' failed transaction happens
# WHEN admin airdrop 5 nfts to anyone
# THEN 'not enough available reserved NFTs' failed transaction happens
# WHEN admin airdrop 3 nfts to anyone
# AND admin decreases reserved supply by 1
# AND anyone makes 1 public buy
# AND admin withdraw minter contract balance
# THEN no failed transactions expected
alloc_locals
let (anyone_address) = anyone.get_address()

anyone.approve(quantity=5)
anyone.whitelist_buy(quantity=5)
admin.set_public_sale_open(TRUE)
anyone.approve(quantity=2)
%{ expect_revert("TRANSACTION_FAILED", "CarbonableMinter: not enough available NFTs") %}
anyone.public_buy(quantity=2)
%{ expect_revert("TRANSACTION_FAILED", "CarbonableMinter: not enough available reserved NFTs") %}
admin.airdrop(to=anyone_address, quantity=5)
admin.airdrop(to=anyone_address, quantity=3)
admin.decrease_reserved_supply_for_mint(slots=1)
anyone.public_buy(quantity=1)
admin.withdraw()

return ()
end

@view
func test_e2e_over_airdrop{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}():
# GIVEN setup context
# WHEN admin airdrop 11 nfts to anyone
# THEN 'not enough available NFTs' failed transaction happens
alloc_locals
let (anyone_address) = anyone.get_address()

%{ expect_revert("TRANSACTION_FAILED", "CarbonableMinter: not enough available NFTs") %}
admin.airdrop(to=anyone_address, quantity=11)

return ()
end
Loading