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