Skip to main content

pallet_revive_uapi/
host.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.
14use crate::{CallFlags, Result, ReturnFlags, StorageFlags};
15
16#[cfg(target_arch = "riscv64")]
17mod riscv64;
18
19/// Implements [`HostFn`] when compiled on supported architectures (RISC-V).
20pub enum HostFnImpl {}
21
22/// Defines all the host apis available to contracts.
23pub trait HostFn: private::Sealed {
24	/// Stores the address of the current contract into the supplied buffer.
25	///
26	/// # Parameters
27	///
28	/// - `output`: A reference to the output data buffer to write the address.
29	fn address(output: &mut [u8; 20]);
30
31	/// Get the contract immutable data.
32	///
33	/// Traps if:
34	/// - Called from within the deploy export.
35	/// - Called by contracts that didn't set immutable data by calling `set_immutable_data` during
36	///   their constructor execution.
37	///
38	/// # Parameters
39	/// - `output`: A reference to the output buffer to write the immutable bytes.
40	fn get_immutable_data(output: &mut &mut [u8]);
41
42	/// Set the contract immutable data.
43	///
44	/// It is only valid to set non-empty immutable data in the constructor once.
45	///
46	/// Traps if:
47	/// - Called from within the call export.
48	/// - Called more than once.
49	/// - The provided data was empty.
50	///
51	/// # Parameters
52	/// - `data`: A reference to the data to be stored as immutable bytes.
53	fn set_immutable_data(data: &[u8]);
54
55	/// Stores the **reducible** balance of the current account into the supplied buffer.
56	///
57	/// # Parameters
58	///
59	/// - `output`: A reference to the output data buffer to write the balance.
60	fn balance(output: &mut [u8; 32]);
61
62	/// Stores the **reducible** balance of the supplied address into the supplied buffer.
63	///
64	/// # Parameters
65	///
66	/// - `addr`: The target address of which to retreive the free balance.
67	/// - `output`: A reference to the output data buffer to write the balance.
68	fn balance_of(addr: &[u8; 20], output: &mut [u8; 32]);
69
70	/// Returns the [EIP-155](https://eips.ethereum.org/EIPS/eip-155) chain ID.
71	fn chain_id(output: &mut [u8; 32]);
72
73	/// Returns the price per ref_time, akin to the EVM
74	/// [GASPRICE](https://www.evm.codes/?fork=cancun#3a) opcode.
75	fn gas_price() -> u64;
76
77	/// Returns the base fee, akin to the EVM
78	/// [BASEFEE](https://www.evm.codes/?fork=cancun#48) opcode.
79	fn base_fee(output: &mut [u8; 32]);
80
81	/// Returns the call data size.
82	fn call_data_size() -> u64;
83
84	/// Call (possibly transferring some amount of funds) into the specified account.
85	///
86	/// # Parameters
87	///
88	/// - `flags`: See [`CallFlags`] for a documentation of the supported flags.
89	/// - `callee`: The address of the callee. Should be decodable as an `T::AccountId`. Traps
90	///   otherwise.
91	/// - `ref_time_limit`: how much *ref_time* Weight to devote to the execution.
92	/// - `proof_size_limit`: how much *proof_size* Weight to devote to the execution.
93	/// - `deposit`: The storage deposit limit for instantiation. Passing `None` means setting no
94	///   specific limit for the call, which implies storage usage up to the limit of the parent
95	///   call.
96	/// - `value`: The value to transfer into the contract.
97	/// - `input`: The input data buffer used to call the contract.
98	/// - `output`: A reference to the output data buffer to write the call output buffer. If `None`
99	///   is provided then the output buffer is not copied.
100	///
101	/// # Errors
102	///
103	/// An error means that the call wasn't successful output buffer is returned unless
104	/// stated otherwise.
105	///
106	/// - [CalleeReverted][`crate::ReturnErrorCode::CalleeReverted]: Output buffer is returned.
107	/// - [CalleeTrapped][`crate::ReturnErrorCode::CalleeTrapped]
108	/// - [TransferFailed][`crate::ReturnErrorCode::TransferFailed]
109	/// - [OutOfResources][`crate::ReturnErrorCode::OutOfResources]
110	fn call(
111		flags: CallFlags,
112		callee: &[u8; 20],
113		ref_time_limit: u64,
114		proof_size_limit: u64,
115		deposit: &[u8; 32],
116		value: &[u8; 32],
117		input_data: &[u8],
118		output: Option<&mut &mut [u8]>,
119	) -> Result;
120
121	/// Same as [HostFn::call] but receives the one-dimensional EVM gas argument.
122	///
123	/// Adds the EVM gas stipend for non-zero value calls.
124	///
125	/// If gas is `u64::MAX`, the call will run with uncapped limits.
126	fn call_evm(
127		flags: CallFlags,
128		callee: &[u8; 20],
129		gas: u64,
130		value: &[u8; 32],
131		input_data: &[u8],
132		output: Option<&mut &mut [u8]>,
133	) -> Result;
134
135	/// Stores the address of the caller into the supplied buffer.
136	///
137	/// If this is a top-level call (i.e. initiated by an extrinsic) the origin address of the
138	/// extrinsic will be returned. Otherwise, if this call is initiated by another contract then
139	/// the address of the contract will be returned.
140	///
141	/// If there is no address associated with the caller (e.g. because the caller is root) then
142	/// it traps with `BadOrigin`.
143	///
144	/// # Parameters
145	///
146	/// - `output`: A reference to the output data buffer to write the caller address.
147	fn caller(output: &mut [u8; 20]);
148
149	/// Stores the origin address (initator of the call stack) into the supplied buffer.
150	///
151	/// If there is no address associated with the origin (e.g. because the origin is root) then
152	/// it traps with `BadOrigin`. This can only happen through on-chain governance actions or
153	/// customized runtimes.
154	///
155	/// # Parameters
156	///
157	/// - `output`: A reference to the output data buffer to write the origin's address.
158	fn origin(output: &mut [u8; 20]);
159
160	/// Retrieve the code hash for a specified contract address.
161	///
162	/// # Parameters
163	///
164	/// - `addr`: The address of the contract.
165	/// - `output`: A reference to the output data buffer to write the code hash.
166	///
167	/// # Note
168	///
169	/// If `addr` is not a contract but the account exists then the hash of empty data
170	/// `0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470` is written,
171	/// otherwise `zero`.
172	fn code_hash(addr: &[u8; 20], output: &mut [u8; 32]);
173
174	/// Returns the code size for a specified contract address.
175	///
176	/// # Parameters
177	///
178	/// - `addr`: The address of the contract.
179	///
180	/// # Note
181	///
182	/// If `addr` is not a contract the `output` will be zero.
183	fn code_size(addr: &[u8; 20]) -> u64;
184
185	/// Execute code in the context (storage, caller, value) of the current contract.
186	///
187	/// Reentrancy protection is always disabled since the callee is allowed
188	/// to modify the callers storage. This makes going through a reentrancy attack
189	/// unnecessary for the callee when it wants to exploit the caller.
190	///
191	/// # Parameters
192	///
193	/// - `flags`: See [`CallFlags`] for a documentation of the supported flags.
194	/// - `address`: The address of the code to be executed. Should be decodable as an
195	///   `T::AccountId`. Traps otherwise.
196	/// - `ref_time_limit`: how much *ref_time* Weight to devote to the execution.
197	/// - `proof_size_limit`: how much *proof_size* Weight to devote to the execution.
198	/// - `deposit_limit`: The storage deposit limit for delegate call. Passing `None` means setting
199	///   no specific limit for the call, which implies storage usage up to the limit of the parent
200	///   call.
201	/// - `input`: The input data buffer used to call the contract.
202	/// - `output`: A reference to the output data buffer to write the call output buffer. If `None`
203	///   is provided then the output buffer is not copied.
204	///
205	/// # Errors
206	///
207	/// An error means that the call wasn't successful and no output buffer is returned unless
208	/// stated otherwise.
209	///
210	/// - [CalleeReverted][`crate::ReturnErrorCode::CalleeReverted]: Output buffer is returned.
211	/// - [CalleeTrapped][`crate::ReturnErrorCode::CalleeTrapped]
212	/// - [OutOfResources][`crate::ReturnErrorCode::OutOfResources]
213	fn delegate_call(
214		flags: CallFlags,
215		address: &[u8; 20],
216		ref_time_limit: u64,
217		proof_size_limit: u64,
218		deposit_limit: &[u8; 32],
219		input_data: &[u8],
220		output: Option<&mut &mut [u8]>,
221	) -> Result;
222
223	/// Same as [HostFn::delegate_call] but receives the one-dimensional EVM gas argument.
224	///
225	/// If gas is `u64::MAX`, the call will run with uncapped limits.
226	fn delegate_call_evm(
227		flags: CallFlags,
228		address: &[u8; 20],
229		gas: u64,
230		input_data: &[u8],
231		output: Option<&mut &mut [u8]>,
232	) -> Result;
233
234	/// Deposit a contract event with the data buffer and optional list of topics. There is a limit
235	/// on the maximum number of topics specified by `event_topics`.
236	///
237	/// There should not be any duplicates in `topics`.
238	///
239	/// # Parameters
240	///
241	/// - `topics`: The topics list. It can't contain duplicates.
242	fn deposit_event(topics: &[[u8; 32]], data: &[u8]);
243
244	/// Retrieve the value under the given key from storage.
245	///
246	/// The key length must not exceed the maximum defined by the `pallet-revive` parameter.
247	///
248	/// # Parameters
249	/// - `key`: The storage key.
250	/// - `output`: A reference to the output data buffer to write the storage entry.
251	///
252	/// # Errors
253	///
254	/// [KeyNotFound][`crate::ReturnErrorCode::KeyNotFound]
255	fn get_storage(flags: StorageFlags, key: &[u8], output: &mut &mut [u8]) -> Result;
256
257	/// Computes the keccak_256 32-bit hash on the given input buffer.
258	///
259	/// - The `input` and `output` buffer may overlap.
260	/// - The output buffer is expected to hold at least 32 bits.
261	/// - It is the callers responsibility to provide an output buffer that is large enough to hold
262	///   the expected amount of bytes returned by the hash function.
263	///
264	/// # Parameters
265	///
266	/// - `input`: The input data buffer.
267	/// - `output`: The output buffer to write the hash result to.
268	fn hash_keccak_256(input: &[u8], output: &mut [u8; 32]);
269
270	/// Stores the input data passed by the caller into the supplied `output` buffer,
271	/// starting from the given input data `offset`.
272	///
273	/// The `output` buffer is guaranteed to always be fully populated:
274	/// - If the call data (starting from the given `offset`) is larger than the `output` buffer,
275	///   only what fits into the `output` buffer is written.
276	/// - If the `output` buffer size exceeds the call data size (starting from `offset`), remaining
277	///   bytes in the `output` buffer are zeroed out.
278	/// - If the provided call data `offset` is out-of-bounds, the whole `output` buffer is zeroed
279	///   out.
280	///
281	/// # Note
282	///
283	/// This function traps if:
284	/// - the input was previously forwarded by a [`call()`][`Self::call()`].
285	/// - the `output` buffer is located in an PolkaVM invalid memory range.
286	///
287	/// # Parameters
288	///
289	/// - `output`: A reference to the output data buffer to write the call data.
290	/// - `offset`: The offset index into the call data from where to start copying.
291	fn call_data_copy(output: &mut [u8], offset: u32);
292
293	/// Stores the U256 value at given `offset` from the input passed by the caller
294	/// into the supplied buffer.
295	///
296	/// # Note
297	/// - If `offset` is out of bounds, a value of zero will be returned.
298	/// - If `offset` is in bounds but there is not enough call data, the available data
299	/// is right-padded in order to fill a whole U256 value.
300	/// - The data written to `output` is a little endian U256 integer value.
301	///
302	/// # Parameters
303	///
304	/// - `output`: A reference to the fixed output data buffer to write the value.
305	/// - `offset`: The offset (index) into the call data.
306	fn call_data_load(output: &mut [u8; 32], offset: u32);
307
308	/// Instantiate a contract with the specified code hash.
309	///
310	/// This function creates an account and executes the constructor defined in the code specified
311	/// by the code hash.
312	///
313	/// # Parameters
314	///
315	/// - `ref_time_limit`: how much *ref_time* Weight to devote to the execution.
316	/// - `proof_size_limit`: how much *proof_size* Weight to devote to the execution.
317	/// - `deposit`: The storage deposit limit for instantiation. Passing `None` means setting no
318	///   specific limit for the call, which implies storage usage up to the limit of the parent
319	///   call.
320	/// - `value`: The value to transfer into the contract.
321	/// - `input`: The code hash and constructor input data buffer. The first 32 bytes are the code
322	///   hash of the code to be instantiated. The remaining bytes are the constructor call data.
323	/// - `address`: A reference to the address buffer to write the address of the contract. If
324	///   `None` is provided then the output buffer is not copied.
325	/// - `output`: A reference to the return value buffer to write the constructor output buffer.
326	///   If `None` is provided then the output buffer is not copied.
327	/// - `salt`: The salt bytes to use for this instantiation.
328	///
329	/// # Errors
330	///
331	/// Please consult the [ReturnErrorCode][`crate::ReturnErrorCode`] enum declaration for more
332	/// information on those errors. Here we only note things specific to this function.
333	///
334	/// An error means that the account wasn't created and no address or output buffer
335	/// is returned unless stated otherwise.
336	///
337	/// - [CalleeReverted][`crate::ReturnErrorCode::CalleeReverted]: Output buffer is returned.
338	/// - [CalleeTrapped][`crate::ReturnErrorCode::CalleeTrapped]
339	/// - [TransferFailed][`crate::ReturnErrorCode::TransferFailed]
340	/// - [OutOfResources][`crate::ReturnErrorCode::OutOfResources]
341	fn instantiate(
342		ref_time_limit: u64,
343		proof_size_limit: u64,
344		deposit: &[u8; 32],
345		value: &[u8; 32],
346		input: &[u8],
347		address: Option<&mut [u8; 20]>,
348		output: Option<&mut &mut [u8]>,
349		salt: Option<&[u8; 32]>,
350	) -> Result;
351
352	/// Load the latest block timestamp in seconds into the supplied buffer
353	///
354	/// # Parameters
355	///
356	/// - `output`: A reference to the output data buffer to write the timestamp.
357	fn now(output: &mut [u8; 32]);
358
359	/// Returns the block ref_time limit.
360	fn gas_limit() -> u64;
361
362	/// Cease contract execution and save a data buffer as a result of the execution.
363	///
364	/// This function never returns as it stops execution of the caller.
365	/// This is the only way to return a data buffer to the caller. Returning from
366	/// execution without calling this function is equivalent to calling:
367	/// ```nocompile
368	/// return_value(ReturnFlags::empty(), &[])
369	/// ```
370	///
371	/// Using an unnamed non empty `ReturnFlags` triggers a trap.
372	///
373	/// # Parameters
374	///
375	/// - `flags`: Flag used to signal special return conditions to the supervisor. See
376	///   [`ReturnFlags`] for a documentation of the supported flags.
377	/// - `return_value`: The return value buffer.
378	fn return_value(flags: ReturnFlags, return_value: &[u8]) -> !;
379
380	/// Set the value at the given key in the contract storage.
381	///
382	/// The key and value lengths must not exceed the maximums defined by the `pallet-revive`
383	/// parameters.
384	///
385	/// # Parameters
386	///
387	/// - `key`: The storage key.
388	/// - `encoded_value`: The storage value.
389	///
390	/// # Return
391	///
392	/// Returns the size of the pre-existing value at the specified key if any.
393	fn set_storage(flags: StorageFlags, key: &[u8], value: &[u8]) -> Option<u32>;
394
395	/// Sets the storage entry for a fixed 256‑bit key with a fixed 256‑bit value.
396	///
397	/// If the provided 32‑byte value is all zeros then the key is cleared (i.e. deleted),
398	/// mimicking Ethereum’s SSTORE behavior.
399	///
400	/// # Parameters
401	/// - `key`: The fixed 256‑bit storage key (32 bytes).
402	/// - `value`: The fixed 256‑bit storage value (32 bytes).
403	///
404	/// # Return
405	/// Returns the size (in bytes) of the pre‑existing value at the specified key, if any.
406	fn set_storage_or_clear(flags: StorageFlags, key: &[u8; 32], value: &[u8; 32]) -> Option<u32>;
407
408	/// Retrieves the storage entry for a fixed 256‑bit key.
409	///
410	/// If the key does not exist, the output buffer is filled with 32 zero bytes.
411	///
412	/// # Parameters
413	/// - `key`: The fixed 256‑bit storage key (32 bytes).
414	/// - `output`: A mutable output buffer (32 bytes) where the storage entry is written.
415	fn get_storage_or_zero(flags: StorageFlags, key: &[u8; 32], output: &mut [u8; 32]);
416
417	/// Stores the value transferred along with this call/instantiate into the supplied buffer.
418	///
419	/// # Parameters
420	///
421	/// - `output`: A reference to the output data buffer to write the transferred value.
422	fn value_transferred(output: &mut [u8; 32]);
423
424	/// Returns the size of the returned data of the last contract call or instantiation.
425	fn return_data_size() -> u64;
426
427	/// Stores the returned data of the last contract call or contract instantiation.
428	///
429	/// # Parameters
430	/// - `output`: A reference to the output buffer to write the data.
431	/// - `offset`: Byte offset into the returned data
432	fn return_data_copy(output: &mut &mut [u8], offset: u32);
433
434	/// Returns the amount of ethereum gas left.
435	fn gas_left() -> u64;
436
437	/// Stores the current block author of into the supplied buffer.
438	///
439	/// # Parameters
440	///
441	/// - `output`: A reference to the output data buffer to write the block author.
442	fn block_author(output: &mut [u8; 20]);
443
444	/// Stores the current block number of the current contract into the supplied buffer.
445	///
446	/// # Parameters
447	///
448	/// - `output`: A reference to the output data buffer to write the block number.
449	fn block_number(output: &mut [u8; 32]);
450
451	/// Stores the block hash of the given block number into the supplied buffer.
452	///
453	/// # Parameters
454	///
455	/// - `block_number`: A reference to the block number buffer.
456	/// - `output`: A reference to the output data buffer to write the block number.
457	fn block_hash(block_number: &[u8; 32], output: &mut [u8; 32]);
458
459	/// Reverts the execution and cedes all supplied gas,
460	/// akin to the `INVALID` EVM opcode.
461	fn consume_all_gas() -> !;
462
463	/// Remove the calling account and transfer remaining **free** balance.
464	///
465	/// This function never returns. Either the termination was successful and the
466	/// execution of the destroyed contract is halted. Or it failed during the termination
467	/// which is considered fatal and results in a trap + rollback.
468	///
469	/// # Parameters
470	///
471	/// - `beneficiary`: The address of the beneficiary account
472	///
473	/// # Traps
474	///
475	/// - The contract is live i.e is already on the call stack.
476	/// - Failed to send the balance to the beneficiary.
477	/// - The deletion queue is full.
478	fn terminate(beneficiary: &[u8; 20]) -> !;
479}
480
481mod private {
482	pub trait Sealed {}
483	impl Sealed for super::HostFnImpl {}
484}