Skip to content

Commit

Permalink
Merge branch 'main' into capped
Browse files Browse the repository at this point in the history
  • Loading branch information
ozgunozerk authored Feb 19, 2025
2 parents 8d87a5f + ea24fae commit 64a6fde
Show file tree
Hide file tree
Showing 15 changed files with 2,541 additions and 6 deletions.
2 changes: 1 addition & 1 deletion examples/fungible-pausable/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![no_std]
#![allow(dead_code)]

mod contract;
mod contract_token_interface;
mod test;
20 changes: 20 additions & 0 deletions examples/fungible-token-interface/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[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 }
openzeppelin-pausable = { workspace = true }
openzeppelin-pausable-macros = { workspace = true }
openzeppelin-fungible-token = { workspace = true }

[dev-dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
//! Fungible Pausable Example Contract.
//!
//! This contract replicates the functionality of the one in "contract.rs",
//! offering the same features. The key difference lies in how SEP-41 compliance
//! is achieved. The contract in "contract.rs" accomplishes this by implementing
//! 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
//! [`openzeppelin_fungible_token::fungible::FungibleToken`] and
//! [`openzeppelin_fungible_token::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 "contract.rs" for better
//! organization of the code, consistency and ease of inspection/debugging.
//! 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 openzeppelin_fungible_token::{self as fungible, mintable::FungibleMintable};
use openzeppelin_pausable::{self as pausable, Pausable};
Expand Down
5 changes: 5 additions & 0 deletions examples/fungible-token-interface/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#![no_std]
#![allow(dead_code)]

mod contract;
mod test;
129 changes: 129 additions & 0 deletions examples/fungible-token-interface/src/test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#![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, #100)")]
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, #100)")]
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, #100)")]
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, #100)")]
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);
}
Loading

0 comments on commit 64a6fde

Please sign in to comment.