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