Skip to main content

Smart Contracts Changelog - v7.4 to v8.0

This page covers pallet-revive, the smart contract pallet on Polymesh for v8. It is part of the v7.4 → v8.0 changelog. See Smart Contracts for the conceptual guide to Polymesh smart contracts, including PolkaVM vs EVM, the eth-rpc proxy, and how to build tooling against it.

Audience: smart contract developers and anyone building tooling that deploys or calls contracts on Polymesh.


Wasm/ink! contracts (pallet-contracts, polymesh_contracts) removed

The legacy Wasm/ink! contracts pallets — pallet-contracts and Polymesh's polymesh_contracts wrapper — are completely removed in v8. Neither pallet is part of the v8 runtime. pallet-revive is now the only smart contract pallet on Polymesh. This isn't a breaking removal in practice, since no contracts were ever deployed on Mainnet through pallet-contracts in the first place.

pallet-revive (new)

pallet-revive has no v7.4 equivalent — it is a new pallet in the mainnet runtime, from Polymesh's polkadot-sdk fork. It is not an EVM-only pallet: contracts run on PolkaVM, a RISC-V-based execution engine, and EVM compatibility (Solidity, standard Ethereum JSON-RPC tooling) is one supported way to interact with it, not the whole of what it does. The AllowEVMBytecode config flag (below) exists precisely because EVM bytecode support is a distinct, separately-toggleable layer on top of the core PolkaVM contract engine.

Address mapping

Polymesh accounts are 32-byte (AccountId32), not 20-byte Ethereum addresses, so the runtime uses AddressMapper = pallet_revive::AccountId32Mapper<Self>. Every existing Polymesh account already has an implicit, deterministic Ethereum address derived from it. Because deriving a 20-byte address from a 32-byte account is lossy, the pallet stores the original account (OriginalAccount) once an account opts in via the map_account call, making the mapping reversible. unmap_account reverses this.

Calls

pallet-revive exposes: eth_transact (submit a raw signed Ethereum transaction), call, instantiate, instantiate_with_code, eth_instantiate_with_code, eth_call, eth_substrate_call, upload_code, remove_code, set_code, map_account, unmap_account, and dispatch_as_fallback_account. These are the standard upstream pallet-revive calls — Polymesh has not added or removed any at the pallet level; the customization is entirely in runtime configuration (below).

Runtime configuration

Values set in impl pallet_revive::Config for Runtime:

SettingValueNotes
ChainId1_641_820 (Mainnet), 1_641_819 (Testnet), 1_641_818 (Develop)The EVM chain ID wallets and tooling (MetaMask, ethers.js) need to target the right network
NativeToEthRatio10^12Bridges Polymesh's 6-decimal POLYX to Ethereum's 18-decimal wei convention
AllowEVMBytecodetrueEVM bytecode execution is enabled, in addition to native PolkaVM contracts
GasScale100Scales EVM gas to Polymesh's weight-based fee model
Precompiles()No custom precompiles configured beyond the pallet's defaults
AddressMapperAccountId32MapperSee above

Errors

pallet-revive has no v7.4 equivalent to diff against, so this is its full error surface as of v8.0.0, grouped by theme:

Contract/code lookup

ErrorMeaning
ContractNotFoundNo contract at the specified address
CodeNotFoundNo code at the supplied code hash
CodeInfoNotFoundNo code info at the supplied code hash
CodeRejectedThe contract failed to compile or is missing required entry points
CodeInUseCode removal denied — still in use by at least one contract
DuplicateContractA contract with the same account ID already exists
RefcountOverOrUnderflowA code hash's reference count over- or under-flowed

Execution & gas

ErrorMeaning
OutOfGasThe contract exhausted its gas limit
MaxCallDepthReachedCall depth exceeded the schedule's limit
ContractTrappedThe contract trapped during execution
ExecutionFailedPolkaVM failed during execution, likely a malformed program
InvalidInstructionThe program contains an invalid instruction
InvalidJumpDynamic jump targeted an invalid destination
StackUnderflow / StackOverflowPopped from an empty stack / pushed onto a full one
BasicBlockTooLargeA basic block exceeds the allowed size
TransferFailedThe requested transfer failed, likely insufficient free balance
ContractRevertedThe contract completed but reverted its storage changes (extrinsic calls only — direct/RPC calls return Ok and require inspecting the flags)

