diff --git a/Cargo.toml b/Cargo.toml index c879b2c..11638ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,10 @@ members = [ "libs/plugin-system", "libs/auto-fix", "apps/api", - "tests/mutation" + "tests/mutation", + "packages/examples/stellar/token-example", + "packages/examples/stellar/access-control-example", + "packages/examples/stellar/upgradeable-example" ] [workspace.package] diff --git a/packages/examples/stellar/access-control-example/Cargo.toml b/packages/examples/stellar/access-control-example/Cargo.toml new file mode 100644 index 0000000..581c1fb --- /dev/null +++ b/packages/examples/stellar/access-control-example/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "access-control-example" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { version = "21.0.0", features = ["alloc"] } + +[dev-dependencies] +soroban-sdk = { version = "21.0.0", features = ["testutils", "alloc"] } diff --git a/packages/examples/stellar/access-control-example/src/lib.rs b/packages/examples/stellar/access-control-example/src/lib.rs new file mode 100644 index 0000000..9b6ec15 --- /dev/null +++ b/packages/examples/stellar/access-control-example/src/lib.rs @@ -0,0 +1,44 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl, contracttype, Address, Env}; + +#[contracttype] +pub enum DataKey { + Admin, + Role(Address), +} + +#[contracttype] +#[derive(Clone, PartialEq)] +pub enum Role { + Admin, + User, + None, +} + +#[contract] +pub struct AccessControlContract; + +#[contractimpl] +impl AccessControlContract { + pub fn initialize(env: Env, admin: Address) { + env.storage().instance().set(&DataKey::Admin, &admin); + env.storage().instance().set(&DataKey::Role(admin), &Role::Admin); + } + + pub fn grant_role(env: Env, caller: Address, account: Address) { + caller.require_auth(); + let stored_admin: Address = env.storage().instance().get(&DataKey::Admin).unwrap(); + assert!(caller == stored_admin, "Only admin can grant roles"); + env.storage().instance().set(&DataKey::Role(account), &Role::User); + } + + pub fn get_role(env: Env, account: Address) -> Role { + env.storage().instance().get(&DataKey::Role(account)).unwrap_or(Role::None) + } + + pub fn restricted_action(env: Env, caller: Address) { + caller.require_auth(); + let role: Role = env.storage().instance().get(&DataKey::Role(caller)).unwrap_or(Role::None); + assert!(role != Role::None, "Access denied: no role assigned"); + } +} diff --git a/packages/examples/stellar/token-example/Cargo.toml b/packages/examples/stellar/token-example/Cargo.toml new file mode 100644 index 0000000..01b4ff0 --- /dev/null +++ b/packages/examples/stellar/token-example/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "token-example" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { version = "21.0.0", features = ["alloc"] } + +[dev-dependencies] +soroban-sdk = { version = "21.0.0", features = ["testutils", "alloc"] } diff --git a/packages/examples/stellar/token-example/src/lib.rs b/packages/examples/stellar/token-example/src/lib.rs new file mode 100644 index 0000000..d331fd4 --- /dev/null +++ b/packages/examples/stellar/token-example/src/lib.rs @@ -0,0 +1,32 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl, contracttype, Address, Env}; + +#[contracttype] +pub enum DataKey { + Admin, + Balance(Address), +} + +#[contract] +pub struct TokenContract; + +#[contractimpl] +impl TokenContract { + pub fn initialize(env: Env, admin: Address, amount: i128) { + env.storage().instance().set(&DataKey::Admin, &admin); + env.storage().instance().set(&DataKey::Balance(admin.clone()), &amount); + } + + pub fn balance(env: Env, account: Address) -> i128 { + env.storage().instance().get(&DataKey::Balance(account)).unwrap_or(0) + } + + pub fn transfer(env: Env, from: Address, to: Address, amount: i128) { + from.require_auth(); + let from_balance: i128 = env.storage().instance().get(&DataKey::Balance(from.clone())).unwrap_or(0); + assert!(from_balance >= amount, "Insufficient balance"); + env.storage().instance().set(&DataKey::Balance(from.clone()), &(from_balance - amount)); + let to_balance: i128 = env.storage().instance().get(&DataKey::Balance(to.clone())).unwrap_or(0); + env.storage().instance().set(&DataKey::Balance(to.clone()), &(to_balance + amount)); + } +} diff --git a/packages/examples/stellar/upgradeable-example/Cargo.toml b/packages/examples/stellar/upgradeable-example/Cargo.toml new file mode 100644 index 0000000..fe9a89f --- /dev/null +++ b/packages/examples/stellar/upgradeable-example/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "upgradeable-example" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { version = "21.0.0", features = ["alloc"] } + +[dev-dependencies] +soroban-sdk = { version = "21.0.0", features = ["testutils", "alloc"] } diff --git a/packages/examples/stellar/upgradeable-example/src/lib.rs b/packages/examples/stellar/upgradeable-example/src/lib.rs new file mode 100644 index 0000000..175aa64 --- /dev/null +++ b/packages/examples/stellar/upgradeable-example/src/lib.rs @@ -0,0 +1,36 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl, contracttype, Address, BytesN, Env}; + +#[contracttype] +pub enum DataKey { + Admin, + Version, +} + +#[contract] +pub struct UpgradeableContract; + +#[contractimpl] +impl UpgradeableContract { + pub fn initialize(env: Env, admin: Address) { + env.storage().instance().set(&DataKey::Admin, &admin); + env.storage().instance().set(&DataKey::Version, &1u32); + } + + pub fn upgrade(env: Env, caller: Address, new_wasm_hash: BytesN<32>) { + caller.require_auth(); + let admin: Address = env.storage().instance().get(&DataKey::Admin).unwrap(); + assert!(caller == admin, "Only admin can upgrade"); + env.deployer().update_current_contract_wasm(new_wasm_hash); + let version: u32 = env.storage().instance().get(&DataKey::Version).unwrap_or(1); + env.storage().instance().set(&DataKey::Version, &(version + 1)); + } + + pub fn version(env: Env) -> u32 { + env.storage().instance().get(&DataKey::Version).unwrap_or(1) + } + + pub fn admin(env: Env) -> Address { + env.storage().instance().get(&DataKey::Admin).unwrap() + } +}