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
1 change: 1 addition & 0 deletions contracts/registry/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ pub enum RegistryError {
BatchSizeExceeded = 5,
InvalidMetadata = 6,
NotRegistered = 7,
NotRevoked = 8,
}
13 changes: 9 additions & 4 deletions contracts/registry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,8 @@ impl RegistryContract {
///
/// Reads the profile entry from persistent storage, extends its TTL using
/// the same threshold and target duration as the write path, and returns
/// the stored value.
/// a decoded view of the profile with `role`, `verified`, and `revoked`
/// fields instead of the raw `packed_flags` bit representation.
///
/// # Arguments
/// * `env` - The Soroban environment.
Expand All @@ -314,13 +315,13 @@ impl RegistryContract {
/// * `RegistryError::NotFound` if no profile is stored for `address`.
///
/// # Returns
/// * `Profile` - The stored profile for the address.
/// * `ProfileView` - The decoded profile view for the address.
///
/// # Example
/// ```ignore
/// let profile = client.get_profile(&issuer);
/// ```
pub fn get_profile(env: Env, address: Address) -> Profile {
pub fn get_profile(env: Env, address: Address) -> ProfileView {
let key = DataKey::Profile(address.clone());
let profile = env
.storage()
Expand All @@ -330,7 +331,7 @@ impl RegistryContract {
env.storage()
.persistent()
.extend_ttl(&key, TTL_THRESHOLD, TTL_EXTEND_TO);
profile
ProfileView::from_profile(&profile)
}

/// Checks whether a registered profile is verified.
Expand Down Expand Up @@ -456,6 +457,7 @@ impl RegistryContract {
/// * `RegistryError::NotFound` if the contract admin is not set (contract
/// was never initialized).
/// * `RegistryError::NotFound` if no profile is stored for `address`.
/// * `RegistryError::NotRevoked` if the profile has not been revoked.
///
/// # Returns
/// * `bool` - `true` when the profile is successfully reinstated.
Expand All @@ -477,6 +479,9 @@ impl RegistryContract {
.persistent()
.get(&key)
.unwrap_or_else(|| panic_with_error!(&env, RegistryError::NotFound));
if !profile.revoked() {
panic_with_error!(&env, RegistryError::NotRevoked);
}
profile.set_verified(true);
profile.set_revoked(false);
env.storage().persistent().set(&key, &profile);
Expand Down
19 changes: 17 additions & 2 deletions contracts/registry/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
extern crate std;

use crate::{
DataKey, Profile, RegistryContract, RegistryContractClient, Role, VerificationStatus,
TTL_EXTEND_TO, TTL_THRESHOLD,
DataKey, Profile, ProfileView, RegistryContract, RegistryContractClient, Role,
VerificationStatus, TTL_EXTEND_TO, TTL_THRESHOLD,
};
use proptest::prelude::*;
use proptest::test_runner::{Config as ProptestConfig, TestRunner};
Expand Down Expand Up @@ -315,6 +315,21 @@ fn test_reinstate_wrong_auth_panics() {
client.reinstate(&issuer);
}

#[test]
#[should_panic(expected = "Error(Contract, #8)")]
fn test_reinstate_not_revoked_panics() {
let (env, client) = setup();
let admin = Address::generate(&env);
client.initialize(&admin);
let issuer = Address::generate(&env);
client.register_issuer(&issuer, &map![&env]);
assert!(!client.is_verified(&issuer));

// Attempting to reinstate a profile that was never revoked should panic
// with NotRevoked (#8).
client.reinstate(&issuer);
}

#[test]
#[should_panic(expected = "Error(Contract, #3)")]
fn test_reinstate_unregistered_panics() {
Expand Down
26 changes: 26 additions & 0 deletions contracts/registry/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,32 @@ impl Profile {
}
}

#[contracttype]
#[derive(Clone, Debug, PartialEq)]
pub struct ProfileView {
pub role: Role,
pub verified: bool,
pub revoked: bool,
pub registered_at: u64,
pub metadata: Map<String, String>,
}

impl ProfileView {
pub fn from_profile(profile: &Profile) -> Self {
ProfileView {
role: profile.role(),
verified: profile.verified(),
revoked: profile.revoked(),
registered_at: profile.registered_at,
metadata: profile.metadata.clone(),
}
}

pub fn role(&self) -> Role {
self.role.clone()
}
}

#[contracttype]
pub enum DataKey {
Admin,
Expand Down
8 changes: 8 additions & 0 deletions create_issues.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Thin wrapper around scripts/maintainer/create-contract-issues.ps1
# Delegates to the canonical maintainer script which handles rate-limit
# retries and duplicate-issue guards.

$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$MaintainerScript = Join-Path $ScriptDir "scripts\maintainer\create-contract-issues.ps1"

& $MaintainerScript @args
15 changes: 15 additions & 0 deletions create_issues.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env python3
"""Thin wrapper around scripts/maintainer/create_issues.py.

Delegates to the canonical maintainer script which handles rate-limit
retries and duplicate-issue guards.
"""

import os
import subprocess
import sys

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
MAINTAINER_SCRIPT = os.path.join(SCRIPT_DIR, "scripts", "maintainer", "create_issues.py")

sys.exit(subprocess.call([sys.executable, MAINTAINER_SCRIPT] + sys.argv[1:]))
9 changes: 9 additions & 0 deletions create_issues.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash
set -euo pipefail

# Thin wrapper around scripts/maintainer/create-contract-issues.sh
# Delegates to the canonical maintainer script which handles rate-limit
# retries and duplicate-issue guards.

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
exec "$SCRIPT_DIR/scripts/maintainer/create-contract-issues.sh" "$@"
11 changes: 9 additions & 2 deletions scripts/verify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,20 @@ if [ ! -f "$STELLAR" ]; then
STELLAR="stellar"
fi

# Load environment configuration
# Load environment configuration safely without sourcing .env as shell code.
# Only simple KEY=VALUE lines are parsed; comments and blank lines are skipped.
if [ ! -f .env ]; then
echo "Error: .env file not found." >&2
echo "Run ./scripts/deploy.sh first to create the .env file with contract IDs." >&2
exit 1
fi
source .env
while IFS='=' read -r key value; do
# Skip blank lines and comments
[[ -z "$key" || "$key" =~ ^[[:space:]]*# ]] && continue
# Skip lines containing no '=' or invalid identifiers
[[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] || continue
export "$key=$value"
done < .env

# Tracking execution status
FAILED=0
Expand Down
Loading