-
Notifications
You must be signed in to change notification settings - Fork 7
[Feat]:: Implemented "Ban Expert" Logic #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feat]:: Implemented "Ban Expert" Logic #10
Conversation
📝 WalkthroughWalkthroughAdds admin-managed registry initialization, admin-authorized expert verification and banning, batch expert addition, a public status getter, admin storage helpers (with TTL touches), status-change events, and expanded tests covering verification and banning lifecycles. Changes
Sequence Diagram(s)mermaid Admin->>Contract: initialize_registry(admin) / ban_expert(expert) / batch_add_experts(...) Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@contracts/identity-registry-contract/src/contract.rs`:
- Around line 41-62: In verify_expert, add a guard to prevent re-verifying a
banned expert: fetch current_status via storage::get_expert_status(env, expert)
(same as ban_expert uses) and if current_status == ExpertStatus::Banned return
Err(RegistryError::AlreadyBanned) before the existing AlreadyVerified check;
this enforces that ban revokes verification (alternatively implement a separate
unban_expert with explicit authorization if unbanning is allowed).
🧹 Nitpick comments (3)
contracts/identity-registry-contract/src/lib.rs (1)
35-37: Consider adding a doc comment for API consistency.The other public methods (
init,add_expert,ban_expert) have doc comments, butget_statusdoes not. Adding one would maintain consistency in the public API documentation.📝 Suggested doc comment
+ /// Get the current status of an expert pub fn get_status(env: Env, expert: Address) -> ExpertStatus { contract::get_expert_status(&env, &expert) }contracts/identity-registry-contract/src/test.rs (2)
99-130: Consider adding explicit authorization verification forban_expert.The test validates the ban flow and error handling, but unlike
test_add_expert(lines 45-58), it doesn't explicitly verify thatban_expertrequires admin authorization viaAuthorizedInvocationcheck. Additionally, per PR objectives,ban_expertshould emit anExpertStatusChangedevent, but this isn't verified.♻️ Suggested additions to enhance test coverage
// Ban the expert (should succeed) client.ban_expert(&expert); + // Verify admin authorization was required + assert_eq!( + env.auths().last().unwrap(), + ( + admin.clone(), + AuthorizedInvocation { + function: AuthorizedFunction::Contract(( + contract_id.clone(), + Symbol::new(&env, "ban_expert"), + (expert.clone(),).into_val(&env) + )), + sub_invocations: std::vec![] + } + ) + ); + + // Verify ExpertStatusChanged event was emitted + let events = env.events().all(); + let event = events.last().unwrap(); + assert_eq!(event.0, contract_id); + let topic: Symbol = event.1.get(0).unwrap().try_into_val(&env).unwrap(); + assert_eq!(topic, Symbol::new(&env, "status_change")); + // Check that status is now Banned let status = client.get_status(&expert);
144-152: Simplify the authorization mocking setup.The sequence of
mock_all_auths_allowing_non_root_auth()followed bymock_auths(&[])is confusing. A simpler pattern, consistent withtest_add_expert_unauthorized, would be to avoid any auth mocking before callingban_expert:♻️ Simplified version
client.init(&admin); env.mock_all_auths(); client.add_expert(&expert); - env.mock_all_auths_allowing_non_root_auth(); - - env.mock_auths(&[]); + // Clear auth mocking - subsequent calls will require real authorization + env.mock_auths(&[]); client.ban_expert(&expert); }Alternatively, for maximum clarity and consistency with
test_add_expert_unauthorized, you could use a scoped approach where auth mocking only applies to theadd_expertcall.
| pub fn ban_expert(env: &Env, expert: &Address) -> Result<(), RegistryError> { | ||
| let admin = storage::get_admin(env).ok_or(RegistryError::NotInitialized)?; | ||
| admin.require_auth(); | ||
|
|
||
| let current_status = storage::get_expert_status(env, expert); | ||
|
|
||
| if current_status == ExpertStatus::Banned { | ||
| return Err(RegistryError::AlreadyBanned); | ||
| } | ||
|
|
||
| storage::set_expert_record(env, expert, ExpertStatus::Banned); | ||
|
|
||
| events::emit_status_change( | ||
| env, | ||
| expert.clone(), | ||
| current_status, | ||
| ExpertStatus::Banned, | ||
| admin, | ||
| ); | ||
|
|
||
| Ok(()) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's look at the verify_expert function implementation
cat -n contracts/identity-registry-contract/src/contract.rs | sed -n '1,80p'Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 2208
🏁 Script executed:
# Search for test files related to ban and verify operations
fd -e rs -path "*/test*" | head -20Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 247
🏁 Script executed:
# Look for any tests that mention ban_expert or the interaction between ban and verify
rg "ban_expert|Banned.*Verified|verify.*ban" -B 3 -A 3 --type rustRepository: LightForgeHub/SkillSphere-Contracts
Length of output: 7289
🏁 Script executed:
# Check if there's a verify_expert function and see its implementation
ast-grep --pattern 'fn verify_expert($_) { $$$ }'Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 61
🏁 Script executed:
# Look for any comments, TODOs, or documentation about expert status handling
rg "TODO|FIXME|NOTE|preemptive|unbann" --type rust -iRepository: LightForgeHub/SkillSphere-Contracts
Length of output: 61
🏁 Script executed:
# Search more thoroughly for tests that might cover re-verification of banned experts
cat -n contracts/identity-registry-contract/src/test.rs | head -300Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 9485
🏁 Script executed:
# Look for the complete test_ban_expert_workflow test
rg "test_ban_expert_workflow" -A 50 -B 5Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 4640
🏁 Script executed:
# Check ExpertStatus enum to understand all possible states
rg "enum ExpertStatus" -A 10Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 847
🏁 Script executed:
# Look for any documentation or comments about the intended behavior of ban/verify
rg "Ban|Verified|expert" contracts/identity-registry-contract/src/lib.rs -B 2 -A 2Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 600
🏁 Script executed:
# Check if there's any test for re-verifying a banned expert (verify after ban)
rg "ban_expert.*verify_expert|verify_expert.*ban_expert" -B 5 -A 5Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 61
🏁 Script executed:
# Search more comprehensively for any mention of re-verification after ban
rg "Verified.*Banned|Banned.*Verified" -B 3 -A 3Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 61
🏁 Script executed:
# Check if there's documentation or requirements about the design
find . -name "README*" -o -name "REQUIREMENTS*" -o -name "*.md" | head -10Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 125
🏁 Script executed:
# Look for any TODOs or FIXMEs related to ban/verify logic
rg "TODO|FIXME" contracts/identity-registry-contract/ -B 2 -A 2Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 61
🏁 Script executed:
# Check the README for design documentation or requirements
cat README.mdRepository: LightForgeHub/SkillSphere-Contracts
Length of output: 8315
🏁 Script executed:
# Look specifically for the PR template to understand requirements
cat ./.github/pull_request_template.mdRepository: LightForgeHub/SkillSphere-Contracts
Length of output: 1480
🏁 Script executed:
# Check if there's any test attempting to re-verify a banned expert
rg "ban_expert" -A 20 contracts/identity-registry-contract/src/test.rs | rg -A 15 "verify_expert|add_expert"Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 1605
🏁 Script executed:
# Look at complete_expert_lifecycle test to confirm it doesn't test re-verification after ban
cat -n contracts/identity-registry-contract/src/test.rs | sed -n '238,261p'Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 971
Add a check in verify_expert to prevent re-verifying banned experts.
The implementation currently allows re-verifying a Banned expert back to Verified status. The verify_expert function only guards against AlreadyVerified but does not check Banned status. This conflicts with the documented semantics that banning "revokes" verification. Add: if current_status == ExpertStatus::Banned { return Err(RegistryError::AlreadyBanned); } before the existing check, or introduce an explicit unban_expert function if unbanning should require separate authorization.
🤖 Prompt for AI Agents
In `@contracts/identity-registry-contract/src/contract.rs` around lines 41 - 62,
In verify_expert, add a guard to prevent re-verifying a banned expert: fetch
current_status via storage::get_expert_status(env, expert) (same as ban_expert
uses) and if current_status == ExpertStatus::Banned return
Err(RegistryError::AlreadyBanned) before the existing AlreadyVerified check;
this enforces that ban revokes verification (alternatively implement a separate
unban_expert with explicit authorization if unbanning is allowed).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@contracts/identity-registry-contract/src/storage.rs`:
- Around line 7-9: The admin record stored under DataKey::Admin currently never
extends its instance TTL, so modify has_admin, set_admin, and get_admin to call
the same extend_ttl() used for expert records: after successfully setting the
admin in set_admin call extend_ttl() to bump TTL; in get_admin and has_admin, if
the admin is found return the value and call extend_ttl() to refresh TTL (mirror
the expert get/set pattern). Locate DataKey::Admin and the functions has_admin,
set_admin, and get_admin and add the extend_ttl() invocation in the same spots
and order as the expert record code to ensure consistent TTL behavior.
♻️ Duplicate comments (1)
contracts/identity-registry-contract/src/contract.rs (1)
18-29: Block re‑verification of banned experts.
verify_expertonly guardsVerified, so aBannedexpert can be re‑verified, undermining the ban semantics. Add an explicitBannedcheck before the existing guard.🐛 Suggested guard in
verify_expertlet current_status = storage::get_expert_status(env, expert); + if current_status == ExpertStatus::Banned { + return Err(RegistryError::AlreadyBanned); + } if current_status == ExpertStatus::Verified { return Err(RegistryError::AlreadyVerified); }
| pub enum DataKey { | ||
| Admin, | ||
| Expert(Address), | ||
| Admin, | ||
| Expert(Address), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cat -n contracts/identity-registry-contract/src/storage.rs | head -50Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 214
🏁 Script executed:
cat contracts/identity-registry-contract/src/storage.rsRepository: LightForgeHub/SkillSphere-Contracts
Length of output: 2568
Extend admin instance TTL to prevent silent expiration.
Admin is stored in instance storage without TTL extension. Unlike expert records which correctly call extend_ttl() on both set and get operations, admin functions (has_admin, set_admin, get_admin) never bump the TTL. Once the admin expires, has_admin() silently returns false and the registry becomes unmanaged or can be re-initialized. Apply the same TTL extension pattern used for expert records:
TTL extension for admin storage
pub fn has_admin(env: &Env) -> bool {
- env.storage().instance().has(&DataKey::Admin)
+ let has = env.storage().instance().has(&DataKey::Admin);
+ if has {
+ env.storage().instance().extend_ttl(LEDGERS_THRESHOLD, LEDGERS_EXTEND_TO);
+ }
+ has
}
pub fn set_admin(env: &Env, admin: &Address) {
env.storage().instance().set(&DataKey::Admin, admin);
+ env.storage().instance().extend_ttl(LEDGERS_THRESHOLD, LEDGERS_EXTEND_TO);
}
pub fn get_admin(env: &Env) -> Option<Address> {
- env.storage().instance().get(&DataKey::Admin)
+ let admin = env.storage().instance().get(&DataKey::Admin);
+ if admin.is_some() {
+ env.storage().instance().extend_ttl(LEDGERS_THRESHOLD, LEDGERS_EXTEND_TO);
+ }
+ admin
}🤖 Prompt for AI Agents
In `@contracts/identity-registry-contract/src/storage.rs` around lines 7 - 9, The
admin record stored under DataKey::Admin currently never extends its instance
TTL, so modify has_admin, set_admin, and get_admin to call the same extend_ttl()
used for expert records: after successfully setting the admin in set_admin call
extend_ttl() to bump TTL; in get_admin and has_admin, if the admin is found
return the value and call extend_ttl() to refresh TTL (mirror the expert get/set
pattern). Locate DataKey::Admin and the functions has_admin, set_admin, and
get_admin and add the extend_ttl() invocation in the same spots and order as the
expert record code to ensure consistent TTL behavior.
|
Hello !!! can you please give me compliments !! |
|
kindly fix the conflicts then ready for merge! @ryzen-xp |
|
Hello @Bosun-Josh121 check it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@contracts/identity-registry-contract/src/contract.rs`:
- Around line 1-5: The file imports ExpertStatus twice causing a duplicate
import error (E0252); remove the redundant use of ExpertStatus so only a single
import remains (keep the canonical import from crate::types::ExpertStatus and
delete the duplicate in the grouped crate import), ensuring functions/types that
reference ExpertStatus still compile and no other use statements are
accidentally removed.
In `@contracts/identity-registry-contract/src/test.rs`:
- Around line 5-8: The test import block contains a duplicate import of
ExpertStatus which causes E0252; remove the redundant import so ExpertStatus is
imported only once (for example keep crate::types::ExpertStatus and delete the
duplicate in the crate::{storage, types::ExpertStatus} or vice versa) and ensure
the remaining imports still include IdentityRegistryContract,
IdentityRegistryContractClient and storage so types and clients resolve
correctly.
♻️ Duplicate comments (1)
contracts/identity-registry-contract/src/contract.rs (1)
40-59: Prevent re-verifying banned experts (ban should be terminal unless explicitly unbanned).
verify_expertstill allows aBannedexpert to be set back toVerified, which undermines the “ban revokes verification” intent. Consider blockingBannedhere (and/or introduce a dedicated unban flow).🔧 Proposed fix
let current_status = storage::get_expert_status(env, expert); + if current_status == ExpertStatus::Banned { + return Err(RegistryError::AlreadyBanned); + } if current_status == ExpertStatus::Verified { return Err(RegistryError::AlreadyVerified); }
|
Hello @ryzen-xp, please makes sure there's no build errors |
|
Hello @Bosun-Josh121 can you recheck |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
contracts/identity-registry-contract/src/contract.rs (2)
17-37: Block re-verification of banned experts in batch flow.
batch_add_expertswill currently re-verifyBannedexperts. If ban is meant to be revocation, this should returnAlreadyBannedbefore setting status toVerified.✅ Proposed fix
for expert in experts { let status = storage::get_expert_status(&env, &expert); + if status == ExpertStatus::Banned { + return Err(RegistryError::AlreadyBanned); + } 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()); }
6-15: Addadmin.require_auth()to prevent admin squatting during initialization.Any caller can invoke
initialize_registryand designate themselves as the admin before the intended admin does. This is a critical vulnerability since the admin role controls all expert verification and banning. All other admin functions (batch_add_experts,verify_expert,ban_expert) properly calladmin.require_auth(); initialization must do the same. Note: the same vulnerability exists inpayment-vault-contract/src/contract.rsin theinitialize_vaultfunction.🔒 Proposed fix
pub fn initialize_registry(env: &Env, admin: &Address) -> Result<(), RegistryError> { if storage::has_admin(env) { return Err(RegistryError::AlreadyInitialized); } + admin.require_auth(); storage::set_admin(env, admin); Ok(()) }
🤖 Fix all issues with AI agents
In `@contracts/identity-registry-contract/src/contract.rs`:
- Around line 17-19: Update the function doc comment to accurately describe
batch_add_experts: replace the singular "Verify an expert" line with a
description indicating this function batch-verifies multiple experts
(admin-only), e.g., note that batch_add_experts takes Env and Vec<Address> and
sets multiple experts' status to Verified, returning Result<(), RegistryError>;
keep mention of admin-only and Batch Verification.
♻️ Duplicate comments (1)
contracts/identity-registry-contract/src/contract.rs (1)
39-61: Prevent re-verifying banned experts (already flagged).Same concern as previous review: add a
Bannedguard before theAlreadyVerifiedcheck.
| /// Verify an expert by setting their status to Verified (Admin only) | ||
| /// Batch Verification | ||
| pub fn batch_add_experts(env:Env, experts: Vec<Address>) -> Result<(), RegistryError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix the batch function doc comment.
The doc comment says “Verify an expert” but this function batch-verifies. Consider updating for accuracy.
🤖 Prompt for AI Agents
In `@contracts/identity-registry-contract/src/contract.rs` around lines 17 - 19,
Update the function doc comment to accurately describe batch_add_experts:
replace the singular "Verify an expert" line with a description indicating this
function batch-verifies multiple experts (admin-only), e.g., note that
batch_add_experts takes Env and Vec<Address> and sets multiple experts' status
to Verified, returning Result<(), RegistryError>; keep mention of admin-only and
Batch Verification.
|
Check tests as well @ryzen-xp |
|
hi @Bosun-Josh121 , plz give me some compliments on drip . |
🧠 SkillSphere Pull Request 🌐
Mark with an
xall the checkboxes that apply (like[x])cargo test(All tests passed)📌 Type of Change
📝 Changes Description
Implemented Ban Expert security feature to enable admins to revoke verification status from bad actors.
Changes:
ban_expert()function insrc/contract.rswith admin authban_expert()andget_status()insrc/lib.rsAlreadyBannederror variantStorage Impact: Single storage write + event emission (similar gas cost to
verify_expert)📸 Evidence
Tests include:
Summary by CodeRabbit
New Features
Tests
✏️ Tip: You can customize this high-level summary in your review settings.