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