Update schemas
The Pendle PT implementation uses three case-sensitive update-type strings:
EmaImpliedRateUpdate
PendleDiscountRateUpdate
EModeCategoryUpdateThe market-state record is stored in LlamaGuardOracle. The two executable recommendation types are stored in RiskOracle.
Common recommendation shape
Executable RiskOracle recommendations contain:
| Field | Purpose |
|---|---|
referenceId | Human-readable source and model provenance |
newValue | ABI-encoded recommendation intended for the relevant agent or reader |
updateType | Exact typed-recommendation name |
market | PT address or encoded eMode ID |
additionalData | ABI-encoded audit context not injected as the parameter value |
Single publication encodes one tuple. Bulk publication encodes five parallel arrays.
Reference IDs
The shared format is:
<updateType>:<sourceChainId>:<market>:<sourceLocator>:v<modelVersion>For EMA and risk-parameter records, sourceLocator is the finalized source block. For a discount-rate record it is the upstream EMA update ID.
EmaImpliedRateUpdate
Market key: PT asset address
newValue = abi.encode(int256 emaLnImpliedRateWad)additionalData is encoded in this order:
| Index | ABI type | Meaning |
|---|---|---|
| 0 | uint256 | Current raw logarithmic implied rate |
| 1 | uint256 | Previous rate EMA |
| 2 | uint32 | EMA span |
| 3 | uint256 | Maturity timestamp |
| 4 | uint256 | Calculation timestamp |
| 5 | uint256 | Finalized source block number |
| 6 | uint32 | Model version |
| 7 | uint8 | Flags |
| 8 | uint256 | Current raw market proportion |
| 9 | uint256 | Previous proportion EMA |
| 10 | uint256 | New proportion EMA |
Flags:
| Bit | Meaning |
|---|---|
| 0 | Rate EMA seeded from the current observation |
| 1 | Proportion EMA seeded from the current observation |
The report also includes a publication deadline. The workflow sets it to 86,400 seconds after calculation.
PendleDiscountRateUpdate
Market key: PT asset address
newValue = abi.encode(uint256 nextDiscountRatePerYear)additionalData:
| Index | ABI type | Meaning |
|---|---|---|
| 0 | uint256 | Current discount rate |
| 1 | uint256 | Unbounded target discount rate |
| 2 | int256 | Signed price deviation, WAD-scaled |
| 3 | uint256 | EMA logarithmic implied rate |
| 4 | uint256 | Time to maturity in years, WAD-scaled |
| 5 | uint256 | Upstream EMA update ID |
| 6 | uint64 | EMA observation timestamp |
| 7 | uint64 | EMA source block |
| 8 | uint32 | EMA span |
| 9 | uint32 | Model version |
| 10 | uint16 | Flags |
| 11 | uint64 | Retired-field sentinel, always zero |
| 12 | uint64 | Retired-field sentinel, always zero |
The last two fields preserve the historical tuple width. Active delay and movement controls now live in the router, AgentHub, and RangeValidationModule; zero does not mean those controls are disabled.
Flags:
| Bit | Meaning |
|---|---|
| 0 | Directional rate step applied |
| 1 | Adapter maximum discount rate applied |
| 2 | Raw adapter price reached the methodology floor |
| 3 | An upward discount-rate move was step-capped |
EModeCategoryUpdate
Market key: eMode ID encoded as a 20-byte address
newValue = abi.encode(
uint256 ltvBps,
uint256 liquidationThresholdBps,
uint256 liquidationBonusBps
)additionalData:
| Index | ABI type | Meaning |
|---|---|---|
| 0 | address | Source PT asset |
| 1 | uint16 | eMode category ID |
| 2 | uint256 | Current discount rate |
| 3 | uint256 | Time to maturity in years, WAD-scaled |
| 4 | uint256 | LB floor in bps |
| 5 | uint256 | LT cap in bps |
| 6 | uint256 | Computed LT bound in bps |
| 7 | uint32 | Model version |
| 8 | uint8 | Flags |
| 9 | uint256 | EMA logarithmic implied rate |
| 10 | uint256 | EMA market proportion |
| 11 | uint256 | Upstream EMA update ID |
| 12 | uint256 | Reference endpoint multiplier, scaled by 10,000 |
| 13 | uint64 | EMA observation timestamp |
| 14 | uint64 | EMA source block |
| 15 | uint256 | Reference market proportion, WAD-scaled |
| 16 | int256 | Liquidation-bonus slope, WAD-scaled |
| 17 | uint256 | Stressed AMM price, WAD-scaled |
Flags:
| Bit | Meaning |
|---|---|
| 0 | Raw adapter price reached the methodology floor |
| 1 | LT was bounded by the configured cap |
| 2 | Reference market proportion reached the 96% ceiling |
| 3 | Negative liquidation-bonus slope was floored to zero |
Signed report envelope
The two router-bound recommendation workflows wrap the bare RiskOracle payload as:
abi.encode(uint64 signedAt, bytes payload)signedAt is the CRE consensus timestamp. The router uses it to enforce the route's maximum report age and strict ordering for each workflow, market, and update type before forwarding the bare payload to RiskOracle.
Decoding guidance
Validate updateType before decoding either byte field. Treat newValue as the typed recommendation and additionalData as provenance. Indexers should retain the raw bytes and use modelVersion when interpreting historical records.