diff --git a/substrate/frame/contracts/fixtures/contracts/account_reentrance_count_call.rs b/substrate/frame/contracts/fixtures/contracts/account_reentrance_count_call.rs new file mode 100644 index 0000000000000..9da4eb6d538a8 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/account_reentrance_count_call.rs @@ -0,0 +1,39 @@ +// This file is part of Substrate. + +// 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 account_reentrance_count works as expected. +#![no_std] +#![no_main] + +use common::input; +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() { + input!(callee: [u8; 32],); + + #[allow(deprecated)] + let reentrance_count = api::account_reentrance_count(callee); + + // Return the reentrance count. + api::return_value(uapi::ReturnFlags::empty(), &reentrance_count.to_le_bytes()); +} diff --git a/substrate/frame/contracts/fixtures/contracts/add_remove_delegate_dependency.rs b/substrate/frame/contracts/fixtures/contracts/add_remove_delegate_dependency.rs new file mode 100644 index 0000000000000..759ff79937404 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/add_remove_delegate_dependency.rs @@ -0,0 +1,70 @@ +// This file is part of Substrate. + +// 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 behavior of adding / removing delegate_dependencies when delegate +//! calling into a contract. +#![no_std] +#![no_main] + +use common::input; +use uapi::{HostFn, HostFnImpl as api}; + +const ALICE: [u8; 32] = [1u8; 32]; + +/// Load input data and perform the action specified by the input. +/// If `delegate_call` is true, then delegate call into the contract. +fn load_input(delegate_call: bool) { + input!( + action: u32, + code_hash: [u8; 32], + ); + + match action { + // 1 = Add delegate dependency + 1 => { + #[allow(deprecated)] + api::add_delegate_dependency(code_hash); + }, + // 2 = Remove delegate dependency + 2 => { + #[allow(deprecated)] + api::remove_delegate_dependency(code_hash); + }, + // 3 = Terminate + 3 => { + api::terminate_v1(&ALICE); + }, + // Everything else is a noop + _ => {}, + } + + if delegate_call { + api::delegate_call(uapi::CallFlags::empty(), code_hash, &[], None).unwrap(); + } +} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() { + load_input(false); +} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() { + load_input(true); +} diff --git a/substrate/frame/contracts/fixtures/contracts/balance.rs b/substrate/frame/contracts/fixtures/contracts/balance.rs new file mode 100644 index 0000000000000..4011b8379cbfa --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/balance.rs @@ -0,0 +1,36 @@ +// This file is part of Substrate. + +// 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] + +use common::output; +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() { + // Initialize buffer with 1s so that we can check that it is overwritten. + output!(balance, [1u8; 8], api::balance,); + + // Assert that the balance is 0. + assert_eq!(&[0u8; 8], balance); +} diff --git a/substrate/frame/contracts/fixtures/contracts/call.rs b/substrate/frame/contracts/fixtures/contracts/call.rs index 0e5f4fbd2ddd1..f7d9d862d7465 100644 --- a/substrate/frame/contracts/fixtures/contracts/call.rs +++ b/substrate/frame/contracts/fixtures/contracts/call.rs @@ -19,8 +19,8 @@ #![no_std] #![no_main] -extern crate common; -use uapi::{CallFlags, HostFn, HostFnImpl as api}; +use common::input; +use uapi::{HostFn, HostFnImpl as api}; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -29,21 +29,18 @@ pub extern "C" fn deploy() {} #[no_mangle] #[polkavm_derive::polkavm_export] pub extern "C" fn call() { - let mut buffer = [0u8; 40]; - let callee_input = 0..4; - let callee_addr = 4..36; - let value = 36..40; - - // Read the input data. - api::input(&mut &mut buffer[..]); + input!( + callee_input: [u8; 4], + callee_addr: [u8; 32], + ); // Call the callee api::call_v1( - CallFlags::empty(), - &buffer[callee_addr], - 0u64, // How much gas to devote for the execution. 0 = all. - &buffer[value], - &buffer[callee_input], + uapi::CallFlags::empty(), + callee_addr, + 0u64, // How much gas to devote for the execution. 0 = all. + &0u64.to_le_bytes(), // value transferred to the contract. + callee_input, None, ) .unwrap(); diff --git a/substrate/frame/contracts/fixtures/contracts/call_return_code.rs b/substrate/frame/contracts/fixtures/contracts/call_return_code.rs new file mode 100644 index 0000000000000..1256588d3b585 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/call_return_code.rs @@ -0,0 +1,54 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!( + 100, + callee_addr: [u8; 32], + input: [u8], + ); + + // Call the callee + let err_code = match api::call_v1( + uapi::CallFlags::empty(), + callee_addr, + 0u64, // How much gas to devote for the execution. 0 = all. + &100u64.to_le_bytes(), // 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()); +} diff --git a/substrate/frame/contracts/fixtures/contracts/call_runtime.rs b/substrate/frame/contracts/fixtures/contracts/call_runtime.rs new file mode 100644 index 0000000000000..2b132398fb680 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/call_runtime.rs @@ -0,0 +1,42 @@ +// This file is part of Substrate. + +// 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 passes its input to `call_runtime` and returns the return value to its caller. +#![no_std] +#![no_main] + +use common::input; +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() { + // Fixture calls should fit into 100 bytes. + input!(100, call: [u8], ); + + // Use the call passed as input to call the runtime. + let err_code = match api::call_runtime(call) { + Ok(_) => 0u32, + Err(code) => code as u32, + }; + + api::return_value(uapi::ReturnFlags::empty(), &err_code.to_le_bytes()); +} diff --git a/substrate/frame/contracts/fixtures/contracts/call_runtime_and_call.rs b/substrate/frame/contracts/fixtures/contracts/call_runtime_and_call.rs new file mode 100644 index 0000000000000..fdeb6097e732f --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/call_runtime_and_call.rs @@ -0,0 +1,51 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!( + 512, + callee_input: [u8; 4], + callee_addr: [u8; 32], + call: [u8], + ); + + // Use the call passed as input to call the runtime. + api::call_runtime(call).unwrap(); + + // Call the callee + api::call_v1( + uapi::CallFlags::empty(), + callee_addr, + 0u64, // How much gas to devote for the execution. 0 = all. + &0u64.to_le_bytes(), // value transferred to the contract. + callee_input, + None, + ) + .unwrap(); +} diff --git a/substrate/frame/contracts/fixtures/contracts/call_with_limit.rs b/substrate/frame/contracts/fixtures/contracts/call_with_limit.rs new file mode 100644 index 0000000000000..5e98aa614e95a --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/call_with_limit.rs @@ -0,0 +1,51 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!( + callee_addr: [u8; 32], + ref_time: u64, + proof_size: u64, + ); + + #[allow(deprecated)] + api::call_v2( + uapi::CallFlags::empty(), + callee_addr, + ref_time, + proof_size, + None, // No deposit limit. + &0u64.to_le_bytes(), // value transferred to the contract. + &[0u8; 0], // input data. + None, + ) + .unwrap(); +} diff --git a/substrate/frame/contracts/fixtures/contracts/caller_contract.rs b/substrate/frame/contracts/fixtures/contracts/caller_contract.rs new file mode 100644 index 0000000000000..c2629e9fa1971 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/caller_contract.rs @@ -0,0 +1,153 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +use uapi::{HostFn, HostFnImpl as api, ReturnErrorCode}; + +#[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],); + + // The value to transfer on instantiation and calls. Chosen to be greater than existential + // deposit. + let value = 32768u64.to_le_bytes(); + let salt = [0u8; 0]; + + // Callee will use the first 4 bytes of the input to return an exit status. + let input = [0u8, 1, 34, 51, 68, 85, 102, 119]; + let reverted_input = [1u8, 34, 51, 68, 85, 102, 119]; + + // Fail to deploy the contract since it returns a non-zero exit status. + #[allow(deprecated)] + let res = api::instantiate_v2( + code_hash, + 0u64, // How much ref_time weight to devote for the execution. 0 = all. + 0u64, // How much proof_size weight to devote for the execution. 0 = all. + None, // No deposit limit. + &value, + &reverted_input, + None, + None, + &salt, + ); + assert!(matches!(res, Err(ReturnErrorCode::CalleeReverted))); + + // Fail to deploy the contract due to insufficient ref_time weight. + #[allow(deprecated)] + let res = api::instantiate_v2( + code_hash, 1u64, // too little ref_time weight + 0u64, // How much proof_size weight to devote for the execution. 0 = all. + None, // No deposit limit. + &value, &input, None, None, &salt, + ); + assert!(matches!(res, Err(ReturnErrorCode::CalleeTrapped))); + + // Fail to deploy the contract due to insufficient proof_size weight. + #[allow(deprecated)] + let res = api::instantiate_v2( + code_hash, 0u64, // How much ref_time weight to devote for the execution. 0 = all. + 1u64, // Too little proof_size weight + None, // No deposit limit. + &value, &input, None, None, &salt, + ); + assert!(matches!(res, Err(ReturnErrorCode::CalleeTrapped))); + + // Deploy the contract successfully. + let mut callee = [0u8; 32]; + let callee = &mut &mut callee[..]; + + #[allow(deprecated)] + api::instantiate_v2( + code_hash, + 0u64, // How much ref_time weight to devote for the execution. 0 = all. + 0u64, // How much proof_size weight to devote for the execution. 0 = all. + None, // No deposit limit. + &value, + &input, + Some(callee), + None, + &salt, + ) + .unwrap(); + assert_eq!(callee.len(), 32); + + // Call the new contract and expect it to return failing exit code. + #[allow(deprecated)] + let res = api::call_v2( + uapi::CallFlags::empty(), + callee, + 0u64, // How much ref_time weight to devote for the execution. 0 = all. + 0u64, // How much proof_size weight to devote for the execution. 0 = all. + None, // No deposit limit. + &value, + &reverted_input, + None, + ); + assert!(matches!(res, Err(ReturnErrorCode::CalleeReverted))); + + // Fail to call the contract due to insufficient ref_time weight. + #[allow(deprecated)] + let res = api::call_v2( + uapi::CallFlags::empty(), + callee, + 1u64, // too little ref_time weight + 0u64, // How much proof_size weight to devote for the execution. 0 = all. + None, // No deposit limit. + &value, + &input, + None, + ); + assert!(matches!(res, Err(ReturnErrorCode::CalleeTrapped))); + + // Fail to call the contract due to insufficient proof_size weight. + #[allow(deprecated)] + let res = api::call_v2( + uapi::CallFlags::empty(), + callee, + 0u64, // How much ref_time weight to devote for the execution. 0 = all. + 1u64, // too little proof_size weight + None, // No deposit limit. + &value, + &input, + None, + ); + assert!(matches!(res, Err(ReturnErrorCode::CalleeTrapped))); + + // Call the contract successfully. + let mut output = [0u8; 4]; + #[allow(deprecated)] + api::call_v2( + uapi::CallFlags::empty(), + callee, + 0u64, // How much ref_time weight to devote for the execution. 0 = all. + 0u64, // How much proof_size weight to devote for the execution. 0 = all. + None, // No deposit limit. + &value, + &input, + Some(&mut &mut output[..]), + ) + .unwrap(); + assert_eq!(&output, &input[4..]) +} diff --git a/substrate/frame/contracts/fixtures/contracts/chain_extension.rs b/substrate/frame/contracts/fixtures/contracts/chain_extension.rs new file mode 100644 index 0000000000000..474df00d69129 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/chain_extension.rs @@ -0,0 +1,42 @@ +// This file is part of Substrate. + +// 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. + +//! Call chain extension by passing through input and output of this contract. +#![no_std] +#![no_main] + +use common::input; +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() { + input!(input, 8, func_id: u32,); + + // the chain extension passes through the input and returns it as output + let mut output_buffer = [0u8; 32]; + let output = &mut &mut output_buffer[0..input.len()]; + + let ret_id = api::call_chain_extension(func_id, input, Some(output)); + assert_eq!(ret_id, func_id); + + api::return_value(uapi::ReturnFlags::empty(), output); +} diff --git a/substrate/frame/contracts/fixtures/contracts/chain_extension_temp_storage.rs b/substrate/frame/contracts/fixtures/contracts/chain_extension_temp_storage.rs new file mode 100644 index 0000000000000..1ab08efb3c7ea --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/chain_extension_temp_storage.rs @@ -0,0 +1,63 @@ +// This file is part of Substrate. + +// 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. + +//! Call chain extension two times with the specified func_ids +//! It then calls itself once +#![no_std] +#![no_main] + +use common::{input, output}; +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() { + input!( + input, + func_id1: u32, + func_id2: u32, + stop_recurse: u8, + ); + + api::call_chain_extension(func_id1, input, None); + api::call_chain_extension(func_id2, input, None); + + if stop_recurse == 0 { + // Setup next call + input[0..4].copy_from_slice(&((3 << 16) | 2u32).to_le_bytes()); + input[4..8].copy_from_slice(&((3 << 16) | 3u32).to_le_bytes()); + input[8] = 1u8; + + // Read the contract address. + output!(addr, [0u8; 32], api::address,); + + // call self + api::call_v1( + uapi::CallFlags::ALLOW_REENTRY, + addr, + 0u64, // How much gas to devote for the execution. 0 = all. + &0u64.to_le_bytes(), // value transferred to the contract. + input, + None, + ) + .unwrap(); + } +} diff --git a/substrate/frame/contracts/fixtures/contracts/common/Cargo.toml b/substrate/frame/contracts/fixtures/contracts/common/Cargo.toml index 127bb575088d5..296f408d011d1 100644 --- a/substrate/frame/contracts/fixtures/contracts/common/Cargo.toml +++ b/substrate/frame/contracts/fixtures/contracts/common/Cargo.toml @@ -6,3 +6,6 @@ authors.workspace = true edition.workspace = true license.workspace = true description = "Common utilities for pallet-contracts-fixtures." + +[dependencies] +uapi = { package = 'pallet-contracts-uapi', path = "../../../uapi", default-features = false } diff --git a/substrate/frame/contracts/fixtures/contracts/common/src/lib.rs b/substrate/frame/contracts/fixtures/contracts/common/src/lib.rs index 29bdbfbb04200..6904ab2f504ca 100644 --- a/substrate/frame/contracts/fixtures/contracts/common/src/lib.rs +++ b/substrate/frame/contracts/fixtures/contracts/common/src/lib.rs @@ -15,7 +15,8 @@ // See the License for the specific language governing permissions and // limitations under the License. #![no_std] -#![cfg(any(target_arch = "wasm32", target_arch = "riscv32"))] + +pub use uapi::{HostFn, HostFnImpl as api}; #[panic_handler] fn panic(_info: &core::panic::PanicInfo) -> ! { @@ -29,3 +30,122 @@ fn panic(_info: &core::panic::PanicInfo) -> ! { core::hint::unreachable_unchecked(); } } + +/// Utility macro to read input passed to a contract. +/// +/// Example: +/// +/// ``` +/// input$!( +/// var1: u32, // [0, 4) var1 decoded as u32 +/// var2: [u8; 32], // [4, 36) var2 decoded as a [u8] slice +/// var3: u8, // [36, 37) var3 decoded as a u8 +/// ); +/// +/// // Input and size can be specified as well: +/// input$!( +/// input, // input buffer (optional) +/// 512, // input size (optional) +/// var4: u32, // [0, 4) var4 decoded as u32 +/// var5: [u8], // [4, ..) var5 decoded as a [u8] slice +/// ); +/// ``` +#[macro_export] +macro_rules! input { + (@inner $input:expr, $cursor:expr,) => {}; + (@size $size:expr, ) => { $size }; + + // Match a u8 variable. + // e.g input!(var1: u8, ); + (@inner $input:expr, $cursor:expr, $var:ident: u8, $($rest:tt)*) => { + let $var = $input[$cursor]; + input!(@inner $input, $cursor + 1, $($rest)*); + }; + + // Size of u8 variable. + (@size $size:expr, $var:ident: u8, $($rest:tt)*) => { + input!(@size $size + 1, $($rest)*) + }; + + // Match a u64 variable. + // e.g input!(var1: u64, ); + (@inner $input:expr, $cursor:expr, $var:ident: u64, $($rest:tt)*) => { + let $var = u64::from_le_bytes($input[$cursor..$cursor + 8].try_into().unwrap()); + input!(@inner $input, $cursor + 8, $($rest)*); + }; + + // Size of u64 variable. + (@size $size:expr, $var:ident: u64, $($rest:tt)*) => { + input!(@size $size + 8, $($rest)*) + }; + + // Match a u32 variable. + // e.g input!(var1: u32, ); + (@inner $input:expr, $cursor:expr, $var:ident: u32, $($rest:tt)*) => { + let $var = u32::from_le_bytes($input[$cursor..$cursor + 4].try_into().unwrap()); + input!(@inner $input, $cursor + 4, $($rest)*); + }; + + // Size of u32 variable. + (@size $size:expr, $var:ident: u32, $($rest:tt)*) => { + input!(@size $size + 4, $($rest)*) + }; + + // Match a u8 slice with the remaining bytes. + // e.g input!(512, var1: [u8; 32], var2: [u8], ); + (@inner $input:expr, $cursor:expr, $var:ident: [u8],) => { + let $var = &$input[$cursor..]; + }; + + // Match a u8 slice of the given size. + // e.g input!(var1: [u8; 32], ); + (@inner $input:expr, $cursor:expr, $var:ident: [u8; $n:expr], $($rest:tt)*) => { + let $var = &$input[$cursor..$cursor+$n]; + input!(@inner $input, $cursor + $n, $($rest)*); + }; + + // Size of a u8 slice. + (@size $size:expr, $var:ident: [u8; $n:expr], $($rest:tt)*) => { + input!(@size $size + $n, $($rest)*) + }; + + // Entry point, with the buffer and it's size specified first. + // e.g input!(buffer, 512, var1: u32, var2: [u8], ); + ($buffer:ident, $size:expr, $($rest:tt)*) => { + let mut $buffer = [0u8; $size]; + let $buffer = &mut &mut $buffer[..]; + $crate::api::input($buffer); + input!(@inner $buffer, 0, $($rest)*); + }; + + // Entry point, with the name of the buffer specified and size of the input buffer computed. + // e.g input!(buffer, var1: u32, var2: u64, ); + ($buffer: ident, $($rest:tt)*) => { + input!($buffer, input!(@size 0, $($rest)*), $($rest)*); + }; + + // Entry point, with the size of the input buffer computed. + // e.g input!(var1: u32, var2: u64, ); + ($($rest:tt)*) => { + input!(buffer, $($rest)*); + }; +} + +/// Utility macro to invoke a host function that expect a `output: &mut &mut [u8]` as last argument. +/// +/// Example: +/// ``` +/// // call `api::caller` and store the output in `caller` +/// output!(caller, [0u8; 32], api::caller,); +/// +/// // call `api::get_storage` and store the output in `address` +/// output!(address, [0u8; 32], api::get_storage, &[1u8; 32]); +/// ``` +#[macro_export] +macro_rules! output { + ($output: ident, $buffer: expr, $host_fn:path, $($arg:expr),*) => { + let mut $output = $buffer; + let $output = &mut &mut $output[..]; + $host_fn($($arg,)* $output); + }; +} diff --git a/substrate/frame/contracts/fixtures/contracts/create_storage_and_call.rs b/substrate/frame/contracts/fixtures/contracts/create_storage_and_call.rs new file mode 100644 index 0000000000000..8b79dd87dffd2 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/create_storage_and_call.rs @@ -0,0 +1,59 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!( + buffer, + input: [u8; 4], + callee: [u8; 32], + deposit_limit: [u8; 8], + ); + + // create 4 byte of storage before calling + api::set_storage(buffer, &[1u8; 4]); + + // Call the callee + #[allow(deprecated)] + api::call_v2( + uapi::CallFlags::empty(), + callee, + 0u64, // How much ref_time weight to devote for the execution. 0 = all. + 0u64, // How much proof_size weight to devote for the execution. 0 = all. + Some(deposit_limit), + &0u64.to_le_bytes(), // value transferred to the contract. + input, + None, + ) + .unwrap(); + + // create 8 byte of storage after calling + // item of 12 bytes because we override 4 bytes + api::set_storage(buffer, &[1u8; 12]); +} diff --git a/substrate/frame/contracts/fixtures/contracts/create_storage_and_instantiate.rs b/substrate/frame/contracts/fixtures/contracts/create_storage_and_instantiate.rs new file mode 100644 index 0000000000000..c68d99eff821e --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/create_storage_and_instantiate.rs @@ -0,0 +1,59 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!( + input: [u8; 4], + code_hash: [u8; 32], + deposit_limit: [u8; 8], + ); + + let value = 10_000u64.to_le_bytes(); + let salt = [0u8; 0]; + let mut address = [0u8; 32]; + let address = &mut &mut address[..]; + + #[allow(deprecated)] + api::instantiate_v2( + code_hash, + 0u64, // How much ref_time weight to devote for the execution. 0 = all. + 0u64, // How much proof_size weight to devote for the execution. 0 = all. + Some(deposit_limit), + &value, + input, + Some(address), + None, + &salt, + ) + .unwrap(); + + // Return the deployed contract address. + api::return_value(uapi::ReturnFlags::empty(), address); +} diff --git a/substrate/frame/contracts/fixtures/contracts/crypto_hashes.rs b/substrate/frame/contracts/fixtures/contracts/crypto_hashes.rs new file mode 100644 index 0000000000000..35cc03f1e7237 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/crypto_hashes.rs @@ -0,0 +1,84 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +use uapi::{HostFn, HostFnImpl as api}; + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() {} + +/// Called by the tests. +/// +/// The `call` function expects data in a certain format in the input buffer. +/// +/// 1. The first byte encodes an identifier for the crypto hash function under test. (*) +/// 2. The rest encodes the input data that is directly fed into the crypto hash function chosen in +/// 1. +/// +/// The `deploy` function then computes the chosen crypto hash function +/// given the input and puts the result 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 chosen hash +/// function. +/// +/// (*) The possible value for the crypto hash identifiers can be found below: +/// +/// | value | Algorithm | Bit Width | +/// |-------|-----------|-----------| +/// | 0 | SHA2 | 256 | +/// | 1 | KECCAK | 256 | +/// | 2 | BLAKE2 | 256 | +/// | 3 | BLAKE2 | 128 | +/// --------------------------------- + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() { + input!( + 256, + chosen_hash_fn: u8, + input: [u8], + ); + + match chosen_hash_fn { + 1 => { + let mut output = [0u8; 32]; + api::hash_sha2_256(input, &mut output); + api::return_value(uapi::ReturnFlags::empty(), &output); + }, + 2 => { + let mut output = [0u8; 32]; + api::hash_keccak_256(input, &mut output); + api::return_value(uapi::ReturnFlags::empty(), &output); + }, + 3 => { + let mut output = [0u8; 32]; + api::hash_blake2_256(input, &mut output); + api::return_value(uapi::ReturnFlags::empty(), &output); + }, + 4 => { + let mut output = [0u8; 16]; + api::hash_blake2_128(input, &mut output); + api::return_value(uapi::ReturnFlags::empty(), &output); + }, + _ => panic!("unknown crypto hash function identifier"), + } +} diff --git a/substrate/frame/contracts/fixtures/contracts/debug_message_invalid_utf8.rs b/substrate/frame/contracts/fixtures/contracts/debug_message_invalid_utf8.rs new file mode 100644 index 0000000000000..6c850a9ec6631 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/debug_message_invalid_utf8.rs @@ -0,0 +1,33 @@ +// This file is part of Substrate. + +// 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. + +//! Emit a debug message with an invalid utf-8 code. +#![no_std] +#![no_main] + +extern crate common; +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::debug_message(b"\xFC").unwrap(); +} diff --git a/substrate/frame/contracts/fixtures/contracts/debug_message_logging_disabled.rs b/substrate/frame/contracts/fixtures/contracts/debug_message_logging_disabled.rs new file mode 100644 index 0000000000000..b9f62adbfffd6 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/debug_message_logging_disabled.rs @@ -0,0 +1,33 @@ +// This file is part of Substrate. + +// 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. + +//! Emit a "Hello World!" debug message but assume that logging is disabled. +#![no_std] +#![no_main] + +extern crate common; +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::debug_message(b"Hello World!").unwrap(); +} diff --git a/substrate/frame/contracts/fixtures/contracts/debug_message_works.rs b/substrate/frame/contracts/fixtures/contracts/debug_message_works.rs new file mode 100644 index 0000000000000..3a2509509d8f1 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/debug_message_works.rs @@ -0,0 +1,33 @@ +// This file is part of Substrate. + +// 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. + +//! Emit a "Hello World!" debug message. +#![no_std] +#![no_main] + +extern crate common; +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::debug_message(b"Hello World!").unwrap(); +} diff --git a/substrate/frame/contracts/fixtures/contracts/delegate_call.rs b/substrate/frame/contracts/fixtures/contracts/delegate_call.rs new file mode 100644 index 0000000000000..f109e8a63a3cb --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/delegate_call.rs @@ -0,0 +1,49 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!(code_hash: [u8; 32],); + + let mut key = [0u8; 32]; + key[0] = 1u8; + + let mut value = [0u8; 32]; + let value = &mut &mut value[..]; + value[0] = 2u8; + + api::set_storage(&key, value); + api::get_storage(&key, value).unwrap(); + assert!(value[0] == 2u8); + + let input = [0u8; 0]; + api::delegate_call(uapi::CallFlags::empty(), code_hash, &input, None).unwrap(); + + api::get_storage(&[1u8], value).unwrap(); + assert!(value[0] == 1u8); +} diff --git a/substrate/frame/contracts/fixtures/contracts/delegate_call_lib.rs b/substrate/frame/contracts/fixtures/contracts/delegate_call_lib.rs new file mode 100644 index 0000000000000..197b396ce4f6c --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/delegate_call_lib.rs @@ -0,0 +1,49 @@ +// This file is part of Substrate. + +// 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] + +use common::output; +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 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(&key, value); + + // Assert that `value_transferred` is equal to the value + // passed to the `caller` contract: 1337. + output!(value_transferred, [0u8; 8], api::value_transferred,); + let value_transferred = u64::from_le_bytes(value_transferred[..].try_into().unwrap()); + assert_eq!(value_transferred, 1337); + + // Assert that ALICE is the caller of the contract. + output!(caller, [0u8; 32], api::caller,); + assert_eq!(&caller[..], &[1u8; 32]); +} diff --git a/substrate/frame/contracts/fixtures/contracts/delegate_call_simple.rs b/substrate/frame/contracts/fixtures/contracts/delegate_call_simple.rs new file mode 100644 index 0000000000000..cf3351c52fdc2 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/delegate_call_simple.rs @@ -0,0 +1,36 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!(code_hash: [u8; 32],); + + // Delegate call into passed code hash. + let input = [0u8; 0]; + api::delegate_call(uapi::CallFlags::empty(), code_hash, &input, None).unwrap(); +} diff --git a/substrate/frame/contracts/fixtures/contracts/destroy_and_transfer.rs b/substrate/frame/contracts/fixtures/contracts/destroy_and_transfer.rs new file mode 100644 index 0000000000000..cfcfd60f21eef --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/destroy_and_transfer.rs @@ -0,0 +1,89 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +use uapi::{HostFn, HostFnImpl as api}; + +const ADDRESS_KEY: [u8; 32] = [0u8; 32]; +const VALUE: [u8; 8] = [0, 0, 1u8, 0, 0, 0, 0, 0]; + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() { + input!(code_hash: [u8; 32],); + + let input = [0u8; 0]; + let mut address = [0u8; 32]; + let address = &mut &mut address[..]; + let salt = [71u8, 17u8]; + + #[allow(deprecated)] + api::instantiate_v2( + code_hash, + 0u64, // How much ref_time weight to devote for the execution. 0 = all. + 0u64, // How much proof_size weight to devote for the execution. 0 = all. + None, // No deposit limit. + &VALUE, + &input, + Some(address), + None, + &salt, + ) + .unwrap(); + + // Return the deployed contract address. + api::set_storage(&ADDRESS_KEY, address); +} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() { + let mut callee_addr = [0u8; 32]; + let callee_addr = &mut &mut callee_addr[..]; + api::get_storage(&ADDRESS_KEY, callee_addr).unwrap(); + + // Calling the destination contract with non-empty input data should fail. + #[allow(deprecated)] + let res = api::call_v2( + uapi::CallFlags::empty(), + callee_addr, + 0u64, // How much ref_time weight to devote for the execution. 0 = all. + 0u64, // How much proof_size weight to devote for the execution. 0 = all. + None, // No deposit limit. + &VALUE, + &[0u8; 1], + None, + ); + assert!(matches!(res, Err(uapi::ReturnErrorCode::CalleeTrapped))); + + // Call the destination contract regularly, forcing it to self-destruct. + #[allow(deprecated)] + api::call_v2( + uapi::CallFlags::empty(), + callee_addr, + 0u64, // How much ref_time weight to devote for the execution. 0 = all. + 0u64, // How much proof_size weight to devote for the execution. 0 = all. + None, // No deposit limit. + &VALUE, + &[0u8; 0], + None, + ) + .unwrap(); +} diff --git a/substrate/frame/contracts/fixtures/contracts/drain.rs b/substrate/frame/contracts/fixtures/contracts/drain.rs new file mode 100644 index 0000000000000..f5c8681c93828 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/drain.rs @@ -0,0 +1,44 @@ +// This file is part of Substrate. + +// 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] + +use common::output; +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() { + output!(balance, [0u8; 8], api::balance,); + let balance = u64::from_le_bytes(balance[..].try_into().unwrap()); + + output!(minimum_balance, [0u8; 8], api::minimum_balance,); + let minimum_balance = u64::from_le_bytes(minimum_balance[..].try_into().unwrap()); + + // 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::transfer(&[0u8; 32], &balance.to_le_bytes()); + assert!(matches!(res, Err(uapi::ReturnErrorCode::TransferFailed))); +} diff --git a/substrate/frame/contracts/fixtures/contracts/ecdsa_recover.rs b/substrate/frame/contracts/fixtures/contracts/ecdsa_recover.rs new file mode 100644 index 0000000000000..0f28ca2c81980 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/ecdsa_recover.rs @@ -0,0 +1,44 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!( + signature: [u8; 65], + hash: [u8; 32], + ); + + let mut output = [0u8; 33]; + api::ecdsa_recover( + &signature[..].try_into().unwrap(), + &hash[..].try_into().unwrap(), + &mut output, + ) + .unwrap(); + api::return_value(uapi::ReturnFlags::empty(), &output); +} diff --git a/substrate/frame/contracts/fixtures/contracts/event_and_return_on_deploy.rs b/substrate/frame/contracts/fixtures/contracts/event_and_return_on_deploy.rs new file mode 100644 index 0000000000000..9186835d29118 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/event_and_return_on_deploy.rs @@ -0,0 +1,36 @@ +// This file is part of Substrate. + +// 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] + +extern crate common; +use uapi::{HostFn, HostFnImpl as api}; + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() { + let buffer = [1u8, 2, 3, 4]; + api::deposit_event(&[0u8; 0], &buffer); + api::return_value(uapi::ReturnFlags::empty(), &buffer); +} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() { + unreachable!() +} diff --git a/substrate/frame/contracts/fixtures/contracts/event_size.rs b/substrate/frame/contracts/fixtures/contracts/event_size.rs new file mode 100644 index 0000000000000..e95130d30839c --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/event_size.rs @@ -0,0 +1,37 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!(len: u32,); + + let buffer = [0u8; 16 * 1024 + 1]; + let data = &buffer[..len as usize]; + + api::deposit_event(&[0u8; 0], data); +} diff --git a/substrate/frame/contracts/fixtures/contracts/float_instruction.rs b/substrate/frame/contracts/fixtures/contracts/float_instruction.rs new file mode 100644 index 0000000000000..b1eaaf8543c67 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/float_instruction.rs @@ -0,0 +1,34 @@ +// This file is part of Substrate. + +// 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] + +extern crate common; + +#[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 +} diff --git a/substrate/frame/contracts/fixtures/contracts/instantiate_return_code.rs b/substrate/frame/contracts/fixtures/contracts/instantiate_return_code.rs new file mode 100644 index 0000000000000..67cd739d85a69 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/instantiate_return_code.rs @@ -0,0 +1,53 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!(buffer, 36, code_hash: [u8; 32],); + let input = &buffer[32..]; + + #[allow(deprecated)] + let err_code = match api::instantiate_v2( + code_hash, + 0u64, // How much ref_time weight to devote for the execution. 0 = all. + 0u64, /* How much proof_size weight to devote for the execution. 0 = + * all. */ + None, // No deposit limit. + &10_000u64.to_le_bytes(), // Value to transfer. + input, + None, + None, + &[0u8; 0], // Empty 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()); +} diff --git a/substrate/frame/contracts/fixtures/contracts/invalid_contract_no_call.rs b/substrate/frame/contracts/fixtures/contracts/invalid_contract_no_call.rs new file mode 100644 index 0000000000000..13af3eb22b1f5 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/invalid_contract_no_call.rs @@ -0,0 +1,25 @@ +// This file is part of Substrate. + +// 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. +//! Valid module but missing the call function +#![no_std] +#![no_main] + +extern crate common; + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() {} diff --git a/substrate/frame/contracts/fixtures/contracts/multi_store.rs b/substrate/frame/contracts/fixtures/contracts/multi_store.rs new file mode 100644 index 0000000000000..b83f3995a42b4 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/multi_store.rs @@ -0,0 +1,43 @@ +// This file is part of Substrate. + +// 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 seperate storage items +#![no_std] +#![no_main] + +use common::input; +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() { + input!( + size1: u32, + size2: u32, + ); + + let buffer = [0u8; 16 * 1024]; + + // 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(&[1u8; 32], &buffer[0..size1 as _]); + api::set_storage(&[2u8; 32], &buffer[0..size2 as _]); +} diff --git a/substrate/frame/contracts/fixtures/contracts/new_set_code_hash_contract.rs b/substrate/frame/contracts/fixtures/contracts/new_set_code_hash_contract.rs new file mode 100644 index 0000000000000..2a59b6e33d89a --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/new_set_code_hash_contract.rs @@ -0,0 +1,32 @@ +// This file is part of Substrate. + +// 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] + +extern crate common; +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()); +} diff --git a/substrate/frame/contracts/fixtures/contracts/ok_trap_revert.rs b/substrate/frame/contracts/fixtures/contracts/ok_trap_revert.rs new file mode 100644 index 0000000000000..55115f8642f3e --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/ok_trap_revert.rs @@ -0,0 +1,44 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +use uapi::{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!(), + _ => {}, + }; +} diff --git a/substrate/frame/contracts/fixtures/contracts/reentrance_count_call.rs b/substrate/frame/contracts/fixtures/contracts/reentrance_count_call.rs new file mode 100644 index 0000000000000..9812dce2e818d --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/reentrance_count_call.rs @@ -0,0 +1,55 @@ +// This file is part of Substrate. + +// 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 account_reentrance_count works as expected. +#![no_std] +#![no_main] + +use common::{input, output}; +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() { + input!(expected_reentrance_count: u32,); + + // Read the contract address. + output!(addr, [0u8; 32], api::address,); + + #[allow(deprecated)] + let reentrance_count = api::reentrance_count(); + assert_eq!(reentrance_count, expected_reentrance_count); + + // Re-enter 5 times in a row and assert that the reentrant counter works as expected. + if expected_reentrance_count != 5 { + let count = (expected_reentrance_count + 1).to_le_bytes(); + + api::call_v1( + uapi::CallFlags::ALLOW_REENTRY, + addr, + 0u64, // How much gas to devote for the execution. 0 = all. + &0u64.to_le_bytes(), // value transferred to the contract. + &count, + None, + ) + .unwrap(); + } +} diff --git a/substrate/frame/contracts/fixtures/contracts/reentrance_count_delegated_call.rs b/substrate/frame/contracts/fixtures/contracts/reentrance_count_delegated_call.rs new file mode 100644 index 0000000000000..9baf950380840 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/reentrance_count_delegated_call.rs @@ -0,0 +1,53 @@ +// This file is part of Substrate. + +// 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 account_reentrance_count works as expected. +#![no_std] +#![no_main] + +use common::input; +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() { + input!( + input, + code_hash: [u8; 32], + call_stack_height: u32, + ); + + let call_stack_height = call_stack_height + 1; + + #[allow(deprecated)] + let reentrance_count = api::reentrance_count(); + + // Reentrance count stays 0. + assert_eq!(reentrance_count, 0); + + // Re-enter 5 times in a row and assert that the reentrant counter works as expected. + if call_stack_height != 5 { + let mut input = [0u8; 36]; + input[0..32].copy_from_slice(code_hash); + input[32..36].copy_from_slice(&call_stack_height.to_le_bytes()); + api::delegate_call(uapi::CallFlags::empty(), code_hash, &input, None).unwrap(); + } +} diff --git a/substrate/frame/contracts/fixtures/contracts/return_with_data.rs b/substrate/frame/contracts/fixtures/contracts/return_with_data.rs new file mode 100644 index 0000000000000..5340f86fbfc58 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/return_with_data.rs @@ -0,0 +1,43 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +use uapi::{HostFn, HostFnImpl as api}; + +#[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], + ); + + let exit_status = uapi::ReturnFlags::from_bits(exit_status[0] as u32).unwrap(); + api::return_value(exit_status, output); +} diff --git a/substrate/frame/contracts/fixtures/contracts/run_out_of_gas.rs b/substrate/frame/contracts/fixtures/contracts/run_out_of_gas.rs new file mode 100644 index 0000000000000..11eaaa7c86247 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/run_out_of_gas.rs @@ -0,0 +1,32 @@ +// This file is part of Substrate. + +// 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] + +extern crate common; + +#[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 {} +} diff --git a/substrate/frame/contracts/fixtures/contracts/self_destruct.rs b/substrate/frame/contracts/fixtures/contracts/self_destruct.rs new file mode 100644 index 0000000000000..94c3ac387a0a6 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/self_destruct.rs @@ -0,0 +1,53 @@ +// This file is part of Substrate. + +// 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] + +use common::{input, output}; +use uapi::{HostFn, HostFnImpl as api}; + +const DJANGO: [u8; 32] = [4u8; 32]; + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() {} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() { + // If the input data is not empty, then recursively call self with empty input data. + // This should trap instead of self-destructing since a contract cannot be removed, while it's + // in the execution stack. If the recursive call traps, then trap here as well. + input!(input, 4,); + + if !input.is_empty() { + output!(addr, [0u8; 32], api::address,); + api::call_v1( + uapi::CallFlags::ALLOW_REENTRY, + addr, + 0u64, // How much gas to devote for the execution. 0 = all. + &0u64.to_le_bytes(), // Value to transfer. + &[0u8; 0], + None, + ) + .unwrap(); + } else { + // Try to terminate and give balance to django. + api::terminate_v1(&DJANGO); + } +} diff --git a/substrate/frame/contracts/fixtures/contracts/self_destructing_constructor.rs b/substrate/frame/contracts/fixtures/contracts/self_destructing_constructor.rs new file mode 100644 index 0000000000000..97b6759b3a66e --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/self_destructing_constructor.rs @@ -0,0 +1,32 @@ +// This file is part of Substrate. + +// 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] + +extern crate common; +use uapi::{HostFn, HostFnImpl as api}; + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() { + api::terminate_v1(&[0u8; 32]); +} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() {} diff --git a/substrate/frame/contracts/fixtures/contracts/set_code_hash.rs b/substrate/frame/contracts/fixtures/contracts/set_code_hash.rs new file mode 100644 index 0000000000000..e3cf4becfb972 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/set_code_hash.rs @@ -0,0 +1,37 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!(addr: [u8; 32],); + api::set_code_hash(addr).unwrap(); + + // we return 1 after setting new code_hash + // next `call` will NOT return this value, because contract code has been changed + api::return_value(uapi::ReturnFlags::empty(), &1u32.to_le_bytes()); +} diff --git a/substrate/frame/contracts/fixtures/contracts/set_empty_storage.rs b/substrate/frame/contracts/fixtures/contracts/set_empty_storage.rs new file mode 100644 index 0000000000000..e7366630e8fcd --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/set_empty_storage.rs @@ -0,0 +1,32 @@ +// This file is part of Substrate. + +// 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] + +extern crate common; +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::set_storage(&[0u8; 32], &[0u8; 4]); +} diff --git a/substrate/frame/contracts/fixtures/contracts/sr25519_verify.rs b/substrate/frame/contracts/fixtures/contracts/sr25519_verify.rs new file mode 100644 index 0000000000000..8920ce0d4f6c2 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/sr25519_verify.rs @@ -0,0 +1,48 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!( + signature: [u8; 64], + pub_key: [u8; 32], + msg: [u8; 11], + ); + + let exit_status = match api::sr25519_verify( + &signature.try_into().unwrap(), + msg, + &pub_key.try_into().unwrap(), + ) { + 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(), &exit_status.to_le_bytes()); +} diff --git a/substrate/frame/contracts/fixtures/contracts/storage_size.rs b/substrate/frame/contracts/fixtures/contracts/storage_size.rs new file mode 100644 index 0000000000000..744ffe8503e87 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/storage_size.rs @@ -0,0 +1,45 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!(len: u32, ); + + let mut buffer = [0u8; 16 * 1024 + 1]; + let data = &buffer[..len as usize]; + + // Place a garbage value in storage, the size of which is specified by the call input. + let mut key = [0u8; 32]; + key[0] = 1; + + api::set_storage(&key, data); + + let data = &mut &mut buffer[..]; + api::get_storage(&key, data).unwrap(); + assert_eq!(data.len(), len as usize); +} diff --git a/substrate/frame/contracts/fixtures/contracts/store_call.rs b/substrate/frame/contracts/fixtures/contracts/store_call.rs new file mode 100644 index 0000000000000..d20d811c294f5 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/store_call.rs @@ -0,0 +1,41 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!(len: u32, ); + + let buffer = [0u8; 16 * 1024 + 1]; + let data = &buffer[..len as usize]; + + // Place a garbage value in storage, the size of which is specified by the call input. + let mut key = [0u8; 32]; + key[0] = 1; + + api::set_storage(&key, data); +} diff --git a/substrate/frame/contracts/fixtures/contracts/store_deploy.rs b/substrate/frame/contracts/fixtures/contracts/store_deploy.rs new file mode 100644 index 0000000000000..26f3b86baff6d --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/store_deploy.rs @@ -0,0 +1,41 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +use uapi::{HostFn, HostFnImpl as api}; + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() { + input!(len: u32, ); + + let buffer = [0u8; 16 * 1024 + 1]; + let data = &buffer[..len as usize]; + + // place a garbage value in storage, the size of which is specified by the call input. + let mut key = [0u8; 32]; + key[0] = 1; + + api::set_storage(&key, data); +} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() {} diff --git a/substrate/frame/contracts/fixtures/contracts/transfer_return_code.rs b/substrate/frame/contracts/fixtures/contracts/transfer_return_code.rs new file mode 100644 index 0000000000000..d3f6a1dd3a081 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/transfer_return_code.rs @@ -0,0 +1,38 @@ +// This file is part of Substrate. + +// 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] + +extern crate common; +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 ret_code = match api::transfer(&[0u8; 32], &100u64.to_le_bytes()) { + 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(), &ret_code.to_le_bytes()); +} diff --git a/substrate/frame/contracts/fixtures/contracts/xcm_execute.rs b/substrate/frame/contracts/fixtures/contracts/xcm_execute.rs new file mode 100644 index 0000000000000..09d0b6cf97281 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/xcm_execute.rs @@ -0,0 +1,39 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!(512, msg: [u8],); + + let mut outcome = [0u8; 512]; + let outcome = &mut &mut outcome[..]; + + #[allow(deprecated)] + api::xcm_execute(msg, outcome).unwrap(); + api::return_value(uapi::ReturnFlags::empty(), outcome); +} diff --git a/substrate/frame/contracts/fixtures/contracts/xcm_send.rs b/substrate/frame/contracts/fixtures/contracts/xcm_send.rs new file mode 100644 index 0000000000000..6d4629e748a76 --- /dev/null +++ b/substrate/frame/contracts/fixtures/contracts/xcm_send.rs @@ -0,0 +1,42 @@ +// This file is part of Substrate. + +// 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] + +use common::input; +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() { + input!( + 512, + dest: [u8; 3], + msg: [u8], + ); + + let mut message_id = [0u8; 32]; + + #[allow(deprecated)] + api::xcm_send(dest, msg, &mut message_id).unwrap(); + api::return_value(uapi::ReturnFlags::empty(), &message_id); +} diff --git a/substrate/frame/contracts/fixtures/data/account_reentrance_count_call.wat b/substrate/frame/contracts/fixtures/data/account_reentrance_count_call.wat deleted file mode 100644 index e6d6ba8bb8140..0000000000000 --- a/substrate/frame/contracts/fixtures/data/account_reentrance_count_call.wat +++ /dev/null @@ -1,37 +0,0 @@ -;; This fixture tests if account_reentrance_count works as expected -;; testing it with 2 different addresses -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_caller" (func $seal_caller (param i32 i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "seal0" "account_reentrance_count" (func $account_reentrance_count (param i32) (result i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 32) buffer where input is copied - ;; [32, 36) size of the input buffer - (data (i32.const 32) "\20") - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "call") - ;; Reading "callee" input address - (call $seal_input (i32.const 0) (i32.const 32)) - - (i32.store - (i32.const 36) - (call $account_reentrance_count (i32.const 0)) - ) - - (call $seal_return (i32.const 0) (i32.const 36) (i32.const 4)) - ) - - (func (export "deploy")) - -) \ No newline at end of file diff --git a/substrate/frame/contracts/fixtures/data/add_remove_delegate_dependency.wat b/substrate/frame/contracts/fixtures/data/add_remove_delegate_dependency.wat deleted file mode 100644 index dac7736244da2..0000000000000 --- a/substrate/frame/contracts/fixtures/data/add_remove_delegate_dependency.wat +++ /dev/null @@ -1,111 +0,0 @@ -;; This contract tests the behavior of adding / removing delegate_dependencies when delegate calling into a contract. -(module - (import "seal0" "add_delegate_dependency" (func $add_delegate_dependency (param i32))) - (import "seal0" "remove_delegate_dependency" (func $remove_delegate_dependency (param i32))) - (import "seal0" "input" (func $input (param i32 i32))) - (import "seal1" "terminate" (func $terminate (param i32))) - (import "seal0" "delegate_call" (func $delegate_call (param i32 i32 i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - - ;; [100, 132) Address of Alice - (data (i32.const 100) - "\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" - "\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" - ) - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - ;; This function loads input data and performs the action specified. - ;; The first 4 bytes of the input specify the action to perform. - ;; The next 32 bytes specify the code hash to use when calling add_delegate_dependency or remove_delegate_dependency. - ;; Actions are: - ;; 1: call add_delegate_dependency - ;; 2: call remove_delegate_dependency. - ;; 3: call terminate. - ;; Any other value is a no-op. - (func $load_input - (local $action i32) - (local $code_hash_ptr i32) - - ;; Store available input size at offset 0. - (i32.store (i32.const 0) (i32.const 512)) - - ;; Read input data. - (call $input (i32.const 4) (i32.const 0)) - - ;; Input data layout. - ;; [0..4) - size of the call - ;; [4..8) - action to perform - ;; [8..42) - code hash of the callee - (local.set $action (i32.load (i32.const 4))) - (local.set $code_hash_ptr (i32.const 8)) - - ;; Assert input size == 36 (4 for action + 32 for code_hash). - (call $assert - (i32.eq - (i32.load (i32.const 0)) - (i32.const 36) - ) - ) - - ;; Call add_delegate_dependency when action == 1. - (if (i32.eq (local.get $action) (i32.const 1)) - (then - (call $add_delegate_dependency (local.get $code_hash_ptr)) - ) - (else) - ) - - ;; Call remove_delegate_dependency when action == 2. - (if (i32.eq (local.get $action) (i32.const 2)) - (then - (call $remove_delegate_dependency - (local.get $code_hash_ptr) - ) - ) - (else) - ) - - ;; Call terminate when action == 3. - (if (i32.eq (local.get $action) (i32.const 3)) - (then - (call $terminate - (i32.const 100) ;; Pointer to beneficiary address - ) - (unreachable) ;; terminate never returns - ) - (else) - ) - ) - - (func (export "deploy") - (call $load_input) - ) - - (func (export "call") - (call $load_input) - - ;; Delegate call into passed code hash. - (call $assert - (i32.eq - (call $delegate_call - (i32.const 0) ;; Set no call flags. - (i32.const 8) ;; Pointer to "callee" code_hash. - (i32.const 0) ;; Input is ignored. - (i32.const 0) ;; Length of the input. - (i32.const 4294967295) ;; u32 max sentinel value: do not copy output. - (i32.const 0) ;; Length is ignored in this case. - ) - (i32.const 0) - ) - ) - ) - -) diff --git a/substrate/frame/contracts/fixtures/data/balance.wat b/substrate/frame/contracts/fixtures/data/balance.wat deleted file mode 100644 index d7970c92e414a..0000000000000 --- a/substrate/frame/contracts/fixtures/data/balance.wat +++ /dev/null @@ -1,42 +0,0 @@ -(module - (import "seal0" "seal_balance" (func $seal_balance (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 8) reserved for $seal_balance output - - ;; [8, 16) length of the buffer for $seal_balance - (data (i32.const 8) "\08") - - ;; [16, inf) zero initialized - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "deploy")) - - (func (export "call") - (call $seal_balance (i32.const 0) (i32.const 8)) - - ;; Balance should be encoded as a u64. - (call $assert - (i32.eq - (i32.load (i32.const 8)) - (i32.const 8) - ) - ) - - ;; Assert the free balance to be zero. - (call $assert - (i64.eq - (i64.load (i32.const 0)) - (i64.const 0) - ) - ) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/call_return_code.wat b/substrate/frame/contracts/fixtures/data/call_return_code.wat deleted file mode 100644 index 4e9ab4dd77ce1..0000000000000 --- a/substrate/frame/contracts/fixtures/data/call_return_code.wat +++ /dev/null @@ -1,42 +0,0 @@ -;; 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. -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 8) 100 balance - (data (i32.const 0) "\64\00\00\00\00\00\00\00") - - ;; [8, 12) here we store the return code of the transfer - - ;; [12, 16) size of the input data - (data (i32.const 12) "\24") - - ;; [16, inf) here we store the input data - ;; 32 byte dest + 4 byte forward - - (func (export "deploy")) - - (func (export "call") - (call $seal_input (i32.const 16) (i32.const 12)) - (i32.store - (i32.const 8) - (call $seal_call - (i32.const 16) ;; Pointer to "callee" address. - (i32.const 32) ;; Length of "callee" address. - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 48) ;; Pointer to input data buffer address - (i32.const 4) ;; Length of input data buffer - (i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Ptr to output buffer len - ) - ) - ;; exit with success and take transfer return code to the output buffer - (call $seal_return (i32.const 0) (i32.const 8) (i32.const 4)) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/call_runtime.wat b/substrate/frame/contracts/fixtures/data/call_runtime.wat deleted file mode 100644 index d3d08ee24541a..0000000000000 --- a/substrate/frame/contracts/fixtures/data/call_runtime.wat +++ /dev/null @@ -1,33 +0,0 @@ -;; This passes its input to `seal_call_runtime` and returns the return value to its caller. -(module - (import "seal0" "call_runtime" (func $call_runtime (param i32 i32) (result i32))) - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; 0x1000 = 4k in little endian - ;; size of input buffer - (data (i32.const 0) "\00\10") - - (func (export "call") - ;; Receive the encoded call - (call $seal_input - (i32.const 4) ;; Pointer to the input buffer - (i32.const 0) ;; Size of the length buffer - ) - ;; Just use the call passed as input and store result to memory - (i32.store (i32.const 0) - (call $call_runtime - (i32.const 4) ;; Pointer where the call is stored - (i32.load (i32.const 0)) ;; Size of the call - ) - ) - (call $seal_return - (i32.const 0) ;; flags - (i32.const 0) ;; returned value - (i32.const 4) ;; length of returned value - ) - ) - - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/call_runtime_and_call.wat b/substrate/frame/contracts/fixtures/data/call_runtime_and_call.wat deleted file mode 100644 index 5d76e19a74c70..0000000000000 --- a/substrate/frame/contracts/fixtures/data/call_runtime_and_call.wat +++ /dev/null @@ -1,56 +0,0 @@ -(module - (import "seal0" "call_runtime" (func $call_runtime (param i32 i32) (result i32))) - (import "seal1" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32))) - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok (local.get 0)) - (unreachable) - ) - ) - - (func (export "call") - ;; Store available input size at offset 0. - (i32.store (i32.const 0) (i32.const 512)) - - ;; read input data - (call $seal_input (i32.const 4) (i32.const 0)) - - ;; Input data layout. - ;; [0..4) - size of the call - ;; [4..8) - how many bytes to add to storage - ;; [8..40) - address of the callee - ;; [40..n) - encoded runtime call - - ;; Invoke call_runtime with the encoded call passed to this contract. - (call $assert (i32.eqz - (call $call_runtime - (i32.const 40) ;; Pointer where the call is stored - (i32.sub - (i32.load (i32.const 0)) ;; Size of the call - (i32.const 36) ;; Subtract size of the subcall-related part: 4 bytes for storage length to add + 32 bytes of the callee address - ) - ) - )) - - ;; call passed contract - (call $assert (i32.eqz - (call $seal_call - (i32.const 0) ;; No flags - (i32.const 8) ;; Pointer to "callee" address. - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 512) ;; Pointer to the buffer with value to transfer - (i32.const 4) ;; Pointer to input data buffer address - (i32.const 4) ;; Length of input data buffer - (i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - ) - )) - ) - - (func (export "deploy")) -) - diff --git a/substrate/frame/contracts/fixtures/data/call_with_limit.wat b/substrate/frame/contracts/fixtures/data/call_with_limit.wat deleted file mode 100644 index 04da59551a8ce..0000000000000 --- a/substrate/frame/contracts/fixtures/data/call_with_limit.wat +++ /dev/null @@ -1,38 +0,0 @@ -;; This expects [account_id, ref_time, proof_size] as input and calls the account_id with the supplied 2D Weight limit. -;; It returns the result of the call as output data. -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal2" "call" (func $seal_call (param i32 i32 i64 i64 i32 i32 i32 i32 i32 i32) (result i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; 0x1000 = 4k in little endian - ;; size of input buffer - (data (i32.const 0) "\00\10") - - (func (export "deploy")) - - (func (export "call") - ;; Receive the encoded account_id, ref_time, proof_size - (call $seal_input - (i32.const 4) ;; Pointer to the input buffer - (i32.const 0) ;; Pointer to the length of the input buffer - ) - (i32.store - (i32.const 0) - (call $seal_call - (i32.const 0) ;; Set no flag. - (i32.const 4) ;; Pointer to "callee" address. - (i64.load (i32.const 36)) ;; How much ref_time to devote for the execution. - (i64.load (i32.const 44)) ;; How much proof_size to devote for the execution. - (i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 0) ;; Length of input data buffer - (i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - ) - ) - (call $seal_return (i32.const 0) (i32.const 0) (i32.const 4)) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/caller_contract.wat b/substrate/frame/contracts/fixtures/data/caller_contract.wat deleted file mode 100644 index 43eb8ccfd54f5..0000000000000 --- a/substrate/frame/contracts/fixtures/data/caller_contract.wat +++ /dev/null @@ -1,286 +0,0 @@ -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_balance" (func $seal_balance (param i32 i32))) - (import "seal2" "call" (func $seal_call (param i32 i32 i64 i64 i32 i32 i32 i32 i32 i32) (result i32))) - (import "seal2" "instantiate" (func $seal_instantiate - (param i32 i64 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32) - )) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "deploy")) - - (func (export "call") - (local $sp i32) - (local $exit_code i32) - - ;; Length of the buffer - (i32.store (i32.const 20) (i32.const 32)) - - ;; Copy input to this contracts memory - (call $seal_input (i32.const 24) (i32.const 20)) - - ;; Input data is the code hash of the contract to be deployed. - (call $assert - (i32.eq - (i32.load (i32.const 20)) - (i32.const 32) - ) - ) - - ;; Read current balance into local variable. - (local.set $sp (i32.const 1024)) - - ;; Fail to deploy the contract since it returns a non-zero exit status. - (local.set $exit_code - (call $seal_instantiate - (i32.const 24) ;; Pointer to the code hash. - (i64.const 0) ;; How much ref_time weight to devote for the execution. 0 = all. - (i64.const 0) ;; How much proof_size weight to devote for the execution. 0 = all. - (i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 9) ;; Pointer to input data buffer address - (i32.const 7) ;; Length of input data buffer - (i32.const 4294967295) ;; u32 max sentinel value: do not copy address - (i32.const 0) ;; Length is ignored in this case - (i32.const 4294967295) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - (i32.const 0) ;; salt_ptr - (i32.const 0) ;; salt_le - ) - ) - - ;; Check non-zero exit status. - (call $assert - (i32.eq (local.get $exit_code) (i32.const 2)) ;; ReturnCode::CalleeReverted - ) - - ;; Fail to deploy the contract due to insufficient ref_time weight. - (local.set $exit_code - (call $seal_instantiate - (i32.const 24) ;; Pointer to the code hash. - (i64.const 1) ;; Supply too little ref_time weight - (i64.const 0) ;; How much proof_size weight to devote for the execution. 0 = all. - (i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Pointer to input data buffer address - (i32.const 8) ;; Length of input data buffer - (i32.const 4294967295) ;; u32 max sentinel value: do not copy address - (i32.const 0) ;; Length is ignored in this case - (i32.const 4294967295) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - (i32.const 0) ;; salt_ptr - (i32.const 0) ;; salt_le - - ) - ) - - ;; Check for special trap exit status. - (call $assert - (i32.eq (local.get $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped - ) - - ;; Fail to deploy the contract due to insufficient ref_time weight. - (local.set $exit_code - (call $seal_instantiate - (i32.const 24) ;; Pointer to the code hash. - (i64.const 0) ;; How much ref_time weight to devote for the execution. 0 = all. - (i64.const 1) ;; Supply too little proof_size weight - (i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Pointer to input data buffer address - (i32.const 8) ;; Length of input data buffer - (i32.const 4294967295) ;; u32 max sentinel value: do not copy address - (i32.const 0) ;; Length is ignored in this case - (i32.const 4294967295) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - (i32.const 0) ;; salt_ptr - (i32.const 0) ;; salt_le - - ) - ) - - ;; Check for special trap exit status. - (call $assert - (i32.eq (local.get $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped - ) - - ;; Length of the output buffer - (i32.store - (i32.sub (local.get $sp) (i32.const 4)) - (i32.const 256) - ) - - ;; Deploy the contract successfully. - (local.set $exit_code - (call $seal_instantiate - (i32.const 24) ;; Pointer to the code hash. - (i64.const 0) ;; How much ref_time weight to devote for the execution. 0 = all. - (i64.const 0) ;; How much proof_size weight to devote for the execution. 0 = all. - (i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Pointer to input data buffer address - (i32.const 8) ;; Length of input data buffer - (i32.const 16) ;; Pointer to the address output buffer - (i32.sub (local.get $sp) (i32.const 4)) ;; Pointer to the address buffer length - (i32.const 4294967295) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - (i32.const 0) ;; salt_ptr - (i32.const 0) ;; salt_le - - ) - ) - - ;; Check for success exit status. - (call $assert - (i32.eq (local.get $exit_code) (i32.const 0)) ;; ReturnCode::Success - ) - - ;; Check that address has the expected length - (call $assert - (i32.eq (i32.load (i32.sub (local.get $sp) (i32.const 4))) (i32.const 32)) - ) - - ;; Zero out destination buffer of output - (i32.store - (i32.sub (local.get $sp) (i32.const 4)) - (i32.const 0) - ) - - ;; Length of the output buffer - (i32.store - (i32.sub (local.get $sp) (i32.const 8)) - (i32.const 4) - ) - - ;; Call the new contract and expect it to return failing exit code. - (local.set $exit_code - (call $seal_call - (i32.const 0) ;; Set no flag - (i32.const 16) ;; Pointer to "callee" address. - (i64.const 0) ;; How much ref_time weight to devote for the execution. 0 = all. - (i64.const 0) ;; How much proof_size weight to devote for the execution. 0 = all. - (i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 9) ;; Pointer to input data buffer address - (i32.const 7) ;; Length of input data buffer - (i32.sub (local.get $sp) (i32.const 4)) ;; Ptr to output buffer - (i32.sub (local.get $sp) (i32.const 8)) ;; Ptr to output buffer len - ) - ) - - ;; Check non-zero exit status. - (call $assert - (i32.eq (local.get $exit_code) (i32.const 2)) ;; ReturnCode::CalleeReverted - ) - - ;; Check that output buffer contains the expected return data. - (call $assert - (i32.eq (i32.load (i32.sub (local.get $sp) (i32.const 8))) (i32.const 3)) - ) - (call $assert - (i32.eq - (i32.load (i32.sub (local.get $sp) (i32.const 4))) - (i32.const 0x00776655) - ) - ) - - ;; Fail to call the contract due to insufficient ref_time weight. - (local.set $exit_code - (call $seal_call - (i32.const 0) ;; Set no flag - (i32.const 16) ;; Pointer to "callee" address. - (i64.const 1) ;; Supply too little ref_time weight - (i64.const 0) ;; How much proof_size weight to devote for the execution. 0 = all. - (i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Pointer to input data buffer address - (i32.const 8) ;; Length of input data buffer - (i32.const 4294967295) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this cas - ) - ) - - ;; Check for special trap exit status. - (call $assert - (i32.eq (local.get $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped - ) - - ;; Fail to call the contract due to insufficient proof_size weight. - (local.set $exit_code - (call $seal_call - (i32.const 0) ;; Set no flag - (i32.const 16) ;; Pointer to "callee" address. - (i64.const 0) ;; How much ref_time weight to devote for the execution. 0 = all. - (i64.const 1) ;; Supply too little proof_size weight - (i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Pointer to input data buffer address - (i32.const 8) ;; Length of input data buffer - (i32.const 4294967295) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this cas - ) - ) - - ;; Check for special trap exit status. - (call $assert - (i32.eq (local.get $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped - ) - - ;; Zero out destination buffer of output - (i32.store - (i32.sub (local.get $sp) (i32.const 4)) - (i32.const 0) - ) - - ;; Length of the output buffer - (i32.store - (i32.sub (local.get $sp) (i32.const 8)) - (i32.const 4) - ) - - ;; Call the contract successfully. - (local.set $exit_code - (call $seal_call - (i32.const 0) ;; Set no flag - (i32.const 16) ;; Pointer to "callee" address. - (i64.const 0) ;; How much ref_time weight to devote for the execution. 0 = all. - (i64.const 0) ;; How much proof_size weight to devote for the execution. 0 = all. - (i32.const 0xffffffff) ;; u32 max sentinel value: pass no deposit limit. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Pointer to input data buffer address - (i32.const 8) ;; Length of input data buffer - (i32.sub (local.get $sp) (i32.const 4)) ;; Ptr to output buffer - (i32.sub (local.get $sp) (i32.const 8)) ;; Ptr to output buffer len - ) - ) - - ;; Check for success exit status. - (call $assert - (i32.eq (local.get $exit_code) (i32.const 0)) ;; ReturnCode::Success - ) - - ;; Check that the output buffer contains the expected return data. - (call $assert - (i32.eq (i32.load (i32.sub (local.get $sp) (i32.const 8))) (i32.const 4)) - ) - (call $assert - (i32.eq - (i32.load (i32.sub (local.get $sp) (i32.const 4))) - (i32.const 0x77665544) - ) - ) - ) - - (data (i32.const 0) "\00\80") ;; The value to transfer on instantiation and calls. - ;; Chosen to be greater than existential deposit. - (data (i32.const 8) "\00\01\22\33\44\55\66\77") ;; The input data to instantiations and calls. -) diff --git a/substrate/frame/contracts/fixtures/data/chain_extension.wat b/substrate/frame/contracts/fixtures/data/chain_extension.wat deleted file mode 100644 index c24ca286ff8c0..0000000000000 --- a/substrate/frame/contracts/fixtures/data/chain_extension.wat +++ /dev/null @@ -1,46 +0,0 @@ -;; Call chain extension by passing through input and output of this contract -(module - (import "seal0" "call_chain_extension" - (func $call_chain_extension (param i32 i32 i32 i32 i32) (result i32)) - ) - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "env" "memory" (memory 16 16)) - - (func $assert (param i32) - (block $ok - (br_if $ok (local.get 0)) - (unreachable) - ) - ) - - ;; [0, 4) len of input output - (data (i32.const 0) "\08") - - ;; [4, 12) buffer for input - - ;; [12, 48) len of output buffer - (data (i32.const 12) "\20") - - ;; [16, inf) buffer for output - - (func (export "deploy")) - - (func (export "call") - (call $seal_input (i32.const 4) (i32.const 0)) - - ;; the chain extension passes through the input and returns it as output - (call $call_chain_extension - (i32.load (i32.const 4)) ;; id - (i32.const 4) ;; input_ptr - (i32.load (i32.const 0)) ;; input_len - (i32.const 16) ;; output_ptr - (i32.const 12) ;; output_len_ptr - ) - - ;; the chain extension passes through the id - (call $assert (i32.eq (i32.load (i32.const 4)))) - - (call $seal_return (i32.const 0) (i32.const 16) (i32.load (i32.const 12))) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/chain_extension_temp_storage.wat b/substrate/frame/contracts/fixtures/data/chain_extension_temp_storage.wat deleted file mode 100644 index 504646df1b0eb..0000000000000 --- a/substrate/frame/contracts/fixtures/data/chain_extension_temp_storage.wat +++ /dev/null @@ -1,85 +0,0 @@ -;; Call chain extension two times with the specified func_ids -;; It then calls itself once -(module - (import "seal0" "seal_call_chain_extension" - (func $seal_call_chain_extension (param i32 i32 i32 i32 i32) (result i32)) - ) - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_address" (func $seal_address (param i32 i32))) - (import "seal1" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 16 16)) - - (func $assert (param i32) - (block $ok - (br_if $ok (local.get 0)) - (unreachable) - ) - ) - - ;; [0, 4) len of input buffer: 8 byte (func_ids) + 1byte (stop_recurse) - (data (i32.const 0) "\09") - - ;; [4, 16) buffer for input - - ;; [16, 48] buffer for self address - - ;; [48, 52] len of self address buffer - (data (i32.const 48) "\20") - - (func (export "deploy")) - - (func (export "call") - ;; input: (func_id1: i32, func_id2: i32, stop_recurse: i8) - (call $seal_input (i32.const 4) (i32.const 0)) - - (call $seal_call_chain_extension - (i32.load (i32.const 4)) ;; id - (i32.const 0) ;; input_ptr - (i32.const 0) ;; input_len - (i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; output_len_ptr - ) - drop - - (call $seal_call_chain_extension - (i32.load (i32.const 8)) ;; _id - (i32.const 0) ;; input_ptr - (i32.const 0) ;; input_len - (i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; output_len_ptr - ) - drop - - (if (i32.eqz (i32.load8_u (i32.const 12))) - (then - ;; stop recursion - (i32.store8 (i32.const 12) (i32.const 1)) - - ;; load own address into buffer - (call $seal_address (i32.const 16) (i32.const 48)) - - ;; call function 2 + 3 of chainext 3 next time - ;; (3 << 16) | 2 - ;; (3 << 16) | 3 - (i32.store (i32.const 4) (i32.const 196610)) - (i32.store (i32.const 8) (i32.const 196611)) - - ;; call self - (call $seal_call - (i32.const 8) ;; Set ALLOW_REENTRY - (i32.const 16) ;; Pointer to "callee" address. - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 512) ;; Pointer to the buffer with value to transfer - (i32.const 4) ;; Pointer to input data buffer address - (i32.load (i32.const 0)) ;; Length of input data buffer - (i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - ) - - ;; check that call succeeded of call - (call $assert (i32.eqz)) - ) - (else) - ) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/create_storage_and_call.wat b/substrate/frame/contracts/fixtures/data/create_storage_and_call.wat deleted file mode 100644 index 2bff53b638fd0..0000000000000 --- a/substrate/frame/contracts/fixtures/data/create_storage_and_call.wat +++ /dev/null @@ -1,60 +0,0 @@ -;; This calls another contract as passed as its account id. It also creates some storage. -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) - (import "seal2" "call" (func $seal_call (param i32 i32 i64 i64 i32 i32 i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "deploy")) - - (func (export "call") - ;; store length of input buffer - (i32.store (i32.const 0) (i32.const 512)) - - ;; copy input at address 4: - ;; first 4 bytes for the size of the storage to be created in callee - ;; next 32 bytes are for the callee address - ;; next bytes for the encoded deposit limit - (call $seal_input (i32.const 4) (i32.const 0)) - - ;; create 4 byte of storage before calling - (call $seal_set_storage - (i32.const 0) ;; Pointer to storage key - (i32.const 0) ;; Pointer to value - (i32.const 4) ;; Size of value - ) - - ;; call passed contract - (call $assert (i32.eqz - (call $seal_call - (i32.const 0) ;; No flags - (i32.const 8) ;; Pointer to "callee" address - (i64.const 0) ;; How much ref_time to devote for the execution. 0 = all - (i64.const 0) ;; How much proof_limit to devote for the execution. 0 = all - (i32.const 40) ;; Pointer to the storage deposit limit - (i32.const 512) ;; Pointer to the buffer with value to transfer - (i32.const 4) ;; Pointer to input data buffer address - (i32.const 4) ;; Length of input data buffer - (i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - ) - )) - - ;; create 8 byte of storage after calling - ;; item of 12 bytes because we override 4 bytes - (call $seal_set_storage - (i32.const 0) ;; Pointer to storage key - (i32.const 0) ;; Pointer to value - (i32.const 12) ;; Size of value - ) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/create_storage_and_instantiate.wat b/substrate/frame/contracts/fixtures/data/create_storage_and_instantiate.wat deleted file mode 100644 index 00c9a657f39f9..0000000000000 --- a/substrate/frame/contracts/fixtures/data/create_storage_and_instantiate.wat +++ /dev/null @@ -1,66 +0,0 @@ -;; This instantiates another contract and passes some input to its constructor. -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) - (import "seal2" "instantiate" (func $seal_instantiate - (param i32 i64 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32) - )) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 8) send 10_000 balance - (data (i32.const 48) "\10\27\00\00\00\00\00\00") - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "deploy")) - - (func (export "call") - ;; store length of input buffer - (i32.store (i32.const 0) (i32.const 512)) - ;; store length of contract address - (i32.store (i32.const 84) (i32.const 32)) - - ;; copy input at address 4 - (call $seal_input (i32.const 4) (i32.const 0)) - - ;; memory layout is: - ;; [0,4): size of input buffer - ;; [4,8): size of the storage to be created in callee - ;; [8,40): the code hash of the contract to instantiate - ;; [40,48): for the encoded deposit limit - ;; [48,52): value to transfer - ;; [52,84): address of the deployed contract - ;; [84,88): len of the address - - ;; instantiate a contract - (call $assert (i32.eqz -;; (i32.store -;; (i32.const 64) - (call $seal_instantiate - (i32.const 8) ;; Pointer to the code hash. - (i64.const 0) ;; How much ref_time weight to devote for the execution. 0 = all. - (i64.const 0) ;; How much proof_size weight to devote for the execution. 0 = all. - (i32.const 40) ;; Pointer to the storage deposit limit - (i32.const 48) ;; Pointer to the buffer with value to transfer - (i32.const 4) ;; Pointer to input data buffer address - (i32.const 4) ;; Length of input data buffer - (i32.const 52) ;; Pointer to where to copy address - (i32.const 84) ;; Pointer to address len ptr - (i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - (i32.const 0) ;; salt_ptr - (i32.const 0) ;; salt_len - ) - )) - ;; return the deployed contract address - (call $seal_return (i32.const 0) (i32.const 52) (i32.const 32)) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/crypto_hashes.wat b/substrate/frame/contracts/fixtures/data/crypto_hashes.wat deleted file mode 100644 index 9d86b02f41921..0000000000000 --- a/substrate/frame/contracts/fixtures/data/crypto_hashes.wat +++ /dev/null @@ -1,83 +0,0 @@ -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - - (import "seal0" "seal_hash_sha2_256" (func $seal_hash_sha2_256 (param i32 i32 i32))) - (import "seal0" "seal_hash_keccak_256" (func $seal_hash_keccak_256 (param i32 i32 i32))) - (import "seal0" "seal_hash_blake2_256" (func $seal_hash_blake2_256 (param i32 i32 i32))) - (import "seal0" "seal_hash_blake2_128" (func $seal_hash_blake2_128 (param i32 i32 i32))) - - (import "env" "memory" (memory 1 1)) - - (type $hash_fn_sig (func (param i32 i32 i32))) - (table 8 funcref) - (elem (i32.const 1) - $seal_hash_sha2_256 - $seal_hash_keccak_256 - $seal_hash_blake2_256 - $seal_hash_blake2_128 - ) - (data (i32.const 1) "20202010201008") ;; Output sizes of the hashes in order in hex. - - ;; Not in use by the tests besides instantiating the contract. - (func (export "deploy")) - - ;; Called by the tests. - ;; - ;; The `call` function expects data in a certain format in the input buffer. - ;; - ;; 1. The first byte encodes an identifier for the crypto hash function - ;; under test. (*) - ;; 2. The rest encodes the input data that is directly fed into the - ;; crypto hash function chosen in 1. - ;; - ;; The `deploy` function then computes the chosen crypto hash function - ;; given the input and puts the result 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 chosen hash - ;; function. - ;; - ;; (*) The possible value for the crypto hash identifiers can be found below: - ;; - ;; | value | Algorithm | Bit Width | - ;; |-------|-----------|-----------| - ;; | 0 | SHA2 | 256 | - ;; | 1 | KECCAK | 256 | - ;; | 2 | BLAKE2 | 256 | - ;; | 3 | BLAKE2 | 128 | - ;; --------------------------------- - (func (export "call") - (local $chosen_hash_fn i32) - (local $input_len_ptr i32) - (local $input_ptr i32) - (local $input_len i32) - (local $output_ptr i32) - (local $output_len i32) - (local.set $input_len_ptr (i32.const 256)) - (local.set $input_ptr (i32.const 10)) - (i32.store (local.get $input_len_ptr) (i32.const 246)) - (call $seal_input (local.get $input_ptr) (local.get $input_len_ptr)) - (local.set $chosen_hash_fn (i32.load8_u (local.get $input_ptr))) - (if (i32.gt_u (local.get $chosen_hash_fn) (i32.const 7)) - (then - ;; We check that the chosen hash fn identifier is within bounds: [0,7] - (unreachable) - ) - ) - (local.set $input_ptr (i32.add (local.get $input_ptr) (i32.const 1))) - (local.set $input_len (i32.sub (i32.load (local.get $input_len_ptr)) (i32.const 1))) - (local.set $output_len (i32.load8_u (local.get $chosen_hash_fn))) - (call_indirect (type $hash_fn_sig) - (local.get $input_ptr) - (local.get $input_len) - (local.get $input_ptr) - (local.get $chosen_hash_fn) ;; Which crypto hash function to execute. - ) - (call $seal_return - (i32.const 0) - (local.get $input_ptr) ;; Linear memory location of the output buffer. - (local.get $output_len) ;; Number of output buffer bytes. - ) - (unreachable) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/debug_message_invalid_utf8.wat b/substrate/frame/contracts/fixtures/data/debug_message_invalid_utf8.wat deleted file mode 100644 index dae0de8841891..0000000000000 --- a/substrate/frame/contracts/fixtures/data/debug_message_invalid_utf8.wat +++ /dev/null @@ -1,28 +0,0 @@ -;; Emit a debug message with an invalid utf-8 code -(module - (import "seal0" "seal_debug_message" (func $seal_debug_message (param i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - - (data (i32.const 0) "\fc") - - (func $assert_eq (param i32 i32) - (block $ok - (br_if $ok - (i32.eq (local.get 0) (local.get 1)) - ) - (unreachable) - ) - ) - - (func (export "call") - (call $assert_eq - (call $seal_debug_message - (i32.const 0) ;; Pointer to the text buffer - (i32.const 12) ;; The size of the buffer - ) - (i32.const 0) ;; Success return code - ) - ) - - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/debug_message_logging_disabled.wat b/substrate/frame/contracts/fixtures/data/debug_message_logging_disabled.wat deleted file mode 100644 index e9ce20ba42b22..0000000000000 --- a/substrate/frame/contracts/fixtures/data/debug_message_logging_disabled.wat +++ /dev/null @@ -1,28 +0,0 @@ -;; Emit a "Hello World!" debug message but assume that logging is disabled. -(module - (import "seal0" "seal_debug_message" (func $seal_debug_message (param i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - - (data (i32.const 0) "Hello World!") - - (func $assert_eq (param i32 i32) - (block $ok - (br_if $ok - (i32.eq (local.get 0) (local.get 1)) - ) - (unreachable) - ) - ) - - (func (export "call") - (call $assert_eq - (call $seal_debug_message - (i32.const 0) ;; Pointer to the text buffer - (i32.const 12) ;; The size of the buffer - ) - (i32.const 0) ;; Success return code - ) - ) - - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/debug_message_works.wat b/substrate/frame/contracts/fixtures/data/debug_message_works.wat deleted file mode 100644 index 44a7b6db1befe..0000000000000 --- a/substrate/frame/contracts/fixtures/data/debug_message_works.wat +++ /dev/null @@ -1,28 +0,0 @@ -;; Emit a "Hello World!" debug message -(module - (import "seal0" "seal_debug_message" (func $seal_debug_message (param i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - - (data (i32.const 0) "Hello World!") - - (func $assert_eq (param i32 i32) - (block $ok - (br_if $ok - (i32.eq (local.get 0) (local.get 1)) - ) - (unreachable) - ) - ) - - (func (export "call") - (call $assert_eq - (call $seal_debug_message - (i32.const 0) ;; Pointer to the text buffer - (i32.const 12) ;; The size of the buffer - ) - (i32.const 0) ;; success return code - ) - ) - - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/delegate_call.wat b/substrate/frame/contracts/fixtures/data/delegate_call.wat deleted file mode 100644 index b8d4f0d47f0ff..0000000000000 --- a/substrate/frame/contracts/fixtures/data/delegate_call.wat +++ /dev/null @@ -1,111 +0,0 @@ -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_get_storage" (func $seal_get_storage (param i32 i32 i32) (result i32))) - (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) - (import "seal0" "seal_delegate_call" (func $seal_delegate_call (param i32 i32 i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 3 3)) - - ;; [0, 32) storage key - (data (i32.const 0) "\01") - - ;; [32, 64) storage key - (data (i32.const 32) "\02") - - ;; [64, 96) buffer where input is copied - - ;; [96, 100) size of the input buffer - (data (i32.const 96) "\20") - - ;; [100, 104) size of buffer for seal_get_storage - (data (i32.const 100) "\20") - - ;; [104, 136) seal_get_storage buffer - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "call") - (local $exit_code i32) - - ;; Reading "callee" code_hash - (call $seal_input (i32.const 64) (i32.const 96)) - - ;; assert input size == 32 - (call $assert - (i32.eq - (i32.load (i32.const 96)) - (i32.const 32) - ) - ) - - ;; place a value in storage, the size of which is specified by the call input. - (call $seal_set_storage - (i32.const 0) ;; Pointer to storage key - (i32.const 32) ;; Pointer to initial value - (i32.load (i32.const 100)) ;; Size of value - ) - - (call $assert - (i32.eq - (call $seal_get_storage - (i32.const 0) ;; Pointer to storage key - (i32.const 104) ;; buffer where to copy result - (i32.const 100) ;; pointer to size of buffer - ) - (i32.const 0) ;; ReturnCode::Success - ) - ) - - (call $assert - (i32.eq - (i32.load (i32.const 104)) ;; value received from storage - (i32.load (i32.const 32)) ;; initial value - ) - ) - - ;; Call deployed library contract code. - (local.set $exit_code - (call $seal_delegate_call - (i32.const 0) ;; Set no call flags - (i32.const 64) ;; Pointer to "callee" code_hash. - (i32.const 0) ;; Input is ignored - (i32.const 0) ;; Length of the input - (i32.const 4294967295) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - ) - ) - - ;; Check for success exit status. - (call $assert - (i32.eq (local.get $exit_code) (i32.const 0)) ;; ReturnCode::Success - ) - - (call $assert - (i32.eq - (call $seal_get_storage - (i32.const 0) ;; Pointer to storage key - (i32.const 104) ;; buffer where to copy result - (i32.const 100) ;; pointer to size of buffer - ) - (i32.const 0) ;; ReturnCode::Success - ) - ) - - ;; Make sure that 'callee' code changed the value - (call $assert - (i32.eq - (i32.load (i32.const 104)) - (i32.const 1) - ) - ) - ) - - (func (export "deploy")) - -) diff --git a/substrate/frame/contracts/fixtures/data/delegate_call_lib.wat b/substrate/frame/contracts/fixtures/data/delegate_call_lib.wat deleted file mode 100644 index 62eea32800a46..0000000000000 --- a/substrate/frame/contracts/fixtures/data/delegate_call_lib.wat +++ /dev/null @@ -1,79 +0,0 @@ -(module - (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) - (import "seal0" "seal_caller" (func $seal_caller (param i32 i32))) - (import "seal0" "seal_value_transferred" (func $seal_value_transferred (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 32) storage key - (data (i32.const 0) "\01") - - ;; [32, 64) buffer for transferred value - - ;; [64, 96) size of the buffer for transferred value - (data (i32.const 64) "\20") - - ;; [96, 128) buffer for the caller - - ;; [128, 160) size of the buffer for caller - (data (i32.const 128) "\20") - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "call") - ;; place a value in storage - (call $seal_set_storage - (i32.const 0) ;; Pointer to storage key - (i32.const 0) ;; Pointer to value - (i32.const 32) ;; Size of value - ) - - ;; This stores the value transferred in the buffer - (call $seal_value_transferred (i32.const 32) (i32.const 64)) - - ;; assert len == 8 - (call $assert - (i32.eq - (i32.load (i32.const 64)) - (i32.const 8) - ) - ) - - ;; assert that contents of the buffer is equal to the value - ;; passed to the `caller` contract: 1337 - (call $assert - (i64.eq - (i64.load (i32.const 32)) - (i64.const 1337) - ) - ) - - ;; fill the buffer with the caller. - (call $seal_caller (i32.const 96) (i32.const 128)) - - ;; assert len == 32 - (call $assert - (i32.eq - (i32.load (i32.const 128)) - (i32.const 32) - ) - ) - - ;; assert that the first 64 byte are the beginning of "ALICE", - ;; who is the caller of the `caller` contract - (call $assert - (i64.eq - (i64.load (i32.const 96)) - (i64.const 0x0101010101010101) - ) - ) - ) - - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/delegate_call_simple.wat b/substrate/frame/contracts/fixtures/data/delegate_call_simple.wat deleted file mode 100644 index ba0a8fcc8ae3b..0000000000000 --- a/substrate/frame/contracts/fixtures/data/delegate_call_simple.wat +++ /dev/null @@ -1,50 +0,0 @@ -;; Just delegate call into the passed code hash and assert success. -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_delegate_call" (func $seal_delegate_call (param i32 i32 i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 3 3)) - - ;; [0, 32) buffer where input is copied - - ;; [32, 36) size of the input buffer - (data (i32.const 32) "\20") - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "call") - ;; Reading "callee" code_hash - (call $seal_input (i32.const 0) (i32.const 32)) - - ;; assert input size == 32 - (call $assert - (i32.eq - (i32.load (i32.const 32)) - (i32.const 32) - ) - ) - - ;; Delegate call into passed code hash - (call $assert - (i32.eq - (call $seal_delegate_call - (i32.const 0) ;; Set no call flags - (i32.const 0) ;; Pointer to "callee" code_hash. - (i32.const 0) ;; Input is ignored - (i32.const 0) ;; Length of the input - (i32.const 4294967295) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - ) - (i32.const 0) - ) - ) - ) - - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/destroy_and_transfer.wat b/substrate/frame/contracts/fixtures/data/destroy_and_transfer.wat deleted file mode 100644 index 2afd3b2fbacf5..0000000000000 --- a/substrate/frame/contracts/fixtures/data/destroy_and_transfer.wat +++ /dev/null @@ -1,161 +0,0 @@ -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_get_storage" (func $seal_get_storage (param i32 i32 i32) (result i32))) - (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) - (import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32))) - (import "seal0" "seal_transfer" (func $seal_transfer (param i32 i32 i32 i32) (result i32))) - (import "seal0" "seal_instantiate" (func $seal_instantiate - (param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32) - )) - (import "env" "memory" (memory 1 1)) - - ;; [0, 8) value to send when creating contract. - (data (i32.const 0) "\00\00\01") - - ;; [8, 16) Value to send when calling contract. - - ;; [16, 48) The key to store the contract address under. - - ;; [48, 80) Buffer where to store the input to the contract - - ;; [88, 96) Size of the buffer - (data (i32.const 88) "\FF") - - ;; [96, 100) Size of the input buffer - (data (i32.const 96) "\20") - - ;; [100, 132) Buffer where to store the address of the instantiated contract - - ;; [132, 134) Salt - (data (i32.const 132) "\47\11") - - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "deploy") - ;; Input data is the code hash of the contract to be deployed. - (call $seal_input (i32.const 48) (i32.const 96)) - (call $assert - (i32.eq - (i32.load (i32.const 96)) - (i32.const 32) - ) - ) - - ;; Deploy the contract with the provided code hash. - (call $assert - (i32.eq - (call $seal_instantiate - (i32.const 48) ;; Pointer to the code hash. - (i32.const 32) ;; Length of the code hash. - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 0) ;; Length of input data buffer - (i32.const 100) ;; Buffer where to store address of new contract - (i32.const 88) ;; Pointer to the length of the buffer - (i32.const 4294967295) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - (i32.const 132) ;; salt_ptr - (i32.const 2) ;; salt_len - ) - (i32.const 0) - ) - ) - - ;; Check that address has expected length - (call $assert - (i32.eq - (i32.load (i32.const 88)) - (i32.const 32) - ) - ) - - ;; Store the return address. - (call $seal_set_storage - (i32.const 16) ;; Pointer to the key - (i32.const 100) ;; Pointer to the value - (i32.const 32) ;; Length of the value - ) - ) - - (func (export "call") - ;; Read address of destination contract from storage. - (call $assert - (i32.eq - (call $seal_get_storage - (i32.const 16) ;; Pointer to the key - (i32.const 100) ;; Pointer to the value - (i32.const 88) ;; Pointer to the len of the value - ) - (i32.const 0) - ) - ) - (call $assert - (i32.eq - (i32.load (i32.const 88)) - (i32.const 32) - ) - ) - - ;; Calling the destination contract with non-empty input data should fail. - (call $assert - (i32.eq - (call $seal_call - (i32.const 100) ;; Pointer to destination address - (i32.const 32) ;; Length of destination address - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 1) ;; Length of input data buffer - (i32.const 4294967295) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - - ) - (i32.const 0x1) - ) - ) - - ;; Call the destination contract regularly, forcing it to self-destruct. - (call $assert - (i32.eq - (call $seal_call - (i32.const 100) ;; Pointer to destination address - (i32.const 32) ;; Length of destination address - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 8) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 0) ;; Length of input data buffer - (i32.const 4294967295) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - ) - (i32.const 0) - ) - ) - - ;; Calling the destination address with non-empty input data should now work since the - ;; contract has been removed. Also transfer a balance to the address so we can ensure this - ;; does not hinder the contract from being removed. - (call $assert - (i32.eq - (call $seal_transfer - (i32.const 100) ;; Pointer to destination address - (i32.const 32) ;; Length of destination address - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer - ) - (i32.const 0) - ) - ) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/drain.wat b/substrate/frame/contracts/fixtures/data/drain.wat deleted file mode 100644 index 18a21cca803d8..0000000000000 --- a/substrate/frame/contracts/fixtures/data/drain.wat +++ /dev/null @@ -1,75 +0,0 @@ -(module - (import "seal0" "seal_balance" (func $seal_balance (param i32 i32))) - (import "seal0" "seal_minimum_balance" (func $seal_minimum_balance (param i32 i32))) - (import "seal0" "seal_transfer" (func $seal_transfer (param i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 8) reserved for $seal_balance output - - ;; [8, 16) length of the buffer for $seal_balance - (data (i32.const 8) "\08") - - ;; [16, 24) reserved for $seal_minimum_balance - - ;; [24, 32) length of the buffer for $seal_minimum_balance - (data (i32.const 24) "\08") - - ;; [32, inf) zero initialized - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "deploy")) - - (func (export "call") - ;; Send entire remaining balance to the 0 address. - (call $seal_balance (i32.const 0) (i32.const 8)) - - ;; Balance should be encoded as a u64. - (call $assert - (i32.eq - (i32.load (i32.const 8)) - (i32.const 8) - ) - ) - - ;; Get the minimum balance. - (call $seal_minimum_balance (i32.const 16) (i32.const 24)) - - ;; Minimum balance should be encoded as a u64. - (call $assert - (i32.eq - (i32.load (i32.const 24)) - (i32.const 8) - ) - ) - - ;; Make the transferred value exceed the balance by adding the minimum balance. - (i64.store (i32.const 0) - (i64.add - (i64.load (i32.const 0)) - (i64.load (i32.const 16)) - ) - ) - - ;; 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 - (call $assert - (i32.eq - (call $seal_transfer - (i32.const 32) ;; Pointer to destination address - (i32.const 48) ;; Length of destination address - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer - ) - (i32.const 5) ;; ReturnCode::TransferFailed - ) - ) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/ecdsa_recover.wat b/substrate/frame/contracts/fixtures/data/ecdsa_recover.wat deleted file mode 100644 index 4910e706069e4..0000000000000 --- a/substrate/frame/contracts/fixtures/data/ecdsa_recover.wat +++ /dev/null @@ -1,55 +0,0 @@ -;; This contract: -;; 1) Reads signature and message hash from the input -;; 2) Calls ecdsa_recover -;; 3) Validates that result is Success -;; 4) Returns recovered compressed public key -(module - (import "seal0" "seal_ecdsa_recover" (func $seal_ecdsa_recover (param i32 i32 i32) (result i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "deploy")) - - ;; [4, 8) len of signature + message hash - 65 bytes + 32 byte = 97 bytes - (data (i32.const 4) "\61") - - ;; Memory layout during `call` - ;; [10, 75) signature - ;; [75, 107) message hash - (func (export "call") - (local $signature_ptr i32) - (local $message_hash_ptr i32) - (local $result i32) - (local.set $signature_ptr (i32.const 10)) - (local.set $message_hash_ptr (i32.const 75)) - ;; Read signature and message hash - 97 bytes - (call $seal_input (local.get $signature_ptr) (i32.const 4)) - (local.set - $result - (call $seal_ecdsa_recover - (local.get $signature_ptr) - (local.get $message_hash_ptr) - (local.get $signature_ptr) ;; Store output into message signature ptr, because we don't need it anymore - ) - ) - (call $assert - (i32.eq - (local.get $result) ;; The result of recovery execution - (i32.const 0x0) ;; 0x0 - Success result - ) - ) - - ;; exit with success and return recovered public key - (call $seal_return (i32.const 0) (local.get $signature_ptr) (i32.const 33)) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/event_and_return_on_deploy.wat b/substrate/frame/contracts/fixtures/data/event_and_return_on_deploy.wat deleted file mode 100644 index 809cfe13545a6..0000000000000 --- a/substrate/frame/contracts/fixtures/data/event_and_return_on_deploy.wat +++ /dev/null @@ -1,26 +0,0 @@ -(module - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func (export "deploy") - (call $seal_deposit_event - (i32.const 0) ;; The topics buffer - (i32.const 0) ;; The topics buffer's length - (i32.const 8) ;; The data buffer - (i32.const 4) ;; The data buffer's length - ) - (call $seal_return - (i32.const 0) - (i32.const 8) - (i32.const 4) - ) - (unreachable) - ) - - (func (export "call") - (unreachable) - ) - - (data (i32.const 8) "\01\02\03\04") -) diff --git a/substrate/frame/contracts/fixtures/data/event_size.wat b/substrate/frame/contracts/fixtures/data/event_size.wat deleted file mode 100644 index 1c1f34b24d728..0000000000000 --- a/substrate/frame/contracts/fixtures/data/event_size.wat +++ /dev/null @@ -1,39 +0,0 @@ -(module - (import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32))) - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "env" "memory" (memory 16 16)) - - ;; [0, 4) size of the input buffer - (data (i32.const 0) "\04") - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "call") - (call $seal_input (i32.const 4) (i32.const 0)) - - ;; assert input size == 4 - (call $assert - (i32.eq - (i32.load (i32.const 0)) - (i32.const 4) - ) - ) - - ;; place a garbage value in storage, the size of which is specified by the call input. - (call $seal_deposit_event - (i32.const 0) ;; topics_ptr - (i32.const 0) ;; topics_len - (i32.const 0) ;; data_ptr - (i32.load (i32.const 4)) ;; data_len - ) - ) - - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/float_instruction.wat b/substrate/frame/contracts/fixtures/data/float_instruction.wat deleted file mode 100644 index efa6b9de52de6..0000000000000 --- a/substrate/frame/contracts/fixtures/data/float_instruction.wat +++ /dev/null @@ -1,12 +0,0 @@ -;; Module that contains a float instruction which is illegal in deterministic mode -(module - (import "env" "memory" (memory 1 1)) - (func (export "call") - f32.const 1 - drop - ) - (func (export "deploy") - f32.const 2 - drop - ) -) diff --git a/substrate/frame/contracts/fixtures/data/instantiate_return_code.wat b/substrate/frame/contracts/fixtures/data/instantiate_return_code.wat deleted file mode 100644 index 6a8654520f106..0000000000000 --- a/substrate/frame/contracts/fixtures/data/instantiate_return_code.wat +++ /dev/null @@ -1,47 +0,0 @@ -;; This instantiats a contract and transfers 100 balance during this call and copies the return code -;; of this call to the output buffer. -;; The first 32 byte of input is the code hash to instantiate -;; The rest of the input is forwarded to the constructor of the callee -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal1" "seal_instantiate" (func $seal_instantiate - (param i32 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32) - )) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 8) 10_000 balance - (data (i32.const 0) "\10\27\00\00\00\00\00\00") - - ;; [8, 12) here we store the return code of the transfer - - ;; [12, 16) size of the input buffer - (data (i32.const 12) "\24") - - ;; [16, inf) input buffer - ;; 32 bye code hash + 4 byte forward - - (func (export "deploy")) - - (func (export "call") - (call $seal_input (i32.const 16) (i32.const 12)) - (i32.store - (i32.const 8) - (call $seal_instantiate - (i32.const 16) ;; Pointer to the code hash. - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 48) ;; Pointer to input data buffer address - (i32.const 4) ;; Length of input data buffer - (i32.const 0xffffffff) ;; u32 max sentinel value: do not copy address - (i32.const 0) ;; Length is ignored in this case - (i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - (i32.const 0) ;; salt_ptr - (i32.const 0) ;; salt_len - ) - ) - ;; exit with success and take transfer return code to the output buffer - (call $seal_return (i32.const 0) (i32.const 8) (i32.const 4)) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/invalid_contract_no_call.wat b/substrate/frame/contracts/fixtures/data/invalid_contract_no_call.wat deleted file mode 100644 index 34f7c99ba85e4..0000000000000 --- a/substrate/frame/contracts/fixtures/data/invalid_contract_no_call.wat +++ /dev/null @@ -1,5 +0,0 @@ -;; Valid module but missing the call function -(module - (import "env" "memory" (memory 1 1)) - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/multi_store.wat b/substrate/frame/contracts/fixtures/data/multi_store.wat deleted file mode 100644 index c334ed54c4eb7..0000000000000 --- a/substrate/frame/contracts/fixtures/data/multi_store.wat +++ /dev/null @@ -1,54 +0,0 @@ -;; Does two stores to two seperate storage items -;; Expects (len0, len1) as input. -(module - (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "env" "memory" (memory 16 16)) - - ;; [0, 32) storage key 0 - (data (i32.const 0) "\01") - - ;; [32, 64) storage key 1 - (data (i32.const 32) "\02") - - ;; [64, 72) buffer where input is copied (expected sizes of storage items) - - ;; [72, 76) size of the input buffer - (data (i32.const 72) "\08") - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "call") - (call $seal_input (i32.const 64) (i32.const 72)) - - ;; assert input size == 8 - (call $assert - (i32.eq - (i32.load (i32.const 72)) - (i32.const 8) - ) - ) - - ;; place a values in storage sizes are specified in the input buffer - ;; we don't care about the contents of the storage item - (call $seal_set_storage - (i32.const 0) ;; Pointer to storage key - (i32.const 0) ;; Pointer to value - (i32.load (i32.const 64)) ;; Size of value - ) - (call $seal_set_storage - (i32.const 32) ;; Pointer to storage key - (i32.const 0) ;; Pointer to value - (i32.load (i32.const 68)) ;; Size of value - ) - ) - - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/new_set_code_hash_contract.wat b/substrate/frame/contracts/fixtures/data/new_set_code_hash_contract.wat deleted file mode 100644 index 86ab2737be484..0000000000000 --- a/substrate/frame/contracts/fixtures/data/new_set_code_hash_contract.wat +++ /dev/null @@ -1,13 +0,0 @@ -(module - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 32) return value - (data (i32.const 0) "\02") - - (func (export "deploy")) - - (func (export "call") - (call $seal_return (i32.const 0) (i32.const 0) (i32.const 4)) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/ok_trap_revert.wat b/substrate/frame/contracts/fixtures/data/ok_trap_revert.wat deleted file mode 100644 index b7eaa9b700af5..0000000000000 --- a/substrate/frame/contracts/fixtures/data/ok_trap_revert.wat +++ /dev/null @@ -1,35 +0,0 @@ -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func (export "deploy") - (call $ok_trap_revert) - ) - - (func (export "call") - (call $ok_trap_revert) - ) - - (func $ok_trap_revert - (i32.store (i32.const 4) (i32.const 4)) - (call $seal_input (i32.const 0) (i32.const 4)) - (block $IF_2 - (block $IF_1 - (block $IF_0 - (br_table $IF_0 $IF_1 $IF_2 - (i32.load8_u (i32.const 0)) - ) - (unreachable) - ) - ;; 0 = return with success - return - ) - ;; 1 = revert - (call $seal_return (i32.const 1) (i32.const 0) (i32.const 0)) - (unreachable) - ) - ;; 2 = trap - (unreachable) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/reentrance_count_call.wat b/substrate/frame/contracts/fixtures/data/reentrance_count_call.wat deleted file mode 100644 index 44db8d041b1da..0000000000000 --- a/substrate/frame/contracts/fixtures/data/reentrance_count_call.wat +++ /dev/null @@ -1,76 +0,0 @@ -;; This fixture recursively tests if reentrance_count returns correct reentrant count value when -;; using seal_call to make caller contract call to itself -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_address" (func $seal_address (param i32 i32))) - (import "seal1" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32))) - (import "seal0" "reentrance_count" (func $reentrance_count (result i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 32) reserved for $seal_address output - - ;; [32, 36) buffer for the call stack height - - ;; [36, 40) size of the input buffer - (data (i32.const 36) "\04") - - ;; [40, 44) length of the buffer for $seal_address - (data (i32.const 40) "\20") - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - (func (export "call") - (local $expected_reentrance_count i32) - (local $seal_call_exit_code i32) - - ;; reading current contract address - (call $seal_address (i32.const 0) (i32.const 40)) - - ;; reading passed input - (call $seal_input (i32.const 32) (i32.const 36)) - - ;; reading manually passed reentrant count - (local.set $expected_reentrance_count (i32.load (i32.const 32))) - - ;; reentrance count is calculated correctly - (call $assert - (i32.eq (call $reentrance_count) (local.get $expected_reentrance_count)) - ) - - ;; re-enter 5 times in a row and assert that the reentrant counter works as expected - (i32.eq (call $reentrance_count) (i32.const 5)) - (if - (then) ;; recursion exit case - (else - ;; incrementing $expected_reentrance_count passed to the contract - (i32.store (i32.const 32) (i32.add (i32.load (i32.const 32)) (i32.const 1))) - - ;; Call to itself - (local.set $seal_call_exit_code - (call $seal_call - (i32.const 8) ;; Allow reentrancy flag set - (i32.const 0) ;; Pointer to "callee" address - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 32) ;; Pointer to input data buffer address - (i32.const 4) ;; Length of input data buffer - (i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Ptr to output buffer len - ) - ) - - (call $assert - (i32.eq (local.get $seal_call_exit_code) (i32.const 0)) - ) - ) - ) - ) - - (func (export "deploy")) -) \ No newline at end of file diff --git a/substrate/frame/contracts/fixtures/data/reentrance_count_delegated_call.wat b/substrate/frame/contracts/fixtures/data/reentrance_count_delegated_call.wat deleted file mode 100644 index 49e0193bcdb10..0000000000000 --- a/substrate/frame/contracts/fixtures/data/reentrance_count_delegated_call.wat +++ /dev/null @@ -1,71 +0,0 @@ -;; This fixture recursively tests if reentrance_count returns correct reentrant count value when -;; using seal_delegate_call to make caller contract delegate call to itself -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) - (import "seal0" "seal_delegate_call" (func $seal_delegate_call (param i32 i32 i32 i32 i32 i32) (result i32))) - (import "seal0" "reentrance_count" (func $reentrance_count (result i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 32) buffer where code hash is copied - - ;; [32, 36) buffer for the call stack height - - ;; [36, 40) size of the input buffer - (data (i32.const 36) "\24") - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - (func (export "call") - (local $callstack_height i32) - (local $delegate_call_exit_code i32) - - ;; Reading input - (call $seal_input (i32.const 0) (i32.const 36)) - - ;; reading passed callstack height - (local.set $callstack_height (i32.load (i32.const 32))) - - ;; incrementing callstack height - (i32.store (i32.const 32) (i32.add (i32.load (i32.const 32)) (i32.const 1))) - - ;; reentrance count stays 0 - (call $assert - (i32.eq (call $reentrance_count) (i32.const 0)) - ) - - (i32.eq (local.get $callstack_height) (i32.const 5)) - (if - (then) ;; exit recursion case - (else - ;; Call to itself - (local.set $delegate_call_exit_code - (call $seal_delegate_call - (i32.const 0) ;; Set no call flags - (i32.const 0) ;; Pointer to "callee" code_hash. - (i32.const 0) ;; Pointer to the input data - (i32.const 36) ;; Length of the input - (i32.const 4294967295) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - ) - ) - - (call $assert - (i32.eq (local.get $delegate_call_exit_code) (i32.const 0)) - ) - ) - ) - - (call $assert - (i32.le_s (local.get $callstack_height) (i32.const 5)) - ) - ) - - (func (export "deploy")) -) \ No newline at end of file diff --git a/substrate/frame/contracts/fixtures/data/return_with_data.wat b/substrate/frame/contracts/fixtures/data/return_with_data.wat deleted file mode 100644 index 93b9daa07a303..0000000000000 --- a/substrate/frame/contracts/fixtures/data/return_with_data.wat +++ /dev/null @@ -1,33 +0,0 @@ -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 128) buffer where input is copied - - ;; [128, 132) length of the input buffer - (data (i32.const 128) "\80") - - ;; Deploy routine is the same as call. - (func (export "deploy") - (call $call) - ) - - ;; Call reads the first 4 bytes (LE) as the exit status and returns the rest as output data. - (func $call (export "call") - ;; Copy input into this contracts memory. - (call $seal_input (i32.const 0) (i32.const 128)) - - ;; Copy all but the first 4 bytes of the input data as the output data. - ;; Use the first byte as exit status - (call $seal_return - (i32.load8_u (i32.const 0)) ;; Exit status - (i32.const 4) ;; Pointer to the data to return. - (i32.sub ;; Count of bytes to copy. - (i32.load (i32.const 128)) - (i32.const 4) - ) - ) - (unreachable) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/run_out_of_gas.wat b/substrate/frame/contracts/fixtures/data/run_out_of_gas.wat deleted file mode 100644 index fe53e92c4fa84..0000000000000 --- a/substrate/frame/contracts/fixtures/data/run_out_of_gas.wat +++ /dev/null @@ -1,8 +0,0 @@ -(module - (import "env" "memory" (memory 1 1)) - (func (export "call") - (loop $inf (br $inf)) ;; just run out of gas - (unreachable) - ) - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/self_destruct.wat b/substrate/frame/contracts/fixtures/data/self_destruct.wat deleted file mode 100644 index 00c3895fddedd..0000000000000 --- a/substrate/frame/contracts/fixtures/data/self_destruct.wat +++ /dev/null @@ -1,83 +0,0 @@ -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_address" (func $seal_address (param i32 i32))) - (import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32))) - (import "seal0" "seal_terminate" (func $seal_terminate (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 32) reserved for $seal_address output - - ;; [32, 36) length of the buffer - (data (i32.const 32) "\20") - - ;; [36, 68) Address of django - (data (i32.const 36) - "\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04" - "\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04" - ) - - ;; [68, 72) reserved for output of $seal_input - - ;; [72, 76) length of the buffer - (data (i32.const 72) "\04") - - ;; [76, inf) zero initialized - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "deploy")) - - (func (export "call") - ;; If the input data is not empty, then recursively call self with empty input data. - ;; This should trap instead of self-destructing since a contract cannot be removed live in - ;; the execution stack cannot be removed. If the recursive call traps, then trap here as - ;; well. - (call $seal_input (i32.const 68) (i32.const 72)) - (if (i32.load (i32.const 72)) - (then - (call $seal_address (i32.const 0) (i32.const 32)) - - ;; Expect address to be 8 bytes. - (call $assert - (i32.eq - (i32.load (i32.const 32)) - (i32.const 32) - ) - ) - - ;; Recursively call self with empty input data. - (call $assert - (i32.eq - (call $seal_call - (i32.const 0) ;; Pointer to own address - (i32.const 32) ;; Length of own address - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 76) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 0) ;; Length of input data buffer - (i32.const 4294967295) ;; u32 max sentinel value: do not copy output - (i32.const 0) ;; Length is ignored in this case - ) - (i32.const 0) - ) - ) - ) - (else - ;; Try to terminate and give balance to django. - (call $seal_terminate - (i32.const 36) ;; Pointer to beneficiary address - (i32.const 32) ;; Length of beneficiary address - ) - (unreachable) ;; seal_terminate never returns - ) - ) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/self_destructing_constructor.wat b/substrate/frame/contracts/fixtures/data/self_destructing_constructor.wat deleted file mode 100644 index 628f283a19fd3..0000000000000 --- a/substrate/frame/contracts/fixtures/data/self_destructing_constructor.wat +++ /dev/null @@ -1,23 +0,0 @@ -(module - (import "seal0" "seal_terminate" (func $seal_terminate (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "deploy") - ;; Self-destruct by sending full balance to the 0 address. - (call $seal_terminate - (i32.const 0) ;; Pointer to destination address - (i32.const 32) ;; Length of destination address - ) - ) - - (func (export "call")) -) diff --git a/substrate/frame/contracts/fixtures/data/set_code_hash.wat b/substrate/frame/contracts/fixtures/data/set_code_hash.wat deleted file mode 100644 index c0a9557b4d001..0000000000000 --- a/substrate/frame/contracts/fixtures/data/set_code_hash.wat +++ /dev/null @@ -1,43 +0,0 @@ -(module - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "seal0" "seal_set_code_hash" (func $seal_set_code_hash (param i32) (result i32))) - - (import "env" "memory" (memory 1 1)) - - ;; [0, 32) here we store input - - ;; [32, 36) input size - (data (i32.const 32) "\20") - - ;; [36, 40) return value - (data (i32.const 36) "\01") - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "call") - (local $exit_code i32) - - (call $seal_input (i32.const 0) (i32.const 32)) - - (local.set $exit_code - (call $seal_set_code_hash (i32.const 0)) ;; Pointer to the input data. - ) - (call $assert - (i32.eq (local.get $exit_code) (i32.const 0)) ;; ReturnCode::Success - ) - - ;; we return 1 after setting new code_hash - ;; next `call` will NOT return this value, because contract code has been changed - (call $seal_return (i32.const 0) (i32.const 36) (i32.const 4)) - ) - - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/set_empty_storage.wat b/substrate/frame/contracts/fixtures/data/set_empty_storage.wat deleted file mode 100644 index dbcd3a1326aa2..0000000000000 --- a/substrate/frame/contracts/fixtures/data/set_empty_storage.wat +++ /dev/null @@ -1,15 +0,0 @@ -;; This module stores a KV pair into the storage -(module - (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) - (import "env" "memory" (memory 16 16)) - - (func (export "call") - ) - (func (export "deploy") - (call $seal_set_storage - (i32.const 0) ;; Pointer to storage key - (i32.const 0) ;; Pointer to value - (i32.load (i32.const 0)) ;; Size of value - ) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/sr25519_verify.wat b/substrate/frame/contracts/fixtures/data/sr25519_verify.wat deleted file mode 100644 index 2da1ceb87eab0..0000000000000 --- a/substrate/frame/contracts/fixtures/data/sr25519_verify.wat +++ /dev/null @@ -1,55 +0,0 @@ -;; This contract: -;; 1) Reads signature, message and public key from the input -;; 2) Calls and return the result of sr25519_verify - -(module - ;; import the host functions from the seal0 module - (import "seal0" "sr25519_verify" (func $sr25519_verify (param i32 i32 i32 i32) (result i32))) - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - - ;; give the program 1 page of memory - (import "env" "memory" (memory 1 1)) - - ;; [0, 4) length of signature + message + public key - 64 + 11 + 32 = 107 bytes - ;; write the length of the input (6b = 107) bytes at offset 0 - (data (i32.const 0) "\6b") - - (func (export "deploy")) - - (func (export "call") - ;; define local variables - (local $signature_ptr i32) - (local $pub_key_ptr i32) - (local $message_len i32) - (local $message_ptr i32) - - ;; set the pointers to the memory locations - ;; Memory layout during `call` - ;; [10, 74) signature - ;; [74, 106) public key - ;; [106, 117) message (11 bytes) - (local.set $signature_ptr (i32.const 10)) - (local.set $pub_key_ptr (i32.const 74)) - (local.set $message_ptr (i32.const 106)) - - ;; store the input into the memory, starting at the signature and - ;; up to 107 bytes stored at offset 0 - (call $seal_input (local.get $signature_ptr) (i32.const 0)) - - ;; call sr25519_verify and store the return code - (i32.store - (i32.const 0) - (call $sr25519_verify - (local.get $signature_ptr) - (local.get $pub_key_ptr) - (i32.const 11) - (local.get $message_ptr) - ) - ) - - ;; exit with success and take transfer return code to the output buffer - (call $seal_return (i32.const 0) (i32.const 0) (i32.const 4)) - ) -) - diff --git a/substrate/frame/contracts/fixtures/data/storage_size.wat b/substrate/frame/contracts/fixtures/data/storage_size.wat deleted file mode 100644 index 728bb4fcf3c09..0000000000000 --- a/substrate/frame/contracts/fixtures/data/storage_size.wat +++ /dev/null @@ -1,68 +0,0 @@ -(module - (import "seal0" "seal_get_storage" (func $seal_get_storage (param i32 i32 i32) (result i32))) - (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "env" "memory" (memory 16 16)) - - ;; [0, 32) storage key - (data (i32.const 0) "\01") - - ;; [32, 36) buffer where input is copied (expected size of storage item) - - ;; [36, 40) size of the input buffer - (data (i32.const 36) "\04") - - ;; [40, 44) size of buffer for seal_get_storage set to max - (data (i32.const 40) "\FF\FF\FF\FF") - - ;; [44, inf) seal_get_storage buffer - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "call") - (call $seal_input (i32.const 32) (i32.const 36)) - - ;; assert input size == 4 - (call $assert - (i32.eq - (i32.load (i32.const 36)) - (i32.const 4) - ) - ) - - ;; place a garbage value in storage, the size of which is specified by the call input. - (call $seal_set_storage - (i32.const 0) ;; Pointer to storage key - (i32.const 0) ;; Pointer to value - (i32.load (i32.const 32)) ;; Size of value - ) - - (call $assert - (i32.eq - (call $seal_get_storage - (i32.const 0) ;; Pointer to storage key - (i32.const 44) ;; buffer where to copy result - (i32.const 40) ;; pointer to size of buffer - ) - (i32.const 0) - ) - ) - - (call $assert - (i32.eq - (i32.load (i32.const 40)) - (i32.load (i32.const 32)) - ) - ) - ) - - (func (export "deploy")) - -) diff --git a/substrate/frame/contracts/fixtures/data/store_call.wat b/substrate/frame/contracts/fixtures/data/store_call.wat deleted file mode 100644 index 746b7a48b551b..0000000000000 --- a/substrate/frame/contracts/fixtures/data/store_call.wat +++ /dev/null @@ -1,45 +0,0 @@ -;; Stores a value of the passed size. -(module - (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "env" "memory" (memory 16 16)) - - ;; [0, 32) storage key - (data (i32.const 0) "\01") - - ;; [32, 36) buffer where input is copied (expected size of storage item) - - ;; [36, 40) size of the input buffer - (data (i32.const 36) "\04") - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "call") - (call $seal_input (i32.const 32) (i32.const 36)) - - ;; assert input size == 4 - (call $assert - (i32.eq - (i32.load (i32.const 36)) - (i32.const 4) - ) - ) - - ;; place a value in storage, the size of which is specified by the call input. - ;; we don't care about the contents of the storage item - (call $seal_set_storage - (i32.const 0) ;; Pointer to storage key - (i32.const 0) ;; Pointer to value - (i32.load (i32.const 32)) ;; Size of value - ) - ) - - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/data/store_deploy.wat b/substrate/frame/contracts/fixtures/data/store_deploy.wat deleted file mode 100644 index 7f115cba977cc..0000000000000 --- a/substrate/frame/contracts/fixtures/data/store_deploy.wat +++ /dev/null @@ -1,45 +0,0 @@ -;; Stores a value of the passed size in constructor. -(module - (import "seal0" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32))) - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "env" "memory" (memory 16 16)) - - ;; [0, 32) storage key - (data (i32.const 0) "\01") - - ;; [32, 36) buffer where input is copied (expected size of storage item) - - ;; [36, 40) size of the input buffer - (data (i32.const 36) "\04") - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "deploy") - (call $seal_input (i32.const 32) (i32.const 36)) - - ;; assert input size == 4 - (call $assert - (i32.eq - (i32.load (i32.const 36)) - (i32.const 4) - ) - ) - - ;; place a value in storage, the size of which is specified by the call input. - ;; we don't care about the contents of the storage item - (call $seal_set_storage - (i32.const 0) ;; Pointer to storage key - (i32.const 0) ;; Pointer to value - (i32.load (i32.const 32)) ;; Size of value - ) - ) - - (func (export "call")) -) diff --git a/substrate/frame/contracts/fixtures/data/transfer_return_code.wat b/substrate/frame/contracts/fixtures/data/transfer_return_code.wat deleted file mode 100644 index 50098851dcf81..0000000000000 --- a/substrate/frame/contracts/fixtures/data/transfer_return_code.wat +++ /dev/null @@ -1,34 +0,0 @@ -;; This transfers 100 balance to the zero account and copies the return code -;; of this transfer to the output buffer. -(module - (import "seal0" "seal_transfer" (func $seal_transfer (param i32 i32 i32 i32) (result i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; [0, 32) zero-adress - (data (i32.const 0) - "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" - "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" - ) - - ;; [32, 40) 100 balance - (data (i32.const 32) "\64\00\00\00\00\00\00\00") - - ;; [40, 44) here we store the return code of the transfer - - (func (export "deploy")) - - (func (export "call") - (i32.store - (i32.const 40) - (call $seal_transfer - (i32.const 0) ;; ptr to destination address - (i32.const 32) ;; length of destination address - (i32.const 32) ;; ptr to value to transfer - (i32.const 8) ;; length of value to transfer - ) - ) - ;; exit with success and take transfer return code to the output buffer - (call $seal_return (i32.const 0) (i32.const 40) (i32.const 4)) - ) -) diff --git a/substrate/frame/contracts/fixtures/data/xcm_execute.wat b/substrate/frame/contracts/fixtures/data/xcm_execute.wat deleted file mode 100644 index 72ef14ed82c74..0000000000000 --- a/substrate/frame/contracts/fixtures/data/xcm_execute.wat +++ /dev/null @@ -1,52 +0,0 @@ -;; This passes its input to `seal_xcm_execute` and returns the return value to its caller. -(module - (import "seal0" "xcm_execute" (func $xcm_execute (param i32 i32 i32) (result i32))) - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; 0x1000 = 4k in little endian - ;; Size of input buffer - (data (i32.const 0) "\00\10") - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "call") - ;; Receive the encoded call - (call $seal_input - (i32.const 4) ;; Pointer to the input buffer - (i32.const 0) ;; Pointer to the buffer length (before call) and to the copied data length (after call) - ) - ;; Input data layout. - ;; [0..4) - size of the call - ;; [4..) - message - - ;; Call xcm_execute with provided input. - (call $assert - (i32.eq - (call $xcm_execute - (i32.const 4) ;; Pointer where the message is stored - (i32.load (i32.const 0)) ;; Size of the message - (i32.const 100) ;; Pointer to the where the outcome is stored - ) - (i32.const 0) - ) - ) - - (call $seal_return - (i32.const 0) ;; flags - (i32.const 100) ;; Pointer to returned value - (i32.const 10) ;; length of returned value - ) - ) - - (func (export "deploy")) -) - diff --git a/substrate/frame/contracts/fixtures/data/xcm_send.wat b/substrate/frame/contracts/fixtures/data/xcm_send.wat deleted file mode 100644 index fe29ddf0f141a..0000000000000 --- a/substrate/frame/contracts/fixtures/data/xcm_send.wat +++ /dev/null @@ -1,59 +0,0 @@ -;; This passes its input to `seal_xcm_send` and returns the return value to its caller. -(module - (import "seal0" "xcm_send" (func $xcm_send (param i32 i32 i32 i32) (result i32))) - (import "seal0" "seal_input" (func $seal_input (param i32 i32))) - (import "seal0" "seal_return" (func $seal_return (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; 0x1000 = 4k in little endian - ;; size of input buffer - (data (i32.const 0) "\00\10") - - (func $assert (param i32) - (block $ok - (br_if $ok - (local.get 0) - ) - (unreachable) - ) - ) - - (func (export "call") - - ;; Receive the encoded call - (call $seal_input - (i32.const 4) ;; Pointer to the input buffer - (i32.const 0) ;; Size of the length buffer - ) - - ;; Input data layout. - ;; [0..4) - size of the call - ;; [4..7) - dest - ;; [7..) - message - - ;; Call xcm_send with provided input. - (call $assert - (i32.eq - (call $xcm_send - (i32.const 4) ;; Pointer where the dest is stored - (i32.const 7) ;; Pointer where the message is stored - (i32.sub - (i32.load (i32.const 0)) ;; length of the input buffer - (i32.const 3) ;; Size of the XCM dest - ) - (i32.const 100) ;; Pointer to the where the message_id is stored - ) - (i32.const 0) - ) - ) - - ;; Return the the message_id - (call $seal_return - (i32.const 0) ;; flags - (i32.const 100) ;; Pointer to returned value - (i32.const 32) ;; length of returned value - ) - ) - - (func (export "deploy")) -) diff --git a/substrate/frame/contracts/fixtures/src/lib.rs b/substrate/frame/contracts/fixtures/src/lib.rs index fbc2647709dce..4d850d75624b4 100644 --- a/substrate/frame/contracts/fixtures/src/lib.rs +++ b/substrate/frame/contracts/fixtures/src/lib.rs @@ -69,8 +69,7 @@ mod test { #[test] fn out_dir_should_have_compiled_mocks() { let out_dir: std::path::PathBuf = env!("OUT_DIR").into(); - let dummy_wasm = out_dir.join("dummy.wasm"); - println!("dummy_wasm: {:?}", dummy_wasm); - assert!(dummy_wasm.exists()); + assert!(out_dir.join("dummy.wasm").exists()); + assert!(out_dir.join("dummy.polkavm").exists()); } } diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs index 4f63104ef268b..28fe3c2af49c7 100644 --- a/substrate/frame/contracts/src/tests.rs +++ b/substrate/frame/contracts/src/tests.rs @@ -178,7 +178,7 @@ parameter_types! { pub struct TestExtension { enabled: bool, last_seen_buffer: Vec, - last_seen_inputs: (u32, u32, u32, u32), + last_seen_input_len: u32, } #[derive(Default)] @@ -201,14 +201,14 @@ impl TestExtension { TestExtensionTestValue::get().last_seen_buffer.clone() } - fn last_seen_inputs() -> (u32, u32, u32, u32) { - TestExtensionTestValue::get().last_seen_inputs + fn last_seen_input_len() -> u32 { + TestExtensionTestValue::get().last_seen_input_len } } impl Default for TestExtension { fn default() -> Self { - Self { enabled: true, last_seen_buffer: vec![], last_seen_inputs: (0, 0, 0, 0) } + Self { enabled: true, last_seen_buffer: vec![], last_seen_input_len: 0 } } } @@ -231,9 +231,7 @@ impl ChainExtension for TestExtension { }, 1 => { let env = env.only_in(); - TestExtensionTestValue::mutate(|e| { - e.last_seen_inputs = (env.val0(), env.val1(), env.val2(), env.val3()) - }); + TestExtensionTestValue::mutate(|e| e.last_seen_input_len = env.val1()); Ok(RetVal::Converging(id)) }, 2 => { @@ -2154,8 +2152,7 @@ fn chain_extension_works() { ) .result .unwrap(); - // those values passed in the fixture - assert_eq!(TestExtension::last_seen_inputs(), (4, 4, 16, 12)); + assert_eq!(TestExtension::last_seen_input_len(), 4); // 2 = charge some extra weight (amount supplied in the fifth byte) let result = Contracts::bare_call( @@ -3511,7 +3508,7 @@ fn failed_deposit_charge_should_roll_back_call() { let result = execute().unwrap(); // Bump the deposit per byte to a high value to trigger a FundsUnavailable error. - DEPOSIT_PER_BYTE.with(|c| *c.borrow_mut() = ED); + DEPOSIT_PER_BYTE.with(|c| *c.borrow_mut() = 20); assert_err_with_weight!(execute(), TokenError::FundsUnavailable, result.actual_weight); } diff --git a/substrate/frame/contracts/src/wasm/mod.rs b/substrate/frame/contracts/src/wasm/mod.rs index 4650a9bc79a36..d00ec2e47521b 100644 --- a/substrate/frame/contracts/src/wasm/mod.rs +++ b/substrate/frame/contracts/src/wasm/mod.rs @@ -2460,7 +2460,7 @@ mod tests { assert_eq!( result, Err(ExecError { - error: Error::::OutOfBounds.into(), + error: Error::::DecodingFailed.into(), origin: ErrorOrigin::Caller, }) ); @@ -3428,4 +3428,20 @@ mod tests { assert_eq!(delegate_dependencies.len(), 1); assert_eq!(delegate_dependencies[0].as_bytes(), [1; 32]); } + + // This test checks that [`Runtime::read_sandbox_memory_as`] works, when the decoded type has a + // max_len greater than the memory size, but the decoded data fits into the memory. + #[test] + fn read_sandbox_memory_as_works_with_max_len_out_of_bounds_but_fitting_actual_data() { + use frame_support::BoundedVec; + use sp_core::ConstU32; + + let mut ext = MockExt::default(); + let runtime = Runtime::new(&mut ext, vec![]); + let data = vec![1u8, 2, 3]; + let memory = data.encode(); + let decoded: BoundedVec> = + runtime.read_sandbox_memory_as(&memory, 0u32).unwrap(); + assert_eq!(decoded.into_inner(), data); + } } diff --git a/substrate/frame/contracts/src/wasm/runtime.rs b/substrate/frame/contracts/src/wasm/runtime.rs index 871ef05c37e65..7b1e35ee1ad72 100644 --- a/substrate/frame/contracts/src/wasm/runtime.rs +++ b/substrate/frame/contracts/src/wasm/runtime.rs @@ -583,9 +583,8 @@ impl<'a, E: Ext + 'a> Runtime<'a, E> { ptr: u32, ) -> Result { let ptr = ptr as usize; - let mut bound_checked = memory - .get(ptr..ptr + D::max_encoded_len() as usize) - .ok_or_else(|| Error::::OutOfBounds)?; + let mut bound_checked = memory.get(ptr..).ok_or_else(|| Error::::OutOfBounds)?; + let decoded = D::decode_with_depth_limit(MAX_DECODE_NESTING, &mut bound_checked) .map_err(|_| DispatchError::from(Error::::DecodingFailed))?; Ok(decoded) diff --git a/substrate/frame/contracts/uapi/src/host.rs b/substrate/frame/contracts/uapi/src/host.rs index 8f76b21ec9f03..21350bc4eb3e4 100644 --- a/substrate/frame/contracts/uapi/src/host.rs +++ b/substrate/frame/contracts/uapi/src/host.rs @@ -38,6 +38,7 @@ macro_rules! hash_fn { // TODO remove cfg once used by all targets #[cfg(target_arch = "wasm32")] +#[inline(always)] fn extract_from_slice(output: &mut &mut [u8], new_len: usize) { debug_assert!(new_len <= output.len()); let tmp = core::mem::take(output); @@ -45,7 +46,8 @@ fn extract_from_slice(output: &mut &mut [u8], new_len: usize) { } #[cfg(target_arch = "wasm32")] -fn ptr_len_or_sentinel(data: &mut Option<&mut [u8]>) -> (*mut u8, u32) { +#[inline(always)] +fn ptr_len_or_sentinel(data: &mut Option<&mut &mut [u8]>) -> (*mut u8, u32) { match data { Some(ref mut data) => (data.as_mut_ptr(), data.len() as _), None => (crate::SENTINEL as _, 0), @@ -53,6 +55,7 @@ fn ptr_len_or_sentinel(data: &mut Option<&mut [u8]>) -> (*mut u8, u32) { } #[cfg(target_arch = "wasm32")] +#[inline(always)] fn ptr_or_sentinel(data: &Option<&[u8]>) -> *const u8 { match data { Some(ref data) => data.as_ptr(), @@ -132,7 +135,7 @@ pub trait HostFn { gas: u64, value: &[u8], input_data: &[u8], - output: Option<&mut [u8]>, + output: Option<&mut &mut [u8]>, ) -> Result; /// Make a call to another contract. @@ -145,7 +148,7 @@ pub trait HostFn { gas: u64, value: &[u8], input_data: &[u8], - output: Option<&mut [u8]>, + output: Option<&mut &mut [u8]>, ) -> Result; /// Call (possibly transferring some amount of funds) into the specified account. @@ -186,7 +189,7 @@ pub trait HostFn { deposit: Option<&[u8]>, value: &[u8], input_data: &[u8], - output: Option<&mut [u8]>, + output: Option<&mut &mut [u8]>, ) -> Result; /// Call into the chain extension provided by the chain if any. @@ -211,7 +214,7 @@ pub trait HostFn { /// # Return /// /// The chain extension returned value, if executed successfully. - fn call_chain_extension(func_id: u32, input: &[u8], output: Option<&mut [u8]>) -> u32; + fn call_chain_extension(func_id: u32, input: &[u8], output: Option<&mut &mut [u8]>) -> u32; /// Call some dispatchable of the runtime. /// @@ -374,7 +377,7 @@ pub trait HostFn { flags: CallFlags, code_hash: &[u8], input_data: &[u8], - output: Option<&mut [u8]>, + output: Option<&mut &mut [u8]>, ) -> Result; /// Deposit a contract event with the data buffer and optional list of topics. There is a limit @@ -485,8 +488,8 @@ pub trait HostFn { gas: u64, value: &[u8], input: &[u8], - address: Option<&mut [u8]>, - output: Option<&mut [u8]>, + address: Option<&mut &mut [u8]>, + output: Option<&mut &mut [u8]>, salt: &[u8], ) -> Result; @@ -534,8 +537,8 @@ pub trait HostFn { deposit: Option<&[u8]>, value: &[u8], input: &[u8], - address: Option<&mut [u8]>, - output: Option<&mut [u8]>, + address: Option<&mut &mut [u8]>, + output: Option<&mut &mut [u8]>, salt: &[u8], ) -> Result; diff --git a/substrate/frame/contracts/uapi/src/host/riscv32.rs b/substrate/frame/contracts/uapi/src/host/riscv32.rs index 4132768abc28d..b1934cc469e4b 100644 --- a/substrate/frame/contracts/uapi/src/host/riscv32.rs +++ b/substrate/frame/contracts/uapi/src/host/riscv32.rs @@ -84,8 +84,8 @@ impl HostFn for HostFnImpl { gas: u64, value: &[u8], input: &[u8], - mut address: Option<&mut [u8]>, - mut output: Option<&mut [u8]>, + mut address: Option<&mut &mut [u8]>, + mut output: Option<&mut &mut [u8]>, salt: &[u8], ) -> Result { todo!() @@ -98,8 +98,8 @@ impl HostFn for HostFnImpl { deposit: Option<&[u8]>, value: &[u8], input: &[u8], - mut address: Option<&mut [u8]>, - mut output: Option<&mut [u8]>, + mut address: Option<&mut &mut [u8]>, + mut output: Option<&mut &mut [u8]>, salt: &[u8], ) -> Result { todo!() @@ -110,7 +110,7 @@ impl HostFn for HostFnImpl { gas: u64, value: &[u8], input_data: &[u8], - mut output: Option<&mut [u8]>, + mut output: Option<&mut &mut [u8]>, ) -> Result { todo!() } @@ -121,7 +121,7 @@ impl HostFn for HostFnImpl { gas: u64, value: &[u8], input_data: &[u8], - mut output: Option<&mut [u8]>, + mut output: Option<&mut &mut [u8]>, ) -> Result { todo!() } @@ -134,7 +134,7 @@ impl HostFn for HostFnImpl { deposit: Option<&[u8]>, value: &[u8], input_data: &[u8], - mut output: Option<&mut [u8]>, + mut output: Option<&mut &mut [u8]>, ) -> Result { todo!() } @@ -147,7 +147,7 @@ impl HostFn for HostFnImpl { flags: CallFlags, code_hash: &[u8], input: &[u8], - mut output: Option<&mut [u8]>, + mut output: Option<&mut &mut [u8]>, ) -> Result { todo!() } @@ -203,7 +203,7 @@ impl HostFn for HostFnImpl { todo!() } - fn call_chain_extension(func_id: u32, input: &[u8], output: Option<&mut [u8]>) -> u32 { + fn call_chain_extension(func_id: u32, input: &[u8], output: Option<&mut &mut [u8]>) -> u32 { todo!() } diff --git a/substrate/frame/contracts/uapi/src/host/wasm32.rs b/substrate/frame/contracts/uapi/src/host/wasm32.rs index 29fa1706a8422..77cf22891e2f5 100644 --- a/substrate/frame/contracts/uapi/src/host/wasm32.rs +++ b/substrate/frame/contracts/uapi/src/host/wasm32.rs @@ -336,13 +336,14 @@ macro_rules! impl_hash_fn { } impl HostFn for HostFnImpl { + #[inline(always)] fn instantiate_v1( code_hash: &[u8], gas: u64, value: &[u8], input: &[u8], - mut address: Option<&mut [u8]>, - mut output: Option<&mut [u8]>, + mut address: Option<&mut &mut [u8]>, + mut output: Option<&mut &mut [u8]>, salt: &[u8], ) -> Result { let (address_ptr, mut address_len) = ptr_len_or_sentinel(&mut address); @@ -379,8 +380,8 @@ impl HostFn for HostFnImpl { deposit: Option<&[u8]>, value: &[u8], input: &[u8], - mut address: Option<&mut [u8]>, - mut output: Option<&mut [u8]>, + mut address: Option<&mut &mut [u8]>, + mut output: Option<&mut &mut [u8]>, salt: &[u8], ) -> Result { let (address_ptr, mut address_len) = ptr_len_or_sentinel(&mut address); @@ -418,12 +419,13 @@ impl HostFn for HostFnImpl { ret_code.into() } + #[inline(always)] fn call( callee: &[u8], gas: u64, value: &[u8], input_data: &[u8], - mut output: Option<&mut [u8]>, + mut output: Option<&mut &mut [u8]>, ) -> Result { let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output); let ret_code = { @@ -449,13 +451,14 @@ impl HostFn for HostFnImpl { ret_code.into() } + #[inline(always)] fn call_v1( flags: CallFlags, callee: &[u8], gas: u64, value: &[u8], input_data: &[u8], - mut output: Option<&mut [u8]>, + mut output: Option<&mut &mut [u8]>, ) -> Result { let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output); let ret_code = { @@ -488,7 +491,7 @@ impl HostFn for HostFnImpl { deposit: Option<&[u8]>, value: &[u8], input_data: &[u8], - mut output: Option<&mut [u8]>, + mut output: Option<&mut &mut [u8]>, ) -> Result { let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output); let deposit_ptr = ptr_or_sentinel(&deposit); @@ -520,11 +523,12 @@ impl HostFn for HostFnImpl { unsafe { sys::caller_is_root() }.into_u32() } + #[inline(always)] fn delegate_call( flags: CallFlags, code_hash: &[u8], input: &[u8], - mut output: Option<&mut [u8]>, + mut output: Option<&mut &mut [u8]>, ) -> Result { let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output); let ret_code = { @@ -602,6 +606,7 @@ impl HostFn for HostFnImpl { ret_code.into() } + #[inline(always)] fn get_storage(key: &[u8], output: &mut &mut [u8]) -> Result { let mut output_len = output.len() as u32; let ret_code = @@ -610,6 +615,7 @@ impl HostFn for HostFnImpl { ret_code.into() } + #[inline(always)] fn get_storage_v1(key: &[u8], output: &mut &mut [u8]) -> Result { let mut output_len = output.len() as u32; let ret_code = { @@ -626,6 +632,7 @@ impl HostFn for HostFnImpl { ret_code.into() } + #[inline(always)] fn take_storage(key: &[u8], output: &mut &mut [u8]) -> Result { let mut output_len = output.len() as u32; let ret_code = { @@ -665,7 +672,7 @@ impl HostFn for HostFnImpl { unsafe { sys::v1::terminate(beneficiary.as_ptr()) } } - fn call_chain_extension(func_id: u32, input: &[u8], mut output: Option<&mut [u8]>) -> u32 { + fn call_chain_extension(func_id: u32, input: &[u8], mut output: Option<&mut &mut [u8]>) -> u32 { let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output); let ret_code = { unsafe { @@ -685,6 +692,7 @@ impl HostFn for HostFnImpl { ret_code.into_u32() } + #[inline(always)] fn input(output: &mut &mut [u8]) { let mut output_len = output.len() as u32; { @@ -707,6 +715,7 @@ impl HostFn for HostFnImpl { (v1) => [gas_left], } + #[inline(always)] fn weight_to_fee(gas: u64, output: &mut &mut [u8]) { let mut output_len = output.len() as u32; { diff --git a/substrate/frame/contracts/uapi/src/lib.rs b/substrate/frame/contracts/uapi/src/lib.rs index 99d77f504edaa..83877c6efd408 100644 --- a/substrate/frame/contracts/uapi/src/lib.rs +++ b/substrate/frame/contracts/uapi/src/lib.rs @@ -36,7 +36,7 @@ macro_rules! define_error_codes { ) => { /// Every error that can be returned to a contract when it calls any of the host functions. #[derive(Debug, PartialEq, Eq)] - #[repr(u32)] + #[repr(u8)] pub enum ReturnErrorCode { /// API call successful. Success = 0,