> For the complete documentation index, see [llms.txt](https://docs.kpk.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kpk.io/funds/infrastructure/onchain-accounting/balance-adapters/polygon-staking.md).

# Polygon Staking

Reports an account's Polygon PoS delegation — staked principal and unclaimed rewards — for any configured validator.

One immutable adapter that reports an account's **Polygon PoS delegation** for *any* configured validator: the staked principal and the unclaimed rewards, both denominated in **POL**. The set of validators to query is governed on the NAV Calculator (per-adapter, `MANAGER`-gated) and passed in as `bytes32` instance coordinates — `ValidatorShare` addresses widened to bytes32 — so adding a validator is a config transaction, not a deploy.

* **Type:** Meta-adapter
* **protocolSubId:** `keccak256("polygon-staking")`
* **Instance key:** the `ValidatorShare` address, widened to bytes32
* **positionId:** `abi.encode(address(validatorShare))`
* **protocolName():** `"Polygon Staking"` — the PRODUCT, not the chain. A bare "Polygon" reads as a network row in a portfolio, and the position is a delegation settled on Ethereum L1.
* **Source:** [`PolygonStakingMetaBalanceAdapter.sol`](https://github.com/karpatkey/onchain-accounting/blob/main/src/balances/MetaBalanceAdapters/PolygonStakingMetaBalanceAdapter.sol)

{% hint style="warning" %}
**This is an Ethereum mainnet adapter, despite the protocol's name.** Polygon PoS staking is settled on **Ethereum L1** by the `StakeManager` at `0x5e3Ef299fDDf15eAa0432E6e66473ace8c13D908`, which mints one `ValidatorShare` contract per validator; delegators hold share balances there. Nothing about this adapter runs on the Polygon chain.
{% endhint %}

***

## Positions returned

| Leg     | PositionKind | isDebt  | Description                               |
| ------- | ------------ | ------- | ----------------------------------------- |
| Staking | `Staking`    | `false` | The account's delegated principal, in POL |
| Rewards | `Rewards`    | `false` | Unclaimed staking rewards, in POL         |

Both legs carry the **same `positionId`** — the validator share address — and are told apart by `positionKind`, not by id. Both come from a single `getStakeAndRewards(account)` call, which returns the principal already denominated in POL rather than in shares, so no exchange-rate conversion applies. Zero legs are dropped, so a configured validator the account has not delegated to contributes nothing rather than zero-value rows.

***

## Unbonding positions are not reported

{% hint style="danger" %}
**A delegation that is mid-unstake reads as smaller than it is.** When a delegator starts an unstake, the shares leave `getStakeAndRewards` and land in a per-account, nonce-indexed withdrawal queue (`unbondNonces` + `unbonds_new`, valued through `withdrawExchangeRate()`). This adapter does not read that queue.

The omission is deliberate. Walking it means iterating an unbounded nonce range per instance per account, on a read path that is already `O(instances)`. The resulting error is an **under-report**, which is the safe direction under this framework's conventions, and DeBank does not surface those positions either — so a covered account mid-unbond reads low against the same reference NAV is reconciled with. Adding it later needs its own `isLocked = true` leg and a bound on the nonce walk.
{% endhint %}

***

## Pricing POL

POL is a registered asset priced by a plain Chainlink primary — **no custom feed contract**. The feed is `0x7bAC85A8a13A4BcD8abb3eB7d6b4d632c5a57676`, whose `description()` reads **`MATIC / USD`**.

That is not a mis-wiring. Chainlink's own mainnet reference data lists this proxy with `baseAsset: POL`; the display name is legacy and the tracked asset is POL. It is corroborated economically: POL is the 1:1 MATIC successor, and `PolygonMigration` still reports `unmigrationLocked() == false` while holding \~9.6 B MATIC, so the pair is arbitrage-enforced in both directions rather than by convention.

Registered at **heartbeat 86400** — exactly the cadence the feed declares. A heartbeat above the declared value would leave a window in which a dead feed still reads fresh, which is the one error this system treats as critical; see [Choosing a heartbeat](/funds/infrastructure/onchain-accounting/price-feeds.md#choosing-a-heartbeat-exactly-the-providers-declared-cadence).

***

## Labels

The breadcrumb is `["Validator", "#<validatorId>"]`, e.g. `["Polygon Staking", "Validator", "#192"]`.

The leaf comes from `validatorId()` rather than the ERC-20 `name()` every other address-keyed meta-adapter uses, because the live share contracts return something opaque — `"Delegated POL #c0"` for validator 192 — with nothing tying the suffix to the validator id a user would recognise. The read is gas-capped and fails open to `"<POL symbol> <share address>"`, so a hostile or non-conforming instance degrades the label instead of reverting a display-only view.

***

## Failure behaviour

A configured instance that is not a readable `ValidatorShare` reverts at `getStakeAndRewards` and is dropped by the meta-adapter's per-instance catch — the account's other positions are unaffected. An instance that runs **out of gas** is not absorbed: the fan-out raises `InstanceGasExhausted`, because recording a starved instance as an empty leg list would under-report behind a complete-looking answer.

If POL is ever unregistered on the NAV Calculator, the adapter returns no legs rather than reverting — an unregistered asset is an ordinary outcome, not an error.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kpk.io/funds/infrastructure/onchain-accounting/balance-adapters/polygon-staking.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
