Delegate
  • Overview
  • Delegating a wallet
  • Comparison with Others
  • FAQ
  • Audits
  • Integrate In Your Project
    • Smart Contract Examples
    • Token Ownership Claiming
  • Upgrade to V2
    • V2 is a Separate Contract
    • V1 → V2 migration
    • Batching
    • Subdelegations
  • Advanced Use Cases
    • Shadow Delegation
  • Delegate Market
    • Overview
    • FAQ
  • Gaming
    • Delegate for Gaming
  • Technical Documentation
    • Delegate Registry
      • Contract Addresses
      • IDelegateRegistry.sol
    • Javascript SDK
      • Installation / Importing
      • Setup
      • Check Delegations
        • checkDelegateForAll
        • checkDelegateForContract
        • checkDelegateForERC721
        • checkDelegateForERC1155
        • checkDelegateForERC20
      • Fetch Delegations
      • Delegate/Revoke
        • delegateAll
        • delegateContract
        • delegateERC721
        • delegateERC1155
        • delegateERC20
    • REST API
      • v2
      • v1
  • Resources
    • Media Kit
    • Github
    • Twitter
    • Live Stats
  • V1 Registry (Legacy)
    • Technical Documentation
Powered by GitBook
On this page
  • In Production: How Yuga Uses Shadow Delegation
  • Infinite Use Cases
  • Core Concepts
  • How to Implement It
  • Resources
  • Summary
  1. Advanced Use Cases

Shadow Delegation

Implement non-custodial NFT delegation using Delegate Registry v2 and the shadow delegation pattern, enforced via Yuga Labs’ ExclusiveDelegateResolver.

PreviousSubdelegationsNextOverview

Last updated 1 day ago

In Production: How Yuga Uses Shadow Delegation

Yuga Labs uses shadow delegation to let holders of Ape NFTs on Ethereum delegate access to a wallet on ApeChain. This allows users to verify ownership and participate in ApeChain experiences without bridging or moving their Apes.

By combining Delegate Registry v2 and ExclusiveDelegateResolver, Yuga enables onchain delegation that’s:

  • Non-custodial: the NFT stays in the original wallet

  • Cross-chain: access is granted to a different wallet on another chain

  • Exclusive: only one delegate per token is valid at a time

Infinite Use Cases

Delegate Registry v2 provides the primitives for onchain NFT access control, forming the base layer upon which shadow delegation builds customizable, scoped, and enforceable delegation logic.

Use cases include:

  • Assign agents to act on behalf of wallets across chains

  • Enable wearables, emotes, or other metadata-bound behaviors

  • Grant permissions in identity systems, social graphs, or gaming avatars

  • Build composable avatars and modular inventories

  • Delegate from cold to hot wallets with restricted rights

  • Enable temporary, non-custodial NFT lending

  • Enforce execution rights on specific chains or applications


Core Concepts

1) Delegate Registry v2

Delegate Registry v2 is an onchain registry that allows users to grant permission to other addresses to act on their behalf. It serves as a data layer, returning a boolean for whether a delegation exists.

Delegations can be scoped:

  • to specific tokens via checkDelegateForERC721

  • to particular contracts checkDelegateForContract

  • across all tokens and contracts checkDelegateForAll

The registry does not enforce rules like exclusivity, expiration, or precedence. It simply stores data. ExclusiveDelegateResolver, developed by Yuga Labs, is responsible for interpreting that data and enforcing logic.

Resolver contracts apply custom logic to interpret delegation records by answering:

"Who currently has the right to act on this token, under these rules?"

Yuga Labs’ ExclusiveDelegateResolver is used in production (e.g. Otherside, ApeChain) to enforce exclusive, scoped, onchain delegation, letting one wallet act on behalf of another without moving the NFT.

It scans delegations scoped to a rightsNamespace value and applies specificity rules (token > contract > all-assets) to return the active delegate.

Cross-chain delegation is possible because rightsNamespace encodes a chain specific ID. This allows a single token to be delegated to different wallets on different chains.

3) The Shadow Delegation Pattern

Shadow delegation is a design pattern that combines Delegate Registry v2 with a resolver like ExclusiveDelegateResolver to enable non-custodial, exclusive delegation, scoped by use case and enforced onchain.

In this pattern:

  • Only one delegation per token (or namespace) should be valid at a time

  • Previous delegates must be explicitly revoked before a new one is assigned

  • Asset ownership remains with the original holder; no escrow or transfers

