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