Skip to Content
DelegationHub

Bot sessions (DelegationHub)

DelegationHub is an onchain session registry for opt-in bot delegation.

A session is:

  • user (the identity being represented)
  • delegate (the bot / executor)
  • perms (permission bitmask)
  • expiry (unix seconds)

Sessions are verified by protocol contracts onchain via isAuthorized(...).

Contract + wiring

Source:

  • src/DelegationHub.sol
  • src/interfaces/IDelegationHub.sol
  • src/lib/DelegationPermissions.sol (canonical bit positions)

Wiring (v1.0.0+):

  • MineCore stores delegationHub and uses it for delegated takeovers + reign routing.
  • Furnace stores delegationHub and uses it for delegated entry (...For functions).
  • ClaimAllHelper verifies sessions via MineCore.delegationHub().
  • VeClaimNFT verifies sessions via Furnace.delegationHub() for safe lock maintenance wrappers.
  • ShareholderRoyalties verifies sessions via Furnace.delegationHub() for safe config wrappers.
  • LpStakingVault7D verifies sessions via Furnace.delegationHub() for safe config wrappers.
  • MarketRouter does not use DelegationHub in v1.0.0 (no Market permission bits; market actions are intentionally not delegated; use standard approvals).

Freeze rule: set the hub address before config freeze.

Read surface

MethodNotes
getSession(user, delegate) -> (perms, expiry)Raw stored session data
isAuthorized(user, delegate, requiredPerms) -> boolChecks expiry and bitmask
nonces(user) -> uint256EIP-712 nonce for gasless set-by-sig

Write surface

MethodCallerNotes
setSession(delegate, perms, expiry)userStores session; overwrites prior
revokeSession(delegate)userClears perms + expiry
setSessionBySig(user, delegate, perms, expiry, nonce, deadline, sig)anyoneGasless; validates signature + nonce + deadline

Signature model:

  • EIP-712 domain:
    • name: ClaimRush DelegationHub
    • version: 1
  • Uses OpenZeppelin SignatureChecker (supports EOAs + EIP-1271 smart wallets).

Consumers in protocol contracts

MineCore: delegated takeover

MineCore.takeoverFor(newKing):

  • msg.sender pays ETH and becomes the executor
  • newKing becomes the King identity
  • requires DelegationHub.isAuthorized(newKing, msg.sender, P_TAKEOVER_FOR)

Default routing for the new reign:

  • ethRecipient = msg.sender (bot)
  • claimRecipient = newKing (user)

Optional:

  • if the session also grants P_ROUTE_REIGN_CLAIM_TO_CALLER, MineCore sets:
    • claimRecipient = msg.sender

Mid-reign routing update:

  • MineCore.setCurrentReignRecipients(ethRecipient, claimRecipient)
    • callable by the active king identity
    • or an authorized delegate with:
      • for ethRecipient: P_SET_REIGN_ETH_RECIPIENT or P_SET_REIGN_ETH_RECIPIENT_TO_CALLER_ONLY
      • for claimRecipient: P_SET_REIGN_CLAIM_RECIPIENT or P_SET_REIGN_CLAIM_RECIPIENT_TO_USER_ONLY

ClaimAllHelper: delegated harvest + withdraw

ClaimAllHelper provides delegation-gated wrappers:

  • claimShareholderForUser(user, ...) requires P_CLAIM_SHAREHOLDER_FOR
  • withdrawKingBalanceForUser(user) requires P_WITHDRAW_KING_BUCKET_FOR
  • claimAllFor(user, ...) requires P_CLAIM_ALL_FOR

Furnace: delegated entry (bot pays, user receives lock)

Delegated entry points:

  • enterWithEthFor(user, ...) requires P_FURNACE_ENTER_ETH_FOR
  • enterWithClaimFromCallerFor(user, ...) requires P_FURNACE_ENTER_CLAIM_FOR
  • enterWithTokenFromCallerFor(user, ...) requires P_FURNACE_ENTER_TOKEN_FOR

VeClaimNFT: delegated lock maintenance (safe, non-custodial)