Calls & reentrancy

ErrorMeaning
InvalidCallFlagsInvalid flag combination passed to a call/delegate-call
TerminatedWhileReentrantTermination denied while the contract is already on the call stack
TerminatedInConstructorA contract self-destructed in its constructor
InputForwardedInput was already forwarded by a prior call and is no longer available
ReentranceDeniedCalled a contract flagged as non-reentrant
ReenteredPalletA contract called back into pallet-revive from the runtime
PrecompileDelegateDeniedDelegate-called a precompile that disallows it

Storage & deposits

ErrorMeaning
OutOfBoundsA buffer outside sandbox memory was passed to a contract API
DecodingFailedInput failed to decode as the expected type
ValueTooLargeAn event body or storage item exceeds the size limit
StateChangeDeniedA state-modifying API was invoked in read-only mode
StorageDepositNotEnoughFundsInsufficient balance to pay the required storage deposit
StorageDepositLimitExhaustedMore storage was created than the deposit limit allows
StorageRefundNotEnoughFundsThe contract lacks balance to refund a storage deposit (should never happen — an accounting bug if seen)
StorageRefundLockedA lock on the contract's storage deposit prevents refunding it
OutOfTransientStorageNo room left in transient storage
InvalidStorageFlagsInvalid flags passed to a storage syscall
CallDataTooLarge / ReturnDataTooLargeCall data or return data exceeds the size limit
TooManyTopicsToo many topics passed to the event-deposit API

Code/blob validation

ErrorMeaning
InvalidScheduleInvalid schedule, e.g. zero weight for a basic operation
BlobTooLargeThe code blob exceeds the size limit
StaticMemoryTooLargeThe contract declares too much memory (read-only + read-write + stack)

Delegate dependencies

ErrorMeaning
MaxDelegateDependenciesReachedThe contract hit its maximum number of delegate dependencies
DelegateDependencyNotFoundThe dependency isn't in the contract's delegate-dependency list
DelegateDependencyAlreadyExistsAlready depends on the given delegate dependency
CannotAddSelfAsDelegateDependencyCan't add a contract's own code hash as its delegate dependency

Account mapping & syscalls

ErrorMeaning
AccountUnmappedAn AccountId32 account tried to interact without a mapping — call map_account first
AccountAlreadyMappedTried to map an account that's already mapped
InvalidSyscallCalled a syscall that doesn't exist at the current API level
InvalidImmutableAccessImmutable data can only be set on deploy and read on calls — set once, non-empty

EVM / Ethereum compatibility

ErrorMeaning
InvalidGenericTransactionThe transaction used to dry-run a contract is invalid
BalanceConversionFailedFailed to convert a U256 to a Balance
EvmConstructorNonEmptyDataEVM constructors don't accept separate data — input is part of the code blob
EvmConstructedFromHashEVM contracts can only be instantiated via code upload, not by code hash — there's no on-chain initcode
UnsupportedPrecompileAddressThe precompile address isn't supported
EcdsaRecoveryFailedECDSA public key recovery failed — likely a wrong recovery ID or signature
TxFeeOverdrawToo much deposit drawn from the shared tx-fee/deposit credit — the gas passed in the Ethereum transaction was too low

Running EVM JSON-RPC

pallet-revive is a Substrate pallet, not a full Ethereum node — it doesn't speak Ethereum's JSON-RPC (eth_call, eth_sendRawTransaction, eth_getBalance, etc.) directly. A separate proxy process, pallet-revive-eth-rpc (binary name eth-rpc), new in v8, translates standard Ethereum JSON-RPC into calls against the node. Run it alongside your node to point MetaMask, ethers.js, or other standard Ethereum tooling at Polymesh.

Migration checklist

  1. Target pallet-revive for all contract work on Polymesh.
  2. To interact with Polymesh contracts using standard Ethereum tooling, run the eth-rpc proxy alongside your node and use the correct ChainId for your network.
  3. Have users call map_account if you need a reversible EVM-address mapping for their Polymesh account (for example, to look up their address in a block explorer).
  4. Handle pallet-revive's error set (above) if you're building a wallet, indexer, or dApp framework against it — most are execution/storage-limit conditions specific to the PolkaVM environment.

pallet-revive is a wholesale-new pallet, so it isn't itemized in the Full Pallet API Reference (a name-based diff against v7.4) — this page and its Errors section above are the reference for it.