This pattern works by combining scoped delegation rights with onchain resolution logic, described in detail in the next section.

How to Implement It

Shadow delegation follows a simple 3-step flow:

  1. Delegate access to a token using delegateERC721()

  2. Resolve the active delegate using ExclusiveDelegateResolver

  3. Enforce the delegation with an onchain check (e.g. require(msg.sender == delegate))

Step 1: Delegate an NFT via Delegate Registry v2

The owner calls delegateERC721() on the registry to assign a delegate for a specific NFT:

delegateERC721(
  address delegate,
  address contract_,
  uint256 tokenId,
  bytes32 rights,
  bool value
);
  • delegate: The address receiving the delegation.

  • contract_: The NFT contract address.

  • tokenId: The specific token ID to delegate.

  • rights: A bytes32 value representing delegation scope.

  • value: Set to true to enable, or false to revoke.

In the shadow delegation pattern, you must scope delegation to a unique chain or application context by computing a rights value. Use the following utility:

import { encodeAbiParameters, keccak256 } from 'viem';

function computeShadowRights(shadowChainId?: number): string {
    if (!isShadowDelegation) return '';
    if (!shadowChainId) return '0x000000000000000000000000000000000000000000000000000000ffffffffff';

    const encodedData = encodeAbiParameters([{ type: 'uint' }], [BigInt(shadowChainId)]);
    const hash = keccak256(encodedData);
    const namespace = hash.slice(0, 50);
    const padding = '000000';
    const maxRights = (BigInt(2) ** BigInt(40) - BigInt(1)).toString(16).padStart(10, '0');
    const rights = namespace + padding + maxRights;
		
    return rights;
  }

⚠️ Revoke Before Reassigning Delegate Registry v2 overwrites existing records instead of appending new ones. If you're delegating to an address that was already assigned under the same rights, first revoke the old record with value = false.

Since ExclusiveDelegateResolver does not track write order or timestamps, failing to revoke may result in the wrong delegate being resolved.

Since the rights value is chain-specific, you can delegate the same token to different wallets across chains, each using a unique shadowChainId. The resolver treats each delegation independently.

Step 2: Use the ExclusiveDelegateResolver

Once delegation is recorded, you can resolve it using ExclusiveDelegateResolver, which applies namespace-based resolution logic (token > contract > all-assets) and scopes based on the first 24 bytes of the rights field. This means a token-level delegation takes priority over a contract-level one under the same namespace.

Resolver interface:

function exclusiveOwnerByRights(
  address nftContract,
  uint256 tokenId,
  bytes24 rightsNamespace
) external view returns (address);

Example usage:

bytes24 rightsNamespace = bytes24(keccak256(abi.encode(shadowChainId)));

address delegate = IExclusiveDelegateResolver(resolverAddress).exclusiveOwnerByRights(
  nftContractAddress,
  tokenId,
  rightsNamespace
);

This reinforces the resolver concept from Core Concept #2. The registry stores raw data and the resolver interprets it according to a rule set (in this case, exclusivity via specificity).

Step 3: Enforce Delegation in Your App or Smart Contract

Whenever your application or NFT/game logic needs to check control, replace ownerOf(tokenId) or raw ownership checks with delegation resolution:

require(msg.sender == delegate, "Not authorized delegate");

This enforces non-custodial, exclusive access via the resolver logic, honoring only the delegate for the scoped rights.


Resources


Summary

Shadow delegation with Delegate Registry v2 and ExclusiveDelegateResolver enables:

  • Fully onchain delegation logic

  • Exclusive, non-custodial access

  • Use case-specific scoping via rightsNamespace

Developers can build on this pattern by customizing how delegations are scoped and managed, without needing to deploy their own resolver contract.

2) Resolver Contracts ()

💡 Use multicall() to Minimize UX & Gas Apps can batch the revocation and reassignment into a single transaction using the registry’s method to reduce friction and cost.

🛠️ See It Live Yuga Labs uses this pattern in production. See how their performs explicit revocation before reassignment (lines 933–991).

Delegate Registry v2:

ApeChain Shadow Delegations:

Yuga’s Exclusive Resolver:

ExclusiveDelegateResolver
multicall()
Shadow Beacon contract
https://github.com/delegatexyz/delegate-registry-v2
https://docs.apechain.com/start-building/NFT-Shadows
https://github.com/yuga-labs/ExclusiveDelegateResolver