Skip to content
Snippets Groups Projects
  1. Mar 10, 2025
  2. Feb 26, 2025
  3. Feb 04, 2025
    • Alexander Theißen's avatar
      revive: Include immutable storage deposit into the contracts `storage_base_deposit` (#7230) · 4c28354b
      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: default avatarcmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
      Co-authored-by: default avatarPG Herveou <pgherveou@gmail.com>
      Co-authored-by: default avatarBastian Köcher <git@kchr.de>
      Co-authored-by: default avatarOliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
  4. Jan 29, 2025
  5. Jan 28, 2025
  6. Jan 15, 2025
  7. Dec 19, 2024
  8. Dec 18, 2024
  9. Dec 13, 2024
  10. Dec 12, 2024
  11. Dec 05, 2024
    • Alexander Theißen's avatar
      pallet-revive: Adjust error handling of sub calls (#6741) · 0d3d4502
      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: default avatarGitHub Action <action@github.com>
  12. Nov 29, 2024
    • Alexander Theißen's avatar
      pallet_revive: Switch to 64bit RISC-V (#6565) · 447902ef
      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 registe...
  13. Nov 19, 2024
  14. Nov 04, 2024
    • Cyrill Leutwiler's avatar
      [pallet-revive] rework balance transfers (#6187) · d69a80e6
      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: default avatarxermicus <cyrill@parity.io>
      Signed-off-by: default avatarCyrill Leutwiler <bigcyrill@hotmail.com>
      Co-authored-by: command-bot <>
      Co-authored-by: default avatarGitHub Action <action@github.com>
      Co-authored-by: default avatarPG Herveou <pgherveou@gmail.com>
  15. Oct 30, 2024
  16. Oct 29, 2024
  17. Oct 18, 2024
  18. Oct 05, 2024
    • Cyrill Leutwiler's avatar
      [pallet-revive] immutable data storage (#5861) · a8ebe9af
      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: default avatarCyrill Leutwiler <bigcyrill@hotmail.com>
      Signed-off-by: default avatarxermicus <cyrill@parity.io>
      Co-authored-by: command-bot <>
      Co-authored-by: default avatarAlexander Theißen <alex.theissen@me.com>
      Co-authored-by: default avatarPG Herveou <pgherveou@gmail.com>
  19. Sep 25, 2024
    • Cyrill Leutwiler's avatar
      [pallet-revive] last call return data API (#5779) · c77095f5
      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: default avatarCyrill Leutwiler <bigcyrill@hotmail.com>
      Signed-off-by: default avatarxermicus <cyrill@parity.io>
      Co-authored-by: command-bot <>
      Co-authored-by: default avatarPG Herveou <pgherveou@gmail.com>
  20. Sep 23, 2024
  21. Sep 13, 2024
  22. Sep 12, 2024
  23. Sep 08, 2024
    • PG Herveou's avatar
      [pallet-revive] update generic runtime types (#5608) · 868a36bd
      PG Herveou authored
      
      fix #5574
      
      - Use U256 instead of BalanceOf<T> and MomentOf<T> in Ext trait
      - Enforce H256 for T::Hash
      
      The Ext trait still depends on the associated type `T: Config`, we can
      look into refactoring it even more later but even in the current state
      it should not influence how the data is encoded / decoded between the
      contract and the host
      ```
      fn caller(&self) -> Origin<Self::T>;
      -> only use to extract the address of the caller 
      
      fn account_id(&self) -> &AccountIdOf<Self::T>;
       -> only used to expose the address or access the account_id internally   
      
      fn gas_meter(&self) -> &GasMeter<Self::T>;
      fn gas_meter_mut(&mut self) -> &mut GasMeter<Self::T>;
       -> encoding does not depend on T
      
      fn call_runtime(&self, call: <Self::T as Config>::RuntimeCall) -> DispatchResultWithPostInfo;
      -> Substrate specific, just an opaque blob of bytes from the contract's perspective
      
      fn contract_info(&mut self) -> &mut ContractInfo<Self::T>;
      fn transient_storage(&mut self) -> &mut TransientStorage<Self::T>;
      -> gated by #[cfg(any(test, feature = "runtime-benchmarks"))]
      ```
      
      ---------
      
      Co-authored-by: default avatarAlexander Theißen <alex.theissen@me.com>
  24. Sep 05, 2024
  25. Aug 23, 2024
    • Alexander Theißen's avatar
      Add initial version of `pallet_revive` (#5293) · 559fa1db
      Alexander Theißen authored
      This is a heavily modified and stripped down version of
      `pallet_contracts`. We decided to fork instead of extend the old pallet.
      Reasons for that are:
      
      - There is no benefit of supporting both on the same pallet as the
      intended payload for the new pallet (recompiled YUL) will be using a
      different ABI.
      - It is much easier since it allows us to remove all the code that was
      necessary to support Wasm and focus fully on running cross compiled YUL
      contracts.
      
      **The code is reviewable but can't be merged because it depends on an
      unreleased version of PolkaVM via git.**
      
      ## Current state
      
      All tests are passing and the code is not quick and dirty but written to
      last. The work is not finished, though. It is included in the
      `kitchensink-runtime` and a node can be built. However, we merge early
      in order to be able to start testing other components as early as
      possible.
      
      Outstanding changes are tracked here and will be merged separately:
      https://github.com/paritytech/polkadot-sdk/issues/5308
      
      ## Syscall Interface
      
      The syscall interface is best explored by generating the docs of this
      crate and looking at the `SyscallDoc` trait. Arguments are passed in
      registers a0-a5 in the order they are listed. If there are more than 6
      arguments (call, instantiate) a pointer to a packed struct of the
      arguments is expected as the only argument. I plan to create variants of
      those syscalls with less arguments specifically for YUL.
      
      Functions are just referenced by their name as ASCII within the PolkaVM
      container. Rather than by a syscall number as it was the case in the
      last implementation.
       
      
      ## Changes vs. `pallet_contracts`
      
      The changes are too numerous to list them all here. This is an
      incomplete list:
      
      - Use PolkaVM instead of wasmi to execute contracts
      - Made Runtime generic over a new `Memory` trait as we can't map memory
      directly on PolkaVM anymore
      - No static verification on code upload. Everything is a determinstic
      runtime failure
      - Removed all migrations and reset the pallet version
      - Removed the nonce storage item and instead use the deployers account
      nonce to generate a unique trie
      - We now bump the deployers account nonce on contract instantiation to
      they are bumped even within a batch transaction
      - Removed the instantiation nonce host function: We should add a new
      `instantiate` variant as a replacement for thos
      - ContractInfoOf of uses the indentity hasher now
      - Remove the determinism feature: User of that feature should switch to
      soft floats
      - The `unstable` attribute has been replaced by a `api_version`
      attribute to declare at which version an API became available
      	- leaving out that attribute makes the API effectively unstable
      - a new `api_version` field on the CodeInfo makes sure that old
      contracts can't access new APIs (necessary due to lack of static
      verification.
      - Added a `behaviour_version` field to CodeInfo that can used if we need
      to introduce breaking changes and keep the old behaviour for existing
      contracts
      - Unified storage vs. transient and fixed vs. variable sized keys all
      into one set of multiplexing host functions
      - Removed all contract observeable limits from the `Config` trait and
      instead hardcode them
      - Removed the Schedule
      - Removed all deprecated host functions
      - Simplify chain extension as preperation for making it a pre-compile
      
      ---------
      
      Co-authored-by: command-bot <>