Skip to content

Neverland-Money/neverland-admin-roles-indexer

Repository files navigation

Neverland Admin Roles Indexer

Dedicated Envio HyperIndex repo for Neverland lending admin authority and delayed upgradeability surfaces.

Current live control model on Monad mainnet:

  • GovernanceTimelock (0x3e4749D9Df7EC5ecd9184c301592bAc058a6F82f) is the live delayed-governance holder for lending root authority and all delayed upgradeability surfaces.
  • RiskTimelock (0x7fa9e0E4dA21d5e92c70815B1B25F39726fD963b) is the live delayed-risk holder for RISK_ADMIN.
  • Sentinel Safe (0x06Fe1d4F4B7cA7D3d1fB3164968F0F7383D02e0E) remains the direct EMERGENCY_ADMIN holder.
  • Governance Safe (0x57976e192C45461F5958045a0bC57102e90440eD) operates the timelocks as proposer / executor / canceller, but no longer directly holds the lending ACL roles or delayed-upgrade owner surfaces.

This indexer exists to answer three questions cleanly and event-sourced:

  • what each admin surface is
  • who currently holds it
  • how it changed over time

It does not index user activity, reserves, incentives, or analytics. It only tracks the lending admin, ownership, and delayed upgradeability surfaces relevant to governance and timelock design. It does not index timelock operator roles, runtime tokenomics admin surfaces, or Safe signer sets.

Indexed Surfaces

ACL roles from ACLManager:

  • DEFAULT_ADMIN
  • POOL_ADMIN
  • RISK_ADMIN
  • EMERGENCY_ADMIN
  • ASSET_LISTING_ADMIN
  • FLASH_BORROWER
  • BRIDGE

Owner and root-governance surfaces:

  • PoolAddressesProvider.owner()
  • PoolAddressesProvider.getACLAdmin()
  • PoolAddressesProviderRegistry.owner()
  • ReservesSetupHelper.owner()
  • WrappedTokenGatewayV3.owner()

Delayed upgradeability surfaces:

  • Core ProxyAdmin.owner()
  • Leaderboard ProxyAdmin.owner()
  • StaticAToken ProxyAdmin.owner()
  • UserVaultBeacon.owner()

Why This Exists

The existing repo tooling can classify powers and inspect known holders, but the Lending ACLManager does not expose enumerable role members onchain. This repo removes that ambiguity by building the holder set from the actual RoleGranted and RoleRevoked event history, plus ownership transfer events.

That makes it the canonical off-chain source for:

  • current holder sets per admin surface
  • exact function-level power documentation per surface
  • append-only history of grants, revokes, role-admin changes, ownership transfers, and ACL-admin rotation
  • current ACL manager address if PoolAddressesProvider rotates it

After the April 10, 2026 timelock migration, this means the indexer is the canonical post-cutover report for verifying that:

  • DEFAULT_ADMIN and POOL_ADMIN are held only by GovernanceTimelock
  • RISK_ADMIN is held only by RiskTimelock
  • the lending owner surfaces are held only by GovernanceTimelock
  • all 4 delayed upgradeability surfaces are held only by GovernanceTimelock

Data Model

Current-state entities:

  • AdminSurface
  • KnownAccount
  • SyncState

Append-only entities:

  • AdminChange

AdminSurface is the main query surface. Each row includes:

  • the surface key, for example RISK_ADMIN or PoolAddressesProvider.owner()
  • its bucket, such as Delayed risk governance or Delayed governance
  • the exact privileged functions attached to that surface
  • the current holder set reconstructed from events
  • the target-holder recommendation from the timelock split plan

targetHolder now reflects the intended steady-state holder after the timelock cutover, not the old pre-migration direct-owner model.

Contracts

Monad mainnet (chainId = 143):

  • GovernanceTimelock: 0x3e4749D9Df7EC5ecd9184c301592bAc058a6F82f
  • RiskTimelock: 0x7fa9e0E4dA21d5e92c70815B1B25F39726fD963b
  • GovernanceSafe: 0x57976e192C45461F5958045a0bC57102e90440eD
  • SentinelSafe: 0x06Fe1d4F4B7cA7D3d1fB3164968F0F7383D02e0E
  • PoolAddressesProvider: 0x49D75170F55C964dfdd6726c74fdEDEe75553A0f
  • ACLManager: 0x73A78AFa04b629e22db3BEC357bfc4a8B4f149DF
  • PoolAddressesProviderRegistry: 0xD0CCDe10CAcd12f1c839Db6400B82a82ab90fa9B
  • ReservesSetupHelper: 0xE7D17A88C66b4ED0b73872937cdC5e081C118DcD
  • WrappedTokenGatewayV3: 0x800409dBd7157813BB76501c30e04596Cc478f25
  • CoreProxyAdmin: 0x6400650cED1eD7179143D40b4431c3cC8c068D90
  • LeaderboardProxyAdmin: 0x400916532d9298acfFD49B826258738115CF23f1
  • StaticATokenProxyAdmin: 0x0cBe49645BCC84eD90A6aA4D93dfEb2Cc836F721
  • UserVaultBeacon: 0xc9Fe3Db9b14A538FaB2eeBa33a8FeaB6ED7DdCeb

The indexer starts from block 32587107 on Monad mainnet. That start block is chosen to cover the authoritative governance and delayed-upgrade surfaces this repo tracks while keeping sync time practical for local verification.

Current Mainnet Holder Report

