Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b0a9d5e
Add creator whitelist early access window
Johnpii1 Jun 29, 2026
ca87184
Merge pull request #1 from Johnpii1/codex/add-whitelist-early-access-…
Johnpii1 Jun 29, 2026
f2058b2
Merge branch 'main' into main
Johnpii1 Jun 29, 2026
2bbfbf4
Fix formatting and cleanup in emergency_pause tests
Johnpii1 Jun 29, 2026
bb18d34
Merge pull request #2 from Johnpii1/Johnpii1-patch-1
Johnpii1 Jun 29, 2026
14d4a92
Fix governance poll registration tests
Johnpii1 Jun 29, 2026
e32e47a
Merge pull request #3 from Johnpii1/codex/fix-compilation-errors-in-c…
Johnpii1 Jun 29, 2026
c78acd5
Merge branch 'main' into main
Johnpii1 Jun 29, 2026
d81197c
Fix creator keys contract compilation
Johnpii1 Jun 29, 2026
c5d3764
Merge pull request #4 from Johnpii1/codex/fix-contract-to-ensure-merg…
Johnpii1 Jun 29, 2026
10233a8
Document creator registration merge boundaries
Johnpii1 Jun 29, 2026
58ae4ab
Merge pull request #5 from Johnpii1/codex/fix-merge-conflicts-in-lib.rs
Johnpii1 Jun 29, 2026
977399d
Fix CI regression coverage
Johnpii1 Jun 29, 2026
0164963
Merge pull request #6 from Johnpii1/codex/fix-ci-to-enable-merging
Johnpii1 Jun 29, 2026
4ef5ea0
Stabilize creator registration TTL handling
Johnpii1 Jun 30, 2026
1bc3f49
Merge branch 'main' into codex/fix-build-failures-for-pull-request
Johnpii1 Jun 30, 2026
06b44e3
Merge pull request #7 from Johnpii1/codex/fix-build-failures-for-pull…
Johnpii1 Jun 30, 2026
be000b2
Document registration TTL delimiter guard
Johnpii1 Jun 30, 2026
1a2e6d6
Merge branch 'main' into codex/fix-build-failures-for-pull-request-vo…
Johnpii1 Jun 30, 2026
3a48952
Merge pull request #8 from Johnpii1/codex/fix-build-failures-for-pull…
Johnpii1 Jun 30, 2026
dffbcd3
fixed build error
Jun 30, 2026
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
2 changes: 1 addition & 1 deletion creator-keys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3101,4 +3101,4 @@ mod tests {
}

