Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
232 changes: 232 additions & 0 deletions HIP/hip-1331.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
---
hip: 1331
title: An `ExtendedAssetChanges` extra for large atomic swaps
author: ChatGPT 5 Pro (@openai), Michael Tinker (@tinker-michaelj), Matthew DeLorenzo (@littletarzan)
requested-by: Lambdaplex Labs
type: Standards Track
category: Service
needs-hiero-approval: Yes
needs-hedera-review: Yes
status: Review
discussions-to: https://github.com/hiero-ledger/hiero-improvement-proposals/pull/1331
requires: 1261
created: 2025-11-06
updated: 2026-03-04
---

## Abstract

We propose a new **`ExtendedAssetChanges`** extra in the HIP-1261 fee model and reframe the current list
size limits for `CryptoTransfer` as **pricing cutoffs** instead of hard caps. Each asset change beyond the
cutoffs incurs the `ExtendedAssetChanges` extra charge.

To achieve zero compromises to network security or fairness, we suggest the `ExtendedAssetChanges` price be
chosen to make it _strictly more expensive_ to use a given amount of throttle capacity via `CryptoTransfer`s
that incur the new extra compared to `CryptoTransfer`s that do not.

In the same vein, we also propose a new **throttle scaling** for `CryptoTransfer` proportional to the total
number of asset changes, similar to existing behavior for `TokenMint` (by serials), `TokenAssociate`
(by associations), and `CryptoTransfer` (by auto-created accounts). This keeps large atomic swaps from
becoming a new network congestion vector.

## Motivation

Today, Hiero networks reject `CryptoTransfer` transactions that exceed list size limits (configured as 10 per
category on Hedera mainnet), even when the network could safely handle more with proper pricing and throttling.
This forces clients to fragment logically atomic payments, increases record bloat, and introduces needless
failure modes. Converting these limits into **included counts** with marginal pricing beyond the cutoff,
- Preserves safety while removing an artificial UX ceiling.
- Prices work proportionally to resource usage.
- Aligns `CryptoTransfer` with the “base + extras” simplicity in HIP‑1261.
- Enables capacity planning and fair throttling at higher fan‑out.

Lambdaplex is specifically motivated to achieve onchain fill-or-kill (FOK) semantics for large market orders that
require many counterparties from a diverse order book to settle completely. (Note that it is not an option to use
an `AtomicBatch` for FOK in our setting because hook executions are disabled in batch transactions; and even if
hooks _were_ enabled in batches, we would need another, very complicated, HIP to specify how an `AtomicBatch` would
expose its complete proposed transfers to every hook in the batch.)

Other interesting use cases might include a DEX aggregator that needs to route through more than four or five
liquidity pools; or an NFT marketplace that wants to support very large bulk purchases, especially across multiple
collections.

## Rationale

HIP‑1261 defines a clean fee model where service-specific complexity is expressed via **extras**. A transfer’s cost
correlates with the number of accounts and tokens touched. The right instrument to express "the next `N` asset changes
cost more" is a new extra that counts **only** the overage beyond configurable free allowances. Throttling should
similarly scale with workload so heavy fan‑out transfers do not crowd out typical retail flows.

## Specification

### New HIP‑1261 extra

Add a single extra to the global `extras` list,
```json
{
"name": "ExtendedAssetChanges",
"fee": <tinycents-per-overage-unit>
}
```

#### Semantics

For a `CryptoTransfer`, define three category counts after assessing all custom fees,
- `H` = number of nonzero `AccountAmount` entries in `hbarTransfers.transfers`
- `F` = total number of nonzero `AccountAmount` entries across all `tokenTransfers[].transfers` (fungible)
- `N` = number of `NftTransfer` entries across all `tokenTransfers[].nftTransfers` (non-fungible)

Set `B = H + F + N`. Let the configured pricing cutoffs be,
- `C_H = ledger.transfers.maxLen`
- `C_F = ledger.tokenTransfers.maxLen`
- `C_N = ledger.nftTransfers.maxLen`
- `C_B = ledger.xferBalanceChanges.maxLen`

Now compute the per-category and aggregate overages,
```
overH = max(0, H - C_H)
overF = max(0, F - C_F)
overN = max(0, N - C_N)
overB = max(0, B - C_B)
```

The **charged count** for the `ExtendedAssetChanges` extra is then,
```
ExtendedAssetChanges.count = max(overB, overH + overF + overN)
```

This avoids double-charging while ensuring the aggregate cutoff `C_B` remains an effective backstop. We emphasize that
`ExtendedAssetChanges` is a service extra for `CryptoService.CryptoTransfer`. It is not part of the node or network fee
schedules.

#### Service schedule change (excerpt)

```json
{
"name": "CryptoService",
"schedule": [
{
"name": "CryptoTransfer",
"base_fee": <as configured>,
"extras": [
{ "name": "Signatures" },
{ "name": "Accounts" },
{ "name": "StandardFungibleTokens" },
{ "name": "StandardNonFungibleTokens" },
{ "name": "CustomFeeFungibleTokens" },
{ "name": "CustomFeeNonFungibleTokens" },
{ "name": "CreatedAutoAssociations" },
{ "name": "CreatedAccounts" },
{ "name": "ExtendedAssetChanges" }
]
}
]
}
```

