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