Add canSend, canReceive, setFrozenTokens, getFrozenTokens - #1990
Add canSend, canReceive, setFrozenTokens, getFrozenTokens#1990HenriqueNogara wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds ERC-7943-style capabilities to the fungible asset EVM precompile, including compliance-side “can send/receive” checks and per-holder frozen-token tracking, with the necessary runtime plumbing (storage, extrinsic, compliance hook) and weights/benchmarks.
Changes:
- Extend the fungible asset precompile interface with
canSend,canReceive,setFrozenTokens, andgetFrozenTokens(plusFrozenevent). - Add frozen-balance tracking for both accounts and portfolios, and enforce frozen amounts in balance-availability checks.
- Add compliance helper
is_holder_compliantand corresponding weights/benchmarks for the new API paths.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| primitives/src/traits.rs | Extends compliance trait with is_holder_compliant for sender/receiver-side checks. |
| precompiles/src/interfaces/FungibleAssetStub.sol | Updates Solidity interface/stub with new ERC-7943 functions/events. |
| pallets/weights/src/pallet_asset.rs | Adds weight functions for freezing, frozen-balance reads, and holder compliance checks. |
| pallets/precompiles/src/interface/mod.rs | Routes new IFungibleAsset calls and enforces read-only restrictions for setFrozenTokens. |
| pallets/precompiles/src/interface/erc7943.rs | Implements the new precompile entrypoints (freeze/getFrozenTokens/canSend/canReceive) with gas adjustment. |
| pallets/portfolio/src/lib.rs | Adds storage + helpers to track frozen balances at the portfolio level. |
| pallets/compliance-manager/src/lib.rs | Implements is_holder_compliant for side-specific compliance evaluation. |
| pallets/asset/src/lib.rs | Adds frozen-balance storage/extrinsic, updates balance checks to account for frozen amounts, and exposes holder-level compliance helper. |
| pallets/asset/src/benchmarking.rs | Adds benchmarks for the new weights and holder compliance paths. |
Suppressed comments (1)
pallets/asset/src/lib.rs:2972
- This helper’s doc comment says it applies to an account, but
asset_holdercan also be a portfolio. Consider updating the wording to avoid misleading future readers.
/// Sets the frozen transfer amount for an account on a given asset.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 13 changed files in this pull request and generated 1 comment.
Suppressed comments (3)
pallets/asset/src/lib.rs:3446
skip_locked_checknow also implicitly skips frozen balance checks, because it bypassesensure_sufficient_balance(which now accounts for frozen tokens). This can makeasset_transfer_reportincorrectly report that a transfer is possible even when the sender has insufficient unfrozen balance.
if Self::get_holders_balance(sender, asset_id) < transfer_value {
asset_transfer_errors.push(Error::<T>::InsufficientBalance.into());
}
} else {
if let Err(e) = Self::ensure_sufficient_balance(sender, asset_id, transfer_value, false)
pallets/portfolio/src/lib.rs:335
- New
PortfolioFrozenAssetsentries are not cleared indelete_portfolio(which currently removesPortfolioAssetBalances/PortfolioLockedAssetsprefixes). SincesetFrozenTokenscan set an amount greater than the portfolio’s balance, a portfolio can be “empty” but still have frozen entries, leaving stale state that could affect a later re-creation of the samePortfolioId. Consider clearingPortfolioFrozenAssets(and/or asserting it is empty) during deletion.
/// Amount of assets frozen in a portfolio.
#[pallet::storage]
pub type PortfolioFrozenAssets<T: Config> = StorageDoubleMap<
_,
Twox64Concat,
PortfolioId,
Blake2_128Concat,
AssetId,
Balance,
ValueQuery,
>;
pallets/asset/src/lib.rs:3771
ensure_sufficient_balancenow performs an additional storage read (FrozenBalance/PortfolioFrozenAssets) for non-controller transfers. Any dispatchables/RPC-weighted paths that rely onensure_sufficient_balance(e.g.base_transfer,asset_transfer_report_*, burns, locking flows) will have increased DB reads and should have their benchmark-derived weights regenerated to avoid undercharging.
let frozen_balance = Self::get_holders_frozen_balance(holder, asset_id);
let unavailable_balance = locked_balance.saturating_add(frozen_balance);
current_balance.saturating_sub(unavailable_balance)
}
|
|
||
| if !asset_details.asset_type.is_fungible() { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
Since the canSend and canReceive calls don't use an amount. This can also be used for NFTs. No need to restrict the asset type here. The ERC-20 precompile methods can still do the type check.
There was a problem hiding this comment.
We will be adding a precompile for NFTs too, so I think they can re-use this method.
changelog
new features
canSend, canReceive, setFrozenTokens, getFrozenTokensto the precompile interface