Skip to content

Commit 89766d6

Browse files
committed
fix: evm vs polkavm devs disclaimers
1 parent 7bf160a commit 89766d6

File tree

2 files changed

+46
-4
lines changed

2 files changed

+46
-4
lines changed

llms.txt

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24410,15 +24410,16 @@ While PolkaVM maintains high-level compatibility with Solidity, several low-leve
2441024410

2441124411
### Contract Code Structure
2441224412

24413-
PolkaVM's contract runtime does not differentiate between runtime code and deploy (constructor) code. Instead, both are emitted into a single PolkaVM contract code blob and live on-chain. Therefore, in EVM terminology, the deploy code equals the runtime code.
24413+
PolkaVM's contract runtime does not differentiate between runtime code and deploy (constructor) code. Instead, both are emitted into a single PolkaVM contract code blob and live on-chain. Therefore, in EVM terminology, the deploy code equals the runtime code. For most standard Solidity contracts, this is transparent. However, if you are analyzing raw bytecode or building tools that expect separate deploy and runtime sections, you'll need to adjust for this unified structure.
2441424414

24415-
In constructor code, the `codesize` instruction returns the call data size instead of the actual code blob size, which differs from standard EVM behavior.
24415+
In the constructor code, the `codesize` instruction returns the call data size instead of the actual code blob size, which differs from standard EVM behavior. Developers might consider that the constructor logic uses codesize to inspect the deployed contract's size (e.g., for self-validation or specific deployment patterns); this will return an incorrect value on PolkaVM. Re-evaluate such logic or use alternative methods to achieve your goal.
2441624416

2441724417
### Solidity-Specific Differences
2441824418

2441924419
Solidity constructs behave differently under PolkaVM:
2442024420

2442124421
- **`address.creationCode`** - returns the bytecode keccak256 hash instead of the actual creation code, reflecting PolkaVM's hash-based code referencing system
24422+
- If your contract relies on `address.creationCode` to verify or interact with the full raw bytecode of a newly deployed contract, this will not work as expected. You will receive a hash, not the code itself. This typically affects highly specialized factory contracts or introspection tools
2442224423

2442324424
### YUL Function Translation Differences
2442424425

@@ -24431,17 +24432,22 @@ The following YUL functions exhibit notable behavioral differences in PolkaVM:
2443124432
- Accessing memory offsets larger than the buffer size traps the contract with an `OutOfBound` error
2443224433
- Compiler optimizations may eliminate unused memory operations, potentially causing `msize` to differ from EVM behavior
2443324434

24435+
For Solidity developers, the compiler generally handles memory efficiently within this 64KB limit. However, if you are writing low-level YUL assembly and perform direct memory manipulations, you must respect the 64KB buffer limit. Attempting to access memory outside this range will cause your transaction to revert. Be aware that `msize` might not always reflect the exact EVM behavior if compiler optimizations occur.
24436+
2443424437
- **Call Data Operations:**
2443524438

2443624439
- **`calldataload`, `calldatacopy`** - in constructor code, the offset parameter is ignored and these functions always return `0`, diverging from EVM behavior where call data represents constructor arguments
24440+
- If your constructor logic in YUL assembly attempts to read constructor arguments using `calldataload` or `calldatacopy` with specific offsets, this will not yield the expected constructor arguments. Instead, these functions will return `zeroed` values. Standard Solidity constructors are handled correctly by the compiler, but manual YUL assembly for constructor argument parsing will need adjustment
2443724441

2443824442
- **Code Operations:**
2443924443