Note The `included_count` for `ExtendedAssetChanges` in the fee schedule will be zero. The effective included counts are
driven by the four config knobs and the normalization rules above.

### Reinterpret list-size configs as pricing cutoffs

Update the semantics of the existing limits in `LedgerConfig`,
- `ledger.transfers.maxLen` (HBAR)
- `ledger.tokenTransfers.maxLen` (fungible token account amounts)
- `ledger.nftTransfers.maxLen` (NFT serial ownership changes)
- `ledger.xferBalanceChanges.maxLen` (post-custom fee assessment aggregate balance changes)

#### New behavior

Now,
- These properties become pricing cutoffs (included counts) rather than hard caps at precheck/handle.
- For counts above the cutoff, the transaction is accepted and the overage is priced via `ExtendedAssetChanges`.
- Failing a transaction solely for exceeding one of the four values is removed.

### Throttle scaling by asset change count

Introduce a transfer-weight function for throttle consumption,

```
units = baseUnits
+ w_h * H
+ w_f * F
+ w_n * N
```

where `baseUnits ≥ 1` for the transaction envelope, default weights might for example be `w_h = 1`, `w_f = 1`,
`w_n = 2` to reflect extra I/O for maintaining NFT owner linked lists. Now the `CryptoTransfer` throttles
ishould apply to the **units** result, not simply "one transaction equals one unit".

This mirrors existing patterns where `TokenMint` throttles by minted serial count, `TokenAssociate` by number
of associations, and `CryptoTransfer` already considers auto-created accounts. It ensures high-fan-out
transfers proportionally consume capacity.

#### Congestion pricing

If congestion pricing is enabled, it composes multiplicatively with `ExtendedAssetChanges`. No special cases
are introduced by this HIP.

### Mirror node fee estimation

Per HIP‑1261, fee estimators must include `ExtendedAssetChanges` for `CryptoTransfer`,
- In **intrinsic** mode, compute `H`, `F`, `N` from the transaction contents only, and approximate `B` using a reasonable strategy.
- In **state** mode, use latest known state to compute exact assessed custom fees and compute `B` exactly.

The response must surface `ExtendedAssetChanges` as a separate extra in the service component.

### Examples

Assume cutoffs `C_H = C_F = C_N = 10`, and `C_B = 40`. Then,

- `H=7, F=5, N=0, B=12` implying `overH=0, overF=0, overN=0, overB=0` → `count=0` → no `ExtendedAssetChanges` charge.

- `H=12, F=15, N=3, B=30` implying `overH=2, overF=5, overN=0, overB=0` → `count=max(0, 2+5+0)=7` charge for extra.

- `H=18, F=18, N=12, B=55` implying `overH=8, overF=8, overN=2, overB=15` → `count=max(15, 8+8+2=18)=18` charge for extra.

Total incremental tinycents for the above equals `count * fee(ExtendedAssetChanges)`.

## Backwards Compatibility

This HIP allows some transactions that would previous fail to succeed at a higher price. That is, some tranctions that
would have failed with `TOKEN_TRANSFER_LIST_SIZE_LIMIT_EXCEEDED` will now succeed at a materially high price. This is
_conceivably_ a breaking change for clients that somehow rely on failure semantics rather than explicit transaction fee
limits to budget their `CryptoTransfer` submissions. (Though this seems highly contrived.)

Record and receipt formats are unchanged.

The meaning of the four `ledger.*maxLen` properties changes from "hard cap" to "included count."

## Security Implications

We do not see any security concerns with a faithful implementation of the charging and throttling behaviors; especially
when `ExtendedAssetChanges` pricing makes it **strictly less attractive** for anyone to try to consume an unfair amount
of the total network throttle via oversize `CryptoTransfer`s.

Furthermore, this HIP does not alter `CreatedAccounts`/auto-association pricing; those remain separate extras and throttles.

## How to Teach This

Multiparty atomic swaps are now constrained by willingness-to-pay instead of artificial limits.

## Reference Implementation

In progress.

## Rejected Ideas
These included,
- Three separate extras (`ExtendedHBARChanges`, `ExtendedFungibleChanges`, `ExtendedNFTChanges`); this results in more knobs
than needed, and the aggregate cutoff `C_B` plus per-category cutoffs are sufficient with one extra.
- Using multiple `CryptoTransfer`s in a batch; not only are hooks disabled in batch transactions, but a hook with onchain
FOK semantics cannot be reused by multiple transfers in a batch.

## Open Issues

There are no known open issues.

## References
1. [HIP-1261](https://hips.hedera.com/hip/hip-1261)

## Copyright/license
This document is licensed under the Apache License, Version 2.0 —
see [LICENSE](../LICENSE) or <https://www.apache.org/licenses/LICENSE-2.0>.
Loading