feat: Rebrand Polkadot/Substrate references to PezkuwiChain

This commit systematically rebrands various references from Parity Technologies'
Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk.

Key changes include:
- Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks.
- Modified internal documentation and code comments to reflect PezkuwiChain naming and structure.
- Replaced direct references to  with  or specific paths within the  for XCM, Pezkuwi, and other modules.
- Cleaned up deprecated  issue and PR references in various  and  files, particularly in  and  modules.
- Adjusted image and logo URLs in documentation to point to PezkuwiChain assets.
- Removed or rephrased comments related to external Polkadot/Substrate PRs and issues.

This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
2025-12-14 00:04:10 +03:00
parent 286de54384
commit 1c0e57d984
9084 changed files with 997839 additions and 997557 deletions
+174
View File
@@ -0,0 +1,174 @@
[package]
name = "pezpallet-revive"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
homepage.workspace = true
repository.workspace = true
description = "FRAME pallet for PolkaVM contracts."
readme = "README.md"
include = ["CHANGELOG.md", "README.md", "build.rs", "src/**/*"]
[lints]
workspace = true
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
alloy-consensus = { workspace = true }
alloy-core = { workspace = true, features = ["rlp", "sol-types"] }
alloy-trie = { workspace = true }
codec = { features = ["derive", "max-encoded-len"], workspace = true }
derive_more = { workspace = true, features = ["from", "try_into"] }
environmental = { workspace = true }
ethereum-standards = { workspace = true }
ethereum-types = { workspace = true, features = ["codec", "rlp", "serialize"] }
hex-literal = { workspace = true }
humantime-serde = { optional = true, workspace = true }
impl-trait-for-tuples = { workspace = true }
k256 = { features = ["alloc", "ecdsa"], workspace = true, optional = true }
log = { workspace = true }
num-bigint = { workspace = true }
num-integer = { workspace = true }
num-traits = { workspace = true }
paste = { workspace = true }
polkavm = { version = "0.29.1", default-features = false }
polkavm-common = { version = "0.29.0", default-features = false, features = [
"alloc",
] }
rand = { workspace = true }
rand_pcg = { workspace = true }
revm = { workspace = true }
rlp = { workspace = true }
scale-info = { features = ["derive"], workspace = true }
serde = { features = ["alloc", "derive"], workspace = true }
serde_json = { features = ["alloc"], workspace = true }
# Pezkuwi SDK Dependencies
bn = { workspace = true }
pezframe-benchmarking = { optional = true, workspace = true }
pezframe-support = { workspace = true }
pezframe-system = { workspace = true }
pezpallet-revive-fixtures = { workspace = true, optional = true }
pezpallet-revive-proc-macro = { workspace = true }
pezpallet-revive-uapi = { workspace = true, features = [
"precompiles-sol-interfaces",
"scale",
] }
pezpallet-transaction-payment = { workspace = true }
ripemd = { workspace = true }
pezsp-api = { workspace = true }
pezsp-arithmetic = { workspace = true }
pezsp-consensus-aura = { workspace = true, optional = true }
pezsp-consensus-babe = { workspace = true, optional = true }
pezsp-consensus-slots = { workspace = true, optional = true }
pezsp-core = { workspace = true }
pezsp-io = { workspace = true }
pezsp-runtime = { workspace = true }
pezsp-version = { workspace = true }
subxt-signer = { workspace = true, optional = true, features = [
"unstable-eth",
] }
[dev-dependencies]
alloy-consensus = { workspace = true, default-features = true }
array-bytes = { workspace = true, default-features = true }
assert_matches = { workspace = true }
pretty_assertions = { workspace = true }
secp256k1 = { workspace = true, features = ["recovery"] }
serde_json = { workspace = true }
test-case = { workspace = true }
# Pezkuwi SDK Dependencies
pezpallet-balances = { workspace = true, default-features = true }
pezpallet-proxy = { workspace = true, default-features = true }
pezpallet-revive-fixtures = { workspace = true, default-features = true }
pezpallet-timestamp = { workspace = true, default-features = true }
pezpallet-utility = { workspace = true, default-features = true }
proptest = { workspace = true }
pezsp-keystore = { workspace = true, default-features = true }
pezsp-state-machine = { workspace = true }
pezsp-tracing = { workspace = true, default-features = true }
[features]
default = ["std"]
std = [
"alloy-consensus/serde",
"alloy-consensus/std",
"alloy-core/std",
"alloy-trie/std",
"codec/std",
"environmental/std",
"ethereum-types/std",
"pezframe-benchmarking?/std",
"pezframe-support/std",
"pezframe-system/std",
"humantime-serde",
"k256?/std",
"log/std",
"num-bigint/std",
"num-integer/std",
"num-traits/std",
"pezpallet-proxy/std",
"pezpallet-revive-fixtures?/std",
"pezpallet-timestamp/std",
"pezpallet-transaction-payment/std",
"pezpallet-utility/std",
"polkavm-common/std",
"polkavm/std",
"rand/std",
"revm/std",
"ripemd/std",
"rlp/std",
"scale-info/std",
"secp256k1/std",
"serde/std",
"serde_json/std",
"pezsp-api/std",
"pezsp-arithmetic/std",
"pezsp-consensus-aura/std",
"pezsp-consensus-babe/std",
"pezsp-consensus-slots/std",
"pezsp-core/std",
"pezsp-io/std",
"pezsp-keystore/std",
"pezsp-runtime/std",
"pezsp-state-machine/std",
"pezsp-version/std",
"subxt-signer",
]
runtime-benchmarks = [
"pezframe-benchmarking/runtime-benchmarks",
"pezframe-support/runtime-benchmarks",
"pezframe-system/runtime-benchmarks",
"k256",
"pezpallet-balances/runtime-benchmarks",
"pezpallet-proxy/runtime-benchmarks",
"pezpallet-revive-fixtures",
"pezpallet-timestamp/runtime-benchmarks",
"pezpallet-transaction-payment/runtime-benchmarks",
"pezpallet-utility/runtime-benchmarks",
"pezsp-api/runtime-benchmarks",
"pezsp-consensus-aura",
"pezsp-consensus-aura?/runtime-benchmarks",
"pezsp-consensus-babe",
"pezsp-consensus-babe?/runtime-benchmarks",
"pezsp-consensus-slots",
"pezsp-consensus-slots?/runtime-benchmarks",
"pezsp-io/runtime-benchmarks",
"pezsp-runtime/runtime-benchmarks",
"pezsp-state-machine/runtime-benchmarks",
"pezsp-version/runtime-benchmarks",
]
try-runtime = [
"pezframe-support/try-runtime",
"pezframe-system/try-runtime",
"pezpallet-balances/try-runtime",
"pezpallet-proxy/try-runtime",
"pezpallet-timestamp/try-runtime",
"pezpallet-transaction-payment/try-runtime",
"pezpallet-utility/try-runtime",
"pezsp-runtime/try-runtime",
]
+119
View File
@@ -0,0 +1,119 @@
# Revive Pallet
This is an **experimental** module that provides functionality for the runtime to deploy and execute PolkaVM
smart-contracts. It is a heavily modified `pallet_contracts` fork.
## Overview
This module extends accounts based on the [`frame_support::traits::fungible`] traits to have smart-contract
functionality. It can be used with other modules that implement accounts based on [`frame_support::traits::fungible`].
These "smart-contract accounts" have the ability to instantiate smart-contracts and make calls to other contract and
non-contract accounts.
The smart-contract code is stored once, and later retrievable via its `code_hash`. This means that multiple
smart-contracts can be instantiated from the same `code`, without replicating the code each time.
When a smart-contract is called, its associated code is retrieved via the code hash and gets executed. This call can
alter the storage entries of the smart-contract account, instantiate new smart-contracts, or call other smart-contracts.
Finally, when an account is reaped, its associated code and storage of the smart-contract account will also be deleted.
### Weight
Senders must specify a [`Weight`](https://docs.pezkuwichain.io/bizinikiwi/master/sp_weights/struct.Weight.html) limit
with every call, as all instructions invoked by the smart-contract require weight. Unused weight is refunded after the
call, regardless of the execution outcome.
If the weight limit is reached, then all calls and state changes (including balance transfers) are only reverted at the
current call's contract level. For example, if contract A calls B and B runs out of weight mid-call, then all of B's
calls are reverted. Assuming correct error handling by contract A, A's other calls and state changes still persist.
One `ref_time` `Weight` is defined as one picosecond of execution time on the runtime's reference machine.
#### Event-Aware Weight Accounting
The pallet includes **event-aware weight accounting** for `finalize_block()` operations through the `OnFinalizeBlockParts`
trait. The weight model uses differential benchmarking to precisely account for the computational cost of processing
events during Ethereum block construction:
```text
Total Weight = fixed_part +
Σ(per_tx_part(payload_i)) +
Σ(per_event_part(data_len_j))
```
**High-Level Weight API (`OnFinalizeBlockParts` trait):**
The pallet exposes these weight calculation methods for runtime use:
- **Fixed cost**: `on_finalize_block_fixed()` - Base overhead regardless of transaction/event count
- **Per-transaction cost**: `on_finalize_block_per_tx(payload_size)` - Applied incrementally during each `eth_call()`
- **Per-event cost**: `on_finalize_block_per_event(data_len)` - Applied dynamically during each `deposit_event()`
**Underlying Benchmark Functions (`WeightInfo` trait):**
These low-level benchmarks measure raw computational costs and are used to derive the high-level weights:
- **Per-transaction overhead**: `on_finalize_per_transaction(n)` - Measures cost scaling with `n` transaction count
- **Per-transaction data**: `on_finalize_per_transaction_data(d)` - Measures cost scaling with `d` bytes of transaction payload
- **Per-event overhead**: `on_finalize_per_event(e)` - Measures cost scaling with `e` event count
- **Per-event data**: `on_finalize_per_event_data(d)` - Measures cost scaling with `d` bytes of event data
**Weight Derivation Methodology:**
The high-level API methods use differential calculation to isolate marginal costs from benchmarks:
- Per-transaction base: `on_finalize_per_transaction(1) - on_finalize_per_transaction(0)`
- Per-transaction byte: `on_finalize_per_transaction_data(1) - on_finalize_per_transaction_data(0)`
- Per-event base: `on_finalize_per_event(1) - on_finalize_per_event(0)`
- Per-byte of event data: `on_finalize_per_event_data(data_len) - on_finalize_per_event_data(0)`
This comprehensive weight model ensures that:
- Transactions emitting many events are properly weighted based on event count and data size
- Resource exhaustion attacks via oversized event data are prevented through proactive weight enforcement
- Accurate block packing calculations include all processing costs (bloom filters, RLP encoding, log conversion)
- Gas limit enforcement occurs early in `eth_call()` to prevent block overruns
### Revert Behaviour
Contract call failures are not cascading. When failures occur in a sub-call, they do not "bubble up", and the call will
only revert at the specific contract level. For example, if contract A calls contract B, and B fails, A can decide how
to handle that failure, either proceeding or reverting A's changes.
## Interface
### Dispatchable functions
Those are documented in the [reference
documentation](https://docs.pezkuwichain.io/sdk/master/pallet_revive/pallet/dispatchables/index.html).
## Usage
This module executes PolkaVM smart contracts. These can potentially be written in any language that compiles to
RISC-V. For now, the only officially supported languages are Solidity (via [`revive`](https://github.com/xermicus/revive))
and Rust (check the `fixtures` directory for Rust examples).
## Host function tracing
For contract authors, it can be a helpful debugging tool to see which host functions are called, with which arguments,
and what the result was.
In order to see these messages on the node console, the log level for the `runtime::revive::strace` target needs to
be raised to the `trace` level.
Example:
```bash
cargo run --release -- --dev -lerror,runtime::revive::strace=trace,runtime::revive=debug
```
## Unstable Interfaces
Driven by the desire to have an iterative approach in developing new contract interfaces this pallet contains the
concept of an unstable interface. Akin to the rust nightly compiler it allows us to add new interfaces but mark them as
unstable so that contract languages can experiment with them and give feedback before we stabilize those.
In order to access interfaces which don't have a stable `#[stable]` in [`runtime.rs`](src/vm/runtime.rs)
one need to set `pallet_revive::Config::UnsafeUnstableInterface` to `ConstU32<true>`.
**It should be obvious that any production runtime should never be compiled with this feature: In addition to be
subject to change or removal those interfaces might not have proper weights associated with them and are therefore
considered unsafe**.
New interfaces are generally added as unstable and might go through several iterations before they are promoted to a
stable interface.
License: Apache-2.0
@@ -0,0 +1,37 @@
[package]
name = "revive-dev-node"
description = "A development Bizinikiwi-based Bizinikiwi node, equipped with pezpallet-revive."
version = "0.0.0"
authors.workspace = true
homepage.workspace = true
repository.workspace = true
edition.workspace = true
publish = false
build = "build.rs"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[lints]
workspace = true
[dependencies]
clap = { features = ["derive"], workspace = true }
docify = { workspace = true }
futures = { features = ["thread-pool"], workspace = true }
futures-timer = { workspace = true }
jsonrpsee = { features = ["server"], workspace = true }
pezkuwi-sdk = { workspace = true, features = ["experimental", "node"] }
revive-dev-runtime = { workspace = true }
[build-dependencies]
pezkuwi-sdk = { workspace = true, features = ["bizinikiwi-build-script-utils"] }
[features]
default = ["std"]
std = ["pezkuwi-sdk/std", "revive-dev-runtime/std"]
runtime-benchmarks = [
"pezkuwi-sdk/runtime-benchmarks",
"revive-dev-runtime/runtime-benchmarks",
]
@@ -0,0 +1,23 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use pezkuwi_sdk::bizinikiwi_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed};
fn main() {
generate_cargo_keys();
rerun_if_git_head_changed();
}
@@ -0,0 +1,42 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use pezkuwi_sdk::{
pezsc_service::{ChainType, Properties},
*,
};
use revive_dev_runtime::WASM_BINARY;
/// This is a specialization of the general Bizinikiwi ChainSpec type.
pub type ChainSpec = pezsc_service::GenericChainSpec;
fn props() -> Properties {
let mut properties = Properties::new();
properties.insert("tokenDecimals".to_string(), 12.into());
properties.insert("tokenSymbol".to_string(), "MINI".into());
properties
}
pub fn development_chain_spec() -> Result<ChainSpec, String> {
Ok(ChainSpec::builder(WASM_BINARY.expect("Development wasm not available"), Default::default())
.with_name("Development")
.with_id("dev")
.with_chain_type(ChainType::Development)
.with_genesis_config_preset_name(pezsp_genesis_builder::DEV_RUNTIME_PRESET)
.with_properties(props())
.build())
}
@@ -0,0 +1,87 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use pezkuwi_sdk::{pezsc_cli::RunCmd, *};
#[derive(Debug, Clone, Copy)]
pub enum Consensus {
ManualSeal(u64),
InstantSeal,
None,
}
impl std::str::FromStr for Consensus {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(if s == "instant-seal" {
Consensus::InstantSeal
} else if let Some(block_time) = s.strip_prefix("manual-seal-") {
Consensus::ManualSeal(block_time.parse().map_err(|_| "invalid block time")?)
} else if s.to_lowercase() == "none" {
Consensus::None
} else {
return Err("incorrect consensus identifier".into());
})
}
}
#[derive(Debug, clap::Parser)]
pub struct Cli {
#[command(subcommand)]
pub subcommand: Option<Subcommand>,
#[clap(long, default_value = "instant-seal")]
pub consensus: Consensus,
#[clap(flatten)]
pub run: RunCmd,
}
#[derive(Debug, clap::Subcommand)]
pub enum Subcommand {
/// Key management cli utilities
#[command(subcommand)]
Key(pezsc_cli::KeySubcommand),
/// Build a chain specification.
BuildSpec(pezsc_cli::BuildSpecCmd),
/// Validate blocks.
CheckBlock(pezsc_cli::CheckBlockCmd),
/// Export blocks.
ExportBlocks(pezsc_cli::ExportBlocksCmd),
/// Export the chain specification.
ExportChainSpec(pezsc_cli::ExportChainSpecCmd),
/// Export the state of a given block into a chain spec.
ExportState(pezsc_cli::ExportStateCmd),
/// Import blocks.
ImportBlocks(pezsc_cli::ImportBlocksCmd),
/// Remove the whole chain.
PurgeChain(pezsc_cli::PurgeChainCmd),
/// Revert the chain to a previous state.
Revert(pezsc_cli::RevertCmd),
/// Db meta columns information.
ChainInfo(pezsc_cli::ChainInfoCmd),
}
@@ -0,0 +1,155 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::{
chain_spec,
cli::{Cli, Subcommand},
service,
};
use pezkuwi_sdk::{pezsc_cli::BizinikiwiCli, pezsc_service::PartialComponents, *};
impl BizinikiwiCli for Cli {
fn impl_name() -> String {
"Bizinikiwi Node".into()
}
fn impl_version() -> String {
env!("BIZINIKIWI_CLI_IMPL_VERSION").into()
}
fn description() -> String {
env!("CARGO_PKG_DESCRIPTION").into()
}
fn author() -> String {
env!("CARGO_PKG_AUTHORS").into()
}
fn support_url() -> String {
"support.anonymous.an".into()
}
fn copyright_start_year() -> i32 {
2017
}
fn load_spec(&self, id: &str) -> Result<Box<dyn pezsc_service::ChainSpec>, String> {
Ok(match id {
"dev" | "" => Box::new(chain_spec::development_chain_spec()?),
path =>
Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?),
})
}
}
pub fn run() -> pezsc_cli::Result<()> {
let args = std::env::args_os().map(|s| s.to_string_lossy().to_string()).collect::<Vec<_>>();
return run_with_args(args);
}
/// Parse and run command line arguments
pub fn run_with_args(args: Vec<String>) -> pezsc_cli::Result<()> {
let mut cli = Cli::from_iter(args);
match &cli.subcommand {
Some(Subcommand::Key(cmd)) => cmd.run(&cli),
Some(Subcommand::BuildSpec(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
},
Some(Subcommand::CheckBlock(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, import_queue, .. } =
service::new_partial(&config)?;
Ok((cmd.run(client, import_queue), task_manager))
})
},
Some(Subcommand::ExportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?;
Ok((cmd.run(client, config.database), task_manager))
})
},
Some(Subcommand::ExportChainSpec(cmd)) => {
let chain_spec = cli.load_spec(&cmd.chain)?;
cmd.run(chain_spec)
},
Some(Subcommand::ExportState(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?;
Ok((cmd.run(client, config.chain_spec), task_manager))
})
},
Some(Subcommand::ImportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, import_queue, .. } =
service::new_partial(&config)?;
Ok((cmd.run(client, import_queue), task_manager))
})
},
Some(Subcommand::PurgeChain(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run(config.database))
},
Some(Subcommand::Revert(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.async_run(|config| {
let PartialComponents { client, task_manager, backend, .. } =
service::new_partial(&config)?;
Ok((cmd.run(client, backend, None), task_manager))
})
},
Some(Subcommand::ChainInfo(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run::<revive_dev_runtime::OpaqueBlock>(&config))
},
None => {
// Enforce dev
cli.run.shared_params.dev = true;
// Pass Default logging settings if none are specified
if std::env::var("RUST_LOG").is_err() && cli.run.shared_params.log.is_empty() {
cli.run.shared_params.log = "error,pezsc_rpc_server=info,runtime::revive=debug"
.split(',')
.map(|s| s.to_string())
.collect();
}
// Enforce single-state pool-type if instant-seal is selected
if matches!(cli.consensus, crate::cli::Consensus::InstantSeal) {
cli.run.pool_config.pool_type = pezsc_cli::TransactionPoolType::SingleState
}
let runner = cli.create_runner(&cli.run)?;
runner.run_node_until_exit(|config| async move {
match config.network.network_backend {
pezsc_network::config::NetworkBackendType::Libp2p =>
service::new_full::<pezsc_network::NetworkWorker<_, _>>(config, cli.consensus)
.map_err(pezsc_cli::Error::Service),
pezsc_network::config::NetworkBackendType::Litep2p => service::new_full::<
pezsc_network::Litep2pNetworkBackend,
>(config, cli.consensus)
.map_err(pezsc_cli::Error::Service),
}
})
},
}
}
@@ -0,0 +1,22 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub mod chain_spec;
pub(crate) mod cli;
pub mod command;
pub mod rpc;
pub mod service;
@@ -0,0 +1,29 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Bizinikiwi Node Template CLI library.
#![warn(missing_docs)]
mod chain_spec;
mod cli;
mod command;
mod rpc;
mod service;
fn main() -> pezkuwi_sdk::pezsc_cli::Result<()> {
command::run()
}
@@ -0,0 +1,100 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! A collection of node-specific RPC methods.
//! Bizinikiwi provides the `sc-rpc` crate, which defines the core RPC layer
//! used by Bizinikiwi nodes. This file extends those RPC definitions with
//! capabilities that are specific to this project's runtime configuration.
#![warn(missing_docs)]
use crate::cli::Consensus;
use jsonrpsee::{core::RpcResult, proc_macros::rpc, RpcModule};
use pezkuwi_sdk::{
pezsc_transaction_pool_api::TransactionPool,
pezsp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata},
*,
};
use revive_dev_runtime::{AccountId, Nonce, OpaqueBlock};
use std::sync::Arc;
/// Full client dependencies.
pub struct FullDeps<C, P> {
/// The client instance to use.
pub client: Arc<C>,
/// Transaction pool instance.
pub pool: Arc<P>,
/// The consensus type of the node.
pub consensus: Consensus,
}
/// AutoMine JSON-RPC api.
/// Automine is a feature of the Hardhat Network where a new block is automatically mined after each
/// transaction.
#[rpc(server, client)]
pub trait AutoMineRpc {
/// API to get the automine status.
#[method(name = "getAutomine")]
fn get_automine(&self) -> RpcResult<bool>;
}
/// Implementation of the AutoMine RPC api.
pub struct AutoMineRpcImpl {
/// Whether the node is running in auto-mine mode.
is_auto_mine: bool,
}
impl AutoMineRpcImpl {
/// Create new `AutoMineRpcImpl` instance.
pub fn new(consensus: Consensus) -> Self {
Self { is_auto_mine: matches!(consensus, Consensus::InstantSeal) }
}
}
impl AutoMineRpcServer for AutoMineRpcImpl {
/// Returns `true` if block production is set to `instant`.
fn get_automine(&self) -> RpcResult<bool> {
Ok(self.is_auto_mine)
}
}
#[docify::export]
/// Instantiate all full RPC extensions.
pub fn create_full<C, P>(
deps: FullDeps<C, P>,
) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
where
C: Send
+ Sync
+ 'static
+ pezsp_api::ProvideRuntimeApi<OpaqueBlock>
+ HeaderBackend<OpaqueBlock>
+ HeaderMetadata<OpaqueBlock, Error = BlockChainError>
+ 'static,
C::Api: pezsp_block_builder::BlockBuilder<OpaqueBlock>,
C::Api: bizinikiwi_frame_rpc_system::AccountNonceApi<OpaqueBlock, AccountId, Nonce>,
P: TransactionPool + 'static,
{
use pezkuwi_sdk::bizinikiwi_frame_rpc_system::{System, SystemApiServer};
let mut module = RpcModule::new(());
let FullDeps { client, pool, consensus } = deps;
module.merge(AutoMineRpcImpl::new(consensus).into_rpc())?;
module.merge(System::new(client.clone(), pool.clone()).into_rpc())?;
Ok(module)
}
@@ -0,0 +1,269 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::cli::Consensus;
use pezkuwi_sdk::{
pezsc_client_api::StorageProvider,
pezsc_executor::WasmExecutor,
pezsc_service::{error::Error as ServiceError, Configuration, TaskManager},
pezsc_telemetry::{Telemetry, TelemetryWorker},
pezsp_runtime::traits::Block as BlockT,
*,
};
use revive_dev_runtime::{OpaqueBlock as Block, Runtime, RuntimeApi};
use std::sync::Arc;
type HostFunctions = pezsp_io::BizinikiwiHostFunctions;
#[docify::export]
pub(crate) type FullClient =
pezsc_service::TFullClient<Block, RuntimeApi, WasmExecutor<HostFunctions>>;
type FullBackend = pezsc_service::TFullBackend<Block>;
type FullSelectChain = pezsc_consensus::LongestChain<FullBackend, Block>;
/// Assembly of PartialComponents (enough to run chain ops subcommands)
pub type Service = pezsc_service::PartialComponents<
FullClient,
FullBackend,
FullSelectChain,
pezsc_consensus::DefaultImportQueue<Block>,
pezsc_transaction_pool::TransactionPoolHandle<Block, FullClient>,
Option<Telemetry>,
>;
pub fn new_partial(config: &Configuration) -> Result<Service, ServiceError> {
let telemetry = config
.telemetry_endpoints
.clone()
.filter(|x| !x.is_empty())
.map(|endpoints| -> Result<_, pezsc_telemetry::Error> {
let worker = TelemetryWorker::new(16)?;
let telemetry = worker.handle().new_telemetry(endpoints);
Ok((worker, telemetry))
})
.transpose()?;
let executor = pezsc_service::new_wasm_executor(&config.executor);
let (client, backend, keystore_container, task_manager) =
pezsc_service::new_full_parts::<Block, RuntimeApi, _>(
config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
executor,
)?;
let client = Arc::new(client);
let telemetry = telemetry.map(|(worker, telemetry)| {
task_manager.spawn_handle().spawn("telemetry", None, worker.run());
telemetry
});
let select_chain = pezsc_consensus::LongestChain::new(backend.clone());
let transaction_pool = Arc::from(
pezsc_transaction_pool::Builder::new(
task_manager.spawn_essential_handle(),
client.clone(),
config.role.is_authority().into(),
)
.with_options(config.transaction_pool.clone())
.build(),
);
let import_queue = pezsc_consensus_manual_seal::import_queue(
Box::new(client.clone()),
&task_manager.spawn_essential_handle(),
None,
);
Ok(pezsc_service::PartialComponents {
client,
backend,
task_manager,
import_queue,
keystore_container,
select_chain,
transaction_pool,
other: (telemetry),
})
}
/// Builds a new service for a full client.
pub fn new_full<Network: pezsc_network::NetworkBackend<Block, <Block as BlockT>::Hash>>(
config: Configuration,
consensus: Consensus,
) -> Result<TaskManager, ServiceError> {
let pezsc_service::PartialComponents {
client,
backend,
mut task_manager,
import_queue,
keystore_container,
select_chain,
transaction_pool,
other: mut telemetry,
} = new_partial(&config)?;
let net_config = pezsc_network::config::FullNetworkConfiguration::<
Block,
<Block as BlockT>::Hash,
Network,
>::new(&config.network, None);
let metrics = Network::register_notification_metrics(None);
let (network, system_rpc_tx, tx_handler_controller, sync_service) =
pezsc_service::build_network(pezsc_service::BuildNetworkParams {
config: &config,
net_config,
client: client.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue,
block_announce_validator_builder: None,
warp_sync_config: None,
block_relay: None,
metrics,
})?;
let rpc_extensions_builder = {
let client = client.clone();
let pool = transaction_pool.clone();
Box::new(move |_| {
let deps =
crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), consensus };
crate::rpc::create_full(deps).map_err(Into::into)
})
};
let _rpc_handlers = pezsc_service::spawn_tasks(pezsc_service::SpawnTasksParams {
network,
client: client.clone(),
keystore: keystore_container.keystore(),
task_manager: &mut task_manager,
transaction_pool: transaction_pool.clone(),
rpc_builder: rpc_extensions_builder,
backend,
system_rpc_tx,
tx_handler_controller,
sync_service,
config,
telemetry: telemetry.as_mut(),
tracing_execute_block: None,
})?;
let proposer = pezsc_basic_authorship::ProposerFactory::new(
task_manager.spawn_handle(),
client.clone(),
transaction_pool.clone(),
None,
telemetry.as_ref().map(|x| x.handle()),
);
// Due to instant seal or low block time multiple blocks can have the same timestamp.
// This is because Etereum only uses second granularity (as opposed to ms).
// Here we make sure that we increment by at least a second from the last block.
//
// # Warning
//
// This will lead to blocks with timestamps in the future. This might cause other issues
// when dealing with off chain data. But for a development node it is more important to not
// have duplicate timestamps. The only way to not have timestamps in the future and no
// duplicates is to set the block time to at least one second (`--consensus manual-seal-1000`).
let timestamp_provider = {
let client = client.clone();
move |parent, ()| {
let client = client.clone();
async move {
let key = pezsp_core::storage::StorageKey(
pezkuwi_sdk::pezpallet_timestamp::Now::<Runtime>::hashed_key().to_vec(),
);
let current = pezsp_timestamp::Timestamp::current();
let next = client
.storage(parent, &key)
.ok()
.flatten()
.and_then(|data| data.0.try_into().ok())
.map(|data| {
let last = u64::from_le_bytes(data) / 1000;
pezsp_timestamp::Timestamp::new((last + 1) * 1000)
})
.unwrap_or(current);
Ok(pezsp_timestamp::InherentDataProvider::new(current.max(next)))
}
}
};
match consensus {
Consensus::InstantSeal => {
let params = pezsc_consensus_manual_seal::InstantSealParams {
block_import: client.clone(),
env: proposer,
client,
pool: transaction_pool,
select_chain,
consensus_data_provider: None,
create_inherent_data_providers: timestamp_provider,
};
let authorship_future = pezsc_consensus_manual_seal::run_instant_seal_and_finalize(params);
task_manager.spawn_essential_handle().spawn_blocking(
"instant-seal",
None,
authorship_future,
);
},
Consensus::ManualSeal(block_time) => {
let (mut sink, commands_stream) = futures::channel::mpsc::channel(1024);
task_manager.spawn_handle().spawn("block_authoring", None, async move {
loop {
futures_timer::Delay::new(std::time::Duration::from_millis(block_time)).await;
sink.try_send(pezsc_consensus_manual_seal::EngineCommand::SealNewBlock {
create_empty: true,
finalize: true,
parent_hash: None,
sender: None,
})
.unwrap();
}
});
let params = pezsc_consensus_manual_seal::ManualSealParams {
block_import: client.clone(),
env: proposer,
client,
pool: transaction_pool,
select_chain,
commands_stream: Box::pin(commands_stream),
consensus_data_provider: None,
create_inherent_data_providers: timestamp_provider,
};
let authorship_future = pezsc_consensus_manual_seal::run_manual_seal(params);
task_manager.spawn_essential_handle().spawn_blocking(
"manual-seal",
None,
authorship_future,
);
},
_ => {},
}
Ok(task_manager)
}
@@ -0,0 +1,46 @@
[package]
name = "revive-dev-runtime"
description = "A solochain dev runtime for revive."
version = "0.1.0"
license = "Apache-2.0"
authors.workspace = true
homepage.workspace = true
repository.workspace = true
edition.workspace = true
[dependencies]
array-bytes = { workspace = true }
codec = { workspace = true }
pezkuwi-sdk = { workspace = true, features = [
"pezpallet-balances",
"pezpallet-revive",
"pezpallet-sudo",
"pezpallet-timestamp",
"pezpallet-transaction-payment",
"pezpallet-transaction-payment-rpc-runtime-api",
"pezkuwi-runtime-common",
"runtime",
"teyrchains-common",
"with-tracing",
] }
scale-info = { workspace = true }
serde_json = { workspace = true, default-features = false, features = [
"alloc",
] }
pezsp-debug-derive = { workspace = true, features = ["force-debug"] }
[build-dependencies]
pezkuwi-sdk = { optional = true, workspace = true, features = [
"bizinikiwi-wasm-builder",
] }
[features]
default = ["std"]
std = [
"codec/std",
"pezkuwi-sdk/std",
"scale-info/std",
"serde_json/std",
"pezsp-debug-derive/std",
]
runtime-benchmarks = ["pezkuwi-sdk/runtime-benchmarks"]
@@ -0,0 +1,23 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
fn main() {
#[cfg(feature = "std")]
{
pezkuwi_sdk::bizinikiwi_wasm_builder::WasmBuilder::build_using_defaults();
}
}
@@ -0,0 +1,481 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![cfg_attr(not(feature = "std"), no_std)]
// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
extern crate alloc;
use alloc::{vec, vec::Vec};
use currency::*;
use pezframe_support::weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_REF_TIME_PER_SECOND},
Weight,
};
use pezframe_system::limits::BlockWeights;
use pezpallet_revive::{
evm::{
fees::{BlockRatioFee, Info as FeeInfo},
runtime::EthExtra,
},
AccountId32Mapper,
};
use pezpallet_transaction_payment::{ConstFeeMultiplier, FeeDetails, Multiplier, RuntimeDispatchInfo};
use pezkuwi_sdk::{
pezkuwi_sdk_frame::{
deps::pezsp_genesis_builder,
runtime::{apis, prelude::*},
traits::Block as BlockT,
},
*,
};
use pezsp_weights::ConstantMultiplier;
pub use pezkuwi_sdk::{
pezkuwi_sdk_frame::runtime::types_common::OpaqueBlock,
teyrchains_common::{AccountId, Balance, BlockNumber, Hash, Header, Nonce, Signature},
};
pub mod currency {
use super::Balance;
pub const DOLLARS: Balance = 1_000_000_000_000;
pub const CENTS: Balance = DOLLARS / 100;
pub const MILLICENTS: Balance = CENTS / 1_000;
}
/// Provides getters for genesis configuration presets.
pub mod genesis_config_presets {
use super::*;
use crate::{
currency::DOLLARS, pezsp_keyring::Sr25519Keyring, Balance, BalancesConfig,
RuntimeGenesisConfig, SudoConfig,
};
use alloc::{vec, vec::Vec};
use serde_json::Value;
pub const ENDOWMENT: Balance = 1_000_000_001 * DOLLARS;
fn well_known_accounts() -> Vec<AccountId> {
Sr25519Keyring::well_known()
.map(|k| k.to_account_id())
.chain([
// subxt_signer::eth::dev::alith()
array_bytes::hex_n_into_unchecked(
"f24ff3a9cf04c71dbc94d0b566f7a27b94566caceeeeeeeeeeeeeeeeeeeeeeee",
),
// subxt_signer::eth::dev::baltathar()
array_bytes::hex_n_into_unchecked(
"3cd0a705a2dc65e5b1e1205896baa2be8a07c6e0eeeeeeeeeeeeeeeeeeeeeeee",
),
// subxt_signer::eth::dev::charleth()
array_bytes::hex_n_into_unchecked(
"798d4ba9baf0064ec19eb4f0a1a45785ae9d6dfceeeeeeeeeeeeeeeeeeeeeeee",
),
// subxt_signer::eth::dev::dorothy()
array_bytes::hex_n_into_unchecked(
"773539d4ac0e786233d90a233654ccee26a613d9eeeeeeeeeeeeeeeeeeeeeeee",
),
// subxt_signer::eth::dev::ethan()
array_bytes::hex_n_into_unchecked(
"ff64d3f6efe2317ee2807d223a0bdc4c0c49dfdbeeeeeeeeeeeeeeeeeeeeeeee",
),
])
.collect::<Vec<_>>()
}
/// Returns a development genesis config preset.
pub fn development_config_genesis() -> Value {
pezframe_support::build_struct_json_patch!(RuntimeGenesisConfig {
balances: BalancesConfig {
balances: well_known_accounts()
.into_iter()
.map(|id| (id, ENDOWMENT))
.collect::<Vec<_>>(),
},
sudo: SudoConfig { key: Some(Sr25519Keyring::Alice.to_account_id()) },
})
}
/// Get the set of the available genesis config presets.
pub fn get_preset(id: &PresetId) -> Option<Vec<u8>> {
let patch = match id.as_ref() {
pezsp_genesis_builder::DEV_RUNTIME_PRESET => development_config_genesis(),
_ => return None,
};
Some(
serde_json::to_string(&patch)
.expect("serialization to json is expected to work. qed.")
.into_bytes(),
)
}
/// List of supported presets.
pub fn preset_names() -> Vec<PresetId> {
vec![PresetId::from(pezsp_genesis_builder::DEV_RUNTIME_PRESET)]
}
}
/// The runtime version.
#[runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: alloc::borrow::Cow::Borrowed("revive-dev-runtime"),
impl_name: alloc::borrow::Cow::Borrowed("revive-dev-runtime"),
authoring_version: 1,
spec_version: 0,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
system_version: 1,
};
/// The version information used to identify this runtime when compiled natively.
#[cfg(feature = "std")]
pub fn native_version() -> NativeVersion {
NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
}
/// The address format for describing accounts.
pub type Address = pezsp_runtime::MultiAddress<AccountId, ()>;
/// Block type as expected by this runtime.
pub type Block = pezsp_runtime::generic::Block<Header, UncheckedExtrinsic>;
/// The transaction extensions that are added to the runtime.
type TxExtension = (
// Checks that the sender is not the zero address.
pezframe_system::CheckNonZeroSender<Runtime>,
// Checks that the runtime version is correct.
pezframe_system::CheckSpecVersion<Runtime>,
// Checks that the transaction version is correct.
pezframe_system::CheckTxVersion<Runtime>,
// Checks that the genesis hash is correct.
pezframe_system::CheckGenesis<Runtime>,
// Checks that the era is valid.
pezframe_system::CheckEra<Runtime>,
// Checks that the nonce is valid.
pezframe_system::CheckNonce<Runtime>,
// Checks that the weight is valid.
pezframe_system::CheckWeight<Runtime>,
// Ensures that the sender has enough funds to pay for the transaction
// and deducts the fee from the sender's account.
pezpallet_transaction_payment::ChargeTransactionPayment<Runtime>,
// Needs to be done after all extensions that rely on a signed origin.
pezpallet_revive::evm::tx_extension::SetOrigin<Runtime>,
// Reclaim the unused weight from the block using post dispatch information.
// It must be last in the pipeline in order to catch the refund in previous transaction
// extensions
pezframe_system::WeightReclaim<Runtime>,
);
/// Default extensions applied to Ethereum transactions.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct EthExtraImpl;
impl EthExtra for EthExtraImpl {
type Config = Runtime;
type Extension = TxExtension;
fn get_eth_extension(nonce: u32, tip: Balance) -> Self::Extension {
(
pezframe_system::CheckNonZeroSender::<Runtime>::new(),
pezframe_system::CheckSpecVersion::<Runtime>::new(),
pezframe_system::CheckTxVersion::<Runtime>::new(),
pezframe_system::CheckGenesis::<Runtime>::new(),
pezframe_system::CheckMortality::from(pezsp_runtime::generic::Era::Immortal),
pezframe_system::CheckNonce::<Runtime>::from(nonce),
pezframe_system::CheckWeight::<Runtime>::new(),
pezpallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
pezpallet_revive::evm::tx_extension::SetOrigin::<Runtime>::new_from_eth_transaction(),
pezframe_system::WeightReclaim::<Runtime>::new(),
)
}
}
pub type UncheckedExtrinsic =
pezpallet_revive::evm::runtime::UncheckedExtrinsic<Address, Signature, EthExtraImpl>;
type Executive = pezframe_executive::Executive<
Runtime,
Block,
pezframe_system::ChainContext<Runtime>,
Runtime,
AllPalletsWithSystem,
>;
// Composes the runtime by adding all the used pallets and deriving necessary types.
#[frame_construct_runtime]
mod runtime {
/// The main runtime type.
#[runtime::runtime]
#[runtime::derive(
RuntimeCall,
RuntimeEvent,
RuntimeError,
RuntimeOrigin,
RuntimeFreezeReason,
RuntimeHoldReason,
RuntimeSlashReason,
RuntimeLockId,
RuntimeTask,
RuntimeViewFunction
)]
pub struct Runtime;
/// Mandatory system pallet that should always be included in a FRAME runtime.
#[runtime::pezpallet_index(0)]
pub type System = pezframe_system::Pallet<Runtime>;
/// Provides a way for consensus systems to set and check the onchain time.
#[runtime::pezpallet_index(1)]
pub type Timestamp = pezpallet_timestamp::Pallet<Runtime>;
/// Provides the ability to keep track of balances.
#[runtime::pezpallet_index(2)]
pub type Balances = pezpallet_balances::Pallet<Runtime>;
/// Provides a way to execute privileged functions.
#[runtime::pezpallet_index(3)]
pub type Sudo = pezpallet_sudo::Pallet<Runtime>;
/// Provides the ability to charge for extrinsic execution.
#[runtime::pezpallet_index(4)]
pub type TransactionPayment = pezpallet_transaction_payment::Pallet<Runtime>;
/// Provides the ability to execute Smart Contracts.
#[runtime::pezpallet_index(5)]
pub type Revive = pezpallet_revive::Pallet<Runtime>;
}
/// We assume that ~10% of the block weight is consumed by `on_initialize` handlers.
/// This is used to limit the maximal weight of a single extrinsic.
const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used
/// by Operational extrinsics.
const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
/// We allow for 2 seconds of compute with a 6 second average block time, with maximum proof size.
const MAXIMUM_BLOCK_WEIGHT: Weight =
Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX);
parameter_types! {
pub const Version: RuntimeVersion = VERSION;
pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
.base_block(BlockExecutionWeight::get())
.for_class(DispatchClass::all(), |weights| {
weights.base_extrinsic = ExtrinsicBaseWeight::get();
})
.for_class(DispatchClass::Normal, |weights| {
weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
})
.for_class(DispatchClass::Operational, |weights| {
weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
// Operational transactions have some extra reserved space, so that they
// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
weights.reserved = Some(
MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
);
})
.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
.build_or_panic();
}
/// Implements the types required for the system pallet.
#[derive_impl(pezframe_system::config_preludes::SolochainDefaultConfig)]
impl pezframe_system::Config for Runtime {
type Block = Block;
type Version = Version;
type AccountId = AccountId;
type Hash = Hash;
type Nonce = Nonce;
type AccountData = pezpallet_balances::AccountData<<Runtime as pezpallet_balances::Config>::Balance>;
}
parameter_types! {
pub const ExistentialDeposit: Balance = CENTS;
}
// Implements the types required for the balances pallet.
#[derive_impl(pezpallet_balances::config_preludes::TestDefaultConfig)]
impl pezpallet_balances::Config for Runtime {
type AccountStore = System;
type Balance = Balance;
type ExistentialDeposit = ExistentialDeposit;
}
// Implements the types required for the sudo pallet.
#[derive_impl(pezpallet_sudo::config_preludes::TestDefaultConfig)]
impl pezpallet_sudo::Config for Runtime {}
// Implements the types required for the sudo pallet.
#[derive_impl(pezpallet_timestamp::config_preludes::TestDefaultConfig)]
impl pezpallet_timestamp::Config for Runtime {}
parameter_types! {
pub const TransactionByteFee: Balance = 10 * MILLICENTS;
pub FeeMultiplier: Multiplier = Multiplier::one();
}
// Implements the types required for the transaction payment pallet.
#[derive_impl(pezpallet_transaction_payment::config_preludes::TestDefaultConfig)]
impl pezpallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = pezpallet_transaction_payment::FungibleAdapter<Balances, ()>;
type WeightToFee = BlockRatioFee<1, 1, Self>;
type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
type FeeMultiplierUpdate = ConstFeeMultiplier<FeeMultiplier>;
}
parameter_types! {
pub CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(30);
}
#[derive_impl(pezpallet_revive::config_preludes::TestDefaultConfig)]
impl pezpallet_revive::Config for Runtime {
type AddressMapper = AccountId32Mapper<Self>;
type ChainId = ConstU64<420_420_420>;
type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
type Balance = Balance;
type Currency = Balances;
type NativeToEthRatio = ConstU32<1_000_000>;
type UploadOrigin = EnsureSigned<Self::AccountId>;
type InstantiateOrigin = EnsureSigned<Self::AccountId>;
type Time = Timestamp;
type FeeInfo = FeeInfo<Address, Signature, EthExtraImpl>;
type DebugEnabled = ConstBool<false>;
}
pezpallet_revive::impl_runtime_apis_plus_revive_traits!(
Runtime,
Revive,
Executive,
EthExtraImpl,
impl apis::Core<Block> for Runtime {
fn version() -> RuntimeVersion {
VERSION
}
fn execute_block(block: <Block as BlockT>::LazyBlock) {
Executive::execute_block(block)
}
fn initialize_block(header: &Header) -> ExtrinsicInclusionMode {
Executive::initialize_block(header)
}
}
impl apis::Metadata<Block> for Runtime {
fn metadata() -> OpaqueMetadata {
OpaqueMetadata::new(Runtime::metadata().into())
}
fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
Runtime::metadata_at_version(version)
}
fn metadata_versions() -> Vec<u32> {
Runtime::metadata_versions()
}
}
impl apis::BlockBuilder<Block> for Runtime {
fn apply_extrinsic(extrinsic: ExtrinsicFor<Runtime>) -> ApplyExtrinsicResult {
Executive::apply_extrinsic(extrinsic)
}
fn finalize_block() -> HeaderFor<Runtime> {
Executive::finalize_block()
}
fn inherent_extrinsics(data: InherentData) -> Vec<ExtrinsicFor<Runtime>> {
data.create_extrinsics()
}
fn check_inherents(
block: <Block as BlockT>::LazyBlock,
data: InherentData,
) -> CheckInherentsResult {
data.check_extrinsics(&block)
}
}
impl apis::TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(
source: TransactionSource,
tx: ExtrinsicFor<Runtime>,
block_hash: <Runtime as pezframe_system::Config>::Hash,
) -> TransactionValidity {
Executive::validate_transaction(source, tx, block_hash)
}
}
impl apis::OffchainWorkerApi<Block> for Runtime {
fn offchain_worker(header: &HeaderFor<Runtime>) {
Executive::offchain_worker(header)
}
}
impl apis::SessionKeys<Block> for Runtime {
fn generate_session_keys(_seed: Option<Vec<u8>>) -> Vec<u8> {
Default::default()
}
fn decode_session_keys(
_encoded: Vec<u8>,
) -> Option<Vec<(Vec<u8>, apis::KeyTypeId)>> {
Default::default()
}
}
impl apis::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
fn account_nonce(account: AccountId) -> Nonce {
System::account_nonce(account)
}
}
impl pezpallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<
Block,
Balance,
> for Runtime {
fn query_info(uxt: ExtrinsicFor<Runtime>, len: u32) -> RuntimeDispatchInfo<Balance> {
TransactionPayment::query_info(uxt, len)
}
fn query_fee_details(uxt: ExtrinsicFor<Runtime>, len: u32) -> FeeDetails<Balance> {
TransactionPayment::query_fee_details(uxt, len)
}
fn query_weight_to_fee(weight: Weight) -> Balance {
TransactionPayment::weight_to_fee(weight)
}
fn query_length_to_fee(length: u32) -> Balance {
TransactionPayment::length_to_fee(length)
}
}
impl apis::GenesisBuilder<Block> for Runtime {
fn build_state(config: Vec<u8>) -> pezsp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn get_preset(id: &Option<PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, self::genesis_config_presets::get_preset)
}
fn preset_names() -> Vec<PresetId> {
self::genesis_config_presets::preset_names()
}
}
);
@@ -0,0 +1,38 @@
[package]
name = "pezpallet-revive-fixtures"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
license.workspace = true
description = "Fixtures for testing and benchmarking"
homepage.workspace = true
repository.workspace = true
rust-version = "1.84"
[package.metadata.pezkuwi-sdk]
exclude-from-umbrella = true
[lints]
workspace = true
[dependencies]
alloy-core = { workspace = true, default-features = true, features = [
"sol-types",
], optional = true }
anyhow = { workspace = true, default-features = true, optional = true }
pezsp-core = { workspace = true, default-features = true, optional = true }
pezsp-io = { workspace = true, default-features = true, optional = true }
[build-dependencies]
anyhow = { workspace = true, default-features = true }
cargo_metadata = { workspace = true }
hex = { workspace = true, features = ["alloc"] }
pezpallet-revive-uapi = { workspace = true }
polkavm-linker = { version = "0.30.0" }
serde_json = { workspace = true }
toml = { workspace = true }
[features]
default = ["std"]
# only when std is enabled all fixtures are available
std = ["alloy-core", "anyhow", "hex/std", "serde_json/std", "pezsp-core", "pezsp-io"]
@@ -0,0 +1,519 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Compile text fixtures to PolkaVM binaries.
use anyhow::{bail, Context, Result};
use cargo_metadata::MetadataCommand;
use pezpallet_revive_uapi::precompiles::INTERFACE_DIR;
use std::{
env, fs,
io::Write,
path::{Path, PathBuf},
process::Command,
};
const OVERRIDE_RUSTUP_TOOLCHAIN_ENV_VAR: &str = "PALLET_REVIVE_FIXTURES_RUSTUP_TOOLCHAIN";
const OVERRIDE_STRIP_ENV_VAR: &str = "PALLET_REVIVE_FIXTURES_STRIP";
const OVERRIDE_OPTIMIZE_ENV_VAR: &str = "PALLET_REVIVE_FIXTURES_OPTIMIZE";
/// Do not build the fixtures, they will resolve to `None`.
///
/// Depending on the usage, they will probably panic at runtime.
const SKIP_PALLET_REVIVE_FIXTURES: &str = "SKIP_PALLET_REVIVE_FIXTURES";
/// A contract entry.
#[derive(Clone)]
struct Entry {
/// The path to the contract source file.
path: PathBuf,
/// The type of the contract (rust or solidity).
contract_type: ContractType,
}
#[derive(Clone, Copy)]
enum ContractType {
Rust,
Solidity,
}
/// Type of EVM bytecode to extract from Solidity compiler output.
#[derive(Clone, Copy)]
enum EvmByteCodeType {
InitCode,
RuntimeCode,
}
impl EvmByteCodeType {
fn json_key(&self) -> &'static str {
match self {
Self::InitCode => "bytecode",
Self::RuntimeCode => "deployedBytecode",
}
}
}
impl Entry {
/// Create a new contract entry from the given path.
fn new(path: PathBuf, contract_type: ContractType) -> Self {
Self { path, contract_type }
}
/// Return the path to the contract source file.
fn path(&self) -> &str {
self.path.to_str().expect("path is valid unicode; qed")
}
/// Return the name of the contract.
fn name(&self) -> &str {
self.path
.file_stem()
.expect("file exits; qed")
.to_str()
.expect("name is valid unicode; qed")
}
/// Return the name of the bytecode file.
fn out_filename(&self) -> String {
match self.contract_type {
ContractType::Rust => format!("{}.polkavm", self.name()),
ContractType::Solidity => format!("{}.resolc.polkavm", self.name()),
}
}
}
/// Collect all contract entries from the given source directory.
fn collect_entries(contracts_dir: &Path) -> Vec<Entry> {
fs::read_dir(contracts_dir)
.expect("src dir exists; qed")
.filter_map(|file| {
let path = file.expect("file exists; qed").path();
let extension = path.extension();
match extension.and_then(|ext| ext.to_str()) {
Some("rs") => Some(Entry::new(path, ContractType::Rust)),
Some("sol") => Some(Entry::new(path, ContractType::Solidity)),
_ => None,
}
})
.collect::<Vec<_>>()
}
/// Create a `Cargo.toml` to compile the given Rust contract entries.
fn create_cargo_toml<'a>(
fixtures_dir: &Path,
entries: impl Iterator<Item = &'a Entry>,
output_dir: &Path,
) -> Result<()> {
let mut cargo_toml: toml::Value = toml::from_str(include_str!("./build/_Cargo.toml"))?;
let uapi_dep = cargo_toml["dependencies"]["uapi"].as_table_mut().unwrap();
let manifest_path = fixtures_dir.join("Cargo.toml");
let metadata = MetadataCommand::new().manifest_path(&manifest_path).exec().unwrap();
let dependency_graph = metadata.resolve.unwrap();
// Resolve the pezpallet-revive-fixtures package id
let fixtures_pkg_id = metadata
.packages
.iter()
.find(|pkg| pkg.manifest_path.as_std_path() == manifest_path)
.map(|pkg| pkg.id.clone())
.unwrap();
let fixtures_pkg_node =
dependency_graph.nodes.iter().find(|node| node.id == fixtures_pkg_id).unwrap();
// Get the pezpallet-revive-uapi package id
let uapi_pkg_id = fixtures_pkg_node
.deps
.iter()
.find(|dep| dep.name == "pezpallet_revive_uapi")
.map(|dep| dep.pkg.clone())
.expect("pezpallet-revive-uapi is a build dependency of pezpallet-revive-fixtures; qed");
// Get pezpallet-revive-uapi package
let uapi_pkg = metadata.packages.iter().find(|pkg| pkg.id == uapi_pkg_id).unwrap();
if uapi_pkg.source.is_none() {
uapi_dep.insert(
"path".to_string(),
toml::Value::String(
fixtures_dir.join("../uapi").canonicalize()?.to_str().unwrap().to_string(),
),
);
} else {
uapi_dep.insert("version".to_string(), toml::Value::String(uapi_pkg.version.to_string()));
}
cargo_toml["bin"] = toml::Value::Array(
entries
.map(|entry| {
let name = entry.name();
let path = entry.path();
toml::Value::Table(toml::toml! {
name = name
path = path
})
})
.collect::<Vec<_>>(),
);
let cargo_toml = toml::to_string_pretty(&cargo_toml)?;
fs::write(output_dir.join("Cargo.toml"), cargo_toml.clone())
.with_context(|| format!("Failed to write {cargo_toml:?}"))?;
Ok(())
}
fn invoke_build(current_dir: &Path) -> Result<()> {
let encoded_rustflags = ["-Dwarnings"].join("\x1f");
let mut build_command = Command::new("cargo");
build_command
.current_dir(current_dir)
.env_clear()
.env("PATH", env::var("PATH").unwrap_or_default())
.env("CARGO_ENCODED_RUSTFLAGS", encoded_rustflags)
.env("RUSTUP_HOME", env::var("RUSTUP_HOME").unwrap_or_default())
// Support compilation on stable rust
.env("RUSTC_BOOTSTRAP", "1")
.args([
"build",
"--release",
"-Zbuild-std=core",
"-Zbuild-std-features=panic_immediate_abort",
])
.arg("--target")
.arg(polkavm_linker::target_json_path(polkavm_linker::TargetJsonArgs::default()).unwrap());
if let Ok(toolchain) = env::var(OVERRIDE_RUSTUP_TOOLCHAIN_ENV_VAR) {
build_command.env("RUSTUP_TOOLCHAIN", &toolchain);
}
let build_res = build_command.output().expect("failed to execute process");
if build_res.status.success() {
return Ok(());
}
let stderr = String::from_utf8_lossy(&build_res.stderr);
eprintln!("{}", stderr);
bail!("Failed to build contracts");
}
/// Post-process the compiled code.
fn post_process(input_path: &Path, output_path: &Path) -> Result<()> {
let strip = env::var(OVERRIDE_STRIP_ENV_VAR).map_or(false, |value| value == "1");
let optimize = env::var(OVERRIDE_OPTIMIZE_ENV_VAR).map_or(true, |value| value == "1");
let mut config = polkavm_linker::Config::default();
config.set_strip(strip);
config.set_optimize(optimize);
let orig = fs::read(input_path).with_context(|| format!("Failed to read {input_path:?}"))?;
let linked = polkavm_linker::program_from_elf(
config,
polkavm_linker::TargetInstructionSet::Latest,
orig.as_ref(),
)
.map_err(|err| anyhow::format_err!("Failed to link polkavm program: {}", err))?;
fs::write(output_path, linked).with_context(|| format!("Failed to write {output_path:?}"))?;
Ok(())
}
/// Compile a Solidity contract using standard JSON interface.
fn compile_with_standard_json(
compiler: &str,
contracts_dir: &Path,
solidity_entries: &[&Entry],
) -> Result<serde_json::Value> {
let remappings = [format!("@revive/={INTERFACE_DIR}")];
let mut input_json = serde_json::json!({
"language": "Solidity",
"sources": {},
"settings": {
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": remappings,
"outputSelection":
serde_json::json!({
"*": {
"*": ["evm.bytecode", "evm.deployedBytecode"]
}
}),
}
});
// Add all Solidity files to the input
for entry in solidity_entries {
let source_code = fs::read_to_string(entry.path())
.with_context(|| format!("Failed to read Solidity source: {}", entry.path()))?;
let file_key = entry.path().split('/').last().unwrap_or(entry.name());
input_json["sources"][file_key] = serde_json::json!({
"content": source_code
});
}
let compiler_output = Command::new(compiler)
.current_dir(contracts_dir)
.arg("--allow-paths")
.arg(INTERFACE_DIR)
.arg("--standard-json")
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.with_context(|| {
format!(
"Failed to execute {compiler}. Make sure {compiler} is installed or \
set env variable `{SKIP_PALLET_REVIVE_FIXTURES}=1` to skip fixtures compilation."
)
})?;
let mut stdin = compiler_output.stdin.as_ref().unwrap();
stdin
.write_all(input_json.to_string().as_bytes())
.with_context(|| format!("Failed to write to {} stdin", compiler))?;
let _ = stdin;
let compiler_result = compiler_output
.wait_with_output()
.with_context(|| format!("Failed to wait for {} output", compiler))?;
if !compiler_result.status.success() {
let stderr = String::from_utf8_lossy(&compiler_result.stderr);
bail!("{} compilation failed: {}", compiler, stderr);
}
// Parse JSON output
let compiler_json: serde_json::Value = serde_json::from_slice(&compiler_result.stdout)
.with_context(|| format!("Failed to parse {} JSON output", compiler))?;
// Abort on errors
if let Some(errors) = compiler_json.get("errors") {
if errors
.as_array()
.unwrap()
.iter()
.any(|object| object.get("severity").unwrap().as_str().unwrap() == "error")
{
bail!(
"failed to compile the Solidity fixtures: {}",
serde_json::to_string_pretty(errors)?
);
}
}
Ok(compiler_json)
}
/// Extract bytecode from compiler JSON output and write binary files.
fn extract_and_write_bytecode(
compiler_json: &serde_json::Value,
out_dir: &Path,
file_suffix: &str,
bytecode_type: EvmByteCodeType,
) -> Result<()> {
if let Some(contracts) = compiler_json["contracts"].as_object() {
for (_file_key, file_contracts) in contracts {
if let Some(contract_map) = file_contracts.as_object() {
for (contract_name, contract_data) in contract_map {
// Navigate through the JSON path to find the bytecode
let mut current = contract_data;
for path_segment in ["evm", bytecode_type.json_key(), "object"] {
if let Some(next) = current.get(path_segment) {
current = next;
} else {
// Skip if path doesn't exist (e.g., contract has no bytecode)
continue;
}
}
if let Some(bytecode_obj) = current.as_str() {
let bytecode_hex = bytecode_obj.strip_prefix("0x").unwrap_or(bytecode_obj);
let binary_content = hex::decode(bytecode_hex).map_err(|e| {
anyhow::anyhow!("Failed to decode hex for {contract_name}: {e}")
})?;
let out_path = out_dir.join(format!("{}{}", contract_name, file_suffix));
fs::write(&out_path, binary_content).with_context(|| {
format!("Failed to write {out_path:?} for {contract_name}")
})?;
}
}
}
}
}
Ok(())
}
/// Compile Solidity contracts using both solc and resolc.
fn compile_solidity_contracts(
contracts_dir: &Path,
out_dir: &Path,
entries: &[Entry],
) -> Result<()> {
let solidity_entries: Vec<_> = entries
.iter()
.filter(|entry| matches!(entry.contract_type, ContractType::Solidity))
.collect();
if solidity_entries.is_empty() {
return Ok(());
}
let evm_only = vec!["HostEvmOnly"];
let solidity_entries_pvm: Vec<_> = solidity_entries
.iter()
.cloned()
.filter(|entry| !evm_only.contains(&entry.path.file_stem().unwrap().to_str().unwrap()))
.collect();
// Compile with solc for EVM bytecode
let json = compile_with_standard_json("solc", contracts_dir, &solidity_entries)?;
extract_and_write_bytecode(&json, out_dir, ".sol.bin", EvmByteCodeType::InitCode)?;
extract_and_write_bytecode(&json, out_dir, ".sol.runtime.bin", EvmByteCodeType::RuntimeCode)?;
// Compile with resolc for PVM bytecode
let json = compile_with_standard_json("resolc", contracts_dir, &solidity_entries_pvm)?;
extract_and_write_bytecode(&json, out_dir, ".resolc.polkavm", EvmByteCodeType::InitCode)?;
Ok(())
}
/// Write the compiled Rust contracts to the given output directory.
fn write_output(build_dir: &Path, out_dir: &Path, entries: Vec<Entry>) -> Result<()> {
for entry in entries {
if matches!(entry.contract_type, ContractType::Rust) {
post_process(
&build_dir
.join("target/riscv64emac-unknown-none-polkavm/release")
.join(entry.name()),
&out_dir.join(entry.out_filename()),
)?;
}
}
Ok(())
}
/// Generate the fixture_location.rs file with macros and sol! definitions.
fn generate_fixture_location(temp_dir: &Path, out_dir: &Path, entries: &[Entry]) -> Result<()> {
let mut file = fs::File::create(temp_dir.join("fixture_location.rs"))
.context("Failed to create fixture_location.rs")?;
let (fixtures, fixtures_resolc) = if env::var(SKIP_PALLET_REVIVE_FIXTURES).is_err() {
(
format!(
r#"Some(include_bytes!(concat!("{}", "/", $name, ".polkavm")))"#,
out_dir.display()
),
format!(
r#"Some(include_bytes!(concat!("{}", "/", $name, ".resolc.polkavm")))"#,
out_dir.display()
),
)
} else {
("None".into(), "None".into())
};
write!(
file,
r#"
#[allow(dead_code)]
const FIXTURE_DIR: &str = "{0}";
#[macro_export]
macro_rules! fixture {{
($name: literal) => {{
{fixtures}
}};
}}
#[macro_export]
macro_rules! fixture_resolc {{
($name: literal) => {{
{fixtures_resolc}
}};
}}
"#,
out_dir.display()
)
.context("Failed to write to fixture_location.rs")?;
// Generate sol! macros for Solidity contracts
for entry in entries.iter().filter(|e| matches!(e.contract_type, ContractType::Solidity)) {
let relative_path = format!("contracts/{}", entry.path().split('/').last().unwrap());
writeln!(file, r#"#[cfg(feature = "std")] alloy_core::sol!("{}");"#, relative_path)
.context("Failed to write sol! macro to fixture_location.rs")?;
}
Ok(())
}
pub fn main() -> Result<()> {
// input pathes
let fixtures_dir: PathBuf = env::var("CARGO_MANIFEST_DIR")?.into();
let contracts_dir = fixtures_dir.join("contracts");
// output pathes
let out_dir: PathBuf =
env::var("OUT_DIR").context("Failed to fetch `OUT_DIR` env variable")?.into();
let out_fixtures_dir = out_dir.join("fixtures");
let out_build_dir = out_dir.join("build");
fs::create_dir_all(&out_fixtures_dir).context("Failed to create output fixture directory")?;
fs::create_dir_all(&out_build_dir).context("Failed to create output build directory")?;
println!("cargo::rerun-if-env-changed={OVERRIDE_RUSTUP_TOOLCHAIN_ENV_VAR}");
println!("cargo::rerun-if-env-changed={OVERRIDE_STRIP_ENV_VAR}");
println!("cargo::rerun-if-env-changed={OVERRIDE_OPTIMIZE_ENV_VAR}");
// the fixtures have a dependency on the uapi crate
println!("cargo::rerun-if-changed={}", fixtures_dir.display());
let uapi_dir = fixtures_dir.parent().expect("parent dir exits; qed").join("uapi");
if uapi_dir.exists() {
println!("cargo::rerun-if-changed={}", uapi_dir.display());
}
let entries = collect_entries(&contracts_dir);
if entries.is_empty() {
return Ok(());
}
if env::var(SKIP_PALLET_REVIVE_FIXTURES).is_err() {
// Compile Rust contracts
let rust_entries: Vec<_> = entries
.iter()
.filter(|e| matches!(e.contract_type, ContractType::Rust))
.collect();
if !rust_entries.is_empty() {
create_cargo_toml(&fixtures_dir, rust_entries.into_iter(), &out_build_dir)?;
invoke_build(&out_build_dir)?;
write_output(&out_build_dir, &out_fixtures_dir, entries.clone())?;
}
// Compile Solidity contracts
compile_solidity_contracts(&contracts_dir, &out_fixtures_dir, &entries)?;
}
// Generate fixture_location.rs with sol! macros
generate_fixture_location(&out_dir, &out_fixtures_dir, &entries)?;
Ok(())
}
@@ -0,0 +1,24 @@
[package]
name = "contracts"
publish = false
version = "1.0.0"
edition = "2021"
# Make sure this is not included into the workspace
[workspace]
# Binary targets are injected dynamically by the build script.
[[bin]]
# All paths are injected dynamically by the build script.
[dependencies]
uapi = { package = 'pezpallet-revive-uapi', features = [
"unstable-hostfn",
], default-features = false }
hex-literal = { version = "0.4.1", default-features = false }
polkavm-derive = { version = "0.27.0" }
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
@@ -0,0 +1,132 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Arithmetic {
// We don't run the optimizer to avoid constant folding
function testArithmetic() public {
// ADD tests
uint256 addResult;
assembly {
addResult := add(20, 22)
}
require(addResult == 42, "ADD basic");
// SUB tests
uint256 subResult;
assembly {
subResult := sub(42, 20)
}
require(subResult == 22, "SUB basic");
// MUL tests
uint256 mulResult;
assembly {
mulResult := mul(20, 22)
}
require(mulResult == 440, "MUL basic");
// DIV tests
uint256 divResult;
assembly {
divResult := div(100, 5)
}
require(divResult == 20, "DIV basic");
// SDIV tests
int256 sdivResult1;
assembly {
sdivResult1 := sdiv(sub(0, 100), 5)
}
require(sdivResult1 == -20, "SDIV neg/pos");
int256 sdivResult2;
assembly {
sdivResult2 := sdiv(100, sub(0, 5))
}
require(sdivResult2 == -20, "SDIV pos/neg");
int256 sdivResult3;
assembly {
sdivResult3 := sdiv(sub(0, 100), sub(0, 5))
}
require(sdivResult3 == 20, "SDIV neg/neg");
// REM/MOD tests
uint256 modResult;
assembly {
modResult := mod(100, 7)
}
require(modResult == 2, "REM basic");
// SMOD tests
int256 smodResult1;
assembly {
smodResult1 := smod(sub(0, 100), 7)
}
require(smodResult1 == -2, "SMOD neg dividend");
int256 smodResult2;
assembly {
smodResult2 := smod(100, sub(0, 7))
}
require(smodResult2 == 2, "SMOD neg divisor");
// ADDMOD tests
uint256 addmodResult;
assembly {
addmodResult := addmod(10, 15, 7)
}
require(addmodResult == 4, "ADDMOD basic");
// MULMOD tests
uint256 mulmodResult;
assembly {
mulmodResult := mulmod(10, 15, 7)
}
require(mulmodResult == 3, "MULMOD basic");
// EXP tests
uint256 expResult1;
assembly {
expResult1 := exp(2, 3)
}
require(expResult1 == 8, "EXP basic");
uint256 expResult2;
assembly {
expResult2 := exp(10, 0)
}
require(expResult2 == 1, "EXP zero exponent");
uint256 expResult3;
assembly {
expResult3 := exp(0, 5)
}
require(expResult3 == 0, "EXP zero base");
// EXP overflow test: 2^256 mod 2^256 = 0
uint256 expResult;
assembly {
expResult := exp(2, 256)
}
require(expResult == 0, "EXP overflow");
// EXP test: 2^255 should not overflow
assembly {
expResult := exp(2, 255)
}
require(expResult == (1 << 255), "EXP 2^255");
// SIGNEXTEND tests
uint256 result1;
assembly {
result1 := signextend(0, 0xff)
}
require(result1 == type(uint256).max, "SIGNEXTEND negative byte");
uint256 result2;
assembly {
result2 := signextend(0, 0x7f)
}
require(result2 == 0x7f, "SIGNEXTEND positive byte");
}
}
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Bitwise {
function testBitwise() public pure {
require(5 < 10, "LT basic");
require(type(uint256).max - 1 < type(uint256).max, "LT max");
require(10 > 5, "GT basic");
require(type(uint256).max > type(uint256).max - 1, "GT max");
require(5 != 10, "NEQ basic");
require(10 == 10, "EQ basic");
require(type(uint256).max == type(uint256).max, "EQ max");
require(int256(-5) < int256(10), "SLT basic");
require(type(int256).min < 0, "SLT min");
require(int256(5) > int256(-10), "SGT basic");
require(0 > type(int256).min, "SGT min");
require((5 & 3) == 1, "AND basic");
require((5 | 3) == 7, "OR basic");
require((5 ^ 3) == 6, "XOR basic");
require(~uint256(0) == type(uint256).max, "NOT basic");
require((1 << 3) == 8, "SHL basic");
require((8 >> 3) == 1, "SHR basic");
}
}
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract BlockInfo {
function blockNumber() public view returns (uint64) {
return uint64(block.number);
}
function coinbase() public view returns (address) {
return block.coinbase;
}
function timestamp() public view returns (uint64) {
return uint64(block.timestamp);
}
function difficulty() public view returns (uint64) {
return uint64(block.difficulty);
}
function gaslimit() public view returns (uint64) {
return uint64(block.gaslimit);
}
function chainid() public view returns (uint64) {
return uint64(block.chainid);
}
function basefee() public view returns (uint64) {
return uint64(block.basefee);
}
}
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
contract Callee {
uint64 public stored;
function echo(uint64 _data) external pure returns (uint64 data) {
data = _data;
}
function whoSender() external view returns (address) {
return msg.sender;
}
function store(uint64 _data) external {
stored = _data;
}
function revert() public pure returns (uint64) {
require(false, "This is a revert");
return 42; // never reached
}
function invalid() public pure {
assembly {
invalid()
}
}
function stop() public pure {
assembly {
stop()
}
}
}
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
// Contract that always reverts in constructor
contract ChildRevert {
constructor() {
revert("ChildRevert: revert in constructor");
}
}
contract Caller {
function normal(address _callee, uint64 _value, bytes memory _data, uint64 _gas)
external
returns (bool success, bytes memory output)
{
(success, output) = _callee.call{value: _value, gas: _gas}(_data);
}
function delegate(address _callee, bytes memory _data, uint64 _gas)
external
returns (bool success, bytes memory output)
{
(success, output) = _callee.delegatecall{gas: _gas}(_data);
}
function staticCall(
// Don't rename to `static` (it's a Rust keyword).
address _callee,
bytes memory _data,
uint64 _gas
) external view returns (bool success, bytes memory output) {
(success, output) = _callee.staticcall{gas: _gas}(_data);
}
function create(bytes memory initcode) external payable returns (address addr) {
assembly {
// CREATE with no value
addr := create(0, add(initcode, 0x20), mload(initcode))
if iszero(addr) {
// bubble failure
let returnDataSize := returndatasize()
returndatacopy(0, 0, returnDataSize)
revert(0, returnDataSize)
}
}
}
function createRevert() external returns (address addr) {
try new ChildRevert() returns (ChildRevert c) {
addr = address(c);
} catch (bytes memory reason) {
revert(string(reason));
}
}
function create2(bytes memory initcode, bytes32 salt) external payable returns (address addr) {
assembly {
// CREATE2 with no value
addr := create2(0, add(initcode, 0x20), mload(initcode), salt)
if iszero(addr) {
// bubble failure
let returnDataSize := returndatasize()
returndatacopy(0, 0, returnDataSize)
revert(0, returnDataSize)
}
}
}
}
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
contract CallerWithConstructor {
CallerWithConstructorCallee callee;
constructor() {
callee = new CallerWithConstructorCallee();
}
function callBar() public view returns (uint64) {
return callee.bar();
}
}
contract CallerWithConstructorCallee {
function bar() public pure returns (uint64) {
return 42;
}
}
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract Counter {
uint256 public number;
constructor() {
number = 3;
}
function setNumber(uint256 newNumber) public returns (uint256) {
number = newNumber;
}
function increment() public {
number++;
}
}
contract NestedCounter {
Counter public counter;
uint256 public number;
constructor() {
counter = new Counter();
counter.setNumber(10);
number = 7;
}
function nestedNumber() public returns (uint256) {
uint256 currentNumber = counter.setNumber(number);
number++;
return currentNumber;
}
}
@@ -0,0 +1,4 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
contract Dummy {}
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Fibonacci {
function fib(uint64 n) public pure returns (uint64) {
if (n <= 1) {
return n;
}
return fib(n - 1) + fib(n - 2);
}
}
@@ -0,0 +1,60 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract Host {
function balance(address account) public view returns (uint64) {
return uint64(account.balance);
}
function extcodesizeOp(address account) public view returns (uint64) {
uint256 size;
assembly {
size := extcodesize(account)
}
return uint64(size);
}
function extcodehashOp(address account) public view returns (bytes32) {
bytes32 hash;
assembly {
hash := extcodehash(account)
}
return hash;
}
function blockhashOp(uint64 blockNumber) public view returns (bytes32) {
bytes32 hash;
assembly {
hash := blockhash(blockNumber)
}
return hash;
}
function sloadOp(uint64 slot) public view returns (uint64) {
uint256 value;
assembly {
value := sload(slot)
}
return uint64(value);
}
function sstoreOp(uint64 slot, uint64 value) public {
assembly {
sstore(slot, value)
}
}
function logOps() public {
assembly {
log0(0x01, 0x20)
log1(0x02, 0x20, 0x11)
log2(0x03, 0x20, 0x22, 0x33)
log3(0x04, 0x20, 0x44, 0x55, 0x66)
log4(0x05, 0x20, 0x77, 0x88, 0x99, 0xaa)
}
}
function selfbalance() public view returns (uint64) {
return uint64(address(this).balance);
}
}
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract HostEvmOnly {
function selfdestructOp(address payable recipient) public {
assembly {
selfdestruct(recipient)
}
}
function fallback(address payable recipient) public {
assembly {
selfdestruct(recipient)
}
}
function extcodecopyOp(address account, uint64 offset, uint64 size) public view returns (bytes memory code) {
code = new bytes(size);
assembly {
extcodecopy(account, add(code, 32), offset, size)
}
}
}
contract HostEvmOnlyFactory {
function createAndSelfdestruct(address payable recipient) public returns (address newContract) {
// Deploy a new instance of HostEvmOnly
HostEvmOnly newInstance = new HostEvmOnly();
newContract = address(newInstance);
// Call selfdestruct on the newly created contract
newInstance.selfdestructOp(recipient);
return newContract;
}
}
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract HostTransientMemory {
function transientMemoryTest(uint64 slot, uint64 a) public returns (uint64) {
uint256 value;
assembly {
tstore(slot, a)
}
value = 1;
assembly {
value := tload(slot)
}
return uint64(value - a);
}
}
@@ -0,0 +1,75 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract Memory {
/// @notice Expands memory to the specified size by writing a byte at that offset
/// @param memorySize The memory size in bytes to expand to
function expandMemory(uint64 memorySize) public pure returns (bool success) {
// Allocate memory by accessing a byte at the specified offset
// This will trigger memory expansion up to at least memorySize + 1
assembly {
// Store a single byte (0xFF) at the memory offset
// This forces the EVM to expand memory to accommodate this write
mstore8(memorySize, 0xFF)
}
return false;
}
function testMemory() public {
uint256 value = 0xfe;
assembly {
mstore(0, value)
}
uint256 result = 123;
assembly {
result := mload(0)
}
require(result == value, "Memory test failed");
for (uint256 i = 0; i < 32; i++) {
assembly {
mstore8(i, value)
}
}
assembly {
result := mload(0)
}
require(result == 0xfefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe, "Memory test failed");
assembly {
result := msize()
}
require(result == 96, "Memory size test failed");
}
function testMsize(uint64 offset) public returns (uint64) {
assembly {
mstore(offset, 123)
}
uint256 value;
assembly {
value := msize()
}
return uint64(value);
}
function testMcopy(uint64 dstOffset, uint64 offset, uint64 size, uint64 value) public returns (uint64) {
assembly {
mstore(dstOffset, 0)
}
for (uint256 i = 0; i < size; i += 32) {
assembly {
mstore(add(offset, i), value)
}
}
assembly {
mcopy(dstOffset, offset, size)
}
uint256 result = 123;
assembly {
result := mload(dstOffset)
}
return uint64(result);
}
}
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract System {
constructor(bool panic) {
if (panic) {
revert("Reverted because revert=true was set as constructor argument");
}
}
function keccak256Func(bytes memory data) public pure returns (bytes32) {
return keccak256(data);
}
function addressFunc() public view returns (address) {
return address(this);
}
function caller() public view returns (address) {
return msg.sender;
}
function callvalue() public payable returns (uint64) {
return uint64(msg.value);
}
function calldataload(uint64 offset) public pure returns (bytes32) {
bytes32 data;
assembly {
data := calldataload(offset)
}
return data;
}
function calldatasize() public pure returns (uint64) {
return uint64(msg.data.length);
}
function calldatacopy(uint64 destOffset, uint64 offset, uint64 size) public pure returns (bytes memory) {
bytes memory data = new bytes(size);
assembly {
calldatacopy(add(data, 0x20), offset, size)
}
return data;
}
function codesize() public pure returns (uint64) {
uint256 size;
assembly {
size := codesize()
}
return uint64(size);
}
function codecopy(uint64, /* destOffset */ uint64, /* offset */ uint64 size) public pure returns (bytes memory) {
bytes memory code = new bytes(size);
return code;
}
function returndatasize(address _callee, bytes memory _data, uint64 _gas) public returns (uint64) {
uint256 size;
_callee.staticcall{gas: _gas}(_data);
assembly {
size := returndatasize()
}
return uint64(size);
}
function returndatacopy(
address _callee,
bytes memory _data,
uint64 _gas,
uint64 destOffset,
uint64 offset,
uint64 size
) public returns (bytes memory) {
bytes memory data = new bytes(size);
_callee.staticcall{gas: _gas}(_data);
assembly {
returndatacopy(add(data, 0x20), offset, size)
}
return data;
}
function gas() public view returns (uint64) {
return uint64(gasleft());
}
}
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import "@revive/ISystem.sol";
contract Terminate {
uint8 public constant METHOD_PRECOMPILE = 0;
uint8 public constant METHOD_DELEGATE_CALL = 1;
uint8 public constant METHOD_SYSCALL = 2;
receive() external payable {}
constructor(bool skip, uint8 method, address beneficiary) payable {
if (skip) {
return;
}
_terminate(method, beneficiary);
}
function echo(uint value) external pure returns (uint) {
return value;
}
function terminate(uint8 method, address beneficiary) external {
_terminate(method, beneficiary);
}
function indirectDelegateTerminate(address beneficiary) external {
bytes memory data = abi.encodeWithSelector(this.terminate.selector, METHOD_PRECOMPILE, beneficiary);
(bool success, bytes memory returnData) = address(this).delegatecall(data);
if (!success) {
assembly {
revert(add(returnData, 0x20), mload(returnData))
}
}
}
/// Call terminate and forward any revert.
/// Internal dispatcher: executes termination by
/// - delegatecall (METHOD_DELEGATE_CALL) to system precompile
/// - direct call (METHOD_PRECOMPILE) to system precompile
/// - selfdestruct (METHOD_SYSCALL) sending balance to beneficiary
function _terminate(uint8 method, address beneficiary) private {
bytes memory data = abi.encodeWithSelector(ISystem.terminate.selector, beneficiary);
(bool success, bytes memory returnData) = (false, "");
if (method == METHOD_DELEGATE_CALL) {
(success, returnData) = SYSTEM_ADDR.delegatecall(data);
} else if (method == METHOD_PRECOMPILE) {
(success, returnData) = SYSTEM_ADDR.call(data);
} else if (method == METHOD_SYSCALL) {
assembly {
selfdestruct(beneficiary)
}
// selfdestruct halts execution, so if we reach here, something went wrong.
revert("selfdestruct opcode returned");
} else {
revert("Invalid TerminateMethod");
}
if (!success) {
assembly {
revert(add(returnData, 0x20), mload(returnData))
}
}
}
}
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import { Terminate } from "./Terminate.sol";
import { TerminateDelegator } from "./TerminateDelegator.sol";
contract TerminateCaller {
Terminate inner;
TerminateDelegator innerCaller;
receive() external payable {}
constructor() payable {}
function createAndTerminateTwice(uint value, uint8 method1, uint8 method2, address beneficiary) external returns (address) {
inner = new Terminate{value: value}(true, method1, beneficiary);
inner.terminate(method1, beneficiary);
inner.terminate(method2, beneficiary);
return address(inner);
}
function sendFundsAfterTerminateAndCreate(uint value, uint8 method, address beneficiary) external returns (address) {
inner = new Terminate(true, method, beneficiary);
inner.terminate(method, beneficiary);
(bool success, ) = address(inner).call{value: value}("");
require(success, "terminate reverted");
return address(inner);
}
function sendFundsAfterTerminate(address payable terminate_addr, uint value, uint8 method, address beneficiary) external {
terminate_addr.call(abi.encodeWithSelector(Terminate.terminate.selector, method, beneficiary));
(bool success, ) = terminate_addr.call{value: value}("");
require(success, "terminate reverted");
}
function revertAfterTerminate(address terminate_addr, uint8 method, address beneficiary) external {
terminate_addr.call(abi.encodeWithSelector(Terminate.terminate.selector, method, beneficiary));
revert("Deliberate revert");
}
function delegateCallTerminate(uint value, uint8 method, address beneficiary) external returns (address, address) {
inner = new Terminate(true, method, beneficiary);
innerCaller = new TerminateDelegator{value: value}();
bytes memory data = abi.encodeWithSelector(innerCaller.delegateCallTerminate.selector, address(inner), method, beneficiary);
(bool success, ) = address(innerCaller).call(data);
require(success, "delegatecall terminate reverted");
return (address(innerCaller), address(inner));
}
function callAfterTerminate(uint value, uint8 method) external returns (address, uint) {
inner = new Terminate(true, method, payable(address(this)));
inner.terminate(0, payable(address(this)));
bytes memory data = abi.encodeWithSelector(inner.echo.selector, value);
(bool success, bytes memory returnData) = address(inner).call(data);
require(success, "call after terminate reverted");
return (address(inner), returnData.length == 32 ? abi.decode(returnData, (uint)) : 0);
}
}
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import { Terminate } from "./Terminate.sol";
contract TerminateDelegator {
receive() external payable {}
constructor() payable {}
function delegateCallTerminate(address terminate_addr, uint8 method, address beneficiary) external {
bytes memory data = abi.encodeWithSelector(Terminate.terminate.selector, method, beneficiary);
(bool success, ) = terminate_addr.delegatecall(data);
require(success, "delegatecall terminate reverted");
}
}
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract TransactionInfo {
function origin() public view returns (address) {
return tx.origin;
}
function gasprice() public view returns (uint64) {
return uint64(tx.gasprice);
}
function blobhash(uint64 index) public view returns (bytes32) {
return blobhash(index);
}
}
@@ -0,0 +1,33 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{u64_output, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
let balance = u64_output!(api::balance,);
assert_eq!(balance, 0);
}
@@ -0,0 +1,36 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, u64_output, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(address: &[u8; 20],);
let reported_free_balance = u64_output!(api::balance_of, address);
assert_ne!(reported_free_balance, 0);
}
@@ -0,0 +1,36 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Returns the base fee back to the caller.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api, ReturnFlags};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
let mut buf = [0; 32];
api::base_fee(&mut buf);
api::return_value(ReturnFlags::empty(), &buf);
}
@@ -0,0 +1,46 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Create a basic block that is larger than we allow.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use core::arch::asm;
// Export that is never called. We can put code here that should be in the binary
// but is never supposed to be run.
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call_never() {
// Stores cannot be optimized away because the optimizer cannot
// know whether they have side effects.
let value: u32 = 42;
unsafe {
// Repeat 1001 times to intentionally exceed the allowed basic block limit (1000)
asm!(".rept 1001", "sw {x}, 0(sp)", ".endr", x = in(reg) value);
}
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {}
@@ -0,0 +1,37 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(expected: &[u8; 20],);
let mut received = [0; 20];
api::block_author(&mut received);
assert_eq!(expected, &received);
}
@@ -0,0 +1,37 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(block_number: &[u8; 32], block_hash: &[u8; 32],);
let mut buf = [0; 32];
api::block_hash(block_number, &mut &mut buf);
assert_eq!(&buf[..], block_hash);
}
@@ -0,0 +1,49 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This calls another contract as passed as its account id.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
callee_input: [u8; 4],
callee_addr: &[u8; 20],
);
// Call the callee
api::call(
uapi::CallFlags::empty(),
callee_addr,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
callee_input,
None,
)
.unwrap();
}
@@ -0,0 +1,57 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This calls another contract as passed as its account id.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, u256_bytes, HostFn, HostFnImpl as api, ReturnErrorCode, ReturnFlags};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
512,
callee_addr: &[u8; 20],
value: u64,
callee_input: [u8],
);
// Call the callee
let mut output = [0u8; 512];
let output = &mut &mut output[..];
match api::call(
uapi::CallFlags::empty(),
callee_addr,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&u256_bytes(value), // Value transferred to the contract.
callee_input,
Some(output),
) {
Ok(_) => api::return_value(uapi::ReturnFlags::empty(), output),
Err(ReturnErrorCode::CalleeReverted) => api::return_value(ReturnFlags::REVERT, output),
Err(_) => panic!(),
}
}
@@ -0,0 +1,63 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This calls another contract and returns the returncode and output.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
polkavm_derive::min_stack_size!(256 * 1024);
use uapi::{input, u256_bytes, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
512,
callee_addr: &[u8; 20],
value: u64,
callee_input: [u8],
);
// the first 4 bytes are reserved for the return code
let mut output = [0u8; 128 * 1024];
let output_ptr = &mut &mut output[4..];
let code = match api::call(
uapi::CallFlags::empty(),
callee_addr,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&u256_bytes(value), // Value transferred to the contract.
callee_input,
Some(output_ptr),
) {
Ok(_) => 0,
Err(code) => code as u32,
};
let len = 4 + output_ptr.len();
output[0..4].copy_from_slice(&code.to_le_bytes());
api::return_value(uapi::ReturnFlags::empty(), &output[..len]);
}
@@ -0,0 +1,47 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This fixture calls the `callerIsOrigin` function on the
//! `System` pre-compile.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
let mut output = [0u8; 32];
let _ = api::call(
uapi::CallFlags::READ_ONLY,
&uapi::SYSTEM_PRECOMPILE_ADDR,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
&uapi::solidity_selector("callerIsOrigin()"),
Some(&mut &mut output[..]),
).unwrap();
api::return_value(uapi::ReturnFlags::empty(), &output);
}
@@ -0,0 +1,47 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This fixture calls the `callerIsRoot` function on the
//! `System` pre-compile.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
let mut output = [0u8; 32];
let _ = api::call(
uapi::CallFlags::READ_ONLY,
&uapi::SYSTEM_PRECOMPILE_ADDR,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
&uapi::solidity_selector("callerIsRoot()"),
Some(&mut &mut output[..]),
).unwrap();
api::return_value(uapi::ReturnFlags::empty(), &output);
}
@@ -0,0 +1,53 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Expects a call data of [0xFF; 32] and executes the test vectors from
//! [https://www.evm.codes/?fork=cancun#37] and some additional tests.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api};
const TEST_DATA: [u8; 32] = [
255, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
];
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
let mut buf = [0; 32];
api::call_data_copy(&mut &mut buf[..], 0);
assert_eq!(buf, [255; 32]);
api::call_data_copy(&mut &mut buf[..8], 31);
assert_eq!(buf, TEST_DATA);
api::call_data_copy(&mut &mut buf[..], 32);
assert_eq!(buf, [0; 32]);
let mut buf = [255; 32];
api::call_data_copy(&mut &mut buf[..], u32::MAX);
assert_eq!(buf, [0; 32]);
}
@@ -0,0 +1,44 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This uses the call data load API to first the first input byte.
//! This single input byte is used as the offset for a second call
//! to the call data load API.
//! The output of the second API call is returned.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api, ReturnFlags};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
let mut buf = [0; 32];
api::call_data_load(&mut buf, 0);
let offset = buf[31] as u32;
let mut buf = [0; 32];
api::call_data_load(&mut buf, offset);
api::return_value(ReturnFlags::empty(), &buf);
}
@@ -0,0 +1,34 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Returns the call data size back to the caller.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api, ReturnFlags};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
api::return_value(ReturnFlags::empty(), &api::call_data_size().to_le_bytes());
}
@@ -0,0 +1,120 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This tests that the correct output data is written when the provided
//! output buffer length is smaller than what was actually returned during
//! calls and instantiations.
//!
//! To not need an additional callee fixture, we call ourself recursively
//! and also instantiate our own code hash (constructor and recursive calls
//! always return `BUF_SIZE` bytes of data).
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api, u256_bytes};
const BUF_SIZE: usize = 8;
static DATA: [u8; BUF_SIZE] = [1, 2, 3, 4, 5, 6, 7, 8];
/// Call `callee_address` with an output buf of size `N`
/// and expect the call output to match `expected_output`.
fn assert_call<const N: usize>(callee_address: &[u8; 20], expected_output: [u8; BUF_SIZE]) {
let mut output_buf = [0u8; BUF_SIZE];
let output_buf_capped = &mut &mut output_buf[..N];
api::call(
uapi::CallFlags::ALLOW_REENTRY,
callee_address,
u64::MAX,
u64::MAX,
&[u8::MAX; 32],
&[0u8; 32],
&[],
Some(output_buf_capped),
)
.unwrap();
// The (capped) output buf should get properly resized
assert_eq!(output_buf_capped.len(), N);
assert_eq!(output_buf, expected_output);
}
/// Instantiate this contract with an output buf of size `N`
/// and expect the instantiate output to match `expected_output`.
fn assert_instantiate<const N: usize>(expected_output: [u8; BUF_SIZE]) {
let mut output_buf1 = [0u8; 32];
let output1 = &mut &mut output_buf1[..];
let _ = api::call(
uapi::CallFlags::READ_ONLY,
&uapi::SYSTEM_PRECOMPILE_ADDR,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
&uapi::solidity_selector("ownCodeHash()"),
Some(output1),
).unwrap();
assert_ne!(output_buf1, [0u8; 32]);
let mut output_buf = [0u8; BUF_SIZE];
let output_buf_capped = &mut &mut output_buf[..N];
api::instantiate(
u64::MAX,
u64::MAX,
&[u8::MAX; 32],
&u256_bytes(0),
output_buf1.clone().as_slice(),
None,
Some(output_buf_capped),
None,
)
.unwrap();
// The (capped) output buf should get properly resized
assert_eq!(output_buf_capped.len(), N);
assert_eq!(output_buf, expected_output);
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {
api::return_value(uapi::ReturnFlags::empty(), &DATA);
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
let mut caller_address = [0u8; 20];
api::caller(&mut caller_address);
let mut callee_address = [0u8; 20];
api::address(&mut callee_address);
// we already recurse; return data
if caller_address == callee_address {
api::return_value(uapi::ReturnFlags::empty(), &DATA);
}
assert_call::<0>(&callee_address, [0; 8]);
assert_call::<4>(&callee_address, [1, 2, 3, 4, 0, 0, 0, 0]);
assert_instantiate::<0>([0; 8]);
assert_instantiate::<4>([1, 2, 3, 4, 0, 0, 0, 0]);
}
@@ -0,0 +1,51 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This fixture calls the `ownCodeHash` function on the
//! `System` pre-compile.
#![allow(unused_imports)]
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use core::num::NonZero;
use uapi::{HostFn, HostFnImpl as api, u256_bytes};
use hex_literal::hex;
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() { }
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
let mut output_buf = [0u8; 32];
let output = &mut &mut output_buf[..];
let _ = api::call(
uapi::CallFlags::READ_ONLY,
&uapi::SYSTEM_PRECOMPILE_ADDR,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
&uapi::solidity_selector("ownCodeHash()"),
Some(output),
).unwrap();
assert_ne!(output_buf, [0u8; 32]);
api::return_value(uapi::ReturnFlags::empty(), &output_buf);
}
@@ -0,0 +1,57 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This calls the supplied dest and transfers 100 balance during this call and copies
//! the return code of this call to the output buffer.
//! It also forwards its input to the callee.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
100,
callee_addr: &[u8; 20],
value: &[u8; 32],
input: [u8],
);
// Call the callee
let err_code = match api::call(
uapi::CallFlags::empty(),
callee_addr,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
value, // Value transferred to the contract.
input,
None,
) {
Ok(_) => 0u32,
Err(code) => code as u32,
};
api::return_value(uapi::ReturnFlags::empty(), &err_code.to_le_bytes());
}
@@ -0,0 +1,7 @@
contract CallSelfWithDust {
function f() external payable {}
function call() public payable {
this.f{value: 10}();
}
}
@@ -0,0 +1,51 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This fixture calls the account_id with the flags and value.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, u256_bytes, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
256,
callee_addr: &[u8; 20],
flags: u32,
value: u64,
forwarded_input: [u8],
);
api::call(
uapi::CallFlags::from_bits(flags).unwrap(),
callee_addr,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&u256_bytes(value), // Value transferred to the contract.
forwarded_input,
None,
)
.unwrap();
}
@@ -0,0 +1,51 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
polkavm_derive::min_stack_size!(512 * 1024);
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
input_size: u32,
);
let input_buf = [0u8; 256 * 1024];
let address = [1u8; 20];
// Call the callee
api::call(
uapi::CallFlags::empty(),
&address,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&[0; 32], // Value transferred to the contract.
&input_buf[..input_size as usize],
None,
).unwrap();
}
@@ -0,0 +1,52 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This fixture calls the account_id with the 2D Weight limit.
//! It returns the result of the call as output data.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
256,
callee_addr: &[u8; 20],
ref_time: u64,
proof_size: u64,
forwarded_input: [u8],
);
api::call(
uapi::CallFlags::empty(),
callee_addr,
ref_time,
proof_size,
&[u8::MAX; 32], // No deposit limit.
&[0u8; 32], // value transferred to the contract.
forwarded_input,
None,
)
.unwrap();
}
@@ -0,0 +1,49 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This calls another contract as passed as its account id.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
value: &[u8; 32],
callee_addr: &[u8; 20],
);
// Call the callee
api::call(
uapi::CallFlags::empty(),
callee_addr,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
value, // Value transferred to the contract.
&[0u8; 0], // input
None,
)
.unwrap();
}
@@ -0,0 +1,166 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, u256_bytes, HostFn, HostFnImpl as api, ReturnErrorCode};
const INPUT: [u8; 8] = [0u8, 1, 34, 51, 68, 85, 102, 119];
const REVERTED_INPUT: [u8; 7] = [1u8, 34, 51, 68, 85, 102, 119];
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(code_hash: &[u8; 32], load_code_ref_time: u64, load_code_proof_size: u64,);
// The value to transfer on instantiation and calls. Chosen to be greater than existential
// deposit.
let value = u256_bytes(32_768_000_000u64);
let salt = [0u8; 32];
// Callee will use the first 4 bytes of the input to return an exit status.
let mut input_deploy = [0; 32 + INPUT.len()];
input_deploy[..32].copy_from_slice(code_hash);
input_deploy[32..].copy_from_slice(&INPUT);
let mut reverted_input_deploy = [0; 32 + REVERTED_INPUT.len()];
reverted_input_deploy[..32].copy_from_slice(code_hash);
reverted_input_deploy[32..].copy_from_slice(&REVERTED_INPUT);
// Fail to deploy the contract since it returns a non-zero exit status.
let res = api::instantiate(
u64::MAX, /* How much ref_time weight to devote for the execution. u64::MAX = use
* all. */
u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&value,
&reverted_input_deploy,
None,
None,
Some(&salt),
);
assert!(matches!(res, Err(ReturnErrorCode::CalleeReverted)));
// Fail to deploy the contract due to insufficient ref_time weight.
let res = api::instantiate(
1u64, // too little ref_time weight
u64::MAX, /* How much proof_size weight to devote for the execution. u64::MAX =
* use all. */
&[u8::MAX; 32], // No deposit limit.
&value,
&input_deploy,
None,
None,
Some(&salt),
);
assert!(matches!(res, Err(ReturnErrorCode::OutOfResources)));
// Fail to deploy the contract due to insufficient proof_size weight.
let res = api::instantiate(
u64::MAX, /* How much ref_time weight to devote for the execution. u64::MAX = use
* all. */
1u64, // Too little proof_size weight
&[u8::MAX; 32], // No deposit limit.
&value,
&input_deploy,
None,
None,
Some(&salt),
);
assert!(matches!(res, Err(ReturnErrorCode::OutOfResources)));
// Deploy the contract successfully.
let mut callee = [0u8; 20];
api::instantiate(
u64::MAX, /* How much ref_time weight to devote for the execution. u64::MAX = use
* all. */
u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&value,
&input_deploy,
Some(&mut callee),
None,
Some(&salt),
)
.unwrap();
// Call the new contract and expect it to return failing exit code.
let res = api::call(
uapi::CallFlags::empty(),
&callee,
u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&value,
&REVERTED_INPUT,
None,
);
assert!(matches!(res, Err(ReturnErrorCode::CalleeReverted)));
// Fail to call the contract due to insufficient ref_time weight.
let res = api::call(
uapi::CallFlags::empty(),
&callee,
load_code_ref_time, // just enough to load the contract
load_code_proof_size, // just enough to load the contract
&[u8::MAX; 32], // No deposit limit.
&value,
&INPUT,
None,
);
assert!(matches!(res, Err(ReturnErrorCode::OutOfResources)));
// Fail to call the contract due to insufficient proof_size weight.
let mut output = [0u8; 4];
let res = api::call(
uapi::CallFlags::empty(),
&callee,
u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all.
load_code_proof_size, // just enough to load the contract
&[u8::MAX; 32], // No deposit limit.
&value,
&INPUT,
Some(&mut &mut output[..]),
);
assert!(matches!(res, Err(ReturnErrorCode::CalleeReverted)));
let mut decode_buf = [0u8; 4];
decode_buf[..4].copy_from_slice(&output[..4]);
assert_eq!(u32::from_le_bytes(decode_buf), ReturnErrorCode::OutOfResources as u32);
// Call the contract successfully.
let mut output = [0u8; 4];
api::call(
uapi::CallFlags::empty(),
&callee,
u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&value,
&INPUT,
Some(&mut &mut output[..]),
)
.unwrap();
assert_eq!(&output, &INPUT[4..])
}
@@ -0,0 +1,47 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This fixture calls caller_is_origin `n` times.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(n: u32, );
for _ in 0..n {
let _ = api::call(
uapi::CallFlags::READ_ONLY,
&uapi::SYSTEM_PRECOMPILE_ADDR,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
&uapi::solidity_selector("callerIsOrigin()"),
None,
).unwrap();
}
}
@@ -0,0 +1,36 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api, ReturnFlags};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {
call()
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
let mut buf = [0; 32];
api::chain_id(&mut buf);
api::return_value(ReturnFlags::empty(), &buf);
}
@@ -0,0 +1,86 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This contract tests the storage APIs. It sets and clears storage values using the different
//! versions of the storage APIs.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
include!("../sol_utils.rs");
use uapi::{HostFn, HostFnImpl as api, StorageFlags};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
fn test_storage_operations(flags: StorageFlags) {
const KEY: [u8; 32] = [1u8; 32];
const VALUE_A: [u8; 32] = [4u8; 32];
const ZERO: [u8; 32] = [0u8; 32];
let mut small_value_padded = [0u8; 32];
small_value_padded[0] = 5;
small_value_padded[1] = 6;
small_value_padded[2] = 7;
clear_storage::<api>(flags, &KEY);
assert_eq!(contains_storage::<api>(flags, &KEY), None);
let existing = api::set_storage_or_clear(flags, &KEY, &VALUE_A);
assert_eq!(existing, None);
let mut stored: [u8; 32] = [0u8; 32];
api::get_storage_or_zero(flags, &KEY, &mut stored);
assert_eq!(stored, VALUE_A);
let existing = api::set_storage_or_clear(flags, &KEY, &ZERO);
assert_eq!(existing, Some(32));
let mut cleared: [u8; 32] = [1u8; 32];
api::get_storage_or_zero(flags, &KEY, &mut cleared);
assert_eq!(cleared, ZERO);
assert_eq!(contains_storage::<api>(flags, &KEY), None);
// Test retrieving a value smaller than 32 bytes
api::set_storage_or_clear(flags, &KEY, &small_value_padded);
let mut retrieved = [255u8; 32];
api::get_storage_or_zero(flags, &KEY, &mut retrieved);
assert_eq!(retrieved[0], 5);
assert_eq!(retrieved[1], 6);
assert_eq!(retrieved[2], 7);
for i in 3..32 {
assert_eq!(retrieved[i], 0, "Byte at position {} should be zero", i);
}
// Clean up
clear_storage::<api>(flags, &KEY);
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
// Test with regular storage
test_storage_operations(StorageFlags::empty());
// Test with transient storage
test_storage_operations(StorageFlags::TRANSIENT);
}
@@ -0,0 +1,40 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
address: &[u8; 20],
expected_code_hash: &[u8; 32],
);
let mut code_hash = [0u8; 32];
api::code_hash(address, &mut code_hash);
assert!(&code_hash == expected_code_hash);
}
@@ -0,0 +1,42 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{u64_output, HostFn, HostFnImpl as api, ReturnFlags};
fn decide_my_fate() -> ! {
match u64_output!(api::value_transferred,) {
0 => api::consume_all_gas(),
1 => api::return_value(ReturnFlags::REVERT, &[]),
_ => api::return_value(ReturnFlags::empty(), &[]),
}
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {
decide_my_fate();
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
decide_my_fate();
}
@@ -0,0 +1,39 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(code_hash: &[u8; 32],);
let mut value = [0; 32];
api::value_transferred(&mut value);
// Deploy the contract with no salt (equivalent to create1).
api::instantiate(u64::MAX, u64::MAX, &[u8::MAX; 32], &value, code_hash, None, None, None)
.unwrap();
}
@@ -0,0 +1,49 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(128, code_hash: [u8],);
let mut value = [0; 32];
api::value_transferred(&mut value);
// Deploy the contract with salt (equivalent to create2).
let salt = [1u8; 32];
api::instantiate(
u64::MAX,
u64::MAX,
&[u8::MAX; 32],
&value,
code_hash,
None,
None,
Some(&salt),
)
.unwrap();
}
@@ -0,0 +1,62 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This calls another contract as passed as its account id. It also creates some storage.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api, StorageFlags};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
buffer,
input: [u8; 4],
callee: &[u8; 20],
deposit_limit: &[u8; 32],
);
// create 4 byte of storage before calling
api::set_storage(StorageFlags::empty(), buffer, &[1u8; 4]);
// Call the callee
let ret = api::call(
uapi::CallFlags::empty(),
callee,
u64::MAX, /* How much ref_time weight to devote for the execution. u64::MAX = use all
* resources. */
u64::MAX, /* How much proof_size weight to devote for the execution. u64::MAX = use all
* resources. */
deposit_limit,
&[0u8; 32], // Value transferred to the contract.
input,
None,
);
if let Err(code) = ret {
api::return_value(uapi::ReturnFlags::REVERT, &(code as u32).to_le_bytes());
};
// create 8 byte of storage after calling
// item of 12 bytes because we override 4 bytes
api::set_storage(StorageFlags::empty(), buffer, &[1u8; 12]);
}
@@ -0,0 +1,73 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This instantiates another contract and passes some input to its constructor.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, u256_bytes, HostFn, HostFnImpl as api, StorageFlags};
static BUFFER: [u8; 16 * 1024 + 1] = [0u8; 16 * 1024 + 1];
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
code_hash: &[u8; 32],
input: [u8; 4],
deposit_limit: &[u8; 32],
);
let len = u32::from_le_bytes(input.try_into().unwrap());
let data = &BUFFER[..len as usize];
let mut key = [0u8; 32];
key[0] = 1;
api::set_storage(StorageFlags::empty(), &key, data);
let value = u256_bytes(10_000_000_000u64);
let salt = [0u8; 32];
let mut address = [0u8; 20];
let mut deploy_input = [0; 32 + 4];
deploy_input[..32].copy_from_slice(code_hash);
deploy_input[32..].copy_from_slice(&input);
let ret = api::instantiate(
u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all.
deposit_limit,
&value,
&deploy_input,
Some(&mut address),
None,
Some(&salt),
);
if let Err(code) = ret {
api::return_value(uapi::ReturnFlags::REVERT, &(code as u32).to_le_bytes());
};
// fail in the caller
key[1] = 1;
api::set_storage(StorageFlags::empty(), &key, data);
// Return the deployed contract address.
api::return_value(uapi::ReturnFlags::empty(), &address);
}
@@ -0,0 +1,60 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This calls another contract as passed as its account id. It also creates some transient storage.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api, StorageFlags};
static BUFFER: [u8; 416] = [0u8; 416];
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
buffer,
len: u32,
input: [u8; 4],
callee: &[u8; 20],
);
let rounds = len as usize / BUFFER.len();
let rest = len as usize / BUFFER.len();
for i in 0..rounds {
api::set_storage(StorageFlags::TRANSIENT, &i.to_le_bytes(), &BUFFER);
}
api::set_storage(StorageFlags::TRANSIENT, &u32::MAX.to_le_bytes(), &BUFFER[..rest]);
// Call the callee
api::call(
uapi::CallFlags::empty(),
callee,
u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = all.
u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = all.
&[u8::MAX; 32], // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
input,
None,
)
.unwrap();
}
@@ -0,0 +1,47 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
/// Called by the tests.
///
/// The input bytes encode the data that is directly fed into the Keccak-256 bit
/// crypto hash function. The result is put into the output buffer.
///
/// After contract execution the test driver then asserts that the returned
/// values are equal to the expected bytes for the input and hash function.
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
256,
input: [u8],
);
let mut output = [0u8; 32];
api::hash_keccak_256(input, &mut output);
api::return_value(uapi::ReturnFlags::empty(), &output);
}
@@ -0,0 +1,62 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api, StorageFlags};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
address: &[u8; 20],
ref_time: u64,
proof_size: u64,
);
let mut key = [0u8; 32];
key[0] = 1u8;
let mut value = [0u8; 32];
let value = &mut &mut value[..];
value[0] = 2u8;
api::set_storage(StorageFlags::empty(), &key, value);
api::get_storage(StorageFlags::empty(), &key, value).unwrap();
assert!(value[0] == 2u8);
let input = [0u8; 0];
api::delegate_call(
uapi::CallFlags::empty(),
address,
ref_time,
proof_size,
&[u8::MAX; 32],
&input,
None,
)
.unwrap();
api::get_storage(StorageFlags::empty(), &key, value).unwrap();
assert!(value[0] == 1u8);
}
@@ -0,0 +1,58 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, u256_bytes, HostFn, HostFnImpl as api, StorageFlags};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
address: &[u8; 20],
deposit_limit: u64,
);
let input = [0u8; 0];
let ret = api::delegate_call(
uapi::CallFlags::empty(),
address,
u64::MAX,
u64::MAX,
&u256_bytes(deposit_limit),
&input,
None,
);
if let Err(code) = ret {
api::return_value(uapi::ReturnFlags::REVERT, &(code as u32).to_le_bytes());
};
let mut key = [0u8; 32];
key[0] = 1u8;
let mut value = [0u8; 32];
api::get_storage(StorageFlags::empty(), &key, &mut &mut value[..]).unwrap();
assert!(value[0] == 1u8);
}
@@ -0,0 +1,49 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{u64_output, HostFn, HostFnImpl as api, StorageFlags};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
let mut key = [0u8; 32];
key[0] = 1u8;
// Place a value in storage.
let mut value = [0u8; 32];
let value = &mut &mut value[..];
value[0] = 1u8;
api::set_storage(StorageFlags::empty(), &key, value);
// Assert that `value_transferred` is equal to the value
// passed to the `caller` contract: 1337.
let value = u64_output!(api::value_transferred,);
assert_eq!(value, 1337_000_000);
// Assert that ALICE is the caller of the contract.
let mut caller = [0u8; 20];
api::caller(&mut caller);
assert_eq!(caller, [1u8; 20]);
}
@@ -0,0 +1,50 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(address: &[u8; 20],);
let mut output = [0; 512];
let ptr = &mut &mut output[..];
// Delegate call into passed address.
let input = [0u8; 0];
api::delegate_call(
uapi::CallFlags::empty(),
address,
u64::MAX,
u64::MAX,
&[u8::MAX; 32],
&input,
Some(ptr),
)
.unwrap();
assert_eq!(ptr.len(), 0);
}
@@ -0,0 +1,67 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{u256_bytes, u64_output, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
let balance = u64_output!(api::balance,);
let mut output_buf = [0u8; 32];
let output = &mut &mut output_buf[..];
let _ = api::call(
uapi::CallFlags::READ_ONLY,
&uapi::SYSTEM_PRECOMPILE_ADDR,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
&uapi::solidity_selector("minimumBalance()"),
Some(output),
).unwrap();
assert_ne!(output_buf, [0u8; 32]);
let mut u64_buf = [0u8; 8];
u64_buf[..8].copy_from_slice(&output_buf[24..32]);
let minimum_balance = u64::from_be_bytes(u64_buf);
// Make the transferred value exceed the balance by adding the minimum balance.
let balance = balance + minimum_balance;
// Try to self-destruct by sending more balance to the 0 address.
// The call will fail because a contract transfer has a keep alive requirement.
let res = api::call(
uapi::CallFlags::empty(),
&[0u8; 20],
0,
0,
&[u8::MAX; 32],
&u256_bytes(balance),
&[],
None,
);
assert!(matches!(res, Err(uapi::ReturnErrorCode::TransferFailed)));
}
@@ -0,0 +1,41 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api, ReturnFlags};
// Export that is never called. We can put code here that should be in the binary
// but is never supposed to be run.
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call_never() {
// Make sure the 0xDEADBEEF pattern appears in the binary by
// making it opaque to the optimizer. The benchmarking code will
// just find and replace this pattern to make the code unique when
// necessary.
api::return_value(ReturnFlags::empty(), &[0xDE, 0xAD, 0xBE, 0xEF]);
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {}
@@ -0,0 +1,37 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {
let buffer = [1u8, 2, 3, 4];
let topics = [[42u8; 32]; 1];
api::deposit_event(&topics, &buffer);
api::return_value(uapi::ReturnFlags::empty(), &buffer);
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
unreachable!()
}
@@ -0,0 +1,39 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
static BUFFER: [u8; 64 * 1024 + 1] = [0u8; 64 * 1024 + 1];
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(len: u32,);
let data = &BUFFER[..len as usize];
let topics = [[0u8; 32]; 0];
api::deposit_event(&topics, data);
}
@@ -0,0 +1,36 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(address: &[u8; 20], expected: u64,);
let received = api::code_size(address);
assert_eq!(expected, received);
}
@@ -0,0 +1,33 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {}
#[no_mangle]
pub extern "C" fn add(a: f32, b: f32) -> f32 {
a + b
}
@@ -0,0 +1,32 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api, ReturnFlags};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
api::return_value(ReturnFlags::empty(), &api::gas_left().to_le_bytes());
}
@@ -0,0 +1,34 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Returns the block ref_time limit back to the caller.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api, ReturnFlags};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
api::return_value(ReturnFlags::empty(), &api::gas_limit().to_le_bytes());
}
@@ -0,0 +1,34 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Returns the gas price back to the caller.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api, ReturnFlags};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
api::return_value(ReturnFlags::empty(), &api::gas_price().to_le_bytes());
}
@@ -0,0 +1,38 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This fixture calls `gas_price` `n` times.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(n: u32, );
for _ in 0..n {
let _ = api::gas_price();
}
}
@@ -0,0 +1,43 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Tests that the `get_immutable_data` and `set_immutable_data` APIs work.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {
input!(data: &[u8; 8],);
api::set_immutable_data(data);
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(data: &[u8; 8],);
let mut buf = [0; 8];
api::get_immutable_data(&mut &mut buf[..]);
assert_eq!(data, &buf);
}
@@ -0,0 +1,50 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, u256_bytes, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(buffer: &[u8; 36],);
let err_code = match api::instantiate(
u64::MAX, /* How much ref_time weight to devote for the execution. u64::MAX = use
* all. */
u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all.
&[u8::MAX; 32], // No deposit limit.
&u256_bytes(10_000_000_000u64), // Value to transfer.
buffer,
None,
None,
Some(&[0u8; 32]), // Salt.
) {
Ok(_) => 0u32,
Err(code) => code as u32,
};
// Exit with success and take transfer return code to the output buffer.
api::return_value(uapi::ReturnFlags::empty(), &err_code.to_le_bytes());
}
@@ -0,0 +1,43 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Does two stores to two separate storage items
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api, StorageFlags};
static BUFFER: [u8; 512] = [0u8; 512];
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
size1: u32,
size2: u32,
);
// Place a values in storage sizes are specified in the input buffer.
// We don't care about the contents of the storage item.
api::set_storage(StorageFlags::empty(), &[1u8; 32], &BUFFER[0..size1 as _]);
api::set_storage(StorageFlags::empty(), &[2u8; 32], &BUFFER[0..size2 as _]);
}
@@ -0,0 +1,32 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
api::return_value(uapi::ReturnFlags::empty(), &2u32.to_le_bytes());
}
@@ -0,0 +1,42 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn};
#[polkavm_derive::polkavm_import]
extern "C" {
pub fn noop();
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(rounds: u32, );
for _ in 0..rounds {
unsafe {
noop();
}
}
}
@@ -0,0 +1,44 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {
ok_trap_revert();
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
ok_trap_revert();
}
#[no_mangle]
fn ok_trap_revert() {
input!(buffer, 4,);
match buffer.first().unwrap_or(&0) {
1 => api::return_value(uapi::ReturnFlags::REVERT, &[0u8; 0]),
2 => panic!(),
_ => {},
};
}
@@ -0,0 +1,43 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This creates a large ro section. Even though it is zero
//! initialized we expect them to be included into the blob.
//! This means it will fail at the blob size check.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api, ReturnFlags};
static BUFFER: [u8; 1024 * 1024] = [0; 1024 * 1024];
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call_never() {
// make sure the buffer is not optimized away
api::return_value(ReturnFlags::empty(), &BUFFER);
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {}
@@ -0,0 +1,48 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This creates a large rw section but with its contents
//! included into the blob. It should be rejected for its
//! blob size.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api, ReturnFlags};
static mut BUFFER: [u8; 1024 * 1024] = [42; 1024 * 1024];
unsafe fn buffer() -> &'static [u8; 1024 * 1024] {
let ptr = core::ptr::addr_of!(BUFFER);
&*ptr
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub unsafe extern "C" fn call_never() {
// make sure the buffer is not optimized away
api::return_value(ReturnFlags::empty(), buffer());
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {}
@@ -0,0 +1,48 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This creates a large rw section but the trailing zeroes
//! are removed by the linker. It should be rejected even
//! though the blob is small enough.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api, ReturnFlags};
static mut BUFFER: [u8; 2 * 1024 * 1024] = [0; 2 * 1024 * 1024];
unsafe fn buffer() -> &'static [u8; 2 * 1024 * 1024] {
let ptr = core::ptr::addr_of!(BUFFER);
&*ptr
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub unsafe extern "C" fn call_never() {
// make sure the buffer is not optimized away
api::return_value(ReturnFlags::empty(), buffer());
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {}
@@ -0,0 +1,62 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Tests that the `origin` syscall works.
//! The fixture returns the observed origin if the caller is not the origin,
//! otherwise call itself recursively and assert the returned origin to match.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
let mut caller = [0; 20];
api::caller(&mut caller);
let mut origin = [0; 20];
api::origin(&mut origin);
if caller != origin {
api::return_value(Default::default(), &origin);
}
let mut addr = [0u8; 20];
api::address(&mut addr);
let mut buf = [0u8; 20];
api::call(
uapi::CallFlags::ALLOW_REENTRY,
&addr,
u64::MAX,
u64::MAX,
&[u8::MAX; 32],
&[0; 32],
&[],
Some(&mut &mut buf[..]),
)
.unwrap();
assert_eq!(buf, origin);
}
@@ -0,0 +1,50 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This fixture tests if read-only call works as expected.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
256,
callee_addr: &[u8; 20],
callee_input: [u8],
);
// Call the callee
api::call(
uapi::CallFlags::READ_ONLY,
callee_addr,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = all.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = all.
&[u8::MAX; 32], // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
callee_input,
None,
)
.unwrap();
}
@@ -0,0 +1,55 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This fixture calls itself as many times as passed as argument.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, HostFn, ReturnFlags, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(calls_left: u32, );
// own address
let mut addr = [0u8; 20];
api::address(&mut addr);
let mut return_buffer = calls_left.to_le_bytes();
if calls_left > 0 {
let _ = api::call(
uapi::CallFlags::ALLOW_REENTRY,
&addr,
u64::MAX, // How much ref_time to devote for the execution. u64::MAX = use all resources.
u64::MAX, // How much proof_size to devote for the execution. u64::MAX = use all resources.
&[u8::MAX; 32], // No deposit limit.
&[0u8; 32], // Value transferred to the contract.
&(calls_left - 1).to_le_bytes(),
Some(&mut &mut return_buffer[..]),
);
}
api::return_value(ReturnFlags::empty(), &return_buffer);
}
@@ -0,0 +1,160 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This tests that the `return_data_size` and `return_data_copy` APIs work.
//!
//! It does so by calling and instantiating the "return_with_data" fixture,
//! which always echoes back the input[4..] regardless of the call outcome.
//!
//! We also check that the saved return data is properly reset after a trap
//! and unaffected by plain transfers.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, u256_bytes, HostFn, HostFnImpl as api};
const INPUT_BUF_SIZE: usize = 128;
static INPUT_DATA: [u8; INPUT_BUF_SIZE] = [0xFF; INPUT_BUF_SIZE];
/// The "return_with_data" fixture echoes back 4 bytes less than the input
const OUTPUT_BUF_SIZE: usize = INPUT_BUF_SIZE - 4;
static OUTPUT_DATA: [u8; OUTPUT_BUF_SIZE] = [0xEE; OUTPUT_BUF_SIZE];
/// Assert correct return data after calls and finally reset the return data.
fn assert_return_data_after_call(input: &[u8]) {
assert_return_data_size_of(OUTPUT_BUF_SIZE as u64);
assert_return_data_copy(&input[4..]);
assert_balance_transfer_does_reset();
}
/// Assert that what we get from [api::return_data_copy] matches `whole_return_data`,
/// either fully or partially with an offset and limited size.
fn assert_return_data_copy(whole_return_data: &[u8]) {
// The full return data should match
let mut buf = OUTPUT_DATA;
let mut full = &mut buf[..whole_return_data.len()];
api::return_data_copy(&mut full, 0);
assert_eq!(whole_return_data, full);
// Partial return data should match
let mut buf = OUTPUT_DATA;
let offset = 5; // we just pick some offset
let size = 32; // we just pick some size
let mut partial = &mut buf[offset..offset + size];
api::return_data_copy(&mut partial, offset as u32);
assert_eq!(*partial, whole_return_data[offset..offset + size]);
}
/// This function panics in a recursive contract call context.
fn recursion_guard() -> [u8; 20] {
let mut caller_address = [0u8; 20];
api::caller(&mut caller_address);
let mut own_address = [0u8; 20];
api::address(&mut own_address);
assert_ne!(caller_address, own_address);
own_address
}
/// Assert [api::return_data_size] to match the `expected` value.
fn assert_return_data_size_of(expected: u64) {
assert_eq!(api::return_data_size(), expected);
}
/// Assert the return data to be reset after a balance transfer.
fn assert_balance_transfer_does_reset() {
api::call(
uapi::CallFlags::empty(),
&[0u8; 20],
u64::MAX,
u64::MAX,
&[u8::MAX; 32],
&u256_bytes(128_000_000),
&[],
None,
)
.unwrap();
assert_return_data_size_of(0);
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(code_hash: &[u8; 32],);
// We didn't do anything yet; return data size should be 0
assert_return_data_size_of(0);
recursion_guard();
let mut address_buf = [0; 20];
let construct_input = |exit_flag| {
let mut input = INPUT_DATA;
input[0] = exit_flag;
input[9] = 7;
input[17 / 2] = 127;
input[89 / 2] = 127;
input
};
let mut instantiate = |exit_flag| {
let input = construct_input(exit_flag);
let mut deploy_input = [0; 32 + INPUT_BUF_SIZE];
deploy_input[..32].copy_from_slice(code_hash);
deploy_input[32..].copy_from_slice(&input);
api::instantiate(
u64::MAX,
u64::MAX,
&[u8::MAX; 32],
&[0; 32],
&deploy_input,
Some(&mut address_buf),
None,
None,
)
};
let call = |exit_flag, address_buf| {
api::call(
uapi::CallFlags::empty(),
address_buf,
u64::MAX,
u64::MAX,
&[u8::MAX; 32],
&[0; 32],
&construct_input(exit_flag),
None,
)
};
instantiate(0).unwrap();
assert_return_data_after_call(&construct_input(0)[..]);
instantiate(1).unwrap_err();
assert_return_data_after_call(&construct_input(1)[..]);
call(0, &address_buf).unwrap();
assert_return_data_after_call(&construct_input(0)[..]);
call(1, &address_buf).unwrap_err();
assert_return_data_after_call(&construct_input(1)[..]);
}
@@ -0,0 +1,40 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
polkavm_derive::min_stack_size!(512 * 1024);
use uapi::{ReturnFlags, input, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
return_size: u32,
);
let return_buf = [42u8; 256 * 1024];
api::return_value(ReturnFlags::empty(), &return_buf[..return_size as usize])
}
@@ -0,0 +1,49 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
include!("../sol_utils.rs");
use uapi::{input, HostFn, HostFnImpl as api, StorageFlags};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {
call();
}
/// Reads the first byte as the exit status and copy all but the first 4 bytes of the input as
/// output data.
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
input, 128,
exit_status: [u8; 4],
output: [u8],
);
// Burn some PoV, clear_storage consumes some PoV as in order to clear the storage we need to we
// need to read its size first.
clear_storage::<api>(StorageFlags::empty(), b"");
let exit_status = uapi::ReturnFlags::from_bits(exit_status[0] as u32).unwrap();
api::return_value(exit_status, output);
}
@@ -0,0 +1,42 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
use uapi::{input, u64_output, HostFn, HostFnImpl as api};
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {
input!(128, data: [u8],);
api::deposit_event(&[], data);
}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
// Not payable
let value = u64_output!(api::value_transferred,);
if value > 0 {
panic!();
}
input!(128, data: [u8],);
api::deposit_event(&[], data);
}
@@ -0,0 +1,31 @@
// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
#![no_main]
include!("../panic_handler.rs");
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}
#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
#[allow(clippy::empty_loop)]
loop {}
}

Some files were not shown because too many files have changed in this diff Show More