2444024444
- **`codecopy`** - only supported within constructor code, reflecting PolkaVM's different approach to code handling and the unified code blob structure
24445+
- If your contracts use `codecopy` (e.g., for self-modifying code or inspecting other contract's runtime bytecode) outside of the constructor, this will not be supported and will likely result in a compile-time error or runtime trap. This implies that patterns like dynamically generating or modifying contract code at runtime are not directly feasible with codecopy on PolkaVM
2444124446

2444224447
- **Control Flow:**
2444324448

2444424449
- **`invalid`** - traps the contract execution but does not consume remaining gas, unlike EVM where it consumes all available gas
24450+
- While `invalid` still reverts the transaction, the difference in gas consumption could subtly affect very specific error handling or gas accounting patterns that rely on `invalid` to consume all remaining gas. For most error scenarios, `revert()` is the standard and recommended practice
2444524451

2444624452
- **Cross-Contract Calls:**
2444724453

@@ -24451,6 +24457,8 @@ The following YUL functions exhibit notable behavioral differences in PolkaVM:
2445124457
- The compiler detects `address payable.{send,transfer}` patterns and disables call reentrancy as a protective heuristic
2445224458
- Using `address payable.{send,transfer}` is already deprecated; PolkaVM will provide dedicated precompiles for safe balance transfers
2445324459

24460+
The traditional EVM pattern of limiting gas in cross-contract calls (especially with the 2300 gas stipend for send/transfer) does not provide reentrancy protection on PolkaVM. Developers must explicitly implement reentrancy guards (e.g., using a reentrancy lock mutex) in their Solidity code when making external calls to untrusted contracts. Relying on gas limits alone for reentrancy prevention is unsafe and will lead to vulnerabilities on PolkaVM.
24461+
2445424462
!!! warning
2445524463
The 2300 gas stipend that is provided by solc for address payable.{send, transfer} calls offers no reentrancy protection in PolkaVM. While the compiler attempts to detect and mitigate this pattern, developers should avoid these deprecated functions.
2445624464

@@ -24463,6 +24471,8 @@ The following YUL functions exhibit notable behavioral differences in PolkaVM:
2446324471

2446424472
PolkaVM translates `dataoffset` and `datasize` instructions to handle contract hashes instead of contract code, enabling seamless use of the `new` keyword in Solidity. However, this translation may fail for contracts creating other contracts within `assembly` blocks.
2446524473

24474+
If you use the Solidity `new` keyword to deploy contracts, the Revive compiler handles this transparently. However, if you are creating contracts manually in YUL assembly using `create` or `create2` opcodes, you must provide the code hash of the contract to be deployed, not its raw bytecode. Attempting to pass raw bytecode will fail. This fundamentally changes how manual contract creation is performed in assembly.
24475+
2446624476
!!! warning
2446724477
Avoid using `create` family opcodes for manual deployment crafting in `assembly` blocks. This pattern is discouraged due to translation complexity and offers no gas savings benefits in PolkaVM.
2446824478

@@ -24471,30 +24481,41 @@ The following YUL functions exhibit notable behavioral differences in PolkaVM:
2447124481
- **`dataoffset`** - returns the contract hash instead of code offset, aligning with PolkaVM's hash-based code referencing
2447224482
- **`datasize`** - returns the constant contract hash size (32 bytes) rather than variable code size
2447324483

24484+
These changes are primarily relevant for low-level YUL assembly developers who are trying to inspect or manipulate contract code directly. `dataoffset` will provide a hash, not a memory offset to the code, and datasize will always be 32 bytes (the size of a hash). This reinforces that direct manipulation of contract bytecode at runtime, as might be done in some EVM patterns, is not supported.
24485+
2447424486
- **Resource Queries:**
2447524487

2447624488
- **`gas`, `gaslimit`** - return only the `ref_time` component of PolkaVM's multi-dimensional weight system, providing the closest analog to traditional gas measurements
24489+
- While `gas` and `gaslimit` still provide a useful metric, consider they represent `ref_time` (computation time) only. If your contract logic depends on precise knowledge of other resource costs (like `proof_size` or `storage_deposit`), you won't get that information from these opcodes. You'll need to use future precompiles for full multi-dimensional resource queries
2447724490

2447824491
- **Blockchain State:**
2447924492

2448024493
- **`prevrandao`, `difficulty`** - both translate to a constant value of `2500000000000000`, as PolkaVM doesn't implement Ethereum's difficulty adjustment or randomness mechanisms
24494+
- If your Solidity contract relies on `block.difficulty` (or its equivalent YUL opcode `difficulty`) for randomness generation or any logic tied to Ethereum's proof-of-work difficulty, this will not provide true randomness on PolkaVM. The value will always be constant. Developers needing on-chain randomness should utilize Polkadot's native randomness sources or dedicated VRF (Verifiable Random Function) solutions if available.
2448124495

2448224496
### Unsupported Operations
2448324497

2448424498
Several EVM operations are not supported in PolkaVM and produce compile-time errors:
2448524499

2448624500
- **`pc`, `extcodecopy`** - these operations are EVM-specific and have no equivalent functionality in PolkaVM's RISC-V architecture
24501+
- Any Solidity contracts that utilize inline assembly to interact with `pc` (program counter) or `extcodecopy` will fail to compile or behave unexpectedly. This means patterns involving introspection of the current execution location or copying external contract bytecode at runtime are not supported
2448724502
- **`blobhash`, `blobbasefee`** - related to Ethereum's rollup model and blob data handling, these operations are unnecessary given Polkadot's superior rollup architecture
24503+
- If you are porting contracts designed for Ethereum's EIP-4844 (proto-danksharding) and rely on these blob-related opcodes, they will not be available on PolkaVM.
2448824504
- **`extcodecopy`, `selfdestruct`** - these deprecated operations are not supported and generate compile-time errors
24505+
- The `selfdestruct` opcode, which allowed contracts to remove themselves from the blockchain, is not supported. Contracts cannot be self-destroyed on PolkaVM. This affects contract upgradeability patterns that rely on self-destruction and redeployment. Similarly, `extcodecopy` is unsupported, impacting contracts that intend to inspect or copy the bytecode of other deployed contracts.
2448924506

2449024507
### Compilation Pipeline Considerations
2449124508

2449224509
PolkaVM processes YUL IR exclusively, meaning all contracts exhibit behavior consistent with Solidity's `via-ir` compilation mode. Developers familiar with the legacy compilation pipeline should expect [IR-based codegen behavior](https://docs.soliditylang.org/en/latest/ir-breaking-changes.html){target=\_blank} when working with PolkaVM contracts.
2449324510

24511+
If you've previously worked with older Solidity compilers that did not use the `via-ir` pipeline by default, you might observe subtle differences in compiled bytecode size or gas usage. It's recommended to familiarize yourself with Solidity's IR-based codegen behavior, as this is the standard for PolkaVM.
24512+
2449424513
### Memory Pointer Limitations
2449524514

2449624515
YUL functions accepting memory buffer offset pointers or size arguments are limited by PolkaVM's 32-bit pointer size. Supplying values above `2^32-1` will trap the contract immediately. The Solidity compiler typically generates valid memory references, making this primarily a concern for low-level assembly code.
2449724516

24517+
For standard Solidity development, this limitation is unlikely to be hit as the compiler handles memory addresses correctly within typical contract sizes. However, if you are writing extremely large contracts using YUL assembly that manipulate memory addresses manually and extensively, ensure that your memory offsets and sizes do not exceed PolkaVM's **fixed 64KB memory limit per contract**. While the YUL functions might accept 32-bit pointers (up to 2^32-1), attempting to access memory beyond the allocated 64KB buffer will trap the contract immediately.
24518+
2449824519
These incompatibilities reflect the fundamental architectural differences between EVM and PolkaVM while maintaining high-level Solidity compatibility. Most developers using standard Solidity patterns will encounter no issues, but those working with assembly code or advanced contract patterns should carefully review these differences during migration.
2449924520
--- END CONTENT ---
2450024521

0 commit comments

Comments
 (0)