Skip to content
Merged
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
26 changes: 23 additions & 3 deletions contracts/identity-registry-contract/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use soroban_sdk::{Address, Env};
use soroban_sdk::{Address, Env, Vec};
use crate::storage;
use crate::error::RegistryError;
use crate::types::ExpertStatus;
use crate::events;
use crate::{error::RegistryError, types::ExpertStatus};

pub fn initialize_registry(env: &Env, admin: &Address) -> Result<(), RegistryError> {
if storage::has_admin(env) {
Expand All @@ -14,6 +13,27 @@ pub fn initialize_registry(env: &Env, admin: &Address) -> Result<(), RegistryErr
Ok(())
}

/// Batch Verification
pub fn batch_add_experts(env:Env, experts: Vec<Address>) -> Result<(), RegistryError> {
if experts.len() > 20 {
return Err(RegistryError::ExpertVecMax);
}

let admin = storage::get_admin(&env).ok_or(RegistryError::NotInitialized)?;
admin.require_auth();

for expert in experts {
let status = storage::get_expert_status(&env, &expert);
if status == ExpertStatus::Verified {
return Err(RegistryError::AlreadyVerified);
}
storage::set_expert_record(&env, &expert, ExpertStatus::Verified);
events::emit_status_change(&env, expert, status, ExpertStatus::Verified, admin.clone());
}

Ok(())
}

pub fn verify_expert(env: &Env, expert: &Address) -> Result<(), RegistryError> {
let admin = storage::get_admin(env).ok_or(RegistryError::NotInitialized)?;

Expand Down
1 change: 1 addition & 0 deletions contracts/identity-registry-contract/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ pub enum RegistryError {
ExpertNotFound = 4,
AlreadyVerified = 5,
AlreadyBanned = 6,
ExpertVecMax = 7,
}
11 changes: 8 additions & 3 deletions contracts/identity-registry-contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ mod types;
#[cfg(test)]
mod test;

use soroban_sdk::{contract, contractimpl, Address, Env};
use crate::error::RegistryError;
use soroban_sdk::{contract, contractimpl, Address, Env, Vec};
use crate::{error::RegistryError};

#[contract]
pub struct IdentityRegistryContract;
Expand All @@ -21,8 +21,13 @@ impl IdentityRegistryContract {
contract::initialize_registry(&env, &admin)
}

/// Batch Add an expert to the whitelist (Admin only)
pub fn batch_add_experts(env: Env, experts: Vec<Address>) -> Result<(), RegistryError> {
contract::batch_add_experts(env, experts)
}

/// Add an expert to the whitelist (Admin only)
pub fn add_expert(env: Env, expert: Address) -> Result<(), RegistryError> {
contract::verify_expert(&env, &expert)
}
}
}
74 changes: 73 additions & 1 deletion contracts/identity-registry-contract/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
extern crate std;

use crate::{IdentityRegistryContract, IdentityRegistryContractClient};
use soroban_sdk::{Env, testutils::Address as _, Symbol, Address, IntoVal, TryIntoVal};
use crate::{storage, types::ExpertStatus};
use soroban_sdk::{Env, testutils::Address as _, Symbol, Address, IntoVal, TryIntoVal, Vec, vec};
use soroban_sdk::testutils::{AuthorizedFunction, AuthorizedInvocation, Events};

#[test]
Expand All @@ -24,6 +25,77 @@ fn test_initialization() {
assert!(res_duplicate.is_err());
}

#[test]
#[should_panic]
fn test_batch_verification_no_admin() {
let env = Env::default();

let contract_id = env.register_contract(None, IdentityRegistryContract);
let client = IdentityRegistryContractClient::new(&env, &contract_id);

let experts = vec![&env, Address::generate(&env), Address::generate(&env), Address::generate(&env)];

client.batch_add_experts(&experts);
}
Comment on lines 28 to 39
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

git ls-files contracts/identity-registry-contract/src/ | head -20

Repository: LightForgeHub/SkillSphere-Contracts

Length of output: 431


🏁 Script executed:

find contracts -name "test.rs" -o -name "lib.rs" | head -10

Repository: LightForgeHub/SkillSphere-Contracts

Length of output: 264


🏁 Script executed:

find . -type f -name "*.rs" | grep -E "(test|contract)" | head -20

Repository: LightForgeHub/SkillSphere-Contracts

Length of output: 687


🏁 Script executed:

cat -n contracts/identity-registry-contract/src/test.rs | head -80

Repository: LightForgeHub/SkillSphere-Contracts

Length of output: 3395


🏁 Script executed:

cat -n contracts/identity-registry-contract/src/contract.rs | head -100

Repository: LightForgeHub/SkillSphere-Contracts

Length of output: 487


🏁 Script executed:

