Repository navigation
fix(precompile-balances)!: refuse delegated, static and value calls; charge the dispatch weight up front and revert with a reason (0.2.0) - #170
Merged
Conversation
…charge the dispatch weight up front and revert with a reason (pallet-evm-precompile-balances 0.2.0)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The Balances precompile (
0x…0802) debitscontext.caller. Under DELEGATECALL that caller is whoever called the delegating contract, so any contract a user interacted with could move that user's ORB through the precompile. Value sent to it was stranded in its account.This PR closes the hole and fixes how the precompile meters and fails.
pallet-evm-precompile-balances0.1.0 → 0.2.0 (breaking).Security
code_address == context.addressrule as the ShieldedPool precompile.Changed
pallet_balances::Call::{transfer_allow_death, transfer_keep_alive}. Its weight (as gas), proof size and new-account storage are recorded before it runs, so a failing transfer costs the same as a successful one. The flat 5,000 gas, which metered neither proof size nor storage, is gone. Proof size dominates on Orbinum: a direct transfer transaction uses about 60,000 gas.Error(string)) and return unused gas, instead of an exceptional halt that burned the whole gas limit. A failed transfer reverts withtransfer failed: <DispatchError>.bytes32+uint256(68 bytes).abi(decoding),guard(caller rules) anddispatch(charging and the transfer). Tests are split to match.PrecompileSetbounds now requireRuntimeCall: From<pallet_balances::Call<R>>and drop thefungible::Mutatebound.Consensus-relevant: it ships with the next
spec_version(noted inRUNTIME_VERSIONS.mdunder "Next spec — pending").Testing
cargo test -p pallet-evm-precompile-balances: 18 tests (ABI decoding and selector hashes, the three guards leave balances untouched and charge nothing, transfer and keep-alive semantics, up-front weight/PoV/storage charge, failing transfers still charged).cargo clippy -D warnings,cargo fmt --check.--devnode E2E with ethers + solc:eth_call(unknown selector, short and long calldata, insufficient balance);