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