Skip to content

feat: NTT support mint/burn on the currencies precompile#1488

Merged
enthusiastmartin merged 8 commits into
masterfrom
ntt-minter
Jul 20, 2026
Merged

feat: NTT support mint/burn on the currencies precompile#1488
enthusiastmartin merged 8 commits into
masterfrom
ntt-minter

Conversation

@mrq1911

@mrq1911 mrq1911 commented Jul 16, 2026

Copy link
Copy Markdown
Member

Runtime-native INttToken surface for Wormhole NTT (option A): the per-asset currencies precompile gains minter-gated mint/burn, so a BURNING-mode spoke NttManager mints/burns ORML balances directly — no new pallet, no balance migration.

What

  • pallet-evm-accounts: NttMinters storage (asset → H160, approvals-style) → single authority allowed to mint/burn per asset
  • set_ntt_minter (ControllerOrigin = Root | GeneralAdmin) → binds the spoke NttManager
  • clear_ntt_minter (new NttEmergencyOrigin = Root | TC majority | GeneralAdmin) → emergency stop, kills mint/burn instantly
  • MultiCurrency precompile: mint(address,uint256) / burn(uint256), NonPayable, caller must equal NttMinters[asset]
  • no setMinter selector on purpose → minter changes are extrinsic-only (unknown selector reverts); deviation to be flagged to Wormhole
  • Solidity custom-error reverts: CallerNotMinter(address), InsufficientBalance(uint256,uint256), MintLimitReached()

Circuit breakers

  • mint → pre-checked against IssuanceIncreaseFuse::can_mint (per-day budget = registry xcm_rate_limit, lockdown-aware); reverts cleanly instead of reserve-and-lockdown, so a rejected NTT delivery can be replayed
  • burn → counts against the global withdraw limit when governance configures the asset as AssetType::External in the asset registry; setting or clearing an NTT minter does not change asset classification, and an explicit set_asset_category override still wins
  • external assets need a price route to HDX → without one every burn reverts (cutover checklist item)
  • note: the fuse measures net issuance increase per period (upstream gross-accounting fix still pending, see ignored rate_limit_should_not_be_bypassed_by_burning_tokens); test pins current semantics

Tests

  • pallet-evm-accounts: 37 passed (5 new: origin gating, zero-address, set/clear)
  • integration currency_precompile_ntt: 14 new — minter guards, issuance/balance deltas, unbound-recipient credit, static context, setMinter rejection, emergency clear, mint budget exhaustion, lockdown, burn-refills-budget (documented), global-withdraw-limit revert with rollback via real runner, governance-managed external classification lifecycle
  • existing currency_precompile suite: 19 passed, unchanged
  • cargo check -p hydradx-runtime clean incl. --features runtime-benchmarks

Left before mainnet

  • run real benchmarks (weights hand-copied from approve_contract-class ops)
  • governance batch: set NTT assets to AssetType::External + set_ntt_minter + xcm_rate_limit values per asset (fuse is unlimited when unset) + price-route check
  • Wormhole ack on extrinsic-only minter; audit (mint/burn paths are consensus-critical)

@github-actions

Copy link
Copy Markdown

Weight Diff Report

0 extrinsic(s) changed across 0 pallet(s). New: 2. Removed: 0.

New extrinsics (2)
Pallet Extrinsic RefTime Proof Reads Writes
pallet_evm_accounts set_ntt_minter 23.3M 0 0 1
pallet_evm_accounts clear_ntt_minter 23.2M 0 0 1

Threshold: ±10%. Base Weight::from_parts(ref_time, proof_size) compared; per-unit components ignored.

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

Crate versions that have not been updated:

  • runtime-integration-tests: v1.104.0
  • pallet-liquidation: v2.6.0
  • hydradx-runtime: v433.0.0

Crate versions that have been updated:

  • pallet-evm-accounts: v1.6.1 -> v1.7.0
  • pallet-transaction-multi-payment: v10.6.0 -> v10.6.1

