fix(pezkuwi-asset-hub): declare PEZ and USDT as sufficient, matching Polkadot AH (#66)

* fix(pezkuwi-asset-hub): declare PEZ and USDT as sufficient assets

The wallet refused USDT.p transfers to any account holding no HEZ:

    Your transfer will fail since the destination account does not have
    enough HEZ to accept other token transfers

It is a false positive, and the chain disagrees with this config.

DeadRecipientValidation skips the whole check when the destination asset is
self-sufficient:

    skipIf = { assetSourceRegistry.isAssetSelfSufficient(destinationChainAsset) }

and StatemineAssetBalance reads that flag from HERE, not from the chain:

    chainAsset.requireStatemine().isSufficient   →  runCatching { … }.getOrDefault(false)

`isSufficient` was absent from typeExtras in every version of this config, so it
resolved to false, the validation ran, and every transfer to a fresh account was
warned against.

Measured on chain (asset-hub-rpc.pezkuwichain.io):

    asset 1    PEZ    sufficient=true   minBalance=1        18 accounts
    asset 1000 wUSDT  sufficient=true   minBalance=10000    21 accounts

Both are sufficient, so neither needs the recipient to hold native balance.

Proof it works in practice rather than only in theory: account
5E2yqgUVVNjU… holds 1750.00 USDT with free=0, providers=0, sufficients=1 and
nonce=0. Zero native balance, no provider reference, and it has never signed a
transaction — so it was brought into existence by the incoming USDT transfer
itself, which is exactly what the wallet was saying could not happen.

Applied to v22 (the version the app fetches, runtime/build.gradle CHAINS_URL) and
to the top-level chains.json.

Noted, not changed here: this config also declares assets 1001/1002/1003 on
Pezkuwi Asset Hub as DOT, ETH and BTC. None of the three exists on chain —
assets.asset() returns None for all of them. They are shown to users and any
transfer would fail.

* Revert "fix(pezkuwi-asset-hub): declare PEZ and USDT as sufficient assets"

This reverts commit af1a8a5468.

* fix(pezkuwi-asset-hub): declare PEZ and USDT as sufficient, matching Polkadot AH

Pezkuwi Asset Hub's two statemine assets carried only `assetId` in typeExtras. The
equivalent entries on Polkadot Asset Hub — USDT (1984) and USDC (1337) — carry
`isSufficient: true`. Same kind of asset, same file, two different declarations.

The omission is not inert. `LocalToDomainChainMapper` reads

    typeExtras["isSufficient"] as Boolean? ?: STATEMINE_IS_SUFFICIENT_DEFAULT   // false

so an absent field resolves to false, `StatemineAssetBalance.isSelfSufficient` returns
false, `DeadRecipientValidation`'s skipIf does not fire, and the validation runs — at
`validOrError`, which is DefaultFailureLevel.ERROR, so the transfer is blocked rather
than warned about.

The chain says otherwise. Measured on asset-hub-rpc.pezkuwichain.io, 2026-08-10:

    asset 1    PEZ    sufficient=true   minBalance=1        18 accounts
    asset 1000 wUSDT  sufficient=true   minBalance=10000    21 accounts

Neither needs the recipient to hold native HEZ, and one account demonstrates it:
5E2yqgUVVNjU… holds 1750.00 USDT with free=0, providers=0, sufficients=1 and nonce=0 —
no native balance, no provider reference, never signed a transaction. It exists because
the incoming USDT transfer created it, which is exactly what the wallet was reporting
could not happen.

43 of the 67 statemine assets in this config declare the field. The 24 that omit it are
genuinely non-sufficient on chain — the Polkadot AH meme tokens. Pezkuwi Asset Hub was
the only case where the declaration disagreed with the chain.

Applied to v22 (the version runtime/build.gradle CHAINS_URL fetches) and the top-level
chains.json, in the same shape as the Polkadot entries.
This commit is contained in:
2026-08-11 02:24:36 -07:00
committed by GitHub
parent c754e51e73
commit 28adea22bc
5 changed files with 22 additions and 12 deletions
+4 -2
View File
@@ -148,7 +148,8 @@
"buyProviders": {},
"sellProviders": {},
"typeExtras": {
"assetId": "1"
"assetId": "1",
"isSufficient": true
}
},
{
@@ -163,7 +164,8 @@
"buyProviders": {},
"sellProviders": {},
"typeExtras": {
"assetId": "1000"
"assetId": "1000",
"isSufficient": true
}
}
],
+5 -3
View File
@@ -116,7 +116,8 @@
"buyProviders": {},
"sellProviders": {},
"typeExtras": {
"assetId": "1"
"assetId": "1",
"isSufficient": true
}
},
{
@@ -131,7 +132,8 @@
"buyProviders": {},
"sellProviders": {},
"typeExtras": {
"assetId": "1000"
"assetId": "1000",
"isSufficient": true
}
},
{
@@ -832,4 +834,4 @@
"defaultBlockTime": 2000
}
}
]
]
+4 -2
View File
@@ -148,7 +148,8 @@
"buyProviders": {},
"sellProviders": {},
"typeExtras": {
"assetId": "1"
"assetId": "1",
"isSufficient": true
}
},
{
@@ -163,7 +164,8 @@
"buyProviders": {},
"sellProviders": {},
"typeExtras": {
"assetId": "1000"
"assetId": "1000",
"isSufficient": true
}
}
],
+4 -2
View File
@@ -148,7 +148,8 @@
"buyProviders": {},
"sellProviders": {},
"typeExtras": {
"assetId": "1"
"assetId": "1",
"isSufficient": true
}
},
{
@@ -163,7 +164,8 @@
"buyProviders": {},
"sellProviders": {},
"typeExtras": {
"assetId": "1000"
"assetId": "1000",
"isSufficient": true
}
}
],