cat -n contracts/identity-registry-contract/src/contract.rs | grep -A 30 "batch_add_experts"

Repository: LightForgeHub/SkillSphere-Contracts

Length of output: 61


🏁 Script executed:

cat -n contracts/identity-registry-contract/src/contract.rs | grep -A 30 "pub fn batch"

Repository: LightForgeHub/SkillSphere-Contracts

Length of output: 61


🏁 Script executed:

wc -l contracts/identity-registry-contract/src/contract.rs

Repository: LightForgeHub/SkillSphere-Contracts

Length of output: 134


🏁 Script executed:

cat -n contracts/identity-registry-contract/src/contract.rs

Repository: LightForgeHub/SkillSphere-Contracts

Length of output: 487


🏁 Script executed:

cat -n contracts/identity-registry-contract/src/lib.rs

Repository: LightForgeHub/SkillSphere-Contracts

Length of output: 1679


This test doesn't actually verify admin auth.

The panic occurs from the .unwrap() on line 32 of batch_add_experts() (when get_admin() returns None due to missing initialization), not from auth enforcement. Additionally, env.mock_all_auths() bypasses the require_auth() check entirely, so the test would never catch an actual auth failure.

Remove env.mock_all_auths(), initialize the admin with client.init(&admin), and let the test fail on the proper auth check:

Suggested fix
 #[test]
 #[should_panic]
 fn test_batch_verification_no_admin() {
     let env = Env::default();
-    env.mock_all_auths();
 
     let contract_id = env.register_contract(None, IdentityRegistryContract);
     let client = IdentityRegistryContractClient::new(&env, &contract_id);
 
+    let admin = Address::generate(&env);
+    client.init(&admin);
+
     let experts = vec![&env, Address::generate(&env), Address::generate(&env), Address::generate(&env)];
 
     client.batch_add_experts(&experts);
 }
πŸ€– Prompt for AI Agents
In `@contracts/identity-registry-contract/src/test.rs` around lines 40 - 52, The
test currently panics due to unwrap on get_admin() and bypasses auth because
env.mock_all_auths() is used; remove env.mock_all_auths(), create an admin
address and call client.init(&admin) (using the admin as the signer) so the
contract has an admin, then call client.batch_add_experts(...) without
authenticating as that admin so the panic comes from the require_auth() check;
reference the test name test_batch_verification_no_admin and the methods
client.init, client.batch_add_experts, env.mock_all_auths, get_admin, and
require_auth to locate and fix the code.


#[test]
fn test_batch_verification_check_status() {
let env = Env::default();
env.mock_all_auths();

let contract_id = env.register_contract(None, IdentityRegistryContract);
let client = IdentityRegistryContractClient::new(&env, &contract_id);

let admin = soroban_sdk::Address::generate(&env);
client.init(&admin);

let e1: Address = Address::generate(&env);
let e2 = Address::generate(&env);
let e3 = Address::generate(&env);
let e4 = Address::generate(&env);
let e5 = Address::generate(&env);

let experts = vec![&env, e1.clone(), e2.clone(), e3.clone(), e4.clone(), e5.clone()];

client.batch_add_experts(&experts);

env.as_contract(&contract_id, ||{
assert_eq!(storage::get_expert_status(&env, &e1), ExpertStatus::Verified);
assert_eq!(storage::get_expert_status(&env, &e2), ExpertStatus::Verified);
assert_eq!(storage::get_expert_status(&env, &e3), ExpertStatus::Verified);
assert_eq!(storage::get_expert_status(&env, &e4), ExpertStatus::Verified);
assert_eq!(storage::get_expert_status(&env, &e5), ExpertStatus::Verified);
})
}

#[test]
#[should_panic(expected = "Error(Contract, #7)")]
fn test_batch_verification_max_vec() {
let env = Env::default();
env.mock_all_auths();

let contract_id = env.register_contract(None, IdentityRegistryContract);
let client = IdentityRegistryContractClient::new(&env, &contract_id);

let admin = soroban_sdk::Address::generate(&env);
client.init(&admin);

let e1 = Address::generate(&env);
let e2 = Address::generate(&env);
let e3 = Address::generate(&env);
let e4 = Address::generate(&env);

let experts = vec![&env, e1.clone(), e2.clone(), e3.clone(), e4.clone(),
e1.clone(), e2.clone(), e3.clone(), e4.clone(),
e1.clone(), e2.clone(), e3.clone(), e4.clone(),
e1.clone(), e2.clone(), e3.clone(), e4.clone(),
e1.clone(), e2.clone(), e3.clone(), e4.clone(),
e1.clone(), e2.clone(), e3.clone(), e4.clone()
];

client.batch_add_experts(&experts);
}

#[test]
fn test_add_expert() {
let env = Env::default();
Expand Down