Delegated lock maintenance entry points:

  • extendLockForUser(user, tokenId, additionalDuration) requires P_VE_EXTEND_LOCK_FOR
  • mergeLocksForUser(user, fromTokenId, intoTokenId) requires P_VE_MERGE_LOCKS_FOR
  • unlockExpiredForUser(user, tokenId) requires P_VE_UNLOCK_EXPIRED_FOR

Non-custodial rules enforced:

  • no ERC20 spend from the user
  • unlock returns CLAIM to user (never to the delegate)
  • merge/extend require the lock(s) are owned by user

Settings/config: delegated config setters (safe, non-custodial)

Delegated config entry points:

  • MineCore.setKingAutoLockConfigForUser(user, ...) requires P_SET_KING_AUTO_LOCK_CONFIG_FOR
  • ShareholderRoyalties.setAutoCompoundConfigForUser(user, ...) requires P_SET_SHAREHOLDER_AUTOCOMPOUND_CONFIG_FOR
  • LpStakingVault7D.setAutoCompoundConfigForUser(user, ...) requires P_SET_LP_AUTOCOMPOUND_CONFIG_FOR

Non-custodial rules enforced:

  • config-only (no value transfer)
  • tokenId parameters must be veNFTs owned by user

Permissions map

Canonical bits are defined in src/lib/DelegationPermissions.sol.

GroupBitPermissionEnables
Crown0P_TAKEOVER_FORMineCore.takeoverFor(newKing)
Crown1P_ROUTE_REIGN_CLAIM_TO_CALLERRoute King-stream mined CLAIM to bot during delegated takeover
Crown2P_SET_REIGN_ETH_RECIPIENTAllow delegate to set ethRecipient mid-reign to any address
Crown3P_SET_REIGN_ETH_RECIPIENT_TO_CALLER_ONLYAllow delegate to set ethRecipient = msg.sender mid-reign
Crown4P_SET_REIGN_CLAIM_RECIPIENTAllow delegate to set claimRecipient mid-reign to any address
Crown5P_SET_REIGN_CLAIM_RECIPIENT_TO_USER_ONLYAllow delegate to set claimRecipient = king mid-reign
Harvest6P_WITHDRAW_KING_BUCKET_FORClaimAllHelper.withdrawKingBalanceForUser(user)
Harvest7P_CLAIM_SHAREHOLDER_FORClaimAllHelper.claimShareholderForUser(user, ...)
Harvest8P_CLAIM_ALL_FORClaimAllHelper.claimAllFor(user, ...)
Furnace9P_FURNACE_ENTER_ETH_FORFurnace.enterWithEthFor(user, ...)
Furnace10P_FURNACE_ENTER_CLAIM_FORFurnace.enterWithClaimFromCallerFor(user, ...)
Furnace11P_FURNACE_ENTER_TOKEN_FORFurnace.enterWithTokenFromCallerFor(user, ...)
VeLock12P_VE_EXTEND_LOCK_FORVeClaimNFT.extendLockForUser(user, tokenId, ...)
VeLock13P_VE_MERGE_LOCKS_FORVeClaimNFT.mergeLocksForUser(user, fromTokenId, intoTokenId)
VeLock14P_VE_UNLOCK_EXPIRED_FORVeClaimNFT.unlockExpiredForUser(user, tokenId)
Config15P_SET_KING_AUTO_LOCK_CONFIG_FORMineCore.setKingAutoLockConfigForUser(user, ...)
Config16P_SET_SHAREHOLDER_AUTOCOMPOUND_CONFIG_FORShareholderRoyalties.setAutoCompoundConfigForUser(user, ...)
Config17P_SET_LP_AUTOCOMPOUND_CONFIG_FORLpStakingVault7D.setAutoCompoundConfigForUser(user, ...)