#[cfg(test)]
mod test_issues;
mod test_issues;
1 change: 1 addition & 0 deletions creator-keys/tests/emergency_pause.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ fn test_pause_blocks_registration_not_reads() {
// Unpause — creator_b registration must now succeed
client.unpause(&admin);
assert!(!client.get_is_paused());

let _ = client
.try_register_creator(
&creator_b,
Expand Down
46 changes: 21 additions & 25 deletions creator-keys/tests/flat_curve_lower_than_linear_regression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,45 +14,45 @@ use contract_test_env::{
register_creator_keys, register_test_creator, set_curve_slope, set_pricing_and_fees,
test_env_with_auths,
};
use soroban_sdk::{testutils::Address as _, Address};
use creator_keys::constants;
use soroban_sdk::Address;

const KEY_PRICE: i128 = 1_000;
const CREATOR_BPS: u32 = 9_000;
const PROTOCOL_BPS: u32 = 1_000;
const LINEAR_SLOPE: i128 = 1;
// Covers price + fees at any supply ≤ 10_000 with slope=1 (max price = 11_000)
const SAFE_PAYMENT: i128 = KEY_PRICE * 30;

fn advance_supply_to(
fn set_registered_supply(
env: &soroban_sdk::Env,
contract_id: &Address,
client: &creator_keys::CreatorKeysContractClient<'_>,
creator: &Address,
buyer: &Address,
target: u32,
) {
let current = client.get_total_key_supply(creator);
for _ in current..target {
client.buy_key(creator, buyer, &SAFE_PAYMENT, &None);
}
let mut profile = client.get_creator(creator);
profile.supply = target;
env.as_contract(contract_id, || {
env.storage()
.persistent()
.set(&constants::storage::creator(creator), &profile);
});
}

#[test]
fn test_flat_buy_price_lower_than_linear_at_supply_100() {
let env = test_env_with_auths();
let (client, _) = register_creator_keys(&env);
let (client, contract_id) = register_creator_keys(&env);
set_pricing_and_fees(&env, &client, KEY_PRICE, CREATOR_BPS, PROTOCOL_BPS);

let buyer = Address::generate(&env);

// Flat curve: slope = 0 → price stays at KEY_PRICE regardless of supply
set_curve_slope(&env, &client, 0);
let creator_flat = register_test_creator(&env, &client, "flat");
advance_supply_to(&client, &creator_flat, &buyer, 100);
set_registered_supply(&env, &contract_id, &client, &creator_flat, 100);
let flat_quote = client.get_buy_quote(&creator_flat);

// Linear curve: slope > 0 → price grows with supply
set_curve_slope(&env, &client, LINEAR_SLOPE);
let creator_linear = register_test_creator(&env, &client, "linear");
advance_supply_to(&client, &creator_linear, &buyer, 100);
set_registered_supply(&env, &contract_id, &client, &creator_linear, 100);
let linear_quote = client.get_buy_quote(&creator_linear);

assert!(
Expand All @@ -66,19 +66,17 @@ fn test_flat_buy_price_lower_than_linear_at_supply_100() {
#[test]
fn test_flat_buy_price_lower_than_linear_at_supply_1000() {
let env = test_env_with_auths();
let (client, _) = register_creator_keys(&env);
let (client, contract_id) = register_creator_keys(&env);
set_pricing_and_fees(&env, &client, KEY_PRICE, CREATOR_BPS, PROTOCOL_BPS);

let buyer = Address::generate(&env);

set_curve_slope(&env, &client, 0);
let creator_flat = register_test_creator(&env, &client, "flat");
advance_supply_to(&client, &creator_flat, &buyer, 1000);
set_registered_supply(&env, &contract_id, &client, &creator_flat, 1000);
let flat_quote = client.get_buy_quote(&creator_flat);

set_curve_slope(&env, &client, LINEAR_SLOPE);
let creator_linear = register_test_creator(&env, &client, "linear");
advance_supply_to(&client, &creator_linear, &buyer, 1000);
set_registered_supply(&env, &contract_id, &client, &creator_linear, 1000);
let linear_quote = client.get_buy_quote(&creator_linear);

assert!(
Expand All @@ -92,19 +90,17 @@ fn test_flat_buy_price_lower_than_linear_at_supply_1000() {
#[test]
fn test_flat_buy_price_lower_than_linear_at_supply_10000() {
let env = test_env_with_auths();
let (client, _) = register_creator_keys(&env);
let (client, contract_id) = register_creator_keys(&env);
set_pricing_and_fees(&env, &client, KEY_PRICE, CREATOR_BPS, PROTOCOL_BPS);

let buyer = Address::generate(&env);

set_curve_slope(&env, &client, 0);
let creator_flat = register_test_creator(&env, &client, "flat");
advance_supply_to(&client, &creator_flat, &buyer, 10_000);
set_registered_supply(&env, &contract_id, &client, &creator_flat, 10_000);
let flat_quote = client.get_buy_quote(&creator_flat);

set_curve_slope(&env, &client, LINEAR_SLOPE);
let creator_linear = register_test_creator(&env, &client, "linear");
advance_supply_to(&client, &creator_linear, &buyer, 10_000);
set_registered_supply(&env, &contract_id, &client, &creator_linear, 10_000);
let linear_quote = client.get_buy_quote(&creator_linear);

assert!(
Expand Down
152 changes: 152 additions & 0 deletions creator-keys/tests/whitelist_window.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
mod contract_test_env;

use contract_test_env::{
compute_expected_buy_price, register_creator_keys, set_key_price_for_tests, test_env_with_auths,
};
use creator_keys::{ContractError, WhitelistConfig, MAX_WHITELIST_SIZE};
use soroban_sdk::{
testutils::{Address as _, Ledger},
vec, Address, String, Vec,
};

fn register_whitelisted_creator(
env: &soroban_sdk::Env,
client: &creator_keys::CreatorKeysContractClient<'_>,
whitelist: Vec<Address>,
window_ledgers: u32,
) -> Address {
let creator = Address::generate(env);
client.register_creator(
&creator,
&String::from_str(env, "alice"),
&None,
&None,
&None,
&Some(WhitelistConfig {
addresses: whitelist,
window_ledgers,
}),
);
creator
}

fn advance_ledgers(env: &soroban_sdk::Env, ledgers: u32) {
let mut ledger = env.ledger().get();
ledger.sequence_number += ledgers;
env.ledger().set(ledger);
}

#[test]
fn test_non_whitelisted_wallet_cannot_buy_during_window() {
let env = test_env_with_auths();
let (client, _) = register_creator_keys(&env);
set_key_price_for_tests(&env, &client, 100);
let approved = Address::generate(&env);
let creator = register_whitelisted_creator(&env, &client, vec![&env, approved], 10);
let buyer = Address::generate(&env);

let result = client.try_buy_key(&creator, &buyer, &100, &None);

assert_eq!(result, Err(Ok(ContractError::WhitelistOnly)));
assert_eq!(client.get_total_key_supply(&creator), 0);
}

#[test]
fn test_whitelisted_wallet_can_buy_during_window() {
let env = test_env_with_auths();
let (client, _) = register_creator_keys(&env);
set_key_price_for_tests(&env, &client, 100);
let buyer = Address::generate(&env);
let creator = register_whitelisted_creator(&env, &client, vec![&env, buyer.clone()], 10);

let supply = client.buy_key(&creator, &buyer, &100, &None);

assert_eq!(supply, 1);
assert_eq!(client.get_key_balance(&creator, &buyer), 1);
}

#[test]
fn test_anyone_can_buy_after_window_expires() {
let env = test_env_with_auths();
let (client, _) = register_creator_keys(&env);
set_key_price_for_tests(&env, &client, 100);
let approved = Address::generate(&env);
let creator = register_whitelisted_creator(&env, &client, vec![&env, approved], 5);
advance_ledgers(&env, 5);
let public_buyer = Address::generate(&env);

let supply = client.buy_key(&creator, &public_buyer, &100, &None);

assert_eq!(supply, 1);
}

#[test]
fn test_get_whitelist_status_tracks_active_and_expired_state() {
let env = test_env_with_auths();
let (client, _) = register_creator_keys(&env);
let buyer = Address::generate(&env);
let registered_at = env.ledger().sequence();
let creator = register_whitelisted_creator(&env, &client, vec![&env, buyer], 7);

let active = client.get_whitelist_status(&creator);
assert!(active.active);
assert_eq!(active.expires_at_ledger, registered_at + 7);
assert_eq!(active.remaining_ledgers, 7);

advance_ledgers(&env, 7);
let expired = client.get_whitelist_status(&creator);
assert!(!expired.active);
assert_eq!(expired.expires_at_ledger, registered_at + 7);
assert_eq!(expired.remaining_ledgers, 0);
}

#[test]
fn test_whitelist_over_500_addresses_reverts_at_registration() {
let env = test_env_with_auths();
let (client, _) = register_creator_keys(&env);
let creator = Address::generate(&env);
let mut addresses = Vec::new(&env);
for _ in 0..=MAX_WHITELIST_SIZE {
addresses.push_back(Address::generate(&env));
}

let result = client.try_register_creator(
&creator,
&String::from_str(&env, "alice"),
&None,
&None,
&None,
&Some(WhitelistConfig {
addresses,
window_ledgers: 10,
}),
);

assert_eq!(result, Err(Ok(ContractError::WhitelistTooLarge)));
assert!(!client.is_creator_registered(&creator));
}

#[test]
fn test_none_whitelist_allows_public_buy_immediately() {
let env = test_env_with_auths();
let (client, _) = register_creator_keys(&env);
set_key_price_for_tests(&env, &client, 100);
let creator = Address::generate(&env);
client.register_creator(
&creator,
&String::from_str(&env, "alice"),
&None,
&None,
&None,
&None,
);
let buyer = Address::generate(&env);

let quote = compute_expected_buy_price(0, 100);
let supply = client.buy_key(&creator, &buyer, &quote, &None);
let status = client.get_whitelist_status(&creator);

assert_eq!(supply, 1);
assert!(!status.active);
assert_eq!(status.remaining_ledgers, 0);
}
Loading