ink_env/api.rs
1// Copyright (C) Use Ink (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//! The public raw interface towards the host engine.
16
17#[cfg(feature = "xcm")]
18use ink_primitives::Weight;
19use ink_primitives::{
20 Address,
21 CodeHashErr,
22 H256,
23 U256,
24 abi::{
25 Ink,
26 Sol,
27 },
28 sol::SolResultEncode,
29};
30use ink_storage_traits::Storable;
31use pallet_revive_uapi::ReturnFlags;
32
33use crate::{
34 DecodeDispatch,
35 DispatchError,
36 Result,
37 backend::{
38 EnvBackend,
39 TypedEnvBackend,
40 },
41 call::{
42 Call,
43 CallParams,
44 ConstructorReturnType,
45 CreateParams,
46 DelegateCall,
47 FromAddr,
48 LimitParamsV2,
49 utils::{
50 DecodeMessageResult,
51 EncodeArgsWith,
52 },
53 },
54 engine::{
55 EnvInstance,
56 OnInstance,
57 },
58 event::Event,
59 hash::{
60 CryptoHash,
61 HashOutput,
62 },
63 types::{
64 Environment,
65 Gas,
66 },
67};
68
69/// Returns the address of the caller of the executed contract.
70///
71/// # Errors
72///
73/// If the returned caller cannot be properly decoded.
74pub fn caller() -> Address {
75 <EnvInstance as OnInstance>::on_instance(TypedEnvBackend::caller)
76}
77
78/// Returns the block's `ref_time` limit.
79/// [GASLIMIT](https://www.evm.codes/?fork=cancun#45) opcode.
80///
81/// See <https://use.ink/docs/v6/basics/gas/#what-is-gas-in-ink> for more information.
82pub fn gas_limit() -> u64 {
83 <EnvInstance as OnInstance>::on_instance(TypedEnvBackend::gas_limit)
84}
85
86/// Returns the price per `ref_time`, akin to the EVM
87/// [GASPRICE](https://www.evm.codes/?fork=cancun#3a) opcode.
88///
89/// See <https://use.ink/docs/v6/basics/gas/#what-is-gas-in-ink> for more information.
90pub fn gas_price() -> u64 {
91 <EnvInstance as OnInstance>::on_instance(TypedEnvBackend::gas_price)
92}
93
94/// Returns the amount of gas left.
95/// This is the `ref_time` left.
96///
97/// See <https://use.ink/docs/v6/basics/gas/#what-is-gas-in-ink> for more information.
98pub fn gas_left() -> u64 {
99 <EnvInstance as OnInstance>::on_instance(TypedEnvBackend::gas_left)
100}
101
102/// Returns the total size of the contract call input data, akin to the EVM
103/// [CALLDATASIZE](https://www.evm.codes/?fork=cancun#36) opcode.
104pub fn call_data_size() -> u64 {
105 <EnvInstance as OnInstance>::on_instance(TypedEnvBackend::call_data_size)
106}
107
108/// Returns the size of the returned data of the last contract call or instantiation,
109/// akin to the EVM [RETURNDATASIZE](https://www.evm.codes/?fork=cancun#3d) opcode.
110pub fn return_data_size() -> u64 {
111 <EnvInstance as OnInstance>::on_instance(TypedEnvBackend::return_data_size)
112}
113
114/// Returns the [EIP-155](https://eips.ethereum.org/EIPS/eip-155) chain ID,
115/// akin to the EVM [CHAINID](https://www.evm.codes/?fork=cancun#46) opcode.
116pub fn chain_id() -> U256 {
117 <EnvInstance as OnInstance>::on_instance(TypedEnvBackend::chain_id)
118}
119
120/// Returns the **reducible** native balance of the supplied address,
121/// akin to the EVM [BALANCE](https://www.evm.codes/?fork=cancun#31) opcode.
122pub fn balance_of(addr: Address) -> U256 {
123 <EnvInstance as OnInstance>::on_instance(|instance| {
124 TypedEnvBackend::balance_of(instance, addr)
125 })
126}
127
128/// Returns the base fee.
129/// This is akin to the EVM [BASEFEE](https://www.evm.codes/?fork=cancun#48) opcode.
130pub fn base_fee() -> U256 {
131 <EnvInstance as OnInstance>::on_instance(TypedEnvBackend::base_fee)
132}
133
134/// Returns the origin address (initator of the call stack).
135/// This is akin to the EVM [ORIGIN](https://www.evm.codes/?fork=cancun#32) opcode.
136///
137/// # Errors
138///
139/// - If there is no address associated with the origin (e.g. because the origin is root).
140pub fn origin() -> Address {
141 <EnvInstance as OnInstance>::on_instance(TypedEnvBackend::origin)
142}
143
144/// Returns the code size for a specified contract address.
145/// This is akin to the EVM [CODESIZE](https://www.evm.codes/?fork=cancun#38) opcode.
146///
147/// # Note
148///
149/// If `addr` is not a contract the `output` will be zero.
150pub fn code_size(addr: Address) -> u64 {
151 <EnvInstance as OnInstance>::on_instance(|instance| {
152 TypedEnvBackend::code_size(instance, addr)
153 })
154}
155
156/// Returns the block hash of the given block number.
157/// This is akin to the EVM [BLOCKHASH](https://www.evm.codes/?fork=cancun#40) opcode.
158pub fn block_hash<E>(block_number: E::BlockNumber) -> H256
159where
160 E: Environment,
161{
162 <EnvInstance as OnInstance>::on_instance(|instance| {
163 TypedEnvBackend::block_hash::<E>(instance, block_number)
164 })
165}
166
167/// Returns the current block author.
168/// This is akin to the EVM [COINBASE](https://www.evm.codes/?fork=cancun#41) opcode.
169pub fn block_author() -> Address {
170 <EnvInstance as OnInstance>::on_instance(TypedEnvBackend::block_author)
171}
172
173/// Returns the transferred value for the contract execution.
174///
175/// # Errors
176///
177/// If the returned value cannot be properly decoded.
178pub fn transferred_value() -> U256 {
179 <EnvInstance as OnInstance>::on_instance(|instance| {
180 TypedEnvBackend::transferred_value(instance)
181 })
182}
183
184/// Returns the price for the specified amount of gas.
185///
186/// # Errors
187///
188/// If the returned value cannot be properly decoded.
189pub fn weight_to_fee(gas: Gas) -> U256 {
190 <EnvInstance as OnInstance>::on_instance(|instance| {
191 TypedEnvBackend::weight_to_fee(instance, gas)
192 })
193}
194
195/// Returns the current block timestamp.
196///
197/// # Errors
198///
199/// If the returned value cannot be properly decoded.
200pub fn block_timestamp<E>() -> E::Timestamp
201where
202 E: Environment,
203{
204 <EnvInstance as OnInstance>::on_instance(|instance| {
205 TypedEnvBackend::block_timestamp::<E>(instance)
206 })
207}
208
209/// Retrieves the account id for a specified address.
210///
211/// # Errors
212///
213/// If the returned value cannot be properly decoded.
214pub fn to_account_id<E>(addr: Address) -> E::AccountId
215where
216 E: Environment,
217{
218 <EnvInstance as OnInstance>::on_instance(|instance| {
219 TypedEnvBackend::to_account_id::<E>(instance, addr)
220 })
221}
222
223/// Returns the account ID of the executed contract.
224///
225/// # Note
226///
227/// This method was formerly known as `address`.
228///
229/// # Errors
230///
231/// If the returned value cannot be properly decoded.
232pub fn account_id<E>() -> E::AccountId
233where
234 E: Environment,
235{
236 <EnvInstance as OnInstance>::on_instance(|instance| {
237 TypedEnvBackend::account_id::<E>(instance)
238 })
239}
240
241/// Returns the address of the executed contract.
242///
243/// # Errors
244///
245/// If the returned value cannot be properly decoded.
246pub fn address() -> Address {
247 <EnvInstance as OnInstance>::on_instance(|instance| {
248 TypedEnvBackend::address(instance)
249 })
250}
251
252/// Returns the balance of the executed contract.
253///
254/// # Errors
255///
256/// If the returned value cannot be properly decoded.
257pub fn balance() -> U256 {
258 <EnvInstance as OnInstance>::on_instance(|instance| {
259 TypedEnvBackend::balance(instance)
260 })
261}
262
263/// Returns the current block number.
264///
265/// # Errors
266///
267/// If the returned value cannot be properly decoded.
268pub fn block_number<E>() -> E::BlockNumber
269where
270 E: Environment,
271{
272 <EnvInstance as OnInstance>::on_instance(|instance| {
273 TypedEnvBackend::block_number::<E>(instance)
274 })
275}
276
277/// Returns the minimum balance that is required for creating an account
278/// (i.e. the chain's existential deposit).
279///
280/// # Errors
281///
282/// If the returned value cannot be properly decoded.
283pub fn minimum_balance() -> U256 {
284 <EnvInstance as OnInstance>::on_instance(|instance| {
285 TypedEnvBackend::minimum_balance(instance)
286 })
287}
288
289/// Emits an event with the given event data.
290///
291/// # Note
292///
293/// In "all" ABI mode, both an ink! and Solidity ABI event are emitted.
294#[cfg(not(ink_abi = "all"))]
295pub fn emit_event<Evt>(event: Evt)
296where
297 Evt: Event<crate::DefaultAbi>,
298{
299 <EnvInstance as OnInstance>::on_instance(|instance| {
300 TypedEnvBackend::emit_event::<Evt, crate::DefaultAbi>(instance, &event)
301 })
302}
303
304/// Emits an event with the given event data.
305///
306/// # Note
307///
308/// In "all" ABI mode, both an ink! and Solidity ABI event are emitted.
309#[cfg(ink_abi = "all")]
310pub fn emit_event<Evt>(event: Evt)
311where
312 Evt: Event<Ink> + Event<Sol>,
313{
314 // Emits ink! ABI encoded event.
315 <EnvInstance as OnInstance>::on_instance(|instance| {
316 TypedEnvBackend::emit_event::<Evt, Ink>(instance, &event)
317 });
318
319 // Emits Solidity ABI encoded event.
320 <EnvInstance as OnInstance>::on_instance(|instance| {
321 TypedEnvBackend::emit_event::<Evt, Sol>(instance, &event)
322 });
323}
324
325/// Emits an event with the given event data using the ink! ABI encoding (i.e. with SCALE
326/// codec for event data encode/decode).
327pub fn emit_event_ink<Evt>(event: Evt)
328where
329 Evt: Event<Ink>,
330{
331 <EnvInstance as OnInstance>::on_instance(|instance| {
332 TypedEnvBackend::emit_event::<Evt, Ink>(instance, &event)
333 })
334}
335
336/// Emits an event with the given event data using the Solidity ABI encoding.
337pub fn emit_event_sol<Evt>(event: Evt)
338where
339 Evt: Event<Sol>,
340{
341 <EnvInstance as OnInstance>::on_instance(|instance| {
342 TypedEnvBackend::emit_event::<Evt, Sol>(instance, &event)
343 })
344}
345
346/// Writes the value to the contract storage under the given storage key and returns the
347/// size of pre-existing value if any.
348///
349/// # Panics
350///
351/// - If the encode length of value exceeds the configured maximum value length of a
352/// storage entry.
353pub fn set_contract_storage<K, V>(key: &K, value: &V) -> Option<u32>
354where
355 K: scale::Encode,
356 V: Storable,
357{
358 <EnvInstance as OnInstance>::on_instance(|instance| {
359 EnvBackend::set_contract_storage::<K, V>(instance, key, value)
360 })
361}
362
363/// Returns the value stored under the given storage key in the contract's storage if any.
364///
365/// # Errors
366///
367/// - If the decoding of the typed value failed (`KeyNotFound`)
368pub fn get_contract_storage<K, R>(key: &K) -> Result<Option<R>>
369where
370 K: scale::Encode,
371 R: Storable,
372{
373 <EnvInstance as OnInstance>::on_instance(|instance| {
374 EnvBackend::get_contract_storage::<K, R>(instance, key)
375 })
376}
377
378/// Removes the `value` at `key`, returning the previous `value` at `key` from storage.
379///
380/// # Errors
381///
382/// - If the decoding of the typed value failed (`KeyNotFound`)
383pub fn take_contract_storage<K, R>(key: &K) -> Result<Option<R>>
384where
385 K: scale::Encode,
386 R: Storable,
387{
388 <EnvInstance as OnInstance>::on_instance(|instance| {
389 EnvBackend::take_contract_storage::<K, R>(instance, key)
390 })
391}
392
393/// Checks whether there is a value stored under the given storage key in the contract's
394/// storage.
395///
396/// If a value is stored under the specified key, the size of the value is returned.
397pub fn contains_contract_storage<K>(key: &K) -> Option<u32>
398where
399 K: scale::Encode,
400{
401 <EnvInstance as OnInstance>::on_instance(|instance| {
402 EnvBackend::contains_contract_storage::<K>(instance, key)
403 })
404}
405
406/// Clears the contract's storage entry under the given storage key.
407///
408/// If a value was stored under the specified storage key, the size of the value is
409/// returned.
410pub fn clear_contract_storage<K>(key: &K) -> Option<u32>
411where
412 K: scale::Encode,
413{
414 <EnvInstance as OnInstance>::on_instance(|instance| {
415 EnvBackend::clear_contract_storage::<K>(instance, key)
416 })
417}
418
419/// Invokes a contract message and returns its result.
420///
421/// # Note
422///
423/// **This will call into the latest version of the host function which allows setting new
424/// weight and storage limit parameters.**
425///
426/// This is a low level way to evaluate another smart contract.
427/// Prefer to use the ink! guided and type safe approach to using this.
428///
429/// # Errors
430///
431/// - If the called account does not exist.
432/// - If the called account is not a contract.
433/// - If arguments passed to the called contract message are invalid.
434/// - If the called contract execution has trapped.
435/// - If the called contract ran out of gas, proof size, or storage deposit upon
436/// execution.
437/// - If the returned value failed to decode properly.
438pub fn invoke_contract<E, Args, R, Abi>(
439 params: &CallParams<E, Call, Args, R, Abi>,
440) -> Result<ink_primitives::MessageResult<R>>
441where
442 E: Environment,
443 Args: EncodeArgsWith<Abi>,
444 R: DecodeMessageResult<Abi>,
445{
446 <EnvInstance as OnInstance>::on_instance(|instance| {
447 TypedEnvBackend::invoke_contract::<E, Args, R, Abi>(instance, params)
448 })
449}
450
451/// Invokes a contract message via delegate call and returns its result.
452///
453/// # Note
454///
455/// This is a low level way to evaluate another smart contract via delegate call.
456/// Prefer to use the ink! guided and type safe approach to using this.
457///
458/// # Errors
459///
460/// - If the specified code hash does not exist.
461/// - If arguments passed to the called code message are invalid.
462/// - If the called code execution has trapped.
463pub fn invoke_contract_delegate<E, Args, R, Abi>(
464 params: &CallParams<E, DelegateCall, Args, R, Abi>,
465) -> Result<ink_primitives::MessageResult<R>>
466where
467 E: Environment,
468 Args: EncodeArgsWith<Abi>,
469 R: DecodeMessageResult<Abi>,
470{
471 <EnvInstance as OnInstance>::on_instance(|instance| {
472 TypedEnvBackend::invoke_contract_delegate::<E, Args, R, Abi>(instance, params)
473 })
474}
475
476/// Instantiates another contract.
477///
478/// # Note
479///
480/// This is a low level way to instantiate another smart contract, calling the latest
481/// `instantiate_v2` host function. // todo
482///
483/// Prefer to use methods on a `ContractRef` or the
484/// [`CreateBuilder`](`crate::call::CreateBuilder`)
485/// through [`build_create`](`crate::call::build_create`) instead.
486///
487/// # Errors
488///
489/// - If the code hash is invalid.
490/// - If the arguments passed to the instantiation process are invalid.
491/// - If the instantiation process traps.
492/// - If the instantiation process runs out of gas.
493/// - If given insufficient endowment.
494/// - If the returned account ID failed to decode properly.
495pub fn instantiate_contract<E, ContractRef, Args, R, Abi>(
496 params: &CreateParams<E, ContractRef, LimitParamsV2, Args, R, Abi>,
497) -> Result<
498 ink_primitives::ConstructorResult<
499 <R as ConstructorReturnType<ContractRef, Abi>>::Output,
500 >,
501>
502where
503 E: Environment,
504 ContractRef: FromAddr + crate::ContractReverseReference,
505 <ContractRef as crate::ContractReverseReference>::Type:
506 crate::reflect::ContractConstructorDecoder,
507 Args: EncodeArgsWith<Abi>,
508 R: ConstructorReturnType<ContractRef, Abi>,
509{
510 <EnvInstance as OnInstance>::on_instance(|instance| {
511 TypedEnvBackend::instantiate_contract::<E, ContractRef, Args, R, Abi>(
512 instance, params,
513 )
514 })
515}
516
517/// Terminates the existence of the currently executed smart contract.
518///
519/// This removes the calling account and transfers all remaining balance
520/// to the given beneficiary.
521///
522/// # Note
523///
524/// This function never returns. Either the termination was successful and the
525/// execution of the destroyed contract is halted. Or it failed during the termination
526/// which is considered fatal and results in a trap and rollback.
527#[cfg(feature = "unstable-hostfn")]
528pub fn terminate_contract(beneficiary: Address) -> ! {
529 <EnvInstance as OnInstance>::on_instance(|instance| {
530 TypedEnvBackend::terminate_contract(instance, beneficiary)
531 })
532}
533
534/// Transfers value from the contract to the destination account ID.
535///
536/// # Note
537///
538/// This is more efficient and simpler than the alternative to make a no-op
539/// contract call or invoke a runtime function that performs the
540/// transaction.
541///
542/// # Errors
543///
544/// - If the contract does not have sufficient free funds.
545/// - If the transfer had brought the sender's total balance below the minimum balance.
546/// You need to use `terminate_contract` in case this is your intention.
547pub fn transfer<E>(destination: Address, value: U256) -> Result<()>
548where
549 E: Environment,
550{
551 <EnvInstance as OnInstance>::on_instance(|instance| {
552 TypedEnvBackend::transfer::<E>(instance, destination, value)
553 })
554}
555
556/// Returns the execution input to the executed contract and decodes it as `T`.
557///
558/// # Note
559///
560/// - The input is the 4-bytes selector followed by the arguments of the called function
561/// in their SCALE encoded representation.
562/// - No prior interaction with the environment must take place before calling this
563/// procedure.
564///
565/// # Usage
566///
567/// Normally contracts define their own `enum` dispatch types respective
568/// to their exported constructors and messages that implement `scale::Decode`
569/// according to the constructors or messages selectors and their arguments.
570/// These `enum` dispatch types are then given to this procedure as the `T`.
571///
572/// When using ink! users do not have to construct those enum dispatch types
573/// themselves as they are normally generated by the ink! code generation
574/// automatically.
575///
576/// # Errors
577///
578/// If the given `T` cannot be properly decoded from the expected input.
579pub fn decode_input<T>() -> core::result::Result<T, DispatchError>
580where
581 T: DecodeDispatch,
582{
583 <EnvInstance as OnInstance>::on_instance(|instance| {
584 EnvBackend::decode_input::<T>(instance)
585 })
586}
587
588/// Returns the value back to the caller of the executed contract.
589///
590/// # Note
591///
592/// This function stops the execution of the contract immediately.
593#[cfg(not(feature = "std"))]
594pub fn return_value<R>(return_flags: ReturnFlags, return_value: &R) -> !
595where
596 R: scale::Encode,
597{
598 <EnvInstance as OnInstance>::on_instance(|instance| {
599 EnvBackend::return_value::<R>(instance, return_flags, return_value)
600 })
601}
602
603/// Returns the value back to the caller of the executed contract.
604///
605/// # Note
606///
607/// When the `std` feature is used, the contract is allowed to
608/// return normally. This feature should only be used for integration tests.
609#[cfg(feature = "std")]
610pub fn return_value<R>(return_flags: ReturnFlags, return_value: &R)
611where
612 R: scale::Encode,
613{
614 <EnvInstance as OnInstance>::on_instance(|instance| {
615 EnvBackend::return_value::<R>(instance, return_flags, return_value)
616 })
617}
618
619/// Returns the *Solidity ABI encoded* value back to the caller of the executed contract.
620///
621/// # Note
622///
623/// This function stops the execution of the contract immediately.
624pub fn return_value_solidity<R>(return_flags: ReturnFlags, return_value: &R) -> !
625where
626 R: for<'a> SolResultEncode<'a>,
627{
628 <EnvInstance as OnInstance>::on_instance(|instance| {
629 EnvBackend::return_value_solidity::<R>(instance, return_flags, return_value)
630 })
631}
632
633/// Conducts the crypto hash of the given input and stores the result in `output`.
634///
635/// # Example
636///
637/// ```
638/// use ink_env::hash::{
639/// HashOutput,
640/// Sha2x256,
641/// };
642/// let input: &[u8] = &[13, 14, 15];
643/// let mut output = <Sha2x256 as HashOutput>::Type::default(); // 256-bit buffer
644/// let hash = ink_env::hash_bytes::<Sha2x256>(input, &mut output);
645/// ```
646pub fn hash_bytes<H>(input: &[u8], output: &mut <H as HashOutput>::Type)
647where
648 H: CryptoHash,
649{
650 <EnvInstance as OnInstance>::on_instance(|instance| {
651 instance.hash_bytes::<H>(input, output)
652 })
653}
654
655/// Conducts the crypto hash of the given encoded input and stores the result in `output`.
656///
657/// # Example
658///
659/// ```
660/// # use ink_env::hash::{Sha2x256, HashOutput};
661/// const EXPECTED: [u8; 32] = [
662/// 243, 242, 58, 110, 205, 68, 100, 244, 187, 55, 188, 248, 29, 136, 145, 115, 186,
663/// 134, 14, 175, 178, 99, 183, 21, 4, 94, 92, 69, 199, 207, 241, 179,
664/// ];
665/// let encodable = (42, "foo", true); // Implements `scale::Encode`
666/// let mut output = <Sha2x256 as HashOutput>::Type::default(); // 256-bit buffer
667/// ink_env::hash_encoded::<Sha2x256, _>(&encodable, &mut output);
668/// assert_eq!(output, EXPECTED);
669/// ```
670pub fn hash_encoded<H, T>(input: &T, output: &mut <H as HashOutput>::Type)
671where
672 H: CryptoHash,
673 T: scale::Encode,
674{
675 <EnvInstance as OnInstance>::on_instance(|instance| {
676 instance.hash_encoded::<H, T>(input, output)
677 })
678}
679
680/// Calls the `bn128_add` G1 addition precompile.
681///
682/// Inputs are affine G1 coordinates over Fq.
683/// Returns the resulting affine point or (0, 0) if the result is ∞ / invalid.
684///
685/// # Note
686///
687/// The precompile address is `0x06`. You can find its implementation here:
688/// <https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/revive/src/precompiles/builtin/bn128.rs>
689pub fn bn128_add(x1: U256, y1: U256, x2: U256, y2: U256) -> (U256, U256) {
690 <EnvInstance as OnInstance>::on_instance(|instance| {
691 instance.bn128_add(x1, y1, x2, y2)
692 })
693}
694
695/// Calls the `bn128_mul` G1 scalar-mul precompile.
696///
697/// Multiplies an affine G1 point (x1, y1) by a scalar ∈ Fr.
698/// Returns the resulting affine point or (0, 0) if the result is ∞ / invalid.
699///
700/// # Note
701///
702/// The precompile address is `0x07`. You can find its implementation here:
703/// <https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/revive/src/precompiles/builtin/bn128.rs>
704pub fn bn128_mul(x1: U256, y1: U256, scalar: U256) -> (U256, U256) {
705 <EnvInstance as OnInstance>::on_instance(|instance| {
706 instance.bn128_mul(x1, y1, scalar)
707 })
708}
709
710/// Calls the `bn128_pairing` precompile.
711///
712/// Input is the Solidity-ABI-encoded sequence of (G1, G2) pairs.
713/// Returns `true` iff the product of pairings evaluates to the identity.
714///
715/// # Note
716///
717/// The precompile address is `0x08`. You can find its implementation here:
718/// <https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/revive/src/precompiles/builtin/bn128.rs>
719pub fn bn128_pairing(input: &[u8]) -> bool {
720 <EnvInstance as OnInstance>::on_instance(|instance| instance.bn128_pairing(input))
721}
722
723/// Recovers the compressed ECDSA public key for given `signature` and `message_hash`,
724/// and stores the result in `output`.
725///
726/// # Example
727///
728/// ```
729/// const signature: [u8; 65] = [
730/// 195, 218, 227, 165, 226, 17, 25, 160, 37, 92, 142, 238, 4, 41, 244, 211, 18, 94,
731/// 131, 116, 231, 116, 255, 164, 252, 248, 85, 233, 173, 225, 26, 185, 119, 235,
732/// 137, 35, 204, 251, 134, 131, 186, 215, 76, 112, 17, 192, 114, 243, 102, 166, 176,
733/// 140, 180, 124, 213, 102, 117, 212, 89, 89, 92, 209, 116, 17, 28,
734/// ];
735/// const message_hash: [u8; 32] = [
736/// 167, 124, 116, 195, 220, 156, 244, 20, 243, 69, 1, 98, 189, 205, 79, 108, 213,
737/// 78, 65, 65, 230, 30, 17, 37, 184, 220, 237, 135, 1, 209, 101, 229,
738/// ];
739/// const EXPECTED_COMPRESSED_PUBLIC_KEY: [u8; 33] = [
740/// 3, 110, 192, 35, 209, 24, 189, 55, 218, 250, 100, 89, 40, 76, 222, 208, 202, 127,
741/// 31, 13, 58, 51, 242, 179, 13, 63, 19, 22, 252, 164, 226, 248, 98,
742/// ];
743/// let mut output = [0; 33];
744/// ink_env::ecdsa_recover(&signature, &message_hash, &mut output);
745/// assert_eq!(output, EXPECTED_COMPRESSED_PUBLIC_KEY);
746/// ```
747pub fn ecdsa_recover(
748 signature: &[u8; 65],
749 message_hash: &[u8; 32],
750 output: &mut [u8; 33],
751) -> Result<()> {
752 <EnvInstance as OnInstance>::on_instance(|instance| {
753 instance.ecdsa_recover(signature, message_hash, output)
754 })
755}
756
757/// Returns an Ethereum address from the ECDSA compressed public key.
758///
759/// # Example
760///
761/// ```
762/// let pub_key = [
763/// 3, 110, 192, 35, 209, 24, 189, 55, 218, 250, 100, 89, 40, 76, 222, 208, 202, 127,
764/// 31, 13, 58, 51, 242, 179, 13, 63, 19, 22, 252, 164, 226, 248, 98,
765/// ];
766/// let EXPECTED_ETH_ADDRESS = [
767/// 253, 240, 181, 194, 143, 66, 163, 109, 18, 211, 78, 49, 177, 94, 159, 79, 207,
768/// 37, 21, 191,
769/// ];
770/// let mut output = [0; 20];
771/// ink_env::ecdsa_to_eth_address(&pub_key, &mut output);
772/// assert_eq!(output, EXPECTED_ETH_ADDRESS);
773/// ```
774///
775/// # Errors
776///
777/// - If the ECDSA public key cannot be recovered from the provided public key.
778#[cfg(feature = "unstable-hostfn")]
779pub fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result<()> {
780 <EnvInstance as OnInstance>::on_instance(|instance| {
781 instance.ecdsa_to_eth_address(pubkey, output)
782 })
783}
784
785/// Verifies a sr25519 signature.
786///
787/// # Example
788///
789/// ```
790/// let signature: [u8; 64] = [
791/// 184, 49, 74, 238, 78, 165, 102, 252, 22, 92, 156, 176, 124, 118, 168, 116, 247,
792/// 99, 0, 94, 2, 45, 9, 170, 73, 222, 182, 74, 60, 32, 75, 64, 98, 174, 69, 55, 83,
793/// 85, 180, 98, 208, 75, 231, 57, 205, 62, 4, 105, 26, 136, 172, 17, 123, 99, 90,
794/// 255, 228, 54, 115, 63, 30, 207, 205, 131,
795/// ];
796/// let message: &[u8; 11] = b"hello world";
797/// let pub_key: [u8; 32] = [
798/// 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44,
799/// 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125,
800/// ];
801///
802/// let result = ink::env::sr25519_verify(&signature, message.as_slice(), &pub_key);
803/// assert!(result.is_ok())
804/// ```
805///
806/// # Errors
807///
808/// - If sr25519 signature cannot be verified.
809///
810/// **WARNING**: this function is from the [unstable interface](https://github.com/paritytech/polkadot-sdk/tree/master/substrate/frame/revive#unstable-interfaces)
811/// which is unsafe and normally is not available on production chains.
812#[cfg(feature = "unstable-hostfn")]
813pub fn sr25519_verify(
814 signature: &[u8; 64],
815 message: &[u8],
816 pub_key: &[u8; 32],
817) -> Result<()> {
818 <EnvInstance as OnInstance>::on_instance(|instance| {
819 instance.sr25519_verify(signature, message, pub_key)
820 })
821}
822
823/// Checks whether `addr` is a contract.
824///
825/// # Notes
826///
827/// If `addr` references a precompile address, the return value will be `true`.
828///
829/// The function [`caller_is_origin`] performs better when checking whether your
830/// contract is being called by a contract or an account. It performs better
831/// for this case as it does not require any storage lookups.
832///
833/// # Errors
834///
835/// If the returned value cannot be properly decoded.
836pub fn is_contract(account: &Address) -> bool {
837 <EnvInstance as OnInstance>::on_instance(|instance| {
838 TypedEnvBackend::is_contract(instance, account)
839 })
840}
841
842/// Retrieves the code hash of the contract at the specified account id.
843///
844/// # Errors
845///
846/// - If no code hash was found for the specified account id.
847/// - If the returned value cannot be properly decoded.
848pub fn code_hash(addr: &Address) -> core::result::Result<H256, CodeHashErr> {
849 <EnvInstance as OnInstance>::on_instance(|instance| {
850 TypedEnvBackend::code_hash(instance, addr)
851 })
852}
853
854/// Retrieves the code hash of the currently executing contract.
855///
856/// # Errors
857///
858/// If the returned value cannot be properly decoded.
859pub fn own_code_hash() -> H256 {
860 <EnvInstance as OnInstance>::on_instance(|instance| {
861 TypedEnvBackend::own_code_hash(instance)
862 })
863}
864
865/// Checks whether the caller of the current contract is the origin of the whole call
866/// stack.
867///
868/// Prefer this over [`is_contract`] when checking whether your contract is being called
869/// by a contract or a plain account. The reason is that it performs better since it does
870/// not need to do any storage lookups.
871///
872/// A return value of `true` indicates that this contract is being called by a plain
873/// account. and `false` indicates that the caller is another contract.
874///
875/// # Errors
876///
877/// If the returned value cannot be properly decoded.
878pub fn caller_is_origin() -> bool {
879 <EnvInstance as OnInstance>::on_instance(|instance| {
880 TypedEnvBackend::caller_is_origin(instance)
881 })
882}
883
884/// Checks whether the caller of the current contract is root.
885///
886/// Note that only the origin of the call stack can be root. Hence this function returning
887/// `true` implies that the contract is being called by the origin.
888///
889/// A return value of `true` indicates that this contract is being called by a root
890/// origin, and `false` indicates that the caller is a signed origin.
891///
892/// # Errors
893///
894/// If the returned value cannot be properly decoded.
895pub fn caller_is_root() -> bool {
896 <EnvInstance as OnInstance>::on_instance(|instance| {
897 TypedEnvBackend::caller_is_root(instance)
898 })
899}
900
901/// Replace the contract code at the specified address with new code.
902///
903/// # Note
904///
905/// There are a few important considerations which must be taken into account when
906/// using this API:
907///
908/// 1. The storage at the code hash will remain untouched.
909///
910/// Contract developers **must ensure** that the storage layout of the new code is
911/// compatible with that of the old code.
912///
913/// 2. The contract address (`AccountId`) remains the same, while the `code_hash` changes.
914///
915/// Contract addresses are initially derived from `hash(deploying_address ++ code_hash ++
916/// salt)`. This makes it possible to determine a contracts address (`AccountId`) using
917/// the `code_hash` of the *initial* code used to instantiate the contract.
918///
919/// However, because `set_code_hash` can modify the underlying `code_hash` of a contract,
920/// it should not be relied upon that a contracts address can always be derived from its
921/// stored `code_hash`.
922///
923/// 3. Re-entrant calls use new `code_hash`.
924///
925/// If a contract calls into itself after changing its code the new call would use the new
926/// code. However, if the original caller panics after returning from the sub call it
927/// would revert the changes made by `set_code_hash` and the next caller would use the old
928/// code.
929///
930/// # Errors
931///
932/// todo: this enum variant no longer exists
933/// `ReturnCode::CodeNotFound` in case the supplied `code_hash` cannot be found on-chain.
934///
935/// # Storage Compatibility
936///
937/// When the smart contract code is modified,
938/// it is important to observe an additional virtual restriction
939/// that is imposed on this procedure:
940/// you should not change the order in which the contract state variables
941/// are declared, nor their type.
942///
943/// Violating the restriction will not prevent a successful compilation,
944/// but will result in the mix-up of values or failure to read the storage correctly.
945/// This can result in severe errors in the application utilizing the contract.
946///
947/// If the storage of your contract looks like this:
948///
949/// ```ignore
950/// #[ink(storage)]
951/// pub struct YourContract {
952/// x: u32,
953/// y: bool,
954/// }
955/// ```
956///
957/// The procedures listed below will make it invalid:
958///
959/// Changing the order of variables:
960///
961/// ```ignore
962/// #[ink(storage)]
963/// pub struct YourContract {
964/// y: bool,
965/// x: u32,
966/// }
967/// ```
968///
969/// Removing existing variable:
970///
971/// ```ignore
972/// #[ink(storage)]
973/// pub struct YourContract {
974/// x: u32,
975/// }
976/// ```
977///
978/// Changing type of a variable:
979///
980/// ```ignore
981/// #[ink(storage)]
982/// pub struct YourContract {
983/// x: u64,
984/// y: bool,
985/// }
986/// ```
987///
988/// Introducing a new variable before any of the existing ones:
989///
990/// ```ignore
991/// #[ink(storage)]
992/// pub struct YourContract {
993/// z: Vec<u32>,
994/// x: u32,
995/// y: bool,
996/// }
997/// ```
998///
999/// Please refer to the
1000/// [Open Zeppelin docs](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#modifying-your-contracts)
1001/// for more details and examples.
1002#[cfg(feature = "unstable-hostfn")]
1003pub fn set_code_hash<E>(code_hash: &H256) -> Result<()>
1004where
1005 E: Environment,
1006{
1007 <EnvInstance as OnInstance>::on_instance(|instance| instance.set_code_hash(code_hash))
1008}
1009
1010/// Estimates the [`Weight`] required to execute a given XCM message.
1011///
1012/// This is done by invoking [the XCM precompile](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/precompiles/struct.XcmPrecompile.html).
1013/// For more details consult the [precompile interface](https://github.com/paritytech/polkadot-sdk/blob/master/polkadot/xcm/pallet-xcm/precompiles/src/interface/IXcm.sol).
1014///
1015/// # Errors
1016///
1017/// - If the message cannot be properly decoded in the XCM precompile.
1018/// - If the XCM execution fails because of the runtime's XCM configuration.
1019///
1020/// # Panics
1021///
1022/// Panics in the off-chain environment.
1023#[cfg(feature = "xcm")]
1024pub fn xcm_weigh<Call>(msg: &xcm::VersionedXcm<Call>) -> Result<Weight>
1025where
1026 Call: scale::Encode,
1027{
1028 <EnvInstance as OnInstance>::on_instance(|instance| {
1029 TypedEnvBackend::xcm_weigh(instance, msg)
1030 })
1031}
1032
1033/// Execute an XCM message locally, using the contract's address as the origin.
1034///
1035/// This is done by invoking [the XCM precompile](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/precompiles/struct.XcmPrecompile.html).
1036/// For more details consult the [precompile interface](https://github.com/paritytech/polkadot-sdk/blob/master/polkadot/xcm/pallet-xcm/precompiles/src/interface/IXcm.sol).
1037///
1038/// # Errors
1039///
1040/// - If the message cannot be properly decoded in the XCM precompile.
1041/// - If the XCM execution fails because of the runtime's XCM configuration.
1042///
1043/// # Panics
1044///
1045/// Panics in the off-chain environment.
1046#[cfg(feature = "xcm")]
1047pub fn xcm_execute<Call>(msg: &xcm::VersionedXcm<Call>, weight: Weight) -> Result<()>
1048where
1049 Call: scale::Encode,
1050{
1051 <EnvInstance as OnInstance>::on_instance(|instance| {
1052 TypedEnvBackend::xcm_execute(instance, msg, weight)
1053 })
1054}
1055
1056/// Send an XCM message, using the contract's address as the origin.
1057///
1058/// The `msg` argument has to be SCALE encoded, it needs to be decodable to a valid
1059/// instance of the `RuntimeCall` enum.
1060///
1061/// This is done by invoking [the XCM precompile](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/precompiles/struct.XcmPrecompile.html).
1062/// For more details consult the [precompile interface](https://github.com/paritytech/polkadot-sdk/blob/master/polkadot/xcm/pallet-xcm/precompiles/src/interface/IXcm.sol).
1063///
1064/// # Errors
1065///
1066/// - If the message cannot be properly decoded in the XCM precompile.
1067///
1068/// # Panics
1069///
1070/// Panics in the off-chain environment.
1071#[cfg(feature = "xcm")]
1072pub fn xcm_send<Call>(
1073 dest: &xcm::VersionedLocation,
1074 msg: &xcm::VersionedXcm<Call>,
1075) -> Result<()>
1076where
1077 Call: scale::Encode,
1078{
1079 <EnvInstance as OnInstance>::on_instance(|instance| {
1080 TypedEnvBackend::xcm_send(instance, dest, msg)
1081 })
1082}
1083
1084/// Returns the size of the buffer that is remaining in the backend.
1085pub fn remaining_buffer() -> usize {
1086 <EnvInstance as OnInstance>::on_instance(|instance| {
1087 EnvBackend::remaining_buffer(instance)
1088 })
1089}