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}