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}