- Mar 10, 2025
-
-
Tiago Bandeira authored
-
- Mar 04, 2025
-
-
PG Herveou authored
In solidity `block.timestamp` should be expressed in seconds see https://docs.soliditylang.org/en/latest/units-and-global-variables.html#block-and-transaction-properties --------- Co-authored-by:
cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by:
Alexander Theißen <alex.theissen@me.com>
-
- Feb 26, 2025
-
-
PG Herveou authored
Add ECrecover 0x1 precompile and remove the unstable equivalent host function. - depend on https://github.com/paritytech/polkadot-sdk/pull/7676 --------- Co-authored-by:
cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by:
Alexander Theißen <alex.theissen@me.com>
-
- Feb 14, 2025
-
-
Alexander Theißen authored
Partly addresses https://github.com/paritytech/polkadot-sdk/issues/6157 The benchmarks measuring the impact of contract sizes on calling or instantiating a contract were bogus because they needed to be written in assembly in order to tightly control the basic block size. This fixes the benchmarks for: - call_with_code_per_byte - upload_code - instantiate_with_code And adds a new benchmark that accounts for the fact that the interpreter will always compile whole basic blocks: - basic_block_compilation After this PR only the weight we assign to instructions need to be addressed. --------- Co-authored-by:
cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by:
PG Herveou <pgherveou@gmail.com>
-
- Feb 04, 2025
-
-
Alexander Theißen authored
This PR is centered around a main fix regarding the base deposit and a bunch of drive by or related fixtures that make sense to resolve in one go. It could be broken down more but I am constantly rebasing this PR and would appreciate getting those fixes in as-one. **This adds a multi block migration to Westend AssetHub that wipes the pallet state clean. This is necessary because of the changes to the `ContractInfo` storage item. It will not delete the child storage though. This will leave a tiny bit of garbage behind but won't cause any problems. They will just be orphaned.** ## Record the deposit for immutable data into the `storage_base_deposit` The `storage_base_deposit` are all the deposit a contract has to pay for existing. It included the deposit for its own metadata and a deposit proportional (< 1.0x) to the size of its code. However, the immutable code size was not recorded there. This would lead to the situation where on terminate this portion wouldn't be refunded staying locked into the contract. It would also make the calculation of the deposit changes on `set_code_hash` more complicated when it updates the immutable data (to be done in #6985). Reason is because it didn't know how much was payed before since the storage prices could have changed in the mean time. In order for this solution to work I needed to delay the deposit calculation for a new contract for after the contract is done executing is constructor as only then we know the immutable data size. Before, we just charged this eagerly in `charge_instantiate` before we execute the constructor. Now, we merely send the ED as free balance before the constructor in order to create the account. After the constructor is done we calculate the contract base deposit and charge it. This will make `set_code_hash` much easier to implement. As a side effect it is now legal to call `set_immutable_data` multiple times per constructor (even though I see no reason to do so). It simply overrides the immutable data with the new value. The deposit accounting will be done after the constructor returns (as mentioned above) instead of when setting the immutable data. ## Don't pre-charge for reading immutable data I noticed that we were pre-charging weight for the max allowable immutable data when reading those values and then refunding after read. This is not necessary as we know its length without reading the storage as we store it out of band in contract metadata. This makes reading it free. Less pre-charging less problems. ## Remove delegate locking Fixes #7092 This is also in the spirit of making #6985 easier to implement. The locking complicates `set_code_hash` as we might need to block settings the code hash when locks exist. Check #7092 for further rationale. ## Enforce "no terminate in constructor" eagerly We used to enforce this rule after the contract execution returned. Now we error out early in the host call. This makes it easier to be sure to argue that a contract info still exists (wasn't terminated) when a constructor successfully returns. All around this his just much simpler than dealing this check. ## Moved refcount functions to `CodeInfo` They never really made sense to exist on `Stack`. But now with the locking gone this makes even less sense. The refcount is stored inside `CodeInfo` to lets just move them there. ## Set `CodeHashLockupDepositPercent` for test runtime The test runtime was setting `CodeHashLockupDepositPercent` to zero. This was trivializing many code paths and excluded them from testing. I set it to `30%` which is our default value and fixed up all the tests that broke. This should give us confidence that the lockup doeposit collections properly works. ## Reworked the `MockExecutable` to have both a `deploy` and a `call` entry point This type used for testing could only have either entry points but not both. In order to fix the `immutable_data_set_overrides` I needed to a new function `add_both` to `MockExecutable` that allows to have both entry points. Make sure to make use of it in the future :) --------- Co-authored-by: command-bot <> Co-authored-by:
cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by:
PG Herveou <pgherveou@gmail.com> Co-authored-by:
Bastian Köcher <git@kchr.de> Co-authored-by:
Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
-
- Feb 03, 2025
-
-
xermicus authored
This PR changes the behavior of `instantiate` when the resulting contract address already exists (because the caller tried to instantiate the same contract with the same salt multiple times): Instead of trapping the caller, return an error code. Solidity allows `catch`ing this, which doesn't work if we are trapping the caller. For example, the change makes the following snippet work: ```Solidity try new Foo{salt: hex"00"}() returns (Foo) { // Instantiation was successful (contract address was free and constructor did not revert) } catch { // This branch is expected to be taken if the instantiation failed because of a duplicate salt } ``` `revive` PR: https://github.com/paritytech/revive/pull/188 --------- Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Co-authored-by:
cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
-
- Jan 29, 2025
-
-
xermicus authored
This PR implements the block author API method. Runtimes ought to implement it such that it corresponds to the `coinbase` EVM opcode. --------- Signed-off-by:
xermicus <cyrill@parity.io> Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Co-authored-by: command-bot <> Co-authored-by:
Alexander Theißen <alex.theissen@me.com> Co-authored-by:
cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
-
- Jan 28, 2025
-
-
xermicus authored
This PR changes how we call runtime API methods with more than 6 arguments: They are no longer spilled to the stack but packed into registers instead. Pointers are 32 bit wide so we can pack two of them into a single 64 bit register. Since we mostly pass pointers, this technique effectively increases the number of arguments we can pass using the available registers. To make this work for `instantiate` too we now pass the code hash and the call data in the same buffer, akin to how the `create` family opcodes work in the EVM. The code hash is fixed in size, implying the start of the constructor call data. --------- Signed-off-by:
xermicus <cyrill@parity.io> Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Co-authored-by: command-bot <> Co-authored-by:
cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by:
Alexander Theißen <alex.theissen@me.com>
-
- Jan 24, 2025
-
-
Alexander Theißen authored
This regression was introduced with some of the recent PRs. Regression fixed and test added. --------- Co-authored-by:
cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
-
- Jan 17, 2025
-
-
Alexander Theißen authored
Update to PolkaVM `0.19`. This version renumbers the opcodes in order to be in-line with the grey paper. Hopefully, for the last time. This means that it breaks existing contracts. --------- Signed-off-by:
xermicus <cyrill@parity.io> Co-authored-by: command-bot <> Co-authored-by:
xermicus <cyrill@parity.io>
-
- Jan 15, 2025
-
-
Michael Müller authored
Closes https://github.com/paritytech/polkadot-sdk/issues/6891. cc @athei @xermicus @pgherveou
-
PG Herveou authored
Remove the `debug_buffer` feature --------- Co-authored-by: command-bot <> Co-authored-by:
Cyrill Leutwiler <cyrill@parity.io> Co-authored-by:
Alexander Theißen <alex.theissen@me.com>
-
Alexandre R. Baldé authored
Closes #6846 . --------- Signed-off-by:
xermicus <cyrill@parity.io> Co-authored-by: command-bot <> Co-authored-by:
Alexander Theißen <alex.theissen@me.com> Co-authored-by:
xermicus <cyrill@parity.io>
-
Michael Müller authored
Closes https://github.com/paritytech/polkadot-sdk/issues/6767. The return type of the host function `caller_is_root` was denoted as `u32` in `pallet_revive_uapi`. This PR fixes the return type to `bool`. As a drive-by, the PR re-exports `pallet_revive::exec::Origin` to extend what can be tested externally. --------- Co-authored-by:
Cyrill Leutwiler <bigcyrill@hotmail.com>
-
- Dec 20, 2024
-
-
Xavier Lau authored
It doesn't make sense to only reorder the features array. For example: This makes it hard for me to compare the dependencies and features, especially some crates have a really really long dependencies list. ```toml [dependencies] c = "*" a = "*" b = "*" [features] std = [ "a", "b", "c", ] ``` This makes my life easier. ```toml [dependencies] a = "*" b = "*" c = "*" [features] std = [ "a", "b", "c", ] ``` --------- Co-authored-by:
Bastian Köcher <git@kchr.de> Co-authored-by: command-bot <>
-
- Dec 19, 2024
-
-
Cyrill Leutwiler authored
This PR implements the base fee syscall API method. Currently this is implemented as a compile time constant in the revive compiler, returning 0. However, since this is an opocde, if we ever need to implement it for compatibility reasons with [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md), it would break already deployed contracts. Thus we provide a syscall method instead. --------- Signed-off-by:
xermicus <cyrill@parity.io> Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Co-authored-by: command-bot <>
-
Cyrill Leutwiler authored
This PR implements the EVM gas price syscall API method. Currently this is a compile time constant in revive, but in the EVM it is an opcode. Thus we should provide an opcode for this in the pallet. --------- Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Signed-off-by:
xermicus <cyrill@parity.io> Co-authored-by: command-bot <>
-
- Dec 18, 2024
-
-
Alexander Theißen authored
- Fixed failing docs.rs build for `pallet-revive-uapi` by fixing a wring attribute in the manifest (we were using `default-target` instead of `targets`) - Removed the macros defining host functions because the cfg attributes introduced in #6866 won't work on them - Added an docs.rs specific attribute so that the `unstable-hostfn` feature tag will show up on the functions that are guarded behind it. --------- Co-authored-by: command-bot <>
-
Cyrill Leutwiler authored
Update to the latest polkavm version, containing a linker fix I need for revive. --------- Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Signed-off-by:
xermicus <cyrill@parity.io> Co-authored-by: command-bot <>
-
Cyrill Leutwiler authored
This PR implements the gas limit API, returning the maximum ref_time per block. Solidity contracts only know a single weight dimension and can use this method to get the block ref_time limit. --------- Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Signed-off-by:
xermicus <cyrill@parity.io> Co-authored-by: command-bot <>
-
Cyrill Leutwiler authored
Call data, return data and code sizes can never exceed `u32::MAX`; they are also not generic. Hence we know that they are guaranteed to always fit into a 64bit register and `revive` can just zero extend them into a 256bit integer value. Which is slightly more efficient than passing them on the stack. --------- Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Signed-off-by:
xermicus <cyrill@parity.io> Co-authored-by: command-bot <> Co-authored-by:
Alexander Theißen <alex.theissen@me.com>
-
Cyrill Leutwiler authored
This PR implements the ref_time_left API method. Solidity knows only a single "gas" dimension; Solidity contracts will use this to query the gas left. --------- Signed-off-by:
xermicus <cyrill@parity.io> Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Co-authored-by: command-bot <>
-
Cyrill Leutwiler authored
This PR implements the call data copy API by adjusting the input method. Closes #6770 --------- Signed-off-by:
xermicus <cyrill@parity.io> Co-authored-by: command-bot <>
-
- Dec 13, 2024
-
-
davidk-pt authored
Follow up refactor to https://github.com/paritytech/polkadot-sdk/pull/6844#pullrequestreview-2497225717 I still need to finish adding `#[cfg(feature = "unstable-api")]` to the rest of the tests and make sure all tests pass, I want to make sure I'm moving into right direction first @athei @xermicus --------- Co-authored-by:
DavidK <davidk@parity.io> Co-authored-by:
Alexander Theißen <alex.theissen@me.com>
-
Cyrill Leutwiler authored
This PR adds an API method to query the contract call data input size. Part of #6770 --------- Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Co-authored-by: command-bot <> Co-authored-by:
Alexander Theißen <alex.theissen@me.com>
-
- Dec 12, 2024
-
-
Cyrill Leutwiler authored
This PR implements the call data load API akin to [how it works on ethereum](https://www.evm.codes/?fork=cancun#35). There will also be a second PR to adjust the input function to resemble the call data copy opcode on EVM. --------- Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Co-authored-by: command-bot <>
-
- Dec 05, 2024
-
-
Alexander Theißen authored
We were trapping the host context in case a sub call was exhausting the storage deposit limit set for this sub call. This prevents the caller from handling this error. In this PR we added a new error code that is returned when either gas or storage deposit limit is exhausted by the sub call. We also remove the longer used `NotCallable` error. No longer used because this is no longer an error: It will just be a balance transfer. We also make `set_code_hash` infallible to be consistent with other host functions which just trap on any error condition. --------- Co-authored-by:
GitHub Action <action@github.com>
-
- Nov 29, 2024
-
-
Alexander Theißen authored
This PR updates pallet_revive to the newest PolkaVM version and adapts the test fixtures and syscall interface to work under 64bit. Please note that after this PR no 32bit contracts can be deployed (they will be rejected at deploy time). Pre-deployed 32bit contracts are now considered defunct since we changes how parameters are passed for functions with more than 6 arguments. ## Fixtures The fixtures are now built for the 64bit target. I also removed the temporary directory mechanism that triggered a full rebuild every time. It also makes it easier to find the compiled fixtures since they are now always in `target/pallet-revive-fixtures`. ## Syscall interface ### Passing pointer Registers and pointers are now 64bit wide. This allows us to pass u64 arguments in a single register. Before we needed two registers to pass them. This means that just as before we need one register per pointer we pass. We keep pointers as `u32` argument by truncating the register. This is done since the memory space of PolkaVM is 32bit. ### Functions with more than 6 arguments We only have 6 registers to pass arguments. This is why we pass a pointer to a struct when we need more than 6. Before this PR we expected a packed struct and interpreted it as SCALE encoded tuple. However, this was buggy because the `MaxEncodedLen` returned something that was larger than the packed size of the structure. This wasn't a problem before. But now the memory space changed in a way that things were placed at the edges of the memory space and those extra bytes lead to an out of bound access. This is why this PR drops SCALE and expects the arguments to be passed as a pointer to a `C` aligned struct. This avoids unaligned accesses. However, revive needs to adapt its codegen to properly align the structure fields. ## TODO - [ ] Add multi block migration that wipes all existing contracts as we made breaking changes to the syscall interface --------- Co-authored-by:
GitHub Action <action@github.com>
-
- Nov 19, 2024
-
-
Ermal Kaleci authored
Enhance the `delegate_call` function to accept an `address` target parameter instead of a `code_hash`. This allows direct identification of the target contract using the provided address. Additionally, introduce parameters for specifying a customizable `ref_time` limit and `proof_size` limit, thereby improving flexibility and control during contract interactions. --------- Co-authored-by:
Alexander Theißen <alex.theissen@me.com>
-
- Nov 04, 2024
-
-
Cyrill Leutwiler authored
This PR removes the `transfer` syscall and changes balance transfers to make the existential deposit (ED) fully transparent for contracts. The `transfer` API is removed since there is no corresponding EVM opcode and transferring via a call introduces barely any overhead. We make the ED transparent to contracts by transferring the ED from the call origin to nonexistent accounts. Without this change, transfers to nonexistant accounts will transfer the supplied value minus the ED from the contracts viewpoint, and consequentially fail if the supplied value lies below the ED. Changing this behavior removes the need for contract code to handle this rather annoying corner case and aligns better with the EVM. The EVM charges a similar deposit from the gas meter, so transferring the ED from the call origin is practically the same as the call origin pays for gas. --------- Signed-off-by:
xermicus <cyrill@parity.io> Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Co-authored-by: command-bot <> Co-authored-by:
GitHub Action <action@github.com> Co-authored-by:
PG Herveou <pgherveou@gmail.com>
-
- Oct 30, 2024
-
-
Cyrill Leutwiler authored
- Bound T::Hash to H256 - Implement the block hash API --------- Signed-off-by:
xermicus <cyrill@parity.io> Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Co-authored-by: command-bot <> Co-authored-by:
GitHub Action <action@github.com>
-
Cyrill Leutwiler authored
This PR implements the contract API to query the code size of a given address. --------- Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Signed-off-by:
xermicus <cyrill@parity.io> Co-authored-by:
GitHub Action <action@github.com> Co-authored-by: command-bot <> Co-authored-by:
PG Herveou <pgherveou@gmail.com>
-
- Oct 29, 2024
-
-
Alexander Theißen authored
This removes the need to use a custom toolchain to build the contract test fixtures. Instead, we supply a custom target and use the currently in use upstream toolchain. --------- Co-authored-by:
Jan Bujak <jan@parity.io> Co-authored-by:
Cyrill Leutwiler <cyrill@parity.io> Co-authored-by: command-bot <>
-
Cyrill Leutwiler authored
Implement a syscall to retreive the transaction origin. --------- Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Signed-off-by:
xermicus <cyrill@parity.io> Co-authored-by:
GitHub Action <action@github.com> Co-authored-by: command-bot <> Co-authored-by:
Alexander Theißen <alex.theissen@me.com>
-
- Oct 22, 2024
-
-
PG Herveou authored
This PR introduces the necessary changes to pallet-revive for integrating with our Ethereum JSON-RPC. The RPC proxy itself will be added in a follow up. ## Changes - A new pallet::call `Call::eth_transact`. This is used as a wrapper to accept unsigned Ethereum transaction, valid call will be routed to `Call::call` or `Call::instantiate_with_code` - A custom UncheckedExtrinsic struct, that wraps the generic one usually and add the ability to check eth_transact calls sent from an Ethereum JSON-RPC proxy. - Generated types and traits to support implementing a JSON-RPC Ethereum proxy. ## Flow Overview: - A user submits a transaction via MetaMask or another Ethereum-compatible wallet. - The proxy dry run the transaction and add metadata to the call (gas limit in Weight, storage deposit limit, and length of bytecode and constructor input for contract instantiation) - The raw transaction, along with the additional metadata, is submitted to the node as an unsigned extrinsic. - On the runtime, our custom UncheckedExtrinsic define a custom Checkable implementation that converts the unsigned extrinsics into checked one - It recovers the signer - validates the payload, and injects signed extensions, allowing the system to increment the nonce and charge the appropriate fees. - re-route the call to pallet-revive::Call::call or pallet-revive::Call::instantiateWithCode ## Dependencies - https://github.com/koute/polkavm/pull/188 ## Follow up PRs - #5926 - #6147 (previously #5953) - #5502 --------- Co-authored-by:
Alexander Theißen <alex.theissen@me.com> Co-authored-by:
Cyrill Leutwiler <cyrill@parity.io>
-
- Oct 18, 2024
-
-
Ermal Kaleci authored
# Description Update `ext_code_hash` to match [EIP-1052](https://eips.ethereum.org/EIPS/eip-1052) specs. Since all possible results are written into output pointer then there's no need for a return value. https://github.com/paritytech/revive/pull/77
-
- Oct 07, 2024
-
-
Alexander Theißen authored
This PR adds **static** validation that prevents upload of code that: 1) Contains basic blocks larger than the specified limit (currently `200`) 2) Contains invalid instructions 3) Uses the `sbrk` instruction Doing that statically at upload time (instead of at runtime) allows us to change the basic block limit or add instructions later without worrying about breaking old code. This is well worth the linear scan of the whole blob on deployment in my opinion. Please note that those checks are not applied when existing code is just run (hot path). Also some drive by fixes: - Remove superflous `publish = true` - Abort fixture build on warning and fix existing warnings - Re-enable optimizations in fixture builds (should be fixed now in PolkaVM) - Disable stripping for fixture builds (maybe we can get some line information on trap via `RUST_LOG`) --------- Co-authored-by: command-bot <> Co-authored-by:
PG Herveou <pgherveou@gmail.com>
-
- Oct 05, 2024
-
-
Cyrill Leutwiler authored
This PR introduces the concept of immutable storage data, used for [Solidity immutable variables](https://docs.soliditylang.org/en/latest/contracts.html#immutable). This is a minimal implementation. Immutable data is attached to a contract; to keep `ContractInfo` fixed in size, we only store the length there, and store the immutable data in a dedicated storage map instead. Which comes at the cost of requiring an additional storage read (costly) for contracts using this feature. We discussed more optimal solutions not requiring any additional storage accesses internally, but they turned out to be non-trivial to implement. Another optimization benefiting multiple calls to the same contract in a single call stack would be to cache the immutable data in `Stack`. However, this potential creates a DOS vulnerability (the attack vector is to call into as many contracts in a single stack as possible, where they all have maximum immutable data to fill the cache as efficiently as possible). So this either has to be guaranteed to be a non-issue by limits, or, more likely, to have some logic to bound the cache. Eventually, we should think about introducing the concept of warm and cold storage reads (akin to EVM). Since immutable variables are commonly used in contracts, this change is blocking our initial launch and we should only optimize it properly in follow-ups. This PR also disables the `set_code_hash` API (which isn't usable for Solidity contracts without pre-compiles anyways). With immutable storage attached to contracts, we now want to run the constructor of the new code hash to collect the immutable data during `set_code_hash`. This will be implemented in a follow up PR. --------- Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Signed-off-by:
xermicus <cyrill@parity.io> Co-authored-by: command-bot <> Co-authored-by:
Alexander Theißen <alex.theissen@me.com> Co-authored-by:
PG Herveou <pgherveou@gmail.com>
-
- Sep 25, 2024
-
-
Cyrill Leutwiler authored
This PR introduces 2 new syscalls: `return_data_size` and `return_data_copy`, resembling the semantics of the EVM `RETURNDATASIZE` and `RETURNDATACOPY` opcodes. The ownership of `ExecReturnValue` (the return data) has moved to the `Frame`. This allows implementing the new contract API functionality in ext with no additional copies. Returned data is passed via contract memory, memory is (will be) metered, hence the amount of returned data can not be statically known, so we should avoid storing copies of the returned data if we can. By moving the ownership of the exectuables return value into the `Frame` struct we achieve this. A zero-copy implementation of those APIs would be technically possible without that internal change by making the callsite in the runtime responsible for moving the returned data into the frame after any call. However, resetting the stored output needs to be handled in ext, since plain transfers will _not_ affect the stored return data (and we don't want to handle this special call case inside the `runtime` API). This has drawbacks: - It can not be tested easily in the mock. - It introduces an inconsistency where resetting the stored output is handled in ext, but the runtime API is responsible to store it back correctly after any calls made. Instead, with ownership of the data in `Frame`, both can be handled in a single place. Handling both in `fn run()` is more natural and leaves less room for runtime API bugs. The returned output is reset each time _before_ running any executable in a nested stack. This change should not incur any overhead to the overall memory usage as _only_ the returned data from the last executed frame will be kept around at any time. --------- Signed-off-by:
Cyrill Leutwiler <bigcyrill@hotmail.com> Signed-off-by:
xermicus <cyrill@parity.io> Co-authored-by: command-bot <> Co-authored-by:
PG Herveou <pgherveou@gmail.com>
-
- Sep 23, 2024
-
-
Cyrill Leutwiler authored
This PR adds the EVM chain ID to Config as well as a corresponding runtime API so contracts can query it. Related issue: https://github.com/paritytech/revive/issues/44 --------- Signed-off-by:
xermicus <cyrill@parity.io> Co-authored-by: command-bot <>
-