-
Notifications
You must be signed in to change notification settings - Fork 12
Description
Summary
OpenZeppelin Stellar Contracts v0.6.0 introduces a new get_existing_roles function that returns all roles that currently have at least one member. This provides a direct on-chain method to enumerate roles without relying on indexer-based event reconstruction.
Current Implementation (Workaround)
The current StellarAccessControlService.getCurrentRoles() implementation uses a two-step workaround:
- Role Discovery via Indexer: If
knownRoleIdsaren't provided during contract registration, the adapter queries the indexer for historicalROLE_GRANTEDandROLE_REVOKEDevents to discover roles - Member Enumeration: Once role IDs are known, it uses
get_role_member_countandget_role_memberto enumerate members
This approach has limitations:
- Requires indexer availability for role discovery
- Depends on historical event data being indexed
- Adds latency due to indexer queries
- May miss roles if indexer data is incomplete
New API from v0.6.0
From storage.rs:
/// Returns a vector containing all existing roles.
/// Defaults to empty vector if no roles exist.
///
/// # Arguments
///
/// * `e` - Access to Soroban environment.
///
/// # Notes
///
/// This function returns all roles that currently have at least one member.
pub fn get_existing_roles(e: &Env) -> Vec<Symbol> {
let key = AccessControlStorageKey::ExistingRoles;
if let Some(existing_roles) = e.storage().persistent().get(&key) {
e.storage().persistent().extend_ttl(&key, ROLE_TTL_THRESHOLD, ROLE_EXTEND_AMOUNT);
existing_roles
} else {
Vec::new(e)
}
}Return type: Vec<Symbol> - A vector of role symbols (identifiers)
Proposed Implementation
1. Add on-chain reader function
Add getExistingRoles() function in packages/adapter-stellar/src/access-control/onchain-reader.ts:
export async function getExistingRoles(
contractAddress: string,
networkConfig: StellarNetworkConfig
): Promise<string[]>2. Update feature detection
Add get_existing_roles to feature detection in packages/adapter-stellar/src/access-control/feature-detection.ts:
const hasExistingRolesFunction = !!functions.find(
(f) => f.name === 'get_existing_roles'
);3. Update service to prefer new method
Modify StellarAccessControlService.getCurrentRoles() to:
- Check if contract supports
get_existing_roles(via feature detection) - If supported, call
get_existing_rolesto get role IDs directly - If not supported, fall back to current indexer-based discovery
- Continue using
get_role_member_countandget_role_memberfor member enumeration
4. Fallback Strategy
The current indexer-based role discovery should remain as a fallback for:
- Contracts deployed before v0.6.0 that don't have
get_existing_roles - Edge cases where on-chain call fails
Acceptance Criteria
- Add
getExistingRoleson-chain reader function - Update feature detection to check for
get_existing_roles - Modify
getCurrentRolesto preferget_existing_roleswhen available - Keep existing indexer-based discovery as fallback
- Add unit tests for the new function
- Update documentation/comments