This document provides comprehensive documentation of all public contract functions in the Dongle smart contract. Each function includes its purpose, parameters, return values, authorization requirements, and possible errors.
Contract: DongleContract (Soroban/Rust)
Network: Stellar
Language: Rust
- Initialization & Admin Management
- Project Registry
- Project Ownership & Claiming
- Project Dependencies
- Featured Registry
- Review Registry
- Verification Registry
- Verification Renewal
- Fee Manager
- Reporting & Moderation
- Collections
- Admin Action Log
- Dispute Resolution
- TTL Management
Purpose: Initialize the contract with an initial admin address. This function must be called exactly once before any other operations.
Parameters:
env(Env): The contract environmentadmin(Address): The initial admin address
Return Value: None (void)
Authorization:
- Any address can call this during initialization (typically the contract deployer)
- Only callable once; subsequent calls will fail
Possible Errors:
- None (initialization is guarded internally)
Example:
initialize(env, admin_address);Purpose: Add a new admin address to the contract (admin-only operation).
Parameters:
env(Env): The contract environmentcaller(Address): The admin calling this function (must be an existing admin)new_admin(Address): The address to promote to admin
Return Value: Result<(), ContractError>
- Success:
Ok(()) - Failure:
ContractError
Authorization:
- Caller must be an existing admin (
is_admin(env, caller)must return true)
Possible Errors:
AdminOnly- Caller is not an adminAdminNotFound- Caller address not found in admin list
Example:
add_admin(env, admin_address, new_admin_address)?;Purpose: Remove an admin address from the contract (admin-only operation).
Parameters:
env(Env): The contract environmentcaller(Address): The admin calling this functionadmin_to_remove(Address): The admin address to remove
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an existing admin
Possible Errors:
AdminOnly- Caller is not an adminCannotRemoveLastAdmin- Cannot remove the last admin (contract must maintain at least one admin)AdminNotFound- Admin to remove not found
Example:
remove_admin(env, caller, admin_to_remove)?;Purpose: Check if an address is an admin.
Parameters:
env(Env): The contract environmentaddress(Address): The address to check
Return Value: bool
trueif the address is an adminfalseotherwise
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let is_admin_flag = is_admin(env, some_address);Purpose: Retrieve the complete list of all admin addresses.
Parameters:
env(Env): The contract environment
Return Value: Vec<Address>
- A vector containing all admin addresses
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let admins = get_admin_list(env);Purpose: Get the total number of admins in the contract.
Parameters:
env(Env): The contract environment
Return Value: u32
- The count of admins
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let admin_count = get_admin_count(env);Purpose: Register a new project on-chain with metadata.
Parameters:
env(Env): The contract environmentparams(ProjectRegistrationParams): Registration parameters containing:owner(Address): The owner/creator of the projectname(String): Project name (max length enforced)slug(String): URL-friendly project identifier (must be unique)description(String): Project description (max length enforced)category(String): Project category (max length enforced)website(Option): Optional project website URLlogo_cid(Option): Optional IPFS CID for project logometadata_cid(Option): Optional IPFS CID for extended metadatatags(Option<Vec>): Optional tags (max 10 tags, validated)social_links(Option<Map<String, String>>): Optional social media links (max 10, validated)launch_timestamp(Option): Optional Unix timestamp of project launch
Return Value: Result<u64, ContractError>
- Success:
Ok(project_id)- The unique ID of the registered project - Failure:
ContractError
Authorization:
- None (permissionless) - Any address can register a project
Possible Errors:
ProjectAlreadyExists- A project with the same slug already existsInvalidProjectName- Project name format is invalidProjectNameTooLong- Project name exceeds maximum lengthInvalidProjectDesc- Project description format is invalidProjectDescTooLong- Project description exceeds maximum lengthInvalidCategory- Category format is invalidCategoryTooLong- Category exceeds maximum lengthInvalidWebsite- Website URL format is invalidWebsiteTooLong- Website URL exceeds maximum lengthInvalidLogoCid- Logo CID format is invalidInvalidMetaCid- Metadata CID format is invalidInvalidTag- Tag format is invalidTooManyTags- More than 10 tags providedInvalidSocialLink- Social link format is invalidTooManySocialLinks- More than 10 social links providedMaxProjectsExceeded- Contract has reached maximum project capacity
Example:
let project_id = register_project(env, ProjectRegistrationParams {
owner: owner_address,
name: String::from_slice(&env, "My Project"),
slug: String::from_slice(&env, "my-project"),
description: String::from_slice(&env, "A great project"),
category: String::from_slice(&env, "DeFi"),
website: Some(String::from_slice(&env, "https://example.com")),
logo_cid: Some(String::from_slice(&env, "QmXxxx...")),
metadata_cid: None,
tags: Some(vec![&env, String::from_slice(&env, "defi")]),
social_links: None,
launch_timestamp: None,
})?;Purpose: Update project metadata (owner-only).
Parameters:
env(Env): The contract environmentparams(ProjectUpdateParams): Update parameters containing:project_id(u64): The ID of the project to updatecaller(Address): The address performing the update (must be project owner)name(Option): Optional new project nameslug(Option): Optional new slugdescription(Option): Optional new descriptioncategory(Option): Optional new categorywebsite(Option<Option>): Optional new website URL (or None to remove)logo_cid(Option<Option>): Optional new logo CIDmetadata_cid(Option<Option>): Optional new metadata CIDtags(Option<Option<Vec>>): Optional new tagssocial_links(Option<Option<Map<String, String>>>): Optional new social linkslaunch_timestamp(Option<Option>): Optional new launch timestamp
Return Value: Result<Project, ContractError>
- Success:
Ok(updated_project)- The updated project data - Failure:
ContractError
Authorization:
- Caller must be the project owner
Possible Errors:
ProjectNotFound- Project ID does not existUnauthorized- Caller is not the project ownerProjectAlreadyExists- New slug conflicts with existing projectInvalidProjectName- Invalid name formatProjectNameTooLong- Name exceeds maximum lengthInvalidProjectDesc- Invalid description formatProjectDescTooLong- Description exceeds maximum lengthInvalidCategory- Invalid category formatCategoryTooLong- Category exceeds maximum lengthInvalidWebsite- Invalid website URLWebsiteTooLong- Website exceeds maximum lengthInvalidLogoCid- Invalid logo CID formatInvalidMetaCid- Invalid metadata CID formatInvalidTag- Invalid tag formatTooManyTags- More than 10 tagsInvalidSocialLink- Invalid social link formatTooManySocialLinks- More than 10 social links
Example:
let updated_project = update_project(env, ProjectUpdateParams {
project_id: 1,
caller: owner_address,
name: Some(String::from_slice(&env, "Updated Project Name")),
slug: None,
description: None,
category: None,
website: None,
logo_cid: None,
metadata_cid: None,
tags: None,
social_links: None,
launch_timestamp: None,
})?;Purpose: Retrieve a single project by ID.
Parameters:
env(Env): The contract environmentproject_id(u64): The ID of the project to retrieve
Return Value: Option<Project>
Some(project)if foundNoneif not found
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
if let Some(project) = get_project(env, 1) {
// Use project data
}Purpose: Retrieve a project by its slug (URL-friendly identifier).
Parameters:
env(Env): The contract environmentslug(String): The project slug
Return Value: Option<Project>
Some(project)if foundNoneif not found
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
if let Some(project) = get_project_by_slug(env, String::from_slice(&env, "my-project")) {
// Use project data
}Purpose: Retrieve projects with pagination, sorted by project ID.
Parameters:
env(Env): The contract environmentstart_id(u64): The starting project ID for paginationlimit(u32): Maximum number of projects to return
Return Value: Vec<Project>
- A vector of projects matching the criteria
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let projects = list_projects(env, 0, 10); // Get first 10 projectsPurpose: Retrieve all projects owned by a specific address.
Parameters:
env(Env): The contract environmentowner(Address): The owner address
Return Value: Vec<Project>
- A vector of all projects owned by the address
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let my_projects = get_projects_by_owner(env, owner_address);Purpose: Get the count of projects owned by an address.
Parameters:
env(Env): The contract environmentowner(Address): The owner address
Return Value: u32
- The number of projects owned by the address
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let count = get_owner_project_count(env, owner_address);Purpose: Get the total number of projects in the contract.
Parameters:
env(Env): The contract environment
Return Value: u64
- The total count of projects
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let total = get_project_count(env);Purpose: Retrieve multiple projects by a list of IDs.
Parameters:
env(Env): The contract environmentids(Vec): A vector of project IDs
Return Value: Vec<Project>
- A vector of projects found (missing IDs are skipped)
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let projects = get_projects_by_ids(env, vec![&env, 1, 2, 3]);Purpose: Retrieve projects filtered by verification status with pagination.
Parameters:
env(Env): The contract environmentstatus(VerificationStatus): The verification status to filter by (Unverified, Pending, Verified, Rejected)start_id(u64): The starting project ID for paginationlimit(u32): Maximum number of projects to return
Return Value: Vec<Project>
- A vector of projects with the specified status
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let verified_projects = list_projects_by_status(env, VerificationStatus::Verified, 0, 20);Purpose: Retrieve projects filtered by category with pagination.
Parameters:
env(Env): The contract environmentcategory(String): The category to filter bystart_id(u32): The starting index for paginationlimit(u32): Maximum number of projects to return
Return Value: Vec<Project>
- A vector of projects in the specified category
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let defi_projects = list_projects_by_category(env, String::from_slice(&env, "DeFi"), 0, 10);Purpose: Retrieve projects filtered by tag with pagination.
Parameters:
env(Env): The contract environmenttag(String): The tag to filter bystart_id(u32): The starting index for paginationlimit(u32): Maximum number of projects to return
Return Value: Vec<Project>
- A vector of projects with the specified tag
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let tagged_projects = list_projects_by_tag(env, String::from_slice(&env, "nft"), 0, 10);Purpose: Archive a project (owner or admin can archive, prevents further reviews/verification).
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID to archivecaller(Address): The address performing the archive
Return Value: Result<(), ContractError>
Authorization:
- Caller must be project owner or admin
Possible Errors:
ProjectNotFound- Project ID does not existUnauthorized- Caller is neither owner nor adminAlreadyArchived- Project is already archived
Example:
archive_project(env, project_id, owner_address)?;Purpose: Reactivate an archived project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID to reactivatecaller(Address): The address performing the reactivation
Return Value: Result<(), ContractError>
Authorization:
- Caller must be project owner or admin
Possible Errors:
ProjectNotFound- Project ID does not existUnauthorized- Caller is neither owner nor adminProjectNotArchived- Project is not archived
Example:
reactivate_project(env, project_id, owner_address)?;Purpose: Link two projects together (owner-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The primary project IDcaller(Address): The project ownerlinked_project_id(u64): The project ID to link
Return Value: Result<(), ContractError>
Authorization:
- Caller must be the owner of the primary project
Possible Errors:
ProjectNotFound- One or both project IDs do not existUnauthorized- Caller is not the project ownerCannotLinkToSelf- Cannot link a project to itselfAlreadyLinked- Projects are already linked
Example:
link_project(env, 1, owner_address, 2)?;Purpose: Unlink two projects (owner-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The primary project IDcaller(Address): The project ownerlinked_project_id(u64): The project ID to unlink
Return Value: Result<(), ContractError>
Authorization:
- Caller must be the owner of the primary project
Possible Errors:
ProjectNotFound- One or both project IDs do not existUnauthorized- Caller is not the project ownerCannotLinkToSelf- Cannot unlink a project from itself
Example:
unlink_project(env, 1, owner_address, 2)?;Purpose: Get all projects linked to a specific project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: Vec<u64>
- A vector of linked project IDs
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let linked_ids = get_linked_projects(env, 1);Purpose: Initiate a project ownership transfer (requires approval from new owner).
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID to transfercaller(Address): The current project ownernew_owner(Address): The address of the new owner
Return Value: Result<(), ContractError>
Authorization:
- Caller must be the current project owner
Possible Errors:
ProjectNotFound- Project ID does not existUnauthorized- Caller is not the project owner
Example:
initiate_transfer(env, project_id, owner_address, new_owner_address)?;Purpose: Cancel a pending project ownership transfer.
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDcaller(Address): The current project owner
Return Value: Result<(), ContractError>
Authorization:
- Caller must be the current project owner
Possible Errors:
ProjectNotFound- Project ID does not existUnauthorized- Caller is not the project ownerTransferNotFound- No pending transfer for this project
Example:
cancel_transfer(env, project_id, owner_address)?;Purpose: Accept a project ownership transfer (new owner accepts).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDcaller(Address): The pending new owner
Return Value: Result<(), ContractError>
Authorization:
- Caller must be the pending new owner of the project
Possible Errors:
ProjectNotFound- Project ID does not existTransferNotFound- No pending transfer for this projectNotTransferRecip- Caller is not the pending new owner
Example:
accept_transfer(env, project_id, new_owner_address)?;Purpose: Mark a project as claimable by others (owner-only). Used when the original owner no longer maintains it.
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDcaller(Address): The project ownerclaimable(bool): True to make claimable, false to revoke
Return Value: Result<(), ContractError>
Authorization:
- Caller must be the project owner
Possible Errors:
ProjectNotFound- Project ID does not existUnauthorized- Caller is not the project owner
Example:
set_project_claimable(env, project_id, owner_address, true)?;Purpose: Submit a claim request for a claimable project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID to claimclaimant(Address): The address submitting the claimproof_cid(String): IPFS CID containing proof of stewardship
Return Value: Result<u64, ContractError>
- Success:
Ok(claim_request_id)- The ID of the claim request - Failure:
ContractError
Authorization:
- Any address can submit a claim for a claimable project
Possible Errors:
ProjectNotFound- Project ID does not existInvalidProjectData- Project is not marked as claimable
Example:
let claim_id = submit_claim_request(env, project_id, claimant_address, String::from_slice(&env, "QmXxxx..."))?;Purpose: Approve a claim request (admin-only).
Parameters:
env(Env): The contract environmentclaim_request_id(u64): The claim request ID to approveadmin(Address): The admin approving the request
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminProjectNotFound- Associated project not found
Example:
approve_claim_request(env, claim_request_id, admin_address)?;Purpose: Reject a claim request (admin-only).
Parameters:
env(Env): The contract environmentclaim_request_id(u64): The claim request ID to rejectadmin(Address): The admin rejecting the request
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an admin
Example:
reject_claim_request(env, claim_request_id, admin_address)?;Purpose: Retrieve a single claim request by ID.
Parameters:
env(Env): The contract environmentclaim_request_id(u64): The claim request ID
Return Value: Option<ClaimRequest>
Some(claim_request)if foundNoneif not found
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
if let Some(claim_req) = get_claim_request(env, claim_id) {
// Use claim request data
}Purpose: Get all claim requests for a specific project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: Vec<ClaimRequest>
- A vector of all claim requests for the project
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let claims = get_claim_requests_for_project(env, project_id);Purpose: Add a dependency to a project (owner-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDcaller(Address): The project ownerdependency(ProjectDependency): The dependency to add containing:reference(DependencyRef): Reference to the dependency (project_id, external_cid, or external_url)label(Option): Optional label (e.g., "oracle", "token")metadata_cid(Option): Optional metadata CIDadded_at(u64): Unix timestamp (usually current time)updated_at(u64): Unix timestamp (usually current time)
Return Value: Result<(), ContractError>
Authorization:
- Caller must be the project owner
Possible Errors:
ProjectNotFound- Project ID does not existUnauthorized- Caller is not the project owner
Example:
add_project_dependency(env, project_id, owner_address, ProjectDependency {
reference: DependencyRef {
project_id: Some(2),
external_cid: None,
external_url: None,
},
label: Some(String::from_slice(&env, "oracle")),
metadata_cid: None,
added_at: env.ledger().timestamp(),
updated_at: env.ledger().timestamp(),
})?;Purpose: Update an existing project dependency (owner-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDcaller(Address): The project ownerdependency_key(DependencyRef): The existing dependency reference to updatenew_dependency(ProjectDependency): The updated dependency data
Return Value: Result<(), ContractError>
Authorization:
- Caller must be the project owner
Possible Errors:
ProjectNotFound- Project ID does not existUnauthorized- Caller is not the project owner
Example:
update_project_dependency(env, project_id, owner_address, old_ref, new_dependency)?;Purpose: Remove a dependency from a project (owner-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDcaller(Address): The project ownerdependency_key(DependencyRef): The dependency reference to remove
Return Value: Result<(), ContractError>
Authorization:
- Caller must be the project owner
Possible Errors:
ProjectNotFound- Project ID does not existUnauthorized- Caller is not the project owner
Example:
remove_project_dependency(env, project_id, owner_address, dependency_ref)?;Purpose: Retrieve all dependencies for a project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: Vec<ProjectDependency>
- A vector of all project dependencies
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let dependencies = get_project_dependencies(env, project_id);Purpose: Set whether a project is featured (admin-only).
Parameters:
env(Env): The contract environmentadmin(Address): The admin addressproject_id(u64): The project ID to feature/unfeaturefeatured(bool): True to feature, false to unfeature
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminProjectNotFound- Project ID does not exist
Example:
set_featured(env, admin_address, project_id, true)?;Purpose: Retrieve all featured projects with pagination.
Parameters:
env(Env): The contract environmentstart(u32): The starting index for paginationlimit(u32): Maximum number of projects to return
Return Value: Vec<Project>
- A vector of featured projects
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let featured = list_featured_projects(env, 0, 20);Purpose: Add or create a review for a project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID being reviewedreviewer(Address): The review authorrating(u32): The rating (typically 1-5, validated by contract)comment_cid(Option): Optional IPFS CID containing the review text
Return Value: Result<(), ContractError>
Authorization:
- Caller (reviewer) can submit review for any project (unless reviews are disabled for that project)
Possible Errors:
ProjectNotFound- Project ID does not existInvalidRating- Rating is not in valid rangeDuplicateReview- Reviewer has already reviewed this projectReviewsDisabled- Reviews are disabled for this projectProjectNotArchived- Cannot review archived projects
Example:
add_review(env, project_id, reviewer_address, 5, Some(String::from_slice(&env, "QmXxxx...")))?;Purpose: Submit a review with content CID (alternative to add_review).
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID being reviewedreviewer(Address): The review authorrating(u32): The ratingreview_cid(String): IPFS CID containing the review content
Return Value: Result<(), ContractError>
Authorization:
- Reviewer can submit review
Possible Errors:
ProjectNotFound- Project ID does not existInvalidRating- Rating is not validDuplicateReview- Reviewer has already reviewed this projectReviewsDisabled- Reviews disabled for project
Example:
submit_review(env, project_id, reviewer_address, 4, String::from_slice(&env, "QmXxxx..."))?;Purpose: Update an existing review (reviewer-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDreviewer(Address): The review authorrating(u32): The new ratingcomment_cid(Option): Optional new comment CID
Return Value: Result<(), ContractError>
Authorization:
- Caller must be the reviewer
Possible Errors:
ProjectNotFound- Project ID does not existReviewNotFound- Review does not exist for this reviewerInvalidRating- Rating is not validNotReviewOwner- Caller is not the reviewer
Example:
update_review(env, project_id, reviewer_address, 3, Some(String::from_slice(&env, "QmYyyy...")))?;Purpose: Delete a review (reviewer-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDreviewer(Address): The review author
Return Value: Result<(), ContractError>
Authorization:
- Caller must be the reviewer
Possible Errors:
ProjectNotFound- Project ID does not existReviewNotFound- Review does not existNotReviewOwner- Caller is not the reviewer
Example:
delete_review(env, project_id, reviewer_address)?;Purpose: Project owner responds to a review.
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDcaller(Address): The project ownerreviewer(Address): The reviewer being responded toresponse(String): The response text
Return Value: Result<(), ContractError>
Authorization:
- Caller must be the project owner
Possible Errors:
ProjectNotFound- Project ID does not existReviewNotFound- Review does not existUnauthorized- Caller is not the project owner
Example:
respond_to_review(env, project_id, owner_address, reviewer_address, String::from_slice(&env, "Thank you for the feedback!"))?;Purpose: Get the project owner's response to a review.
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDreviewer(Address): The reviewer
Return Value: Option<String>
Some(response)if a response existsNoneif no response
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
if let Some(response) = get_review_response(env, project_id, reviewer_address) {
// Use response text
}Purpose: Retrieve a specific review by project and reviewer.
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDreviewer(Address): The reviewer address
Return Value: Option<Review>
Some(review)if foundNoneif not found
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
if let Some(review) = get_review(env, project_id, reviewer_address) {
// Use review data
}Purpose: Get the content CID of a review.
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDreviewer(Address): The reviewer address
Return Value: Option<String>
Some(cid)if a review with content CID existsNoneotherwise
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
if let Some(cid) = get_review_cid(env, project_id, reviewer_address) {
// Fetch full review from IPFS
}Purpose: Get all review content CIDs for a project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: Vec<(Address, String)>
- A vector of (reviewer_address, content_cid) pairs
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let review_cids = get_project_review_cids(env, project_id);
// Each entry is (reviewer_address, cid_string)Purpose: Retrieve multiple reviews by a list of (project_id, reviewer) pairs.
Parameters:
env(Env): The contract environmentids(Vec<(u64, Address)>): Vector of (project_id, reviewer_address) tuples
Return Value: Vec<Review>
- Vector of reviews found (missing combinations are skipped)
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let reviews = get_reviews_by_ids(env, vec![&env, (1, reviewer1), (1, reviewer2)]);Purpose: List reviews for a project with pagination.
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDstart_id(u32): The starting index for paginationlimit(u32): Maximum number of reviews to return
Return Value: Vec<Review>
- A vector of reviews for the project
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let reviews = list_reviews(env, project_id, 0, 50);Purpose: Get aggregated statistics for a project (review count, average rating).
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: ProjectStats
- Contains:
rating_sum(u64): Sum of all ratingsreview_count(u32): Number of reviewsaverage_rating(u32): Average rating
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let stats = get_project_stats(env, project_id);
let avg = stats.average_rating;Purpose: Get statistics for multiple projects at once.
Parameters:
env(Env): The contract environmentids(Vec): Vector of project IDs
Return Value: Vec<(u64, ProjectStats)>
- Vector of (project_id, stats) tuples
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let batch_stats = get_stats_batch(env, vec![&env, 1, 2, 3]);Purpose: Enable or disable reviews for a project (owner-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDcaller(Address): The project ownerenabled(bool): True to enable reviews, false to disable
Return Value: Result<(), ContractError>
Authorization:
- Caller must be the project owner
Possible Errors:
ProjectNotFound- Project ID does not existUnauthorized- Caller is not the project owner
Example:
set_reviews_enabled(env, project_id, owner_address, false)?;Purpose: Check if reviews are enabled for a project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: bool
trueif reviews are enabledfalseif disabled
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let enabled = get_reviews_enabled(env, project_id);Purpose: Report a review for moderation (spam, abuse, etc.).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDreviewer(Address): The review authorreporter(Address): The address reporting the review
Return Value: Result<(), ContractError>
Authorization:
- Any address can report a review
Possible Errors:
ProjectNotFound- Project ID does not existReviewNotFound- Review does not existAlreadyReported- Caller has already reported this reviewReviewAlreadyReported- Review has already been reported
Example:
report_review(env, project_id, reviewer_address, reporter_address)?;Purpose: Hide a review from public view (admin-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDreviewer(Address): The review authoradmin(Address): The admin hiding the review
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminProjectNotFound- Project ID does not existReviewNotFound- Review does not existReviewAlreadyHidden- Review is already hidden
Example:
hide_review(env, project_id, reviewer_address, admin_address)?;Purpose: Restore a hidden review to public view (admin-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDreviewer(Address): The review authoradmin(Address): The admin restoring the review
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminProjectNotFound- Project ID does not existReviewNotFound- Review does not existReviewNotHidden- Review is not hidden
Example:
restore_review(env, project_id, reviewer_address, admin_address)?;Purpose: Permanently delete a review (admin-only, irreversible).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDreviewer(Address): The review authoradmin(Address): The admin deleting the review
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminProjectNotFound- Project ID does not existReviewNotFound- Review does not exist
Example:
admin_delete_review(env, project_id, reviewer_address, admin_address)?;Purpose: Request verification of a project (requires fee, if configured).
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID to verifyrequester(Address): The address requesting verificationevidence_cid(String): IPFS CID containing verification evidence
Return Value: Result<(), ContractError>
Authorization:
- Any address can request verification for any project
- Project owner typically submits their own projects
Possible Errors:
ProjectNotFound- Project ID does not existProjectTooYoung- Project age is below minimum required ageUnauthorized- If project is not claimable and caller is not ownerInvalidProjectData- Project data is invalid
Example:
request_verification(env, project_id, requester_address, String::from_slice(&env, "QmXxxx..."))?;Purpose: Approve a pending verification request (admin-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDadmin(Address): The admin approving
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminProjectNotFound- Project ID does not existVerificationNotFound- No pending verification request
Example:
approve_verification(env, project_id, admin_address)?;Purpose: Reject a pending verification request (admin-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDadmin(Address): The admin rejecting
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminProjectNotFound- Project ID does not existVerificationNotFound- No pending verification request
Example:
reject_verification(env, project_id, admin_address)?;Purpose: Revoke an active verification (admin-only, typically for compliance).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDadmin(Address): The admin revokingreason(String): Reason for revocation
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminProjectNotFound- Project ID does not existVerificationNotFound- Project is not verifiedNotRevocable- Verification cannot be revoked (already revoked, etc.)
Example:
revoke_verification(env, project_id, admin_address, String::from_slice(&env, "Compliance issue"))?;Purpose: Get the current verification status of a project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: Result<VerificationRecord, ContractError>
- Contains:
request_id(u64): ID of the verification requestproject_id(u64): Project IDrequester(Address): Who requested verificationstatus(VerificationStatus): Current status (Unverified, Pending, Verified, Rejected)evidence_cid(String): CID of evidencetimestamp(u64): Request timestampfee_amount(u128): Fee paidrevoke_reason(Option): Reason if revokedexpires_at(u64): Expiry timestamp (0 = no expiry)last_renewed_at(u64): Last renewal timestamp
Authorization:
- None (read-only, permissionless)
Possible Errors:
ProjectNotFound- Project ID does not existVerificationNotFound- No verification record for this project
Example:
let verification = get_verification(env, project_id)?;Purpose: Get verification records for multiple projects.
Parameters:
env(Env): The contract environmentids(Vec): Vector of project IDs
Return Value: Vec<(u64, VerificationRecord)>
- Vector of (project_id, verification_record) tuples
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let verifications = get_verifications_batch(env, vec![&env, 1, 2, 3]);Purpose: Get the complete verification history for a project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: Vec<VerificationRecord>
- A vector of all verification records (past and present)
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let history = get_verification_history(env, project_id);Purpose: Check if a project's verification has expired.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: Result<bool, ContractError>
trueif verification has expiredfalseif not expired or no expiry configured
Authorization:
- None (read-only, permissionless)
Possible Errors:
ProjectNotFound- Project ID does not existVerificationNotFound- No verification for project
Example:
let expired = is_verification_expired(env, project_id)?;Purpose: Request renewal of an expiring or expired verification.
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDrequester(Address): The address requesting renewalevidence_cid(String): IPFS CID containing updated evidence
Return Value: Result<(), ContractError>
Authorization:
- Any address can request (typically project owner)
Possible Errors:
ProjectNotFound- Project ID does not existVerificationNotFound- No existing verification to renew
Example:
request_renewal(env, project_id, requester_address, String::from_slice(&env, "QmXxxx..."))?;Purpose: Approve a renewal request (admin-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDadmin(Address): The admin approving
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminProjectNotFound- Project ID does not exist
Example:
approve_renewal(env, project_id, admin_address)?;Purpose: Reject a renewal request (admin-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDadmin(Address): The admin rejecting
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminProjectNotFound- Project ID does not exist
Example:
reject_renewal(env, project_id, admin_address)?;Purpose: Get the current renewal request for a project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: Result<VerificationRenewalRecord, ContractError>
- Contains renewal request details
Authorization:
- None (read-only, permissionless)
Possible Errors:
ProjectNotFound- Project ID does not exist
Example:
let renewal = get_renewal_request(env, project_id)?;Purpose: Get renewal history for a project with pagination.
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDstart_index(u32): Starting indexlimit(u32): Maximum records to return
Return Value: Vec<VerificationRenewalRecord>
- Vector of renewal records
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let renewal_history = get_renewal_history(env, project_id, 0, 10);Purpose: Configure fees for contract operations (admin-only).
Parameters:
env(Env): The contract environmentadmin(Address): The admin setting feestoken(Option): Token address (None for Stellar native, Some for specific token)verification_fee(u128): Fee amount for verification requestsregistration_fee(u128): Fee amount for project registration (if enabled)treasury(Address): Address receiving collected fees
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an admin
Example:
set_fee(env, admin_address, None, 1000000, 500000, treasury_address)?;Purpose: Pay required fee for a project operation.
Parameters:
env(Env): The contract environmentpayer(Address): The address paying the feeproject_id(u64): The project ID the fee is fortoken(Option): Token to pay in (None for native, Some for token contract)
Return Value: Result<(), ContractError>
Authorization:
- Payer must authorize the payment
Possible Errors:
ProjectNotFound- Project ID does not existFeeConfigNotSet- Fee configuration not set upTreasuryNotSet- Treasury address not configuredInsufficientFee- Payment is less than required fee
Example:
pay_fee(env, payer_address, project_id, None)?;Purpose: Get the current fee configuration.
Parameters:
env(Env): The contract environment
Return Value: Result<FeeConfig, ContractError>
- Contains:
token(Option): Token used for feesverification_fee(u128): Verification fee amountregistration_fee(u128): Registration fee amount
Authorization:
- None (read-only, permissionless)
Possible Errors:
FeeConfigNotSet- No fee configuration has been set
Example:
let fees = get_fee_config(env)?;Purpose: Report a project for spam, scams, broken links, or abuse.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID to reportreporter(Address): The address reportingreason_cid(String): IPFS CID containing detailed reason
Return Value: Result<(), ContractError>
Authorization:
- Any address can report a project
Possible Errors:
ProjectNotFound- Project ID does not existAlreadyReported- Caller has already reported this projectInvalidReportReason- Reason is invalid
Example:
report_project(env, project_id, reporter_address, String::from_slice(&env, "QmXxxx..."))?;Purpose: Get all reports for a project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: Vec<ProjectReport>
- A vector of all reports, containing:
project_id(u64): The projectreporter(Address): Who reportedreason_cid(String): CID of reasontimestamp(u64): Report timestamp
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let reports = get_project_reports(env, project_id);Purpose: Get the number of reports for a project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: u32
- Count of reports
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let report_count = get_project_report_count(env, project_id);Purpose: Check if a user has already reported a project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDreporter(Address): The reporter address
Return Value: bool
trueif user has reported,falseotherwise
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let has_reported = has_user_reported(env, project_id, user_address);Purpose: Clear all reports for a project (admin-only).
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDadmin(Address): The admin clearing reports
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminProjectNotFound- Project ID does not exist
Example:
clear_project_reports(env, project_id, admin_address)?;Purpose: Create a new curated collection of projects (admin-only).
Parameters:
env(Env): The contract environmentadmin(Address): The admin creating the collectionname(String): Collection namedescription(String): Collection description
Return Value: Result<u64, ContractError>
- Success:
Ok(collection_id)- The ID of the created collection - Failure:
ContractError
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminCollectionExists- Collection with same name already exists
Example:
let collection_id = create_collection(env, admin_address,
String::from_slice(&env, "DeFi Projects"),
String::from_slice(&env, "Top decentralized finance projects"))?;Purpose: Update collection name and description (admin-only).
Parameters:
env(Env): The contract environmentadmin(Address): The admin updatingcollection_id(u64): The collection IDname(String): New collection namedescription(String): New description
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminCollectionNotFound- Collection ID does not existCollectionExists- New name conflicts with existing collection
Example:
update_collection(env, admin_address, collection_id,
String::from_slice(&env, "Updated Name"),
String::from_slice(&env, "Updated description"))?;Purpose: Delete a collection and its project associations (admin-only).
Parameters:
env(Env): The contract environmentadmin(Address): The admin deletingcollection_id(u64): The collection ID
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminCollectionNotFound- Collection ID does not exist
Example:
delete_collection(env, admin_address, collection_id)?;Purpose: Add a project to a collection (admin-only).
Parameters:
env(Env): The contract environmentadmin(Address): The admin addingcollection_id(u64): The collection IDproject_id(u64): The project ID to add
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminCollectionNotFound- Collection ID does not existProjectNotFound- Project ID does not existAlreadyInCollection- Project already in collection
Example:
add_project_to_collection(env, admin_address, collection_id, project_id)?;Purpose: Remove a project from a collection (admin-only).
Parameters:
env(Env): The contract environmentadmin(Address): The admin removingcollection_id(u64): The collection IDproject_id(u64): The project ID to remove
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminCollectionNotFound- Collection ID does not existProjectNotFound- Project ID does not exist
Example:
remove_project_from_collection(env, admin_address, collection_id, project_id)?;Purpose: Retrieve a collection by ID.
Parameters:
env(Env): The contract environmentcollection_id(u64): The collection ID
Return Value: Result<Collection, ContractError>
- Contains:
id(u64): Collection IDname(String): Collection namedescription(String): Descriptioncreated_at(u64): Creation timestampupdated_at(u64): Last update timestamp
Authorization:
- None (read-only, permissionless)
Possible Errors:
CollectionNotFound- Collection ID does not exist
Example:
let collection = get_collection(env, collection_id)?;Purpose: List all collections with pagination.
Parameters:
env(Env): The contract environmentstart(u32): Starting indexlimit(u32): Maximum collections to return
Return Value: Vec<Collection>
- Vector of collections
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let collections = list_collections(env, 0, 20);Purpose: List project IDs in a collection with pagination.
Parameters:
env(Env): The contract environmentcollection_id(u64): The collection IDstart(u32): Starting indexlimit(u32): Maximum project IDs to return
Return Value: Vec<u64>
- Vector of project IDs
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let project_ids = list_collection_projects(env, collection_id, 0, 50);Purpose: Get the number of projects in a collection.
Parameters:
env(Env): The contract environmentcollection_id(u64): The collection ID
Return Value: u32
- Count of projects in collection
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let count = get_collection_project_count(env, collection_id);Purpose: Get the total number of collections.
Parameters:
env(Env): The contract environment
Return Value: u64
- Total collection count
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let total = get_collection_count(env);Purpose: Retrieve a single admin action log entry by ID.
Parameters:
env(Env): The contract environmentlog_id(u64): The log entry ID
Return Value: Option<AdminActionEntry>
Some(entry)if found,Noneotherwise- Contains:
id(u64): Log entry IDadmin(Address): Admin who performed actionaction_type(AdminActionType): Type of actiontarget_id(Option): Affected project/collection IDtarget_address(Option): Affected addresstimestamp(u64): Action timestampreason_cid(Option): CID of reason/details
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
if let Some(entry) = get_admin_action_log_entry(env, log_id) {
// Use log entry
}Purpose: List admin action log entries with pagination (most recent first).
Parameters:
env(Env): The contract environmentstart(u32): Starting indexlimit(u32): Maximum entries to return
Return Value: Vec<AdminActionEntry>
- Vector of admin action entries
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let recent_actions = list_admin_actions(env, 0, 100);Purpose: Get the total number of admin action log entries.
Parameters:
env(Env): The contract environment
Return Value: u64
- Total number of log entries
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let total_actions = get_admin_action_log_count(env);Purpose: Open a dispute claiming a project is a duplicate of another.
Parameters:
env(Env): The contract environmentproject_id(u64): The project suspected of being duplicateoriginal_project_id(u64): The project claimed to be the originalcreator(Address): The address opening the disputeevidence_cid(String): IPFS CID containing evidence of duplication
Return Value: Result<u64, ContractError>
- Success:
Ok(dispute_id)- The ID of the created dispute - Failure:
ContractError
Authorization:
- Any address can open a dispute
Possible Errors:
ProjectNotFound- One or both project IDs do not exist
Example:
let dispute_id = open_duplicate_dispute(env, project_id, original_project_id, creator_address, String::from_slice(&env, "QmXxxx..."))?;Purpose: Resolve a duplicate dispute with an action (admin-only).
Parameters:
env(Env): The contract environmentdispute_id(u64): The dispute IDadmin(Address): The admin resolvingaction(DisputeResolutionAction): The resolution action:Reject- Reject the dispute claimArchiveProject(project_id)- Archive the suspected duplicateLinkDuplicates- Link the two projects as related
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an adminProjectNotFound- Associated project not found
Example:
resolve_duplicate_dispute(env, dispute_id, admin_address, DisputeResolutionAction::ArchiveProject(project_id))?;Purpose: Retrieve a duplicate dispute by ID.
Parameters:
env(Env): The contract environmentdispute_id(u64): The dispute ID
Return Value: Option<DuplicateDispute>
Some(dispute)if found,Noneotherwise- Contains:
id(u64): Dispute IDproject_id(u64): Suspected duplicate projectoriginal_project_id(u64): Claimed original projectcreator(Address): Who opened the disputeevidence_cid(String): Evidence CIDstatus(DisputeStatus): Pending/Rejected/Resolvedcreated_at(u64): Creation timestampresolved_at(u64): Resolution timestamp
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
if let Some(dispute) = get_duplicate_dispute(env, dispute_id) {
// Use dispute data
}Purpose: Get all duplicate disputes for a project.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: Vec<DuplicateDispute>
- Vector of all disputes (both as reported project and as original)
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let disputes = get_disputes_for_project(env, project_id);Purpose: Extend Time-to-Live for a project and its related data.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: None (void)
Authorization:
- None (permissionless)
Possible Errors:
- None
Example:
extend_project_ttl(env, project_id);Purpose: Extend TTL for a specific review.
Parameters:
env(Env): The contract environmentproject_id(u64): The project IDreviewer(Address): The reviewer address
Return Value: None (void)
Authorization:
- None (permissionless)
Possible Errors:
- None
Example:
extend_review_ttl(env, project_id, reviewer_address);Purpose: Extend TTL for all admin-related data for an admin.
Parameters:
env(Env): The contract environmentadmin(Address): The admin address
Return Value: None (void)
Authorization:
- None (permissionless)
Possible Errors:
- None
Example:
extend_admin_ttl(env, admin_address);Purpose: Extend TTL for critical contract configuration (admin list, fee config, treasury).
Parameters:
env(Env): The contract environment
Return Value: None (void)
Authorization:
- None (permissionless)
Possible Errors:
- None
Example:
extend_critical_config_ttl(env);Purpose: Extend TTL for user-related data (owner projects, user reviews).
Parameters:
env(Env): The contract environmentuser(Address): The user address
Return Value: None (void)
Authorization:
- None (permissionless)
Possible Errors:
- None
Example:
extend_user_ttl(env, user_address);Purpose: Extend TTL for verification data.
Parameters:
env(Env): The contract environmentproject_id(u64): The project ID
Return Value: None (void)
Authorization:
- None (permissionless)
Possible Errors:
- None
Example:
extend_verification_ttl(env, project_id);Purpose: Set minimum project age before verification is allowed (admin-only).
Parameters:
env(Env): The contract environmentadmin(Address): The admin setting the valuemin_age_seconds(u64): Minimum age in seconds
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an admin
Example:
set_min_project_age(env, admin_address, 7 * 24 * 60 * 60)?; // 7 daysPurpose: Get the minimum project age setting.
Parameters:
env(Env): The contract environment
Return Value: u64
- Minimum age in seconds
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let min_age = get_min_project_age(env);Purpose: Set how long a verification is valid (admin-only).
Parameters:
env(Env): The contract environmentadmin(Address): The admin setting the valueduration_seconds(u64): Duration in seconds (0 = infinite)
Return Value: Result<(), ContractError>
Authorization:
- Caller must be an admin
Possible Errors:
AdminOnly- Caller is not an admin
Example:
set_verification_duration(env, admin_address, 365 * 24 * 60 * 60)?; // 1 yearPurpose: Get the verification validity duration setting.
Parameters:
env(Env): The contract environment
Return Value: u64
- Duration in seconds
Authorization:
- None (read-only, permissionless)
Possible Errors:
- None
Example:
let duration = get_verification_duration(env);The contract uses these error codes consistently:
| Error | Code | When It Occurs |
|---|---|---|
ProjectNotFound |
1 | Project ID doesn't exist |
Unauthorized |
2 | Caller lacks required authorization |
ProjectAlreadyExists |
3 | Project slug already registered |
InvalidRating |
4 | Rating outside valid range |
ReviewNotFound |
5 | Review doesn't exist |
DuplicateReview |
6 | Reviewer already reviewed project |
NotReviewOwner |
7 | Caller is not the review author |
VerificationNotFound |
8 | No verification record found |
InvalidStatus |
9 | Invalid status value |
AdminOnly |
10 | Caller is not an admin |
FeeConfigNotSet |
11 | Fee configuration not initialized |
TreasuryNotSet |
12 | Treasury address not set |
InsufficientFee |
13 | Payment below required fee |
InvalidProjectData |
14 | Project data validation failed |
ProjectNameTooLong |
15 | Project name exceeds max length |
InvalidNameFormat |
16 | Project name format invalid |
CannotRemoveLastAdmin |
17 | Cannot remove only remaining admin |
ProjectTooYoung |
18 | Project doesn't meet minimum age |
InvalidTag |
19 | Tag format invalid |
TooManyTags |
20 | More than 10 tags provided |
InvalidSocialLink |
21 | Social link format invalid |
TooManySocialLinks |
22 | More than 10 social links provided |
AlreadyReported |
23 | Address already reported this |
InvalidReportReason |
24 | Report reason format invalid |
AdminNotFound |
25 | Admin address not found |
InvalidProjectName |
26 | Project name validation failed |
InvalidProjectDesc |
27 | Project description validation failed |
InvalidCategory |
28 | Category validation failed |
ProjectDescTooLong |
29 | Description exceeds max length |
MaxProjectsExceeded |
30 | Contract project limit reached |
InvalidWebsite |
31 | Website URL validation failed |
InvalidLogoCid |
32 | Logo CID validation failed |
InvalidMetaCid |
33 | Metadata CID validation failed |
CategoryTooLong |
34 | Category exceeds max length |
WebsiteTooLong |
35 | Website URL exceeds max length |
NotRevocable |
36 | Verification cannot be revoked |
TransferNotFound |
37 | No pending transfer found |
NotTransferRecip |
38 | Caller is not transfer recipient |
ReviewsDisabled |
39 | Reviews disabled for project |
ReviewAlreadyReported |
40 | Review already reported |
ReviewAlreadyHidden |
41 | Review already hidden |
ReviewNotHidden |
42 | Review is not hidden |
AlreadyArchived |
43 | Project already archived |
ProjectNotArchived |
44 | Project not archived |
ReportsCleared |
45 | Reports have been cleared |
CollectionNotFound |
46 | Collection ID doesn't exist |
CollectionExists |
47 | Collection already exists |
AlreadyInCollection |
48 | Project already in collection |
AlreadyLinked |
49 | Projects already linked |
CannotLinkToSelf |
50 | Cannot link project to itself |
// 1. Register a project
let project_id = register_project(env, ProjectRegistrationParams {
owner: owner_address,
name: String::from_slice(&env, "MyDeFiToken"),
slug: String::from_slice(&env, "mydefitoken"),
description: String::from_slice(&env, "A decentralized finance token"),
category: String::from_slice(&env, "DeFi"),
website: Some(String::from_slice(&env, "https://mydefi.com")),
logo_cid: Some(String::from_slice(&env, "QmXxxx...")),
metadata_cid: None,
tags: Some(vec![&env, String::from_slice(&env, "token"), String::from_slice(&env, "defi")]),
social_links: None,
launch_timestamp: None,
})?;
// 2. Update project information
update_project(env, ProjectUpdateParams {
project_id,
caller: owner_address,
name: Some(String::from_slice(&env, "MyDeFi Token v2")),
..defaults..
})?;
// 3. Add dependencies
add_project_dependency(env, project_id, owner_address, ProjectDependency {
reference: DependencyRef {
project_id: Some(other_project_id),
external_cid: None,
external_url: None,
},
label: Some(String::from_slice(&env, "core-dependency")),
metadata_cid: None,
added_at: env.ledger().timestamp(),
updated_at: env.ledger().timestamp(),
})?;
// 4. Request verification
request_verification(env, project_id, owner_address, String::from_slice(&env, "QmEvidence..."))?;
// 5. Admin approves verification
approve_verification(env, project_id, admin_address)?;
// 6. Retrieve and display project
if let Some(project) = get_project(env, project_id) {
// Use project data for frontend display
}// 1. Add review as a user
add_review(env, project_id, reviewer_address, 4, Some(String::from_slice(&env, "QmReview...")))?;
// 2. Get project statistics
let stats = get_project_stats(env, project_id);
// stats.average_rating, stats.review_count
// 3. Project owner responds to review
respond_to_review(env, project_id, owner_address, reviewer_address, String::from_slice(&env, "Thank you!"))?;
// 4. Get all reviews for a project
let reviews = list_reviews(env, project_id, 0, 50);
// 5. Report an inappropriate review
report_review(env, project_id, reviewer_address, reporter_address)?;
// 6. Admin hides the reported review
hide_review(env, project_id, reviewer_address, admin_address)?;// 1. Create a curated collection
let collection_id = create_collection(env, admin_address,
String::from_slice(&env, "Top DeFi Projects"),
String::from_slice(&env, "Curated list of the best DeFi protocols"))?;
// 2. Add projects to collection
add_project_to_collection(env, admin_address, collection_id, project_id1)?;
add_project_to_collection(env, admin_address, collection_id, project_id2)?;
// 3. Get collection details
let collection = get_collection(env, collection_id)?;
// 4. List projects in collection
let project_ids = list_collection_projects(env, collection_id, 0, 100);
let projects = get_projects_by_ids(env, project_ids);
// 5. Update collection info
update_collection(env, admin_address, collection_id,
String::from_slice(&env, "Top 10 DeFi Projects"),
String::from_slice(&env, "Updated curated list"))?;// 1. User reports duplicate
let dispute_id = open_duplicate_dispute(env, suspect_project_id, original_project_id, reporter_address, String::from_slice(&env, "QmDuplicate..."))?;
// 2. Admin reviews and resolves
if let Some(dispute) = get_duplicate_dispute(env, dispute_id) {
// Review evidence, then resolve
resolve_duplicate_dispute(env, dispute_id, admin_address, DisputeResolutionAction::LinkDuplicates)?;
}- Authorization Checks: All state-modifying operations verify caller authorization
- Data Validation: All inputs are validated for format, length, and content
- Unique Constraints: Project slugs and other identifiers are enforced as unique
- Immutable Records: Verification and review records maintain tamper-proof timestamps
- Admin Action Logging: All admin actions are logged for auditability
- Fee Handling: Fee collection requires proper treasury and token configuration
- TTL Management: Data expiry is managed to prevent bloat on persistent storage
- Always check return types: Functions return
ResultorOption- handle both success and failure cases - Validate project ownership: For owner-only operations, verify ownership before calling
- Use pagination: For list operations, use appropriate start_id/limit to avoid timeouts
- Cache project data: Once retrieved, cache project data locally when possible
- Monitor admin actions: Regularly review admin action logs for compliance
- Handle duplicates gracefully: Use dispute resolution for duplicate detection
- Extend TTLs proactively: Call TTL extension functions during maintenance windows
- Test with realistic data: Test with actual project metadata and verification scenarios
This documentation matches the current implementation as of June 2024. For updates, refer to the contract source code in the repository.