github PolymeshAssociation/Polymesh v8.1.1

3 hours ago

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's AssetId in the low 16 bytes.
  • Supports ERC-721, ERC-721Metadata, ERC-165, ERC-7943 and Polymesh mint/burn/totalSupply.
  • tokenURI resolves the NFT's tokenUri metadata, falling back to the collection's
    baseTokenUri with {tokenId} substitution.
  • safeTransferFrom only accepts EOA receivers (onERC721Received cannot be called from a
    precompile); ownerOf reverts for portfolio-held NFTs; balanceOf counts NFTs held by the
    account key, not the whole identity.

NFT Approvals

  • New extrinsics Nft::approve (per-token spender) and Nft::set_approval_for_all
    (collection-wide operator).
  • New events NFTApproval, NFTApprovalForAll, NFTApprovalSpent.
  • New errors NFTApprovalNotAuthorized and InsufficientNFTApproval.
  • 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, externalAgentsAuthorizeBecomeAgent and
    externalAgentsAcceptBecomeAgent, and emits AssetCreated, TickerRegistered and
    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, freezePartialTokens and
    unfreezePartialTokens to the fungible-asset precompile.
  • forcedTransfer now delivers directly to a named recipient via the new
    Asset::controller_transfer_to, and takes a to address 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_frozen freezes a holder entirely; Asset::set_frozen_tokens,
    freeze_partial_tokens and unfreeze_partial_tokens freeze a partial balance.
  • Frozen holders are blocked at transfer time, and the ERC-3643 canSend/canReceive views
    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, MultiSig and Relayer calls. 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 Asset events: FrozenBalanceSet, SetAccountFreeze, ControllerTransferTo.
  • NFTApi runtime API bumped to version 4, adding token_approval and operator_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 the pallet_revive call carrying it.
    Secondary keys therefore need permission for the underlying extrinsic.
  • Settlement::transfer_funds with from = Some(Account) and a caller other than the owner now
    accepts non-fungible funds, consuming an NFT approval instead of failing.
    Settlement::AllowancesNotSupportedForNFTs is renamed to
    DeprecatedAllowancesNotSupportedForNFTs (its index is preserved) and NFT spender transfers
    now fail with Nft::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 ChargeTransactionPayment signed 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.forcedTransfer takes a new to parameter, changing its selector.

Data Migration

  • Backfill Nft::NFTAccountCount from Nft::NFTHolder (pallet-nft storage version 7 -> 8).
  • Backfill Portfolio::PortfolioNFTCount from Portfolio::PortfolioNFT
    (pallet-portfolio storage version 4 -> 5).

Runtime Integration

  • pallet_precompiles gains a Config trait, which runtimes must implement; it carries the
    runtime call type and the TokenUriMetadataKey / BaseTokenUriMetadataKey global metadata
    keys used by tokenURI.
  • Runtimes wire pallet_revive's DispatchHook to
    pallet_precompiles::common::DispatchWithCallMetadata, and register the two new precompiles.
  • polymesh_transaction_payment::Config no longer has a DidRegistrars associated type.
  • ComplianceFnConfig gains a required is_holder_compliant method.
  • Settlement::unsafe_affirm_instruction is split into
    caller_is_permissioned_and_affirmation_is_pending and unverified_affirm_instruction.

Other Changes

  • Added NonFungibleAssetStub.sol/.bin and PolymeshRuntime.sol/.bin, exported from the
    polymesh-precompiles crate for block-explorer verification;
    scripts/build_precompile_stub.sh now 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_nft and pallet_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

Don't miss a new Polymesh release

NewReleases is sending notifications on new releases.