Runtime version has not been increased.

@mrq1911
mrq1911 marked this pull request as ready for review July 16, 2026 15:27
Copilot AI review requested due to automatic review settings July 16, 2026 15:27

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a runtime-native INttToken surface for Wormhole NTT by extending the per-asset MultiCurrency EVM precompile with minter-gated mint/burn, and introducing runtime storage/extrinsics to bind (and emergency-clear) a single minter authority per asset.

Changes:

  • Add NttMinters storage plus set_ntt_minter / clear_ntt_minter extrinsics in pallet-evm-accounts, including weights, benchmarks, and unit tests.
  • Extend the MultiCurrency precompile with mint(address,uint256) / burn(uint256), enforcing NttMinters[asset] and reverting with Solidity custom errors.
  • Add integration coverage for NTT flows and bump runtime/spec versions.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
runtime/hydradx/src/weights/pallet_evm_accounts.rs Adds runtime weights for set_ntt_minter / clear_ntt_minter.
runtime/hydradx/src/lib.rs Bumps spec_version for the runtime upgrade.
runtime/hydradx/src/evm/precompiles/multicurrency.rs Implements minter-gated mint/burn on the currencies precompile with circuit-breaker gating and custom-error reverts.
runtime/hydradx/src/evm/precompiles/mod.rs Adds a helper to revert with Solidity custom errors.
runtime/hydradx/src/evm/mod.rs Wires the new NttEmergencyOrigin into the runtime config.
runtime/hydradx/src/evm/erc20_currency.rs Adds Mint/Burn selectors to the ERC20 selector enum.
runtime/hydradx/src/benchmarking/evm_accounts.rs Adds benchmarks for the new NTT minter extrinsics.
runtime/hydradx/Cargo.toml Bumps hydradx-runtime crate version.
pallets/transaction-multi-payment/src/mock.rs Updates mock runtime config with NttEmergencyOrigin.
pallets/liquidation/src/tests/mock.rs Updates mock runtime config with NttEmergencyOrigin.
pallets/evm-accounts/src/weights.rs Extends pallet WeightInfo and default weights for new extrinsics.
pallets/evm-accounts/src/tests.rs Adds unit tests for set/clear minter behavior and origin gating.
pallets/evm-accounts/src/mock.rs Updates pallet mock config with NttEmergencyOrigin.
pallets/evm-accounts/src/lib.rs Adds NttMinters storage, events/errors, and set_ntt_minter / clear_ntt_minter calls.
integration-tests/src/evm.rs Adds an integration test module covering NTT mint/burn, selectors, reverts, and breaker interactions.
integration-tests/Cargo.toml Bumps integration test crate version.
Cargo.lock Updates lockfile for crate version bumps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

type EvmNonceProvider = EvmNonceProvider;
type FeeMultiplier = sp_core::ConstU32<50>;
type ControllerOrigin = EitherOf<EnsureRoot<Self::AccountId>, GeneralAdmin>;
// faster than ControllerOrigin (TC majority) so NTT mint/burn can be stopped in minutes
Comment on lines +450 to +456
T::ControllerOrigin::ensure_origin(origin)?;

ensure!(!minter.is_zero(), Error::<T>::InvalidMinterAddress);

<NttMinters<T>>::insert(asset_id, minter);

Self::deposit_event(Event::NttMinterSet { asset_id, minter });
@mrq1911 mrq1911 changed the title NTT: minter-gated mint/burn on the currencies precompile feat: NTT support mint/burn on the currencies precompile Jul 16, 2026
# Conflicts:
#	Cargo.lock
#	integration-tests/Cargo.toml
#	pallets/liquidation/Cargo.toml
@enthusiastmartin
enthusiastmartin merged commit e791f1d into master Jul 20, 2026
9 of 11 checks passed
@github-actions

Copy link
Copy Markdown

Quick benchmark at commit 98970e5 has been executed successfully.
View results

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants