From a94825331df31d9edb2b6780660a0f869b06a17a Mon Sep 17 00:00:00 2001 From: Pam Selle Date: Wed, 29 Oct 2025 11:37:40 -0400 Subject: [PATCH 1/2] Remove fungible-token-interface and update nft enumerable, and lib deps --- Cargo.lock | 357 +++--------------- Cargo.toml | 15 +- contracts/fungible-token-interface/Cargo.toml | 20 - .../fungible-token-interface/src/contract.rs | 140 ------- contracts/fungible-token-interface/src/lib.rs | 5 - .../fungible-token-interface/src/test.rs | 129 ------- contracts/nft-enumerable/Cargo.toml | 4 +- contracts/nft-enumerable/src/contract.rs | 4 +- contracts/nft-enumerable/src/lib.rs | 1 + contracts/nft-enumerable/src/test.rs | 2 - 10 files changed, 62 insertions(+), 615 deletions(-) delete mode 100644 contracts/fungible-token-interface/Cargo.toml delete mode 100644 contracts/fungible-token-interface/src/contract.rs delete mode 100644 contracts/fungible-token-interface/src/lib.rs delete mode 100644 contracts/fungible-token-interface/src/test.rs diff --git a/Cargo.lock b/Cargo.lock index 60a8715..2e722b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,12 +177,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.22.1" @@ -347,16 +341,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "ctor" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" -dependencies = [ - "quote", - "syn 2.0.101", -] - [[package]] name = "ctor" version = "0.5.0" @@ -624,16 +608,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "fungible-token-interface-example" -version = "0.0.1" -dependencies = [ - "soroban-sdk 22.0.8", - "stellar-fungible", - "stellar-pausable", - "stellar-pausable-macros", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -673,9 +647,9 @@ dependencies = [ name = "guess-the-number" version = "0.0.1" dependencies = [ - "soroban-sdk 23.0.3", + "soroban-sdk", "stellar-registry", - "stellar-xdr 23.0.0", + "stellar-xdr", ] [[package]] @@ -872,9 +846,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" name = "nft-enumerable-example" version = "0.0.1" dependencies = [ - "soroban-sdk 22.0.8", - "stellar-default-impl-macro", - "stellar-non-fungible", + "soroban-sdk", + "stellar-macros", + "stellar-tokens", ] [[package]] @@ -1179,7 +1153,7 @@ version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" dependencies = [ - "base64 0.22.1", + "base64", "chrono", "hex", "indexmap 1.9.3", @@ -1247,18 +1221,6 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" -[[package]] -name = "soroban-builtin-sdk-macros" -version = "22.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2e42bf80fcdefb3aae6ff3c7101a62cf942e95320ed5b518a1705bc11c6b2f" -dependencies = [ - "itertools", - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "soroban-builtin-sdk-macros" version = "23.0.1" @@ -1271,25 +1233,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "soroban-env-common" -version = "22.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "027cd856171bfd6ad2c0ffb3b7dfe55ad7080fb3050c36ad20970f80da634472" -dependencies = [ - "arbitrary", - "crate-git-revision", - "ethnum", - "num-derive", - "num-traits", - "serde", - "soroban-env-macros 22.1.3", - "soroban-wasmi", - "static_assertions", - "stellar-xdr 22.1.0", - "wasmparser", -] - [[package]] name = "soroban-env-common" version = "23.0.1" @@ -1302,69 +1245,23 @@ dependencies = [ "num-derive", "num-traits", "serde", - "soroban-env-macros 23.0.1", + "soroban-env-macros", "soroban-wasmi", "static_assertions", - "stellar-xdr 23.0.0", + "stellar-xdr", "wasmparser", ] -[[package]] -name = "soroban-env-guest" -version = "22.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a07dda1ae5220d975979b19ad4fd56bc86ec7ec1b4b25bc1c5d403f934e592e" -dependencies = [ - "soroban-env-common 22.1.3", - "static_assertions", -] - [[package]] name = "soroban-env-guest" version = "23.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccd1e40963517b10963a8e404348d3fe6caf9c278ac47a6effd48771297374d6" dependencies = [ - "soroban-env-common 23.0.1", + "soroban-env-common", "static_assertions", ] -[[package]] -name = "soroban-env-host" -version = "22.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66e8b03a4191d485eab03f066336112b2a50541a7553179553dc838b986b94dd" -dependencies = [ - "ark-bls12-381", - "ark-ec", - "ark-ff", - "ark-serialize", - "curve25519-dalek", - "ecdsa", - "ed25519-dalek", - "elliptic-curve", - "generic-array", - "getrandom", - "hex-literal", - "hmac", - "k256", - "num-derive", - "num-integer", - "num-traits", - "p256", - "rand", - "rand_chacha", - "sec1", - "sha2", - "sha3", - "soroban-builtin-sdk-macros 22.1.3", - "soroban-env-common 22.1.3", - "soroban-wasmi", - "static_assertions", - "stellar-strkey 0.0.9", - "wasmparser", -] - [[package]] name = "soroban-env-host" version = "23.0.1" @@ -1393,29 +1290,14 @@ dependencies = [ "sec1", "sha2", "sha3", - "soroban-builtin-sdk-macros 23.0.1", - "soroban-env-common 23.0.1", + "soroban-builtin-sdk-macros", + "soroban-env-common", "soroban-wasmi", "static_assertions", - "stellar-strkey 0.0.13", + "stellar-strkey", "wasmparser", ] -[[package]] -name = "soroban-env-macros" -version = "22.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00eff744764ade3bc480e4909e3a581a240091f3d262acdce80b41f7069b2bd9" -dependencies = [ - "itertools", - "proc-macro2", - "quote", - "serde", - "serde_json", - "stellar-xdr 22.1.0", - "syn 2.0.101", -] - [[package]] name = "soroban-env-macros" version = "23.0.1" @@ -1427,24 +1309,10 @@ dependencies = [ "quote", "serde", "serde_json", - "stellar-xdr 23.0.0", + "stellar-xdr", "syn 2.0.101", ] -[[package]] -name = "soroban-ledger-snapshot" -version = "22.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2826e2c9d364edbb2ea112dc861077c74557bdad0a7a00487969088c7c648169" -dependencies = [ - "serde", - "serde_json", - "serde_with", - "soroban-env-common 22.1.3", - "soroban-env-host 22.1.3", - "thiserror", -] - [[package]] name = "soroban-ledger-snapshot" version = "23.0.3" @@ -1454,33 +1322,11 @@ dependencies = [ "serde", "serde_json", "serde_with", - "soroban-env-common 23.0.1", - "soroban-env-host 23.0.1", + "soroban-env-common", + "soroban-env-host", "thiserror", ] -[[package]] -name = "soroban-sdk" -version = "22.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7ac27d7573e62b745513fa1be8dab7a09b9676a7f39db97164f1d458a344749" -dependencies = [ - "arbitrary", - "bytes-lit", - "ctor 0.2.9", - "derive_arbitrary", - "ed25519-dalek", - "rand", - "rustc_version", - "serde", - "serde_json", - "soroban-env-guest 22.1.3", - "soroban-env-host 22.1.3", - "soroban-ledger-snapshot 22.0.8", - "soroban-sdk-macros 22.0.8", - "stellar-strkey 0.0.9", -] - [[package]] name = "soroban-sdk" version = "23.0.3" @@ -1490,38 +1336,18 @@ dependencies = [ "arbitrary", "bytes-lit", "crate-git-revision", - "ctor 0.5.0", + "ctor", "derive_arbitrary", "ed25519-dalek", "rand", "rustc_version", "serde", "serde_json", - "soroban-env-guest 23.0.1", - "soroban-env-host 23.0.1", - "soroban-ledger-snapshot 23.0.3", - "soroban-sdk-macros 23.0.3", - "stellar-strkey 0.0.13", -] - -[[package]] -name = "soroban-sdk-macros" -version = "22.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef0d7d62b2584696d306b8766728971c7d0731a03a5e047f1fc68722ac8cf0c" -dependencies = [ - "crate-git-revision", - "darling", - "itertools", - "proc-macro2", - "quote", - "rustc_version", - "sha2", - "soroban-env-common 22.1.3", - "soroban-spec 22.0.8", - "soroban-spec-rust 22.0.8", - "stellar-xdr 22.1.0", - "syn 2.0.101", + "soroban-env-guest", + "soroban-env-host", + "soroban-ledger-snapshot", + "soroban-sdk-macros", + "stellar-strkey", ] [[package]] @@ -1537,53 +1363,25 @@ dependencies = [ "proc-macro2", "quote", "sha2", - "soroban-env-common 23.0.1", - "soroban-spec 23.0.3", - "soroban-spec-rust 23.0.3", - "stellar-xdr 23.0.0", + "soroban-env-common", + "soroban-spec", + "soroban-spec-rust", + "stellar-xdr", "syn 2.0.101", ] -[[package]] -name = "soroban-spec" -version = "22.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4ad0867aec99770ed614fedbec7ac4591791df162ff9e548ab7ebd07cd23a9c" -dependencies = [ - "base64 0.13.1", - "stellar-xdr 22.1.0", - "thiserror", - "wasmparser", -] - [[package]] name = "soroban-spec" version = "23.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd257b0365307e0b8d38040ee0364abcc610fc6e61960ff5e26803922d098921" dependencies = [ - "base64 0.22.1", - "stellar-xdr 23.0.0", + "base64", + "stellar-xdr", "thiserror", "wasmparser", ] -[[package]] -name = "soroban-spec-rust" -version = "22.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebe31c042adfa2885ec47b67b08fcead8707da80a3fe737eaf2a9ae1a8cfdc3" -dependencies = [ - "prettyplease", - "proc-macro2", - "quote", - "sha2", - "soroban-spec 22.0.8", - "stellar-xdr 22.1.0", - "syn 2.0.101", - "thiserror", -] - [[package]] name = "soroban-spec-rust" version = "23.0.3" @@ -1594,8 +1392,8 @@ dependencies = [ "proc-macro2", "quote", "sha2", - "soroban-spec 23.0.3", - "stellar-xdr 23.0.0", + "soroban-spec", + "stellar-xdr", "syn 2.0.101", "thiserror", ] @@ -1648,67 +1446,20 @@ dependencies = [ ] [[package]] -name = "stellar-constants" -version = "0.3.0" -source = "git+https://github.com/OpenZeppelin/stellar-contracts?tag=v0.3.0#659fcabdc0e4712254dfebe4f45efd54f49826e9" -dependencies = [ - "soroban-sdk 22.0.8", -] - -[[package]] -name = "stellar-default-impl-macro" -version = "0.3.0" -source = "git+https://github.com/OpenZeppelin/stellar-contracts?tag=v0.3.0#659fcabdc0e4712254dfebe4f45efd54f49826e9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "stellar-fungible" -version = "0.3.0" -source = "git+https://github.com/OpenZeppelin/stellar-contracts?tag=v0.3.0#659fcabdc0e4712254dfebe4f45efd54f49826e9" -dependencies = [ - "soroban-sdk 22.0.8", - "stellar-constants", -] - -[[package]] -name = "stellar-macro-helpers" -version = "0.3.0" -source = "git+https://github.com/OpenZeppelin/stellar-contracts?tag=v0.3.0#659fcabdc0e4712254dfebe4f45efd54f49826e9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "stellar-non-fungible" -version = "0.3.0" -source = "git+https://github.com/OpenZeppelin/stellar-contracts?tag=v0.3.0#659fcabdc0e4712254dfebe4f45efd54f49826e9" -dependencies = [ - "soroban-sdk 22.0.8", - "stellar-constants", -] - -[[package]] -name = "stellar-pausable" -version = "0.3.0" -source = "git+https://github.com/OpenZeppelin/stellar-contracts?tag=v0.3.0#659fcabdc0e4712254dfebe4f45efd54f49826e9" +name = "stellar-contract-utils" +version = "0.5.0" +source = "git+https://github.com/OpenZeppelin/stellar-contracts?tag=v0.5.0#969a22096aea7326adf076f0efcde290cc476cba" dependencies = [ - "soroban-sdk 22.0.8", + "soroban-sdk", ] [[package]] -name = "stellar-pausable-macros" -version = "0.3.0" -source = "git+https://github.com/OpenZeppelin/stellar-contracts?tag=v0.3.0#659fcabdc0e4712254dfebe4f45efd54f49826e9" +name = "stellar-macros" +version = "0.5.0" +source = "git+https://github.com/OpenZeppelin/stellar-contracts?tag=v0.5.0#969a22096aea7326adf076f0efcde290cc476cba" dependencies = [ "proc-macro2", "quote", - "stellar-macro-helpers", "syn 2.0.101", ] @@ -1732,22 +1483,11 @@ dependencies = [ "regex", "sha2", "stellar-build", - "stellar-strkey 0.0.13", - "stellar-xdr 23.0.0", + "stellar-strkey", + "stellar-xdr", "syn 2.0.101", ] -[[package]] -name = "stellar-strkey" -version = "0.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e3aa3ed00e70082cb43febc1c2afa5056b9bb3e348bbb43d0cd0aa88a611144" -dependencies = [ - "crate-git-revision", - "data-encoding", - "thiserror", -] - [[package]] name = "stellar-strkey" version = "0.0.13" @@ -1759,19 +1499,12 @@ dependencies = [ ] [[package]] -name = "stellar-xdr" -version = "22.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ce69db907e64d1e70a3dce8d4824655d154749426a6132b25395c49136013e4" +name = "stellar-tokens" +version = "0.5.0" +source = "git+https://github.com/OpenZeppelin/stellar-contracts?tag=v0.5.0#969a22096aea7326adf076f0efcde290cc476cba" dependencies = [ - "arbitrary", - "base64 0.13.1", - "crate-git-revision", - "escape-bytes", - "hex", - "serde", - "serde_with", - "stellar-strkey 0.0.9", + "soroban-sdk", + "stellar-contract-utils", ] [[package]] @@ -1781,7 +1514,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89d2848e1694b0c8db81fd812bfab5ea71ee28073e09ccc45620ef3cf7a75a9b" dependencies = [ "arbitrary", - "base64 0.22.1", + "base64", "cfg_eval", "crate-git-revision", "escape-bytes", @@ -1790,7 +1523,7 @@ dependencies = [ "serde", "serde_with", "sha2", - "stellar-strkey 0.0.13", + "stellar-strkey", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 79c05a6..a9b6a1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,10 +10,11 @@ repository = "https://github.com/theahaco/scaffold-stellar" version = "0.0.1" [workspace.dependencies.soroban-sdk] -version = "22.0.8" +version = "23.0.2" -[workspace.dependencies.soroban-token-sdk] -version = "22.0.8" +[workspace.dependencies.stellar-access] +git = "https://github.com/OpenZeppelin/stellar-contracts" +tag = "v0.5.0" [workspace.dependencies.stellar-default-impl-macro] git = "https://github.com/OpenZeppelin/stellar-contracts" @@ -23,6 +24,10 @@ tag = "v0.3.0" git = "https://github.com/OpenZeppelin/stellar-contracts" tag = "v0.3.0" +[workspace.dependencies.stellar-macros] +git = "https://github.com/OpenZeppelin/stellar-contracts" +tag = "v0.5.0" + [workspace.dependencies.stellar-non-fungible] git = "https://github.com/OpenZeppelin/stellar-contracts" tag = "v0.3.0" @@ -35,6 +40,10 @@ tag = "v0.3.0" git = "https://github.com/OpenZeppelin/stellar-contracts" tag = "v0.3.0" +[workspace.dependencies.stellar-tokens] +git = "https://github.com/OpenZeppelin/stellar-contracts" +tag = "v0.5.0" + [profile.release] opt-level = "z" debug = false diff --git a/contracts/fungible-token-interface/Cargo.toml b/contracts/fungible-token-interface/Cargo.toml deleted file mode 100644 index ebf27ee..0000000 --- a/contracts/fungible-token-interface/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "fungible-token-interface-example" -edition.workspace = true -license.workspace = true -repository.workspace = true -publish = false -version.workspace = true - -[lib] -crate-type = ["cdylib"] -doctest = false - -[dependencies] -soroban-sdk = { workspace = true } -stellar-pausable = { workspace = true } -stellar-pausable-macros = { workspace = true } -stellar-fungible = { workspace = true } - -[dev-dependencies] -soroban-sdk = { workspace = true, features = ["testutils"] } diff --git a/contracts/fungible-token-interface/src/contract.rs b/contracts/fungible-token-interface/src/contract.rs deleted file mode 100644 index fdf9aa1..0000000 --- a/contracts/fungible-token-interface/src/contract.rs +++ /dev/null @@ -1,140 +0,0 @@ -//! Fungible Pausable Example Contract. -//! -//! This contract replicates the functionality of the contract in -//! "examples/fungible-pausable", offering the same features. The key difference -//! lies in how SEP-41 compliance is achieved. The contract in "contract.rs" -//! accomplishes this by implementing -//! [`stellar_fungible::fungible::FungibleToken`] and -//! [`stellar_fungible::burnable::FungibleBurnable`], whereas this -//! version directly implements [`soroban_sdk::token::TokenInterface`]. -//! -//! Ultimately, it is up to the user to choose their preferred approach to -//! creating a SEP-41 token. We suggest the approach in -//! "examples/fungible-pausable" for better organization of the code, -//! consistency and ease of inspection/debugging. - -use soroban_sdk::{ - contract, contracterror, contractimpl, panic_with_error, symbol_short, token::TokenInterface, - Address, Env, String, Symbol, -}; -use stellar_fungible::Base; -use stellar_pausable::{self as pausable, Pausable}; -use stellar_pausable_macros::when_not_paused; - -pub const OWNER: Symbol = symbol_short!("OWNER"); - -#[contract] -pub struct ExampleContract; - -#[contracterror] -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -#[repr(u32)] -pub enum ExampleContractError { - Unauthorized = 1, -} - -#[contractimpl] -impl ExampleContract { - pub fn __constructor(e: &Env, owner: Address, initial_supply: i128) { - Base::set_metadata(e, 18, String::from_str(e, "My Token"), String::from_str(e, "TKN")); - Base::mint(e, &owner, initial_supply); - e.storage().instance().set(&OWNER, &owner); - } - - /// `TokenInterface` doesn't require implementing `total_supply()` because - /// of the need for backwards compatibility with Stellar classic assets. - pub fn total_supply(e: &Env) -> i128 { - Base::total_supply(e) - } - - #[when_not_paused] - pub fn mint(e: &Env, account: Address, amount: i128) { - // When `ownable` module is available, - // the following checks should be equivalent to: - // `ownable::only_owner(&e);` - let owner: Address = e.storage().instance().get(&OWNER).expect("owner should be set"); - owner.require_auth(); - - Base::mint(e, &account, amount); - } -} - -#[contractimpl] -impl Pausable for ExampleContract { - fn paused(e: &Env) -> bool { - pausable::paused(e) - } - - fn pause(e: &Env, caller: Address) { - // When `ownable` module is available, - // the following checks should be equivalent to: - // `ownable::only_owner(&e);` - caller.require_auth(); - let owner: Address = e.storage().instance().get(&OWNER).expect("owner should be set"); - if owner != caller { - panic_with_error!(e, ExampleContractError::Unauthorized); - } - - pausable::pause(e); - } - - fn unpause(e: &Env, caller: Address) { - // When `ownable` module is available, - // the following checks should be equivalent to: - // `ownable::only_owner(&e);` - caller.require_auth(); - let owner: Address = e.storage().instance().get(&OWNER).expect("owner should be set"); - if owner != caller { - panic_with_error!(e, ExampleContractError::Unauthorized); - } - - pausable::unpause(e); - } -} - -#[contractimpl] -impl TokenInterface for ExampleContract { - fn balance(e: Env, account: Address) -> i128 { - Base::balance(&e, &account) - } - - fn allowance(e: Env, owner: Address, spender: Address) -> i128 { - Base::allowance(&e, &owner, &spender) - } - - #[when_not_paused] - fn transfer(e: Env, from: Address, to: Address, amount: i128) { - Base::transfer(&e, &from, &to, amount); - } - - #[when_not_paused] - fn transfer_from(e: Env, spender: Address, from: Address, to: Address, amount: i128) { - Base::transfer_from(&e, &spender, &from, &to, amount); - } - - fn approve(e: Env, owner: Address, spender: Address, amount: i128, live_until_ledger: u32) { - Base::approve(&e, &owner, &spender, amount, live_until_ledger); - } - - #[when_not_paused] - fn burn(e: Env, from: Address, amount: i128) { - Base::burn(&e, &from, amount) - } - - #[when_not_paused] - fn burn_from(e: Env, spender: Address, from: Address, amount: i128) { - Base::burn_from(&e, &spender, &from, amount) - } - - fn decimals(e: Env) -> u32 { - Base::decimals(&e) - } - - fn name(e: Env) -> String { - Base::name(&e) - } - - fn symbol(e: Env) -> String { - Base::symbol(&e) - } -} diff --git a/contracts/fungible-token-interface/src/lib.rs b/contracts/fungible-token-interface/src/lib.rs deleted file mode 100644 index 0dfb969..0000000 --- a/contracts/fungible-token-interface/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![no_std] -#![allow(dead_code)] - -mod contract; -mod test; diff --git a/contracts/fungible-token-interface/src/test.rs b/contracts/fungible-token-interface/src/test.rs deleted file mode 100644 index 35a32b6..0000000 --- a/contracts/fungible-token-interface/src/test.rs +++ /dev/null @@ -1,129 +0,0 @@ -#![cfg(test)] - -extern crate std; - -use soroban_sdk::{testutils::Address as _, Address, Env, String}; - -use crate::contract::{ExampleContract, ExampleContractClient}; - -fn create_client<'a>(e: &Env, owner: &Address, initial_supply: i128) -> ExampleContractClient<'a> { - let address = e.register(ExampleContract, (owner, initial_supply)); - ExampleContractClient::new(e, &address) -} - -#[test] -fn initial_state() { - let e = Env::default(); - let owner = Address::generate(&e); - let client = create_client(&e, &owner, 1000); - - assert_eq!(client.total_supply(), 1000); - assert_eq!(client.balance(&owner), 1000); - assert_eq!(client.symbol(), String::from_str(&e, "TKN")); - assert_eq!(client.name(), String::from_str(&e, "My Token")); - assert_eq!(client.decimals(), 18); - assert!(!client.paused()); -} - -#[test] -fn transfer_works() { - let e = Env::default(); - let owner = Address::generate(&e); - let recipient = Address::generate(&e); - let client = create_client(&e, &owner, 1000); - - e.mock_all_auths(); - client.transfer(&owner, &recipient, &100); - assert_eq!(client.balance(&owner), 900); - assert_eq!(client.balance(&recipient), 100); -} - -#[test] -#[should_panic(expected = "Error(Contract, #1000)")] -fn transfer_fails_when_paused() { - let e = Env::default(); - let owner = Address::generate(&e); - let recipient = Address::generate(&e); - let client = create_client(&e, &owner, 1000); - - e.mock_all_auths(); - client.pause(&owner); - client.transfer(&owner, &recipient, &100); -} - -#[test] -fn transfer_from_works() { - let e = Env::default(); - let owner = Address::generate(&e); - let spender = Address::generate(&e); - let recipient = Address::generate(&e); - let client = create_client(&e, &owner, 1000); - - e.mock_all_auths(); - client.approve(&owner, &spender, &200, &100); - client.transfer_from(&spender, &owner, &recipient, &200); - assert_eq!(client.balance(&owner), 800); - assert_eq!(client.balance(&recipient), 200); -} - -#[test] -#[should_panic(expected = "Error(Contract, #1000)")] -fn transfer_from_fails_when_paused() { - let e = Env::default(); - let owner = Address::generate(&e); - let spender = Address::generate(&e); - let recipient = Address::generate(&e); - let client = create_client(&e, &owner, 1000); - - e.mock_all_auths(); - client.pause(&owner); - client.transfer_from(&spender, &owner, &recipient, &200); -} - -#[test] -fn mint_works() { - let e = Env::default(); - let owner = Address::generate(&e); - let client = create_client(&e, &owner, 1000); - - e.mock_all_auths(); - client.mint(&owner, &500); - assert_eq!(client.total_supply(), 1500); - assert_eq!(client.balance(&owner), 1500); -} - -#[test] -#[should_panic(expected = "Error(Contract, #1000)")] -fn mint_fails_when_paused() { - let e = Env::default(); - let owner = Address::generate(&e); - let client = create_client(&e, &owner, 1000); - - e.mock_all_auths(); - client.pause(&owner); - client.mint(&owner, &500); -} - -#[test] -fn burn_works() { - let e = Env::default(); - let owner = Address::generate(&e); - let client = create_client(&e, &owner, 1000); - - e.mock_all_auths(); - client.burn(&owner, &200); - assert_eq!(client.total_supply(), 800); - assert_eq!(client.balance(&owner), 800); -} - -#[test] -#[should_panic(expected = "Error(Contract, #1000)")] -fn burn_fails_when_paused() { - let e = Env::default(); - let owner = Address::generate(&e); - let client = create_client(&e, &owner, 1000); - - e.mock_all_auths(); - client.pause(&owner); - client.burn(&owner, &200); -} diff --git a/contracts/nft-enumerable/Cargo.toml b/contracts/nft-enumerable/Cargo.toml index 581750d..8394aec 100644 --- a/contracts/nft-enumerable/Cargo.toml +++ b/contracts/nft-enumerable/Cargo.toml @@ -12,8 +12,8 @@ doctest = false [dependencies] soroban-sdk = { workspace = true } -stellar-non-fungible = { workspace = true } -stellar-default-impl-macro = { workspace = true } +stellar-tokens = { workspace = true } +stellar-macros = { workspace = true } [dev-dependencies] soroban-sdk = { workspace = true, features = ["testutils"] } diff --git a/contracts/nft-enumerable/src/contract.rs b/contracts/nft-enumerable/src/contract.rs index c9ec487..3a2fd22 100644 --- a/contracts/nft-enumerable/src/contract.rs +++ b/contracts/nft-enumerable/src/contract.rs @@ -5,8 +5,8 @@ //! IDs owned by each account. use soroban_sdk::{contract, contractimpl, contracttype, Address, Env, String}; -use stellar_default_impl_macro::default_impl; -use stellar_non_fungible::{ +use stellar_macros::default_impl; +use stellar_tokens::non_fungible::{ burnable::NonFungibleBurnable, enumerable::{Enumerable, NonFungibleEnumerable}, Base, NonFungibleToken, diff --git a/contracts/nft-enumerable/src/lib.rs b/contracts/nft-enumerable/src/lib.rs index 0dfb969..f1ec4a1 100644 --- a/contracts/nft-enumerable/src/lib.rs +++ b/contracts/nft-enumerable/src/lib.rs @@ -2,4 +2,5 @@ #![allow(dead_code)] mod contract; +#[cfg(test)] mod test; diff --git a/contracts/nft-enumerable/src/test.rs b/contracts/nft-enumerable/src/test.rs index 1286f2f..83f4fda 100644 --- a/contracts/nft-enumerable/src/test.rs +++ b/contracts/nft-enumerable/src/test.rs @@ -1,5 +1,3 @@ -#![cfg(test)] - extern crate std; use soroban_sdk::{testutils::Address as _, Address, Env}; From aea13d76da12916fcec7a76c451c9555748cbd56 Mon Sep 17 00:00:00 2001 From: Pam Selle Date: Wed, 29 Oct 2025 11:38:22 -0400 Subject: [PATCH 2/2] Add fungible-allowlist to replace interface contract --- Cargo.lock | 18 +++ contracts/fungible-allowlist/Cargo.toml | 20 +++ contracts/fungible-allowlist/src/contract.rs | 71 +++++++++ contracts/fungible-allowlist/src/lib.rs | 7 + contracts/fungible-allowlist/src/test.rs | 154 +++++++++++++++++++ 5 files changed, 270 insertions(+) create mode 100644 contracts/fungible-allowlist/Cargo.toml create mode 100644 contracts/fungible-allowlist/src/contract.rs create mode 100644 contracts/fungible-allowlist/src/lib.rs create mode 100644 contracts/fungible-allowlist/src/test.rs diff --git a/Cargo.lock b/Cargo.lock index 2e722b9..5c53646 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -608,6 +608,16 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "fungible-allowlist-example" +version = "0.0.1" +dependencies = [ + "soroban-sdk", + "stellar-access", + "stellar-macros", + "stellar-tokens", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1433,6 +1443,14 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "stellar-access" +version = "0.5.0" +source = "git+https://github.com/OpenZeppelin/stellar-contracts?tag=v0.5.0#969a22096aea7326adf076f0efcde290cc476cba" +dependencies = [ + "soroban-sdk", +] + [[package]] name = "stellar-build" version = "0.0.4" diff --git a/contracts/fungible-allowlist/Cargo.toml b/contracts/fungible-allowlist/Cargo.toml new file mode 100644 index 0000000..4cf40c5 --- /dev/null +++ b/contracts/fungible-allowlist/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "fungible-allowlist-example" +edition.workspace = true +license.workspace = true +repository.workspace = true +publish = false +version.workspace = true + +[lib] +crate-type = ["cdylib"] +doctest = false + +[dependencies] +soroban-sdk = { workspace = true } +stellar-access = { workspace = true } +stellar-macros = { workspace = true } +stellar-tokens = { workspace = true } + +[dev-dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } diff --git a/contracts/fungible-allowlist/src/contract.rs b/contracts/fungible-allowlist/src/contract.rs new file mode 100644 index 0000000..42c8a80 --- /dev/null +++ b/contracts/fungible-allowlist/src/contract.rs @@ -0,0 +1,71 @@ +//! Fungible AllowList Example Contract. + +//! This contract showcases how to integrate the AllowList extension with a +//! SEP-41-compliant fungible token. It includes essential features such as +//! controlled token transfers by an admin who can allow or disallow specific +//! accounts. + +use soroban_sdk::{contract, contractimpl, symbol_short, Address, Env, String}; +use stellar_access::access_control::{self as access_control, AccessControl}; +use stellar_macros::{default_impl, only_role}; +use stellar_tokens::fungible::{ + allowlist::{AllowList, FungibleAllowList}, + burnable::FungibleBurnable, + Base, FungibleToken, +}; + +#[contract] +pub struct ExampleContract; + +#[contractimpl] +impl ExampleContract { + pub fn __constructor(e: &Env, admin: Address, manager: Address, initial_supply: i128) { + Base::set_metadata( + e, + 18, + String::from_str(e, "AllowList Token"), + String::from_str(e, "ALT"), + ); + + access_control::set_admin(e, &admin); + + // create a role "manager" and grant it to `manager` + access_control::grant_role_no_auth(e, &admin, &manager, &symbol_short!("manager")); + + // Allow the admin to transfer tokens + AllowList::allow_user(e, &admin); + + // Mint initial supply to the admin + Base::mint(e, &admin, initial_supply); + } +} + +#[default_impl] +#[contractimpl] +impl FungibleToken for ExampleContract { + type ContractType = AllowList; +} +#[contractimpl] +impl FungibleAllowList for ExampleContract { + fn allowed(e: &Env, account: Address) -> bool { + AllowList::allowed(e, &account) + } + + #[only_role(operator, "manager")] + fn allow_user(e: &Env, user: Address, operator: Address) { + AllowList::allow_user(e, &user) + } + + #[only_role(operator, "manager")] + fn disallow_user(e: &Env, user: Address, operator: Address) { + AllowList::disallow_user(e, &user) + } +} + +#[default_impl] +#[contractimpl] +impl AccessControl for ExampleContract {} + +#[default_impl] +#[contractimpl] +impl FungibleBurnable for ExampleContract {} diff --git a/contracts/fungible-allowlist/src/lib.rs b/contracts/fungible-allowlist/src/lib.rs new file mode 100644 index 0000000..a3e21cd --- /dev/null +++ b/contracts/fungible-allowlist/src/lib.rs @@ -0,0 +1,7 @@ +#![no_std] +#![allow(dead_code)] + +mod contract; + +#[cfg(test)] +mod test; diff --git a/contracts/fungible-allowlist/src/test.rs b/contracts/fungible-allowlist/src/test.rs new file mode 100644 index 0000000..8b2afd8 --- /dev/null +++ b/contracts/fungible-allowlist/src/test.rs @@ -0,0 +1,154 @@ +extern crate std; + +use soroban_sdk::{testutils::Address as _, Address, Env}; + +use crate::contract::{ExampleContract, ExampleContractClient}; + +fn create_client<'a>( + e: &Env, + admin: &Address, + manager: &Address, + initial_supply: &i128, +) -> ExampleContractClient<'a> { + let address = e.register(ExampleContract, (admin, manager, initial_supply)); + ExampleContractClient::new(e, &address) +} + +#[test] +#[should_panic(expected = "Error(Contract, #113)")] +fn cannot_transfer_before_allow() { + let e = Env::default(); + let admin = Address::generate(&e); + let manager = Address::generate(&e); + let user1 = Address::generate(&e); + let user2 = Address::generate(&e); + let initial_supply = 1_000_000; + let client = create_client(&e, &admin, &manager, &initial_supply); + let transfer_amount = 1000; + + // Verify initial state - admin is allowed, others are not + assert!(client.allowed(&admin)); + assert!(!client.allowed(&user1)); + assert!(!client.allowed(&user2)); + + // Admin can't transfer to user1 initially (user1 not allowed) + e.mock_all_auths(); + client.transfer(&admin, &user1, &transfer_amount); +} + +#[test] +fn transfer_to_allowed_account_works() { + let e = Env::default(); + let admin = Address::generate(&e); + let manager = Address::generate(&e); + let user1 = Address::generate(&e); + let user2 = Address::generate(&e); + let initial_supply = 1_000_000; + let client = create_client(&e, &admin, &manager, &initial_supply); + let transfer_amount = 1000; + + e.mock_all_auths(); + + // Verify initial state - admin is allowed, others are not + assert!(client.allowed(&admin)); + assert!(!client.allowed(&user1)); + assert!(!client.allowed(&user2)); + + // Allow user1 + client.allow_user(&user1, &manager); + assert!(client.allowed(&user1)); + + // Now admin can transfer to user1 + client.transfer(&admin, &user1, &transfer_amount); + assert_eq!(client.balance(&user1), transfer_amount); +} + +#[test] +#[should_panic(expected = "Error(Contract, #113)")] +fn cannot_transfer_after_disallow() { + let e = Env::default(); + let admin = Address::generate(&e); + let manager = Address::generate(&e); + let user1 = Address::generate(&e); + let user2 = Address::generate(&e); + let initial_supply = 1_000_000; + let client = create_client(&e, &admin, &manager, &initial_supply); + let transfer_amount = 1000; + + e.mock_all_auths(); + + // Verify initial state - admin is allowed, others are not + assert!(client.allowed(&admin)); + assert!(!client.allowed(&user1)); + assert!(!client.allowed(&user2)); + + // Allow user1 + client.allow_user(&user1, &manager); + assert!(client.allowed(&user1)); + + // Now admin can transfer to user1 + client.transfer(&admin, &user1, &transfer_amount); + assert_eq!(client.balance(&user1), transfer_amount); + + // Disallow user1 + client.disallow_user(&user1, &manager); + assert!(!client.allowed(&user1)); + + // Admin can't transfer to user1 after disallowing + client.transfer(&admin, &user1, &100); +} + +#[test] +fn allowlist_transfer_from_override_works() { + let e = Env::default(); + let admin = Address::generate(&e); + let manager = Address::generate(&e); + let user1 = Address::generate(&e); + let user2 = Address::generate(&e); + let initial_supply = 1_000_000; + let client = create_client(&e, &admin, &manager, &initial_supply); + let transfer_amount = 1000; + + e.mock_all_auths(); + + // Verify initial state - admin is allowed, others are not + assert!(client.allowed(&admin)); + assert!(!client.allowed(&user1)); + assert!(!client.allowed(&user2)); + + // Allow user2 + client.allow_user(&user2, &manager); + assert!(client.allowed(&user2)); + + // Now admin can transfer to user1 + client.approve(&admin, &user1, &transfer_amount, &1000); + client.transfer_from(&user1, &admin, &user2, &transfer_amount); + assert_eq!(client.balance(&user2), transfer_amount); +} + +#[test] +fn allowlist_approve_override_works() { + let e = Env::default(); + let admin = Address::generate(&e); + let manager = Address::generate(&e); + let user1 = Address::generate(&e); + let user2 = Address::generate(&e); + let initial_supply = 1_000_000; + let client = create_client(&e, &admin, &manager, &initial_supply); + let transfer_amount = 1000; + + e.mock_all_auths(); + + // Verify initial state - admin is allowed, others are not + assert!(client.allowed(&admin)); + assert!(!client.allowed(&user1)); + assert!(!client.allowed(&user2)); + + // Allow user1 + client.allow_user(&user1, &manager); + assert!(client.allowed(&user1)); + + // Approve user2 to transfer from user1 + client.approve(&user1, &user2, &transfer_amount, &1000); + assert_eq!(client.allowance(&user1, &user2), transfer_amount); +}