This patch release completes the EVM precompile surface started in v8.1: full ERC-3643 and
ERC-7943 coverage for fungible assets, a new ERC-721 precompile for NFT collections, and a
general-purpose IPolymeshRuntime precompile. It also adds holder-level asset freezing, NFT
approvals, and first-class support for ETH wallets in the Relayer (subsidy) and MultiSig pallets.
Runtime spec_version is 8_001_010. v8.1.0 was never released to mainnet, so the precompile
ABI changes below affect only integrators building against the v8.1.0 development surface.
New Features
ERC-721 Precompile for NFT Collections
- NFT collections are now accessible via a standard ERC-721 precompile, at address prefix
9
with the collection'sAssetIdin the low 16 bytes. - Supports ERC-721, ERC-721Metadata, ERC-165, ERC-7943 and Polymesh
mint/burn/totalSupply. tokenURIresolves the NFT'stokenUrimetadata, falling back to the collection's
baseTokenUriwith{tokenId}substitution.safeTransferFromonly accepts EOA receivers (onERC721Receivedcannot be called from a
precompile);ownerOfreverts for portfolio-held NFTs;balanceOfcounts NFTs held by the
account key, not the whole identity.
NFT Approvals
- New extrinsics
Nft::approve(per-token spender) andNft::set_approval_for_all
(collection-wide operator). - New events
NFTApproval,NFTApprovalForAll,NFTApprovalSpent. - New errors
NFTApprovalNotAuthorizedandInsufficientNFTApproval. - New storage
Nft::TokenApproval,Nft::OperatorApproval, plus per-account/per-portfolio NFT
counts (Nft::NFTAccountCount,Portfolio::PortfolioNFTCount). - Per-token approvals are cleared whenever an NFT changes hands.
IPolymeshRuntime Precompile
- A general-purpose precompile at the fixed address
0xFFFF, for extrinsics not scoped to an
asset. - Exposes
assetCreateAsset,assetRegisterTicker,identityRegisterDid,
identitySelfRegisterDid,externalAgentsAuthorizeBecomeAgentand
externalAgentsAcceptBecomeAgent, and emitsAssetCreated,TickerRegisteredand
DidCreated. - Every call changes state, so the whole interface is rejected in a read-only (
eth_call/
STATICCALL) context.
ERC-3643 / ERC-7943 Coverage for Fungible Assets
- Adds
canSend,canReceive,setFrozenTokens,getFrozenTokens,setName,setSymbol,
pause,unpause,setAddressFrozen,isAgent,freezePartialTokensand
unfreezePartialTokensto the fungible-asset precompile. forcedTransfernow delivers directly to a named recipient via the new
Asset::controller_transfer_to, and takes atoaddress accordingly.
Holder Freezing
- External agents can now freeze an individual holder's tokens, rather than only the asset as a
whole. A holder is either an account key or a portfolio, and every new call accepts both. Asset::set_holder_frozenfreezes a holder entirely;Asset::set_frozen_tokens,
freeze_partial_tokensandunfreeze_partial_tokensfreeze a partial balance.- Frozen holders are blocked at transfer time, and the ERC-3643
canSend/canReceiveviews
report the result. - New errors:
Asset::InvalidTransferSenderIsFrozen,Asset::InsufficientFrozenBalance,
Asset::FreezePartialTokenMustNotExceedHoldersBalance,Portfolio::PortfolioIsFrozen. - New storage:
Asset::FrozenBalance,Asset::FrozenAccounts,
Portfolio::PortfolioFrozenAssets,Portfolio::FrozenPortfolios.
ETH Wallet Support
- ETH wallets can be subsidised by the Relayer pallet, including the pre-charged storage deposit
of an Ethereum transaction. - ETH wallets can be MultiSig signers.
- ETH wallets accepting authorizations (
Identity::join_identity_as_key,
MultiSig::accept_multisig_signer, etc.) do not pay the transaction fee; as with Substrate
keys, the authorization creator pays. - Ethereum transactions may carry
Identity,MultiSigandRelayercalls. EIP-7702 and
EIP-4844 transaction types are rejected.
New External API
Asset:set_frozen_tokens,set_holder_frozen,controller_transfer_to,
freeze_partial_tokens,unfreeze_partial_tokens.Nft:approve,set_approval_for_all,controller_transfer_to.- New
Assetevents:FrozenBalanceSet,SetAccountFreeze,ControllerTransferTo. NFTApiruntime API bumped to version 4, addingtoken_approvalandoperator_approval.
Modified External API
- Permissions for calls entering the runtime through the EVM are now checked against the
extrinsic actually being dispatched, rather than against thepallet_revivecall carrying it.
Secondary keys therefore need permission for the underlying extrinsic. Settlement::transfer_fundswithfrom = Some(Account)and a caller other than the owner now
accepts non-fungible funds, consuming an NFT approval instead of failing.
Settlement::AllowancesNotSupportedForNFTsis renamed to
DeprecatedAllowancesNotSupportedForNFTs(its index is preserved) and NFT spender transfers
now fail withNft::InsufficientNFTApproval.Settlement::transfer_funds: removed a redundant check, allowing an instruction where the
caller is the receiver but has no custody of the receiving portfolio.- Transaction tipping is now restricted to Governance Committee members only; DID Registrars
(formerly CDD Providers) can no longer tip. - The
ChargeTransactionPaymentsigned extension is now a named struct carrying the tip and a
(non-encoded) storage deposit. The wire encoding of a signed transaction is unchanged, but the
extension's shape in runtime metadata is not. IFungibleAsset.forcedTransfertakes a newtoparameter, changing its selector.
Data Migration
- Backfill
Nft::NFTAccountCountfromNft::NFTHolder(pallet-nft storage version 7 -> 8). - Backfill
Portfolio::PortfolioNFTCountfromPortfolio::PortfolioNFT
(pallet-portfolio storage version 4 -> 5).
Runtime Integration
pallet_precompilesgains aConfigtrait, which runtimes must implement; it carries the
runtime call type and theTokenUriMetadataKey/BaseTokenUriMetadataKeyglobal metadata
keys used bytokenURI.- Runtimes wire
pallet_revive'sDispatchHookto
pallet_precompiles::common::DispatchWithCallMetadata, and register the two new precompiles. polymesh_transaction_payment::Configno longer has aDidRegistrarsassociated type.ComplianceFnConfiggains a requiredis_holder_compliantmethod.Settlement::unsafe_affirm_instructionis split into
caller_is_permissioned_and_affirmation_is_pendingandunverified_affirm_instruction.
Other Changes
- Added
NonFungibleAssetStub.sol/.binandPolymeshRuntime.sol/.bin, exported from the
polymesh-precompilescrate for block-explorer verification;
scripts/build_precompile_stub.shnow builds and checks all three stubs. - All precompiles reject delegatecall.
- Added
docs/spec/: 22 protocol specification documents covering identity and keys through
treasury and committees. - Added the Hashlock v8.0.0 audit report under
audit/. - Regenerated weights for
pallet_asset,pallet_nftandpallet_portfolio. - Substantially expanded the integration test suite (identity, compliance, settlement,
statistics, corporate actions, STO, portfolio custody, relayer, precompiles).
Full Changelog: v8.1.0...v8.1.1