Snapshot captured after the 2026-04-10 phase-1 timelock migration completed on Monad mainnet.

This report is intentionally about the governed admin surfaces themselves. The Governance Safe still operates both timelocks, but those operator roles are not modeled as AdminSurface rows in this repo.

Steady-State Summary

  • GovernanceTimelock is the only live holder of:
    • DEFAULT_ADMIN
    • POOL_ADMIN
    • PoolAddressesProvider.getACLAdmin()
    • PoolAddressesProvider.owner()
    • PoolAddressesProviderRegistry.owner()
    • ReservesSetupHelper.owner()
    • WrappedTokenGatewayV3.owner()
    • Core ProxyAdmin.owner()
    • Leaderboard ProxyAdmin.owner()
    • StaticAToken ProxyAdmin.owner()
    • UserVaultBeacon.owner()
  • RiskTimelock is the only live holder of:
    • RISK_ADMIN
  • Sentinel Safe is the only live holder of:
    • EMERGENCY_ADMIN
  • The following roles remain unset:
    • ASSET_LISTING_ADMIN
    • FLASH_BORROWER
    • BRIDGE

Lending / Governance Surfaces

Surface Current holder(s) Notes
DEFAULT_ADMIN 0x3e4749D9Df7EC5ecd9184c301592bAc058a6F82f GovernanceTimelock is the only live holder.
POOL_ADMIN 0x3e4749D9Df7EC5ecd9184c301592bAc058a6F82f GovernanceTimelock is the only live holder.
RISK_ADMIN 0x7fa9e0E4dA21d5e92c70815B1B25F39726fD963b RiskTimelock is the only live holder.
EMERGENCY_ADMIN 0x06Fe1d4F4B7cA7D3d1fB3164968F0F7383D02e0E Sentinel Safe is the only live holder.
ASSET_LISTING_ADMIN none Currently unset.
FLASH_BORROWER none Currently unset.
BRIDGE none Currently unset.
PoolAddressesProvider.getACLAdmin() 0x3e4749D9Df7EC5ecd9184c301592bAc058a6F82f GovernanceTimelock now controls ACL seeding.
PoolAddressesProvider.owner() 0x3e4749D9Df7EC5ecd9184c301592bAc058a6F82f GovernanceTimelock now controls provider upgrades and root wiring.
PoolAddressesProviderRegistry.owner() 0x3e4749D9Df7EC5ecd9184c301592bAc058a6F82f GovernanceTimelock now owns the registry.
ReservesSetupHelper.owner() 0x3e4749D9Df7EC5ecd9184c301592bAc058a6F82f GovernanceTimelock now owns the onboarding helper.
WrappedTokenGatewayV3.owner() 0x3e4749D9Df7EC5ecd9184c301592bAc058a6F82f GovernanceTimelock now owns the wrapped-native gateway.

Delayed Upgradeability Surfaces

Surface Current holder(s) Notes
Core ProxyAdmin.owner() 0x3e4749D9Df7EC5ecd9184c301592bAc058a6F82f GovernanceTimelock now owns the core tokenomics ProxyAdmin.
Leaderboard ProxyAdmin.owner() 0x3e4749D9Df7EC5ecd9184c301592bAc058a6F82f GovernanceTimelock now owns the leaderboard ProxyAdmin.
StaticAToken ProxyAdmin.owner() 0x3e4749D9Df7EC5ecd9184c301592bAc058a6F82f GovernanceTimelock now owns the static wrapper ProxyAdmin.
UserVaultBeacon.owner() 0x3e4749D9Df7EC5ecd9184c301592bAc058a6F82f GovernanceTimelock now owns the UserVaultBeacon.

Queries

Example GraphQL query for current holders and powers:

query AdminSurfaces {
  AdminSurface(order_by: { bucket: asc, key: asc }) {
    key
    bucket
    surfaceKind
    contractName
    contractAddress
    currentHolders
    roleAdminKey
    functions
    targetHolder
  }
}

Example GraphQL query for the final steady-state authority map:

query FinalAuthorityMap {
  AdminSurface(
    where: {
      bucket: { _in: ["Delayed governance", "Delayed risk governance", "Immediate emergency"] }
    }
    order_by: [{ bucket: asc }, { key: asc }]
  ) {
    key
    bucket
    currentHolders
    targetHolder
  }
}

Example GraphQL query for the full history of one surface:

query RiskAdminHistory {
  AdminChange(
    where: { surfaceKey: { _eq: "RISK_ADMIN" } }
    order_by: [{ blockNumber: asc }, { logIndex: asc }]
  ) {
    changeType
    previousValue
    newValue
    actor
    txHash
    blockNumber
    timestamp
  }
}

Local Development

pnpm install
pnpm run codegen
pnpm run local:docker:up
pnpm run dev

Common commands:

  • pnpm run codegen
  • pnpm run build
  • pnpm run dev
  • pnpm run start
  • pnpm run test
  • pnpm run type-check
  • pnpm run local:docker:up
  • pnpm run local:docker:down

Design Rules

  • Index only authority surfaces, not general protocol activity.
  • Build current role holders strictly from event history, not address heuristics.
  • Keep the role and power classification explicit in indexed data.
  • Treat PoolAddressesProvider.ACLManagerUpdated as a state reset for ACL-role holders, because authority moves to a new manager contract.
  • Keep the repo small enough to audit quickly.

About

Neverland lending admin and tokenomics authority indexer

Resources

License

Stars

Watchers

Forks

Contributors