referrerpolicy=no-referrer-when-downgrade

pallet_revive_uapi/
lib.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! External C API to communicate with Polkadot SDK's `pallet-revive` module.
16//!
17//! Refer to the FRAME `pallet-revive` module for more documentation.
18
19#![no_std]
20#![cfg_attr(docsrs, feature(doc_cfg))]
21
22mod flags;
23pub use flags::*;
24mod host;
25mod macros;
26
27pub mod precompiles;
28pub use precompiles::{
29	storage::STORAGE_PRECOMPILE_ADDR, system::SYSTEM_PRECOMPILE_ADDR, utils::solidity_selector,
30};
31
32pub use host::{HostFn, HostFnImpl};
33
34/// Convert a u64 into a [u8; 32].
35pub const fn u256_bytes(value: u64) -> [u8; 32] {
36	let mut buffer = [0u8; 32];
37	let bytes = value.to_le_bytes();
38
39	buffer[0] = bytes[0];
40	buffer[1] = bytes[1];
41	buffer[2] = bytes[2];
42	buffer[3] = bytes[3];
43	buffer[4] = bytes[4];
44	buffer[5] = bytes[5];
45	buffer[6] = bytes[6];
46	buffer[7] = bytes[7];
47	buffer
48}
49
50macro_rules! define_error_codes {
51    (
52        $(
53            $( #[$attr:meta] )*
54            $name:ident = $discr:literal,
55        )*
56    ) => {
57        /// Every error that can be returned to a contract when it calls any of the host functions.
58        #[derive(Debug, PartialEq, Eq)]
59        #[repr(u32)]
60        pub enum ReturnErrorCode {
61            /// API call successful.
62            Success = 0,
63            $(
64                $( #[$attr] )*
65                $name = $discr,
66            )*
67            /// Returns if an unknown error was received from the host module.
68            Unknown,
69        }
70
71        impl From<ReturnCode> for Result {
72            fn from(return_code: ReturnCode) -> Self {
73                match return_code.0 {
74                    0 => Ok(()),
75                    $(
76                        $discr => Err(ReturnErrorCode::$name),
77                    )*
78                    _ => Err(ReturnErrorCode::Unknown),
79                }
80            }
81        }
82    };
83}
84
85impl From<ReturnErrorCode> for u32 {
86	fn from(code: ReturnErrorCode) -> u32 {
87		code as u32
88	}
89}
90
91impl From<ReturnErrorCode> for u64 {
92	fn from(error: ReturnErrorCode) -> Self {
93		u32::from(error).into()
94	}
95}
96
97define_error_codes! {
98	/// The called function trapped and has its state changes reverted.
99	/// In this case no output buffer is returned.
100	/// Can only be returned from `call` and `instantiate`.
101	CalleeTrapped = 1,
102	/// The called function ran to completion but decided to revert its state.
103	/// An output buffer is returned when one was supplied.
104	/// Can only be returned from `call` and `instantiate`.
105	CalleeReverted = 2,
106	/// The passed key does not exist in storage.
107	KeyNotFound = 3,
108	/// Transfer failed for other not further specified reason. Most probably
109	/// reserved or locked balance of the sender that was preventing the transfer.
110	TransferFailed = 4,
111	/// The subcall ran out of weight or storage deposit.
112	OutOfResources = 5,
113	/// ECDSA public key recovery failed. Most probably wrong recovery id or signature.
114	EcdsaRecoveryFailed = 7,
115	/// sr25519 signature verification failed.
116	Sr25519VerifyFailed = 8,
117	/// Contract instantiation failed because the address already exists.
118	/// Occurs when instantiating the same contract with the same salt more than once.
119	DuplicateContractAddress = 11,
120}
121
122/// The raw return code returned by the host side.
123#[repr(transparent)]
124pub struct ReturnCode(u32);
125
126/// Used as a sentinel value when reading and writing contract memory.
127///
128/// We use this value to signal `None` to a contract when only a primitive is
129/// allowed and we don't want to go through encoding a full Rust type.
130/// Using `u32::Max` is a safe sentinel because contracts are never
131/// allowed to use such a large amount of resources. So this value doesn't
132/// make sense for a memory location or length.
133const SENTINEL: u32 = u32::MAX;
134
135impl From<ReturnCode> for Option<u32> {
136	fn from(code: ReturnCode) -> Self {
137		(code.0 < SENTINEL).then_some(code.0)
138	}
139}
140
141impl ReturnCode {
142	/// Returns the raw underlying `u32` representation.
143	pub fn into_u32(self) -> u32 {
144		self.0
145	}
146	/// Returns the underlying `u32` converted into `bool`.
147	pub fn into_bool(self) -> bool {
148		self.0.ne(&0)
149	}
150}
151
152type Result = core::result::Result<(), ReturnErrorCode>;
153
154/// Helper to pack two `u32` values into a `u64` register.
155///
156/// Pointers to PVM memory are always 32 bit in size. Thus contracts can pack two
157/// pointers into a single register when calling a syscall API method.
158///
159/// This is done in syscall API methods where the number of arguments is exceeding
160/// the available registers.
161pub fn pack_hi_lo(hi: u32, lo: u32) -> u64 {
162	((hi as u64) << 32) | lo as u64
163}