feat: NTT support mint/burn on the currencies precompile#1488
Conversation
Weight Diff Report0 extrinsic(s) changed across 0 pallet(s). New: 2. Removed: 0. New extrinsics (2)
Threshold: ±10%. Base |
|
Crate versions that have not been updated:
Crate versions that have been updated:
Runtime version has not been increased. |
There was a problem hiding this comment.
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
NttMintersstorage plusset_ntt_minter/clear_ntt_minterextrinsics inpallet-evm-accounts, including weights, benchmarks, and unit tests. - Extend the MultiCurrency precompile with
mint(address,uint256)/burn(uint256), enforcingNttMinters[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 |
| 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 }); |
# Conflicts: # Cargo.lock # integration-tests/Cargo.toml # pallets/liquidation/Cargo.toml
|
Quick benchmark at commit 98970e5 has been executed successfully. |
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:NttMintersstorage (asset → H160, approvals-style) → single authority allowed to mint/burn per assetset_ntt_minter(ControllerOrigin = Root | GeneralAdmin) → binds the spoke NttManagerclear_ntt_minter(newNttEmergencyOrigin= Root | TC majority | GeneralAdmin) → emergency stop, kills mint/burn instantlymint(address,uint256)/burn(uint256), NonPayable, caller must equalNttMinters[asset]setMinterselector on purpose → minter changes are extrinsic-only (unknown selector reverts); deviation to be flagged to WormholeCallerNotMinter(address),InsufficientBalance(uint256,uint256),MintLimitReached()Circuit breakers
IssuanceIncreaseFuse::can_mint(per-day budget = registryxcm_rate_limit, lockdown-aware); reverts cleanly instead of reserve-and-lockdown, so a rejected NTT delivery can be replayedAssetType::Externalin the asset registry; setting or clearing an NTT minter does not change asset classification, and an explicitset_asset_categoryoverride still winsrate_limit_should_not_be_bypassed_by_burning_tokens); test pins current semanticsTests
currency_precompile_ntt: 14 new — minter guards, issuance/balance deltas, unbound-recipient credit, static context,setMinterrejection, emergency clear, mint budget exhaustion, lockdown, burn-refills-budget (documented), global-withdraw-limit revert with rollback via real runner, governance-managed external classification lifecyclecurrency_precompilesuite: 19 passed, unchangedcargo check -p hydradx-runtimeclean incl.--features runtime-benchmarksLeft before mainnet
approve_contract-class ops)AssetType::External+set_ntt_minter+xcm_rate_limitvalues per asset (fuse is unlimited when unset) + price-route check