Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ Cargo.lock

# IDE settings
.vscode/

# Test snapshots
test_snapshots/
13 changes: 13 additions & 0 deletions contracts/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[workspace]
members = [
"common",
"course-registry",
"quest-engine",
"reward-pool",
Expand Down
1 change: 1 addition & 0 deletions contracts/badge-nft/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ doctest = false

[dependencies]
soroban-sdk = { workspace = true }
contracts-common = { path = "../common" }

[dev-dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }
Expand Down
21 changes: 4 additions & 17 deletions contracts/badge-nft/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ pub struct ContractUpgraded {
// to avoid duplicate symbol errors at link time.
#[cfg(feature = "contract")]
mod contract_impl {
use contracts_common::require_admin;
use soroban_sdk::{contract, contractimpl, Address, BytesN, Env, Vec};

use crate::types::{Badge, DataKey};
Expand Down Expand Up @@ -96,17 +97,12 @@ mod contract_impl {
/// the learner's badge vector and panicking on match. This enforces
/// one-badge-per-course invariants.
pub fn mint_badge(env: Env, caller: Address, learner: Address, course_id: u32) {
caller.require_auth();

let stored_admin: Address = env
.storage()
.instance()
.get(&DataKey::Admin)
.expect("Contract not initialized");
assert!(
caller == stored_admin,
"Unauthorized: Caller is not the authorized registry"
);
require_admin(&env, &caller, &stored_admin);

let badges_key = DataKey::UserBadges(learner.clone());
let mut badges: Vec<Badge> = env
Expand Down Expand Up @@ -152,19 +148,12 @@ mod contract_impl {
/// from the learner's `Badge` vector. If the badge is not present,
/// the function is a no-op (no event emitted, no panic).
pub fn revoke_badge(env: Env, admin: Address, learner: Address, course_id: u32) {
// 1. admin.require_auth()
admin.require_auth();

// 2. Fetch 'Admin' (Registry) address from Instance storage. Assert caller == Admin.
let stored_admin: Address = env
.storage()
.instance()
.get(&DataKey::Admin)
.expect("Contract not initialized");
assert!(
admin == stored_admin,
"Unauthorized: Caller is not the authorized registry"
);
require_admin(&env, &admin, &stored_admin);

// 3. Construct DataKey::UserBadges(learner).
let badges_key = DataKey::UserBadges(learner.clone());
Expand Down Expand Up @@ -255,14 +244,12 @@ mod contract_impl {
/// Soroban host. Admin-only. Emits `ContractUpgraded` on
/// success; panics with `"Unauthorized"` for non-admins.
pub fn upgrade_contract(env: Env, admin: Address, new_wasm_hash: BytesN<32>) {
admin.require_auth();

let stored_admin: Address = env
.storage()
.instance()
.get(&DataKey::Admin)
.expect("Not initialized");
assert!(admin == stored_admin, "Unauthorized");
require_admin(&env, &admin, &stored_admin);

env.deployer()
.update_current_contract_wasm(new_wasm_hash.clone());
Expand Down
4 changes: 2 additions & 2 deletions contracts/badge-nft/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ fn test_mint_badge_not_initialized() {
}

#[test]
#[should_panic(expected = "Unauthorized: Caller is not the authorized registry")]
#[should_panic(expected = "HostError: Error(Contract, #1)")]
fn test_mint_badge_unauthorized_caller() {
let (env, client) = setup();
let registry = Address::generate(&env);
Expand Down Expand Up @@ -279,7 +279,7 @@ fn test_revoke_badge_emits_event() {
}

#[test]
#[should_panic(expected = "Unauthorized: Caller is not the authorized registry")]
#[should_panic(expected = "Error(Contract, #1)")]
fn test_revoke_badge_unauthorized_caller() {
let (env, client) = setup();
let registry = Address::generate(&env);
Expand Down
Loading
Loading