ink_revive_types/primitives.rs
1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18#![cfg_attr(not(feature = "std"), allow(unused_imports))]
19
20use alloc::vec::Vec;
21use ink_primitives::{
22 H160,
23 H256,
24 Weight,
25};
26use pallet_revive_uapi::ReturnFlags;
27use scale::{
28 Decode,
29 Encode,
30 MaxEncodedLen,
31};
32use scale_info::TypeInfo;
33use sp_runtime::{
34 DispatchError,
35 RuntimeDebug,
36 traits::{
37 Saturating,
38 Zero,
39 },
40};
41
42/// The amount of balance that was either charged or refunded in order to pay for storage.
43#[derive(
44 Clone,
45 Eq,
46 PartialEq,
47 Ord,
48 PartialOrd,
49 Encode,
50 Decode,
51 MaxEncodedLen,
52 RuntimeDebug,
53 TypeInfo,
54)]
55pub enum StorageDeposit<Balance> {
56 /// The transaction reduced storage consumption.
57 ///
58 /// This means that the specified amount of balance was transferred from the involved
59 /// deposit accounts to the origin.
60 Refund(Balance),
61 /// The transaction increased storage consumption.
62 ///
63 /// This means that the specified amount of balance was transferred from the origin
64 /// to the involved deposit accounts.
65 Charge(Balance),
66}
67
68impl<Balance: Zero> Default for StorageDeposit<Balance> {
69 fn default() -> Self {
70 Self::Charge(Zero::zero())
71 }
72}
73
74impl<Balance: Zero + Copy> StorageDeposit<Balance> {
75 /// Returns how much balance is charged or `0` in case of a refund.
76 pub fn charge_or_zero(&self) -> Balance {
77 match self {
78 Self::Charge(amount) => *amount,
79 Self::Refund(_) => Zero::zero(),
80 }
81 }
82
83 pub fn is_zero(&self) -> bool {
84 match self {
85 Self::Charge(amount) => amount.is_zero(),
86 Self::Refund(amount) => amount.is_zero(),
87 }
88 }
89}
90
91impl<Balance> StorageDeposit<Balance>
92where
93 Balance: Saturating + Ord + Copy,
94{
95 /// This is essentially a saturating signed add.
96 pub fn saturating_add(&self, rhs: &Self) -> Self {
97 use StorageDeposit::*;
98 match (self, rhs) {
99 (Charge(lhs), Charge(rhs)) => Charge(lhs.saturating_add(*rhs)),
100 (Refund(lhs), Refund(rhs)) => Refund(lhs.saturating_add(*rhs)),
101 (Charge(lhs), Refund(rhs)) => {
102 if lhs >= rhs {
103 Charge(lhs.saturating_sub(*rhs))
104 } else {
105 Refund(rhs.saturating_sub(*lhs))
106 }
107 }
108 (Refund(lhs), Charge(rhs)) => {
109 if lhs > rhs {
110 Refund(lhs.saturating_sub(*rhs))
111 } else {
112 Charge(rhs.saturating_sub(*lhs))
113 }
114 }
115 }
116 }
117
118 /// This is essentially a saturating signed sub.
119 pub fn saturating_sub(&self, rhs: &Self) -> Self {
120 use StorageDeposit::*;
121 match (self, rhs) {
122 (Charge(lhs), Refund(rhs)) => Charge(lhs.saturating_add(*rhs)),
123 (Refund(lhs), Charge(rhs)) => Refund(lhs.saturating_add(*rhs)),
124 (Charge(lhs), Charge(rhs)) => {
125 if lhs >= rhs {
126 Charge(lhs.saturating_sub(*rhs))
127 } else {
128 Refund(rhs.saturating_sub(*lhs))
129 }
130 }
131 (Refund(lhs), Refund(rhs)) => {
132 if lhs > rhs {
133 Refund(lhs.saturating_sub(*rhs))
134 } else {
135 Charge(rhs.saturating_sub(*lhs))
136 }
137 }
138 }
139 }
140
141 /// If the amount of deposit (this type) is constrained by a `limit` this calculates
142 /// how much balance (if any) is still available from this limit.
143 ///
144 /// # Note
145 ///
146 /// In case of a refund the return value can be larger than `limit`.
147 pub fn available(&self, limit: &Balance) -> Balance {
148 use StorageDeposit::*;
149 match self {
150 Charge(amount) => limit.saturating_sub(*amount),
151 Refund(amount) => limit.saturating_add(*amount),
152 }
153 }
154}
155
156/// Result type of a `bare_call` or `bare_instantiate` call as well as
157/// `ContractsApi::call` and `ContractsApi::instantiate`.
158///
159/// It contains the execution result together with some auxiliary information.
160///
161/// #Note
162///
163/// It has been extended to include `events` at the end of the struct while not bumping
164/// the `ContractsApi` version. Therefore when SCALE decoding a `ContractResult` its
165/// trailing data should be ignored to avoid any potential compatibility issues.
166#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
167pub struct ContractResult<R, Balance> {
168 /// How much weight was consumed during execution.
169 pub gas_consumed: Weight,
170 /// How much weight is required as gas limit in order to execute this call.
171 ///
172 /// This value should be used to determine the weight limit for on-chain execution.
173 ///
174 /// # Note
175 ///
176 /// This can only be different from [`Self::gas_consumed`] when weight pre charging
177 /// is used. Currently, only `seal_call_runtime` makes use of pre charging.
178 /// Additionally, any `seal_call` or `seal_instantiate` makes use of pre-charging
179 /// when a non-zero `gas_limit` argument is supplied.
180 pub gas_required: Weight,
181 /// How much balance was paid by the origin into the contract's deposit account in
182 /// order to pay for storage.
183 ///
184 /// The storage deposit is never actually charged from the origin in case of
185 /// [`Self::result`] is `Err`. This is because on error all storage changes are
186 /// rolled back including the payment of the deposit.
187 pub storage_deposit: StorageDeposit<Balance>,
188 /// The execution result of the vm binary code.
189 pub result: Result<R, DispatchError>,
190}
191
192/// Output of a contract call or instantiation which ran to completion.
193#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo, Default)]
194pub struct ExecReturnValue {
195 /// Flags passed along by `seal_return`. Empty when `seal_return` was never called.
196 pub flags: ReturnFlags,
197 /// Buffer passed along by `seal_return`. Empty when `seal_return` was never called.
198 pub data: Vec<u8>,
199}
200
201impl ExecReturnValue {
202 /// The contract did revert all storage changes.
203 pub fn did_revert(&self) -> bool {
204 self.flags.contains(ReturnFlags::REVERT)
205 }
206}
207
208/// The result of a successful contract instantiation.
209#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
210pub struct InstantiateReturnValue {
211 /// The output of the called constructor.
212 pub result: ExecReturnValue,
213 /// The address of the new contract.
214 pub addr: H160,
215}
216
217/// The result of successfully uploading a contract.
218#[derive(Clone, PartialEq, Eq, Encode, Decode, MaxEncodedLen, RuntimeDebug, TypeInfo)]
219pub struct CodeUploadReturnValue<Balance> {
220 /// The key under which the new code is stored.
221 pub code_hash: H256,
222 /// The deposit that was reserved at the caller. Is zero when the code already
223 /// existed.
224 pub deposit: Balance,
225}
226
227/// Result type of a `bare_code_upload` call.
228pub type CodeUploadResult<Balance> =
229 Result<CodeUploadReturnValue<Balance>, DispatchError>;