Claude-skill-registry crane-access

This skill should be used when the user asks about "access control", "onlyOwner", "onlyOperator", "ownership transfer", "MultiStepOwnable", "ERC8023", "operable pattern", "function-level permissions", "reentrancy protection", "reentrancy lock", or needs to restrict function access in Crane Diamond contracts.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/crane-access" ~/.claude/skills/majiayu000-claude-skill-registry-crane-access && rm -rf "$T"
manifest: skills/data/crane-access/SKILL.md
source content

Crane Access Control Components

Crane provides three access control patterns for Diamond proxies: MultiStepOwnable (ERC-8023), Operable, and ReentrancyLock.

Component Selection

NeedComponentPurpose
Ownership with time-lockMultiStepOwnableTwo-step ownership transfer with buffer period
Delegated permissionsOperableGlobal and function-level operator authorization
Reentrancy protectionReentrancyLockTransient storage lock for cross-function reentrancy

Quick Start: Add Access Control

// Import modifiers
import {MultiStepOwnableModifiers} from "@crane/contracts/access/ERC8023/MultiStepOwnableModifiers.sol";
import {OperableModifiers} from "@crane/contracts/access/operable/OperableModifiers.sol";
import {ReentrancyLockModifiers} from "@crane/contracts/access/reentrancy/ReentrancyLockModifiers.sol";

// Use in your Target contract
contract MyTarget is MultiStepOwnableModifiers, OperableModifiers, ReentrancyLockModifiers {
    function adminOnly() external onlyOwner {
        // Only owner can call
    }

    function operatorOnly() external onlyOperator {
        // Global operators or function-specific operators
    }

    function ownerOrOperator() external onlyOwnerOrOperator {
        // Either owner or operator can call
    }

    function noReentrant() external nonReentrant {
        // Protected from reentrancy
    }
}

MultiStepOwnable (ERC-8023)

Time-locked two-step ownership transfer with buffer period.

Storage

struct Storage {
    address owner;
    address pendingOwner;
    bool pendingOwnerConfirmed;
    uint256 ownershipBufferPeriod;  // e.g., 1 days
    uint256 bufferPeriodEnd;
}

Ownership Transfer Flow

  1. Initiate: Owner calls
    initiateOwnershipTransfer(newOwner)
  2. Wait: Buffer period must elapse
  3. Confirm: Owner calls
    confirmOwnershipTransfer(newOwner)
  4. Accept: New owner calls
    acceptOwnershipTransfer()
// Step 1: Current owner initiates
MultiStepOwnableRepo._initiateOwnershipTransfer(newOwner);

// Step 2: Wait for buffer period (e.g., 1 day)

// Step 3: Current owner confirms
MultiStepOwnableRepo._confirmOwnershipTransfer(newOwner);

// Step 4: New owner accepts
MultiStepOwnableRepo._acceptOwnershipTransfer();

// Owner can cancel anytime before acceptance
MultiStepOwnableRepo._cancelPendingOwnershipTransfer();

Guard Functions

// Revert if msg.sender is not owner
MultiStepOwnableRepo._onlyOwner();

// Revert if msg.sender is not pending owner
MultiStepOwnableRepo._onlyPendingOwner();

Modifiers

modifier onlyOwner() {
    MultiStepOwnableRepo._onlyOwner();
    _;
}

Initialization

// In DFPkg.initAccount()
MultiStepOwnableRepo._initialize(
    initialOwner,    // First owner
    1 days           // Buffer period for transfers
);

Operable Pattern

Delegated authorization for global and function-level permissions.

Storage

struct Storage {
    mapping(address => bool) isOperator;  // Global operators
    mapping(bytes4 func => mapping(address => bool)) isOperatorFor;  // Function-level
}

Authorization Levels

  1. Global Operator: Can call any function protected by
    onlyOperator
  2. Function Operator: Can only call specific functions

Setting Permissions (Owner Only)

// Grant/revoke global operator status
OperableRepo._setOperatorStatus(operatorAddress, true);   // Grant
OperableRepo._setOperatorStatus(operatorAddress, false);  // Revoke

// Grant/revoke function-level operator
OperableRepo._setFunctionOperatorStatus(
    IMyContract.someFunction.selector,  // Function selector
    operatorAddress,                     // Operator
    true                                 // Approval
);

Checking Permissions

// Check global operator
bool isGlobal = OperableRepo._isOperator(account);

// Check function operator
bool isForFunc = OperableRepo._isFunctionOperator(
    IMyContract.someFunction.selector,
    account
);

Guard Functions

// Revert if not global OR function operator for msg.sig
OperableRepo._onlyOperator();

// Revert if not owner AND not operator
OperableRepo._onlyOwnerOrOperator();

Modifiers

// Only global or function-level operators
modifier onlyOperator() {
    OperableRepo._onlyOperator();
    _;
}

// Owner OR any operator
modifier onlyOwnerOrOperator() {
    OperableRepo._onlyOwnerOrOperator();
    _;
}

ReentrancyLock

Transient storage-based reentrancy protection (EIP-1153).

Usage

modifier nonReentrant() {
    ReentrancyLockRepo._onlyUnlocked();
    ReentrancyLockRepo._lock();
    _;
    ReentrancyLockRepo._unlock();
}

Functions

// Lock the reentrancy guard
ReentrancyLockRepo._lock();

// Unlock the reentrancy guard
ReentrancyLockRepo._unlock();

// Check if locked
bool locked = ReentrancyLockRepo._isLocked();

// Revert if locked (guard function)
ReentrancyLockRepo._onlyUnlocked();

Benefits

  • Uses transient storage (cleared after transaction)
  • Gas efficient compared to storage-based guards
  • Protects against cross-function reentrancy

Component Files

ComponentFiles
MultiStepOwnable
MultiStepOwnableRepo.sol
,
MultiStepOwnableModifiers.sol
,
MultiStepOwnableTarget.sol
,
MultiStepOwnableFacet.sol
Operable
OperableRepo.sol
,
OperableModifiers.sol
,
OperableTarget.sol
,
OperableFacet.sol
ReentrancyLock
ReentrancyLockRepo.sol
,
ReentrancyLockModifiers.sol
,
ReentrancyLockTarget.sol
,
ReentrancyLockFacet.sol

AccessFacetFactoryService

Deploy access control facets:

import {AccessFacetFactoryService} from "@crane/contracts/access/AccessFacetFactoryService.sol";

// Deploy MultiStepOwnable facet
IFacet ownerFacet = AccessFacetFactoryService.deployMultiStepOwnableFacet(create3Factory);

// Deploy Operable facet
IFacet operableFacet = AccessFacetFactoryService.deployOperableFacet(create3Factory);

// Deploy ReentrancyLock facet
IFacet reentrancyFacet = AccessFacetFactoryService.deployReentrancyLockFacet(create3Factory);

Additional Resources

Reference Files

For detailed patterns and examples:

  • references/access-patterns.md
    - Complete access control integration patterns