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