ink_env/
backend.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
15use ink_primitives::{
16    Address,
17    CodeHashErr,
18    H256,
19    U256,
20    abi::AbiEncodeWith,
21    sol::SolResultEncode,
22    types::Environment,
23};
24use ink_storage_traits::Storable;
25pub use pallet_revive_uapi::ReturnFlags;
26
27use crate::{
28    DecodeDispatch,
29    DispatchError,
30    Result,
31    call::{
32        Call,
33        CallParams,
34        ConstructorReturnType,
35        CreateParams,
36        DelegateCall,
37        FromAddr,
38        LimitParamsV2,
39        utils::DecodeMessageResult,
40    },
41    event::{
42        Event,
43        TopicEncoder,
44    },
45    hash::{
46        CryptoHash,
47        HashOutput,
48    },
49};
50
51/// Environmental contract functionality that does not require `Environment`.
52pub trait EnvBackend {
53    /// Writes the value to the contract storage under the given storage key.
54    ///
55    /// Returns the size of the pre-existing value at the specified key if any.
56    fn set_contract_storage<K, V>(&mut self, key: &K, value: &V) -> Option<u32>
57    where
58        K: scale::Encode,
59        V: Storable;
60
61    /// Returns the value stored under the given storage key in the contract's storage if
62    /// any.
63    ///
64    /// # Errors
65    ///
66    /// - If the decoding of the typed value failed
67    fn get_contract_storage<K, R>(&mut self, key: &K) -> Result<Option<R>>
68    where
69        K: scale::Encode,
70        R: Storable;
71
72    /// Removes the `value` at `key`, returning the previous `value` at `key` from storage
73    /// if any.
74    ///
75    /// # Errors
76    ///
77    /// - If the decoding of the typed value failed
78    fn take_contract_storage<K, R>(&mut self, key: &K) -> Result<Option<R>>
79    where
80        K: scale::Encode,
81        R: Storable;
82
83    /// Returns the size of a value stored under the given storage key is returned if any.
84    fn contains_contract_storage<K>(&mut self, key: &K) -> Option<u32>
85    where
86        K: scale::Encode;
87
88    /// Clears the contract's storage key entry under the given storage key.
89    ///
90    /// Returns the size of the previously stored value at the specified key if any.
91    fn clear_contract_storage<K>(&mut self, key: &K) -> Option<u32>
92    where
93        K: scale::Encode;
94
95    /// Returns the execution input to the executed contract and decodes it as `T`.
96    ///
97    /// # Note
98    ///
99    /// - The input is the 4-bytes selector followed by the arguments of the called
100    ///   function in their SCALE encoded representation.
101    /// - No prior interaction with the environment must take place before calling this
102    ///   procedure.
103    ///
104    /// # Usage
105    ///
106    /// Normally contracts define their own `enum` dispatch types respective
107    /// to their exported constructors and messages that implement `scale::Decode`
108    /// according to the constructors or messages selectors and their arguments.
109    /// These `enum` dispatch types are then given to this procedure as the `T`.
110    ///
111    /// When using ink! users do not have to construct those enum dispatch types
112    /// themselves as they are normally generated by the ink! code generation
113    /// automatically.
114    ///
115    /// # Errors
116    ///
117    /// If the given `T` cannot be properly decoded from the expected input.
118    fn decode_input<T>(&mut self) -> core::result::Result<T, DispatchError>
119    where
120        T: DecodeDispatch;
121
122    /// Returns the value back to the caller of the executed contract.
123    ///
124    /// # Note
125    ///
126    /// Calling this method will end contract execution immediately.
127    /// It will return the given return value back to its caller.
128    ///
129    /// The `flags` parameter can be used to revert the state changes of the
130    /// entire execution if necessary.
131    #[cfg(not(feature = "std"))]
132    fn return_value<R>(&mut self, flags: ReturnFlags, return_value: &R) -> !
133    where
134        R: scale::Encode;
135
136    /// Returns the value back to the caller of the executed contract.
137    ///
138    /// # Note
139    ///
140    /// When the `std` feature is used, the contract is allowed to
141    /// return normally. This feature should only be used for integration tests.
142    ///
143    /// The `flags` parameter can be used to revert the state changes of the
144    /// entire execution if necessary.
145    #[cfg(feature = "std")]
146    fn return_value<R>(&mut self, flags: ReturnFlags, return_value: &R)
147    where
148        R: scale::Encode;
149
150    /// Returns the *Solidity ABI encoded* value back to the caller of the executed
151    /// contract.
152    ///
153    /// # Note
154    ///
155    /// This function stops the execution of the contract immediately.
156    fn return_value_solidity<R>(&mut self, flags: ReturnFlags, return_value: &R) -> !
157    where
158        R: for<'a> SolResultEncode<'a>;
159
160    /// Conducts the crypto hash of the given input and stores the result in `output`.
161    fn hash_bytes<H>(&mut self, input: &[u8], output: &mut <H as HashOutput>::Type)
162    where
163        H: CryptoHash;
164
165    /// Conducts the crypto hash of the given encoded input and stores the result in
166    /// `output`.
167    fn hash_encoded<H, T>(&mut self, input: &T, output: &mut <H as HashOutput>::Type)
168    where
169        H: CryptoHash,
170        T: scale::Encode;
171
172    /// Recovers the compressed ECDSA public key for given `signature` and `message_hash`,
173    /// and stores the result in `output`.
174    fn ecdsa_recover(
175        &mut self,
176        signature: &[u8; 65],
177        message_hash: &[u8; 32],
178        output: &mut [u8; 33],
179    ) -> Result<()>;
180
181    /// Retrieves an Ethereum address from the ECDSA compressed `pubkey`
182    /// and stores the result in `output`.
183    #[cfg(feature = "unstable-hostfn")]
184    fn ecdsa_to_eth_address(
185        &mut self,
186        pubkey: &[u8; 33],
187        output: &mut [u8; 20],
188    ) -> Result<()>;
189
190    /// Verifies a sr25519 signature.
191    ///
192    /// # Errors
193    ///
194    /// - If the signature verification failed.
195    ///
196    /// **WARNING**: this function is from the [unstable interface](https://github.com/paritytech/substrate/tree/master/frame/contracts#unstable-interfaces),
197    /// which is unsafe and normally is not available on production chains.
198    #[cfg(feature = "unstable-hostfn")]
199    fn sr25519_verify(
200        &mut self,
201        signature: &[u8; 64],
202        message: &[u8],
203        pub_key: &[u8; 32],
204    ) -> Result<()>;
205
206    /// Sets a new code hash for the current contract.
207    ///
208    /// This effectively replaces the code which is executed for this contract address.
209    ///
210    /// # Errors
211    ///
212    /// - If the supplied `code_hash` cannot be found on-chain.
213    #[cfg(feature = "unstable-hostfn")]
214    fn set_code_hash(&mut self, code_hash: &H256) -> Result<()>;
215
216    /// Returns the size of the buffer that is remaining in the backend.
217    fn remaining_buffer(&mut self) -> usize;
218}
219
220/// Environmental contract functionality.
221pub trait TypedEnvBackend: EnvBackend {
222    /// Returns the address of the caller of the executed contract.
223    ///
224    /// # Note
225    ///
226    /// For more details visit: [`caller`][`crate::caller`]
227    fn caller(&mut self) -> Address;
228
229    /// Returns the transferred value for the contract execution.
230    ///
231    /// # Note
232    ///
233    /// For more details visit: [`transferred_value`][`crate::transferred_value`]
234    fn transferred_value(&mut self) -> U256;
235
236    /// Returns the price for the specified amount of gas.
237    ///
238    /// # Note
239    ///
240    /// For more details visit: [`weight_to_fee`][`crate::weight_to_fee`]
241    fn weight_to_fee(&mut self, gas: u64) -> U256;
242
243    /// Returns the timestamp of the current block.
244    ///
245    /// # Note
246    ///
247    /// For more details visit: [`block_timestamp`][`crate::block_timestamp`]
248    fn block_timestamp<E: Environment>(&mut self) -> E::Timestamp;
249
250    /// Retrieves the account id for a specified address.
251    ///
252    /// # Note
253    ///
254    /// For more details visit: [`to_account_id`][`crate::to_account_id`]
255    fn to_account_id<E: Environment>(&mut self, addr: Address) -> E::AccountId;
256
257    /// Returns the address of the executed contract.
258    ///
259    /// # Note
260    ///
261    /// For more details visit: [`account_id`][`crate::account_id`]
262    fn account_id<E: Environment>(&mut self) -> E::AccountId;
263
264    /// Returns the address of the executed contract.
265    ///
266    /// # Note
267    ///
268    /// For more details visit: [`address`][`crate::address`]
269    fn address(&mut self) -> Address;
270
271    /// Returns the balance of the executed contract.
272    ///
273    /// # Note
274    ///
275    /// For more details visit: [`balance`][`crate::balance`]
276    fn balance(&mut self) -> U256;
277
278    /// Returns the current block number.
279    ///
280    /// # Note
281    ///
282    /// For more details visit: [`block_number`][`crate::block_number`]
283    fn block_number<E: Environment>(&mut self) -> E::BlockNumber;
284
285    /// Returns the minimum balance that is required for creating an account
286    /// (i.e. the chain's existential deposit).
287    ///
288    /// # Note
289    ///
290    /// For more details visit: [`minimum_balance`][`crate::minimum_balance`]
291    fn minimum_balance(&mut self) -> U256;
292
293    /// Emits an event with the given event data.
294    ///
295    /// # Note
296    ///
297    /// For more details visit: [`emit_event`][`crate::emit_event`]
298    fn emit_event<Evt, Abi>(&mut self, event: &Evt)
299    where
300        Evt: Event<Abi>,
301        Abi: TopicEncoder;
302
303    /// Invokes a contract message and returns its result.
304    ///
305    /// # Note
306    ///
307    /// **This will call into the latest `call_v2` host function.**
308    ///
309    /// For more details visit: [`invoke_contract`][`crate::invoke_contract`]
310    fn invoke_contract<E, Args, R, Abi>(
311        &mut self,
312        call_data: &CallParams<E, Call, Args, R, Abi>,
313    ) -> Result<ink_primitives::MessageResult<R>>
314    where
315        E: Environment,
316        Args: AbiEncodeWith<Abi>,
317        R: DecodeMessageResult<Abi>;
318
319    /// Invokes a contract message via delegate call and returns its result.
320    ///
321    /// # Note
322    ///
323    /// For more details visit:
324    /// [`invoke_contract_delegate`][`crate::invoke_contract_delegate`]
325    fn invoke_contract_delegate<E, Args, R, Abi>(
326        &mut self,
327        call_data: &CallParams<E, DelegateCall, Args, R, Abi>,
328    ) -> Result<ink_primitives::MessageResult<R>>
329    where
330        E: Environment,
331        Args: AbiEncodeWith<Abi>,
332        R: DecodeMessageResult<Abi>;
333
334    /// Instantiates another contract.
335    ///
336    /// # Note
337    ///
338    /// For more details visit: [`instantiate_contract`][`crate::instantiate_contract`]
339    fn instantiate_contract<E, ContractRef, Args, R, Abi>(
340        &mut self,
341        params: &CreateParams<E, ContractRef, LimitParamsV2, Args, R, Abi>,
342    ) -> Result<
343        ink_primitives::ConstructorResult<
344            <R as ConstructorReturnType<ContractRef, Abi>>::Output,
345        >,
346    >
347    where
348        E: Environment,
349        ContractRef: FromAddr + crate::ContractReverseReference,
350        <ContractRef as crate::ContractReverseReference>::Type:
351            crate::reflect::ContractConstructorDecoder,
352        Args: AbiEncodeWith<Abi>,
353        R: ConstructorReturnType<ContractRef, Abi>;
354
355    /// Terminates a smart contract.
356    ///
357    /// # Note
358    ///
359    /// For more details visit: [`terminate_contract`][`crate::terminate_contract`]
360    #[cfg(feature = "unstable-hostfn")]
361    fn terminate_contract(&mut self, beneficiary: Address) -> !;
362
363    /// Transfers value from the contract to the destination account ID.
364    ///
365    /// # Note
366    ///
367    /// For more details visit: [`transfer`][`crate::transfer`]
368    fn transfer<E>(&mut self, destination: Address, value: U256) -> Result<()>
369    where
370        E: Environment;
371
372    /// Checks whether a specified contract lives at `addr`.
373    ///
374    /// # Note
375    ///
376    /// For more details visit: [`is_contract`][`crate::is_contract`]
377    fn is_contract(&mut self, account: &Address) -> bool;
378
379    /// Checks whether the caller of the current contract is the origin of the whole call
380    /// stack.
381    ///
382    /// # Note
383    ///
384    /// For more details visit: [`caller_is_origin`][`crate::caller_is_origin`]
385    fn caller_is_origin(&mut self) -> bool;
386
387    /// Checks whether the caller of the current contract is root.
388    ///
389    /// # Note
390    ///
391    /// For more details visit: [`caller_is_root`][`crate::caller_is_root`]
392    fn caller_is_root(&mut self) -> bool;
393
394    /// Retrieves the code hash of the contract at the given `account` id.
395    ///
396    /// # Note
397    ///
398    /// For more details visit: [`code_hash`][`crate::code_hash`]
399    fn code_hash(&mut self, account: &Address)
400    -> core::result::Result<H256, CodeHashErr>;
401
402    /// Retrieves the code hash of the currently executing contract.
403    ///
404    /// # Note
405    ///
406    /// For more details visit: [`own_code_hash`][`crate::own_code_hash`]
407    fn own_code_hash(&mut self) -> H256;
408
409    /// Execute an XCM message locally, using the contract's address as the origin.
410    ///
411    /// # Note
412    ///
413    /// For more details visit: [`xcm`][`crate::xcm_execute`].
414    #[cfg(all(feature = "xcm", feature = "unstable-hostfn"))]
415    fn xcm_execute<E, Call>(&mut self, msg: &xcm::VersionedXcm<Call>) -> Result<()>
416    where
417        E: Environment,
418        Call: scale::Encode;
419
420    /// Send an XCM message, using the contract's address as the origin.
421    ///
422    /// # Note
423    ///
424    /// For more details visit: [`xcm`][`crate::xcm_send`].
425    #[cfg(all(feature = "xcm", feature = "unstable-hostfn"))]
426    fn xcm_send<E, Call>(
427        &mut self,
428        dest: &xcm::VersionedLocation,
429        msg: &xcm::VersionedXcm<Call>,
430    ) -> Result<xcm::v4::XcmHash>
431    where
432        E: Environment,
433        Call: scale::Encode;
434}