Search Apps Documentation Source Content File Folder Download Copy Actions Download

/r/gnoswap/access

Directory · 5 Files
README.md Open

Access

Centralized role-based access control system for GnoSwap protocol contracts.

Overview

The Access package provides a unified permission management system for all GnoSwap protocol contracts. It manages role-to-address mappings and provides convenient assertion functions for authorization checks throughout the protocol.

This package acts as a centralized registry where each protocol component (pool, router, staker, etc.) registers its address under a specific role. Other contracts can then query this registry to verify permissions before executing privileged operations. Admin role ownership is managed by the RBAC realm and is updated on ownership transfer; this package only stores the latest role address.

Architecture

The access control system consists of:

  1. Role Registry: Maps role names (strings) to contract addresses
  2. Role Management: Functions to set/remove roles (RBAC-only)
  3. Authorization Checks: Functions to verify if an address has a specific role
  4. Assert Helpers: Convenience functions that panic on authorization failure

System Roles

The following roles are used across the GnoSwap protocol:

  • admin: Protocol administrator with elevated privileges
  • devops: DevOps operations for system maintenance
  • governance: Governance contract for protocol decisions
  • router: Swap router for token exchanges
  • pool: Pool management contract
  • position: Position NFT management
  • staker: Liquidity staking contract
  • emission: GNS token emission controller
  • protocol_fee: Protocol fee collection and distribution
  • launchpad: Token launchpad for new projects
  • gov_staker: Governance staking contract
  • xgns: xGNS token contract for governance

Key Functions

Role Management (RBAC Only)

SetRoleAddress

Sets or updates a role's address. Creates new role if it doesn't exist. The admin role is updated by RBAC ownership transfers and should not be managed directly by other contracts.

1// Only callable by RBAC contract
2access.SetRoleAddress(cur, "router", routerAddress)

RemoveRole

Removes a role from the system.

1// Only callable by RBAC contract
2access.RemoveRole(cur, "old_role")

Role Query Functions

GetAddress

Returns the address for a role and whether it exists.

1addr, exists := access.GetAddress("router")
2if !exists {
3    // Handle missing role
4}

MustGetAddress

Returns the address for a role or panics if it doesn't exist.

1// Panics if role doesn't exist
2routerAddr := access.MustGetAddress("router")

GetRoleAddresses

Returns a copy of all role-to-address mappings.

1allRoles := access.GetRoleAddresses()
2for roleName, addr := range allRoles {
3    println(roleName, "->", addr)
4}

Authorization Functions

IsAuthorized

Checks if an address has a specific role (non-panicking).

1if access.IsAuthorized("admin", caller) {
2    // Caller is admin
3}

Assert Functions (Panic on Failure)

These functions panic with a descriptive error if authorization fails:

AssertIsAdmin

Requires admin role.

1access.AssertIsAdmin(caller)

AssertIsGovernance

Requires governance role.

1access.AssertIsGovernance(caller)

AssertIsAdminOrGovernance

Requires either admin or governance role.

1access.AssertIsAdminOrGovernance(caller)

Role-Specific Assertions

1access.AssertIsRouter(caller)
2access.AssertIsPool(caller)
3access.AssertIsPosition(caller)
4access.AssertIsStaker(caller)
5access.AssertIsEmission(caller)
6access.AssertIsProtocolFee(caller)
7access.AssertIsLaunchpad(caller)
8access.AssertIsGovStaker(caller)
9access.AssertIsGovXGNS(caller)

AssertIsAuthorized

Generic authorization check for any role.

1access.AssertIsAuthorized("custom_role", caller)

AssertHasAnyRole

Requires the caller to have at least one of the specified roles.

1access.AssertHasAnyRole(caller, "admin", "governance", "devops")

Validation Functions

AssertIsValidAddress

Panics if the address is invalid.

1access.AssertIsValidAddress(addr)

AssertIsUser

Panics if the caller is not a user realm (i.e., a contract is calling).

1access.AssertIsUser(r)

Usage Examples

Example 1: Protecting Admin Functions

 1package pool
 2
 3import "gno.land/r/gnoswap/access"
 4
 5func SetPoolFeeRate(rate uint64) {
 6    caller := std.PrevRealm().Addr()
 7    access.AssertIsAdminOrGovernance(caller)
 8
 9    // Admin/governance authorized, proceed
10    setFeeRate(rate)
11}

Example 2: Role-Based Function Access

 1package staker
 2
 3import "gno.land/r/gnoswap/access"
 4
 5func DistributeRewards(amount uint64) {
 6    caller := std.PrevRealm().Addr()
 7    access.AssertIsEmission(caller)
 8
 9    // Only emission contract can distribute
10    distributeToStakers(amount)
11}

Example 3: Multi-Role Authorization

 1package common
 2
 3import "gno.land/r/gnoswap/access"
 4
 5func EmergencyPause() {
 6    caller := std.PrevRealm().Addr()
 7    access.AssertHasAnyRole(caller, "admin", "devops", "governance")
 8
 9    // Any of the authorized roles can pause
10    pauseProtocol()
11}

Example 4: Non-Panicking Authorization Check

 1package router
 2
 3import "gno.land/r/gnoswap/access"
 4
 5func GetSwapFee(caller address) uint64 {
 6    // Lower fee for admin
 7    if access.IsAuthorized("admin", caller) {
 8        return 0 // Admin gets free swaps
 9    }
10
11    return standardFee
12}

Security Model

Centralized Management

  • All role assignments are managed through this single contract
  • Provides a unified view of permissions across the entire protocol
  • Prevents inconsistencies in authorization logic

RBAC-Only Updates

  • Only the RBAC contract can modify role assignments
  • Uses package address verification to enforce this restriction
  • Prevents unauthorized role manipulation

Explicit Authorization

  • All authorization checks are explicit and auditable
  • Panic-based assertions make authorization failures obvious
  • No implicit or default permissions

Integration with RBAC

The Access contract works in conjunction with the RBAC (Role-Based Access Control) package:

  1. RBAC: Manages role definitions and ownership transfer
  2. Access: Provides centralized role-to-address registry and authorization checks

Role updates flow: RBAC.UpdateRoleAddress()Access.SetRoleAddress()

Best Practices

  1. Use Assertions for Critical Functions: Always use assert functions for operations that should only proceed with proper authorization
  2. Check Existence Before Use: Use GetAddress when you need to handle missing roles gracefully
  3. Document Role Requirements: Clearly document which roles are required for each function
  4. Avoid Hardcoding Addresses: Always use role-based checks instead of hardcoding addresses
  5. Test Authorization: Thoroughly test all authorization paths in your contracts

Error Handling

Authorization failures result in panics with descriptive error messages:

  • "unauthorized: caller X is not Y" - Caller doesn't have required role
  • "role X does not exist" - Role hasn't been registered
  • "invalid address: X" - Address validation failed
  • "caller is not user" - Contract called user-only function

Limitations

  • Role names are case-sensitive strings
  • Each role can only map to one address at a time
  • Role changes take effect immediately (no timelock)