Integration guidance

  • Keep sessions short-lived (hours/days), refresh as needed.
  • Use minimal perms for the bot’s job.
  • Treat recipient routing perms as high risk:
    • P_SET_REIGN_ETH_RECIPIENT can redirect the dethroned-King ETH payout for the active reign.
    • P_SET_REIGN_CLAIM_RECIPIENT can redirect mined CLAIM mid-reign.
    • Prefer constrained variants (...TO_CALLER_ONLY, ...TO_USER_ONLY) where possible.
  • Treat delegation as security-sensitive UX (like approvals):
    • show the delegate address
    • show expiry
    • show selected permissions
    • provide a one-click revoke

Agent SDK

This repo’s TypeScript SDK (agents/sdk/) includes helpers for DelegationHub:

  • canonical permission bits (agents/sdk/src/delegation/permissions.ts)
  • EIP-712 typed data builder (buildSetSessionTypedData)
  • sign + submit setSessionBySig (signSetSession, submitSetSessionBySig)

Examples:

# Local demo (user signs with derived actor0; delegate submits with derived actor1) RPC_URL=http://127.0.0.1:8545 npm -C agents/sdk run example:delegation # Production-style: user wallet signs typed data; delegate submits signature RPC_URL=http://127.0.0.1:8545 \ npm -C agents/sdk run example:session -- --cmd build \ --user 0xUserAddress \ --delegate 0xDelegateAddress \ --perms TAKEOVER_FOR,CLAIM_ALL_FOR \ --out /tmp/session.json \ --pretty # user signs /tmp/session.json via eth_signTypedData_v4 RPC_URL=http://127.0.0.1:8545 PRIVATE_KEYS=0x<delegatePrivateKey> \ npm -C agents/sdk run example:session -- --cmd submit --typed-data /tmp/session.json --sig 0x... # Revoke (gasless) RPC_URL=http://127.0.0.1:8545 \ npm -C agents/sdk run example:session -- --cmd build --revoke --user 0xUserAddress --delegate 0xDelegateAddress --out /tmp/revoke.json --pretty RPC_URL=http://127.0.0.1:8545 PRIVATE_KEYS=0x<delegatePrivateKey> \ npm -C agents/sdk run example:session -- --cmd submit --typed-data /tmp/revoke.json --sig 0x... # Run a delegated agent loop RPC_URL=http://127.0.0.1:8545 npm -C agents/sdk run example:agent -- --actor-index 1 --acting-for 0xUserAddress --once # Delegated safe maintenance (ve upkeep + optional config sync) RPC_URL=http://127.0.0.1:8545 \ ENABLE_SAFE_MAINTENANCE=1 \ VE_EXTEND_IF_REMAINING_DAYS=7 \ VE_EXTEND_BY_DAYS=30 \ npm -C agents/sdk run example:agent -- --actor-index 1 --acting-for 0xUserAddress --once Optional config sync env vars: - `KING_AUTO_LOCK_*` (MineCore king auto-lock config) - `ROYALTIES_AUTOCOMPOUND_*` (ShareholderRoyalties auto-compound config) - `LP_AUTOCOMPOUND_*` (LP vault auto-compound config)

Observability and indexing

DelegationHub already emits SessionSet(...) events when a user grants, updates, or revokes a session.

In addition, the protocol emits Events.DelegationSessionUsed(...) for delegated entrypoints that have a canonical actionType id (takeover, claim, furnace enter, lock maintenance, settings/config):

  • actionType is one of: TAKEOVER, CLAIM, FURNACE_ENTER, VE_LOCK, CONFIG (see src/lib/DelegationActionTypes.sol)
  • permsUsed is the permission bitmask actually consumed for the action
  • refId is a small reference for auditors/indexers:
    • takeover: reignId
    • furnace enter: tokenId
    • ve lock maintenance: tokenId (merge uses intoTokenId / destination lock)
    • config setters: tokenId when applicable, otherwise 0
    • claim helpers: 0

The subgraph in this repo indexes these into:

  • DelegationSession (rolling session state, including last used + last action)
  • DelegationSessionUse (immutable activity feed with tx hashes)
  • DelegationSessionSetEvent (immutable session change feed with tx hashes)

These entities power:

  • Security → Bot access (sessions list + activity feed + one-click revoke)
  • Radar Inbox alerts (bot session used, session granted/updated/revoked, recipients changed mid-reign)