1use crate::{
21 evm::DryRunConfig, mock::MockHandler, storage::WriteOutcome, BalanceOf, Config, Time, H160,
22 U256,
23};
24use alloc::{boxed::Box, fmt::Debug, string::String, vec::Vec};
25use codec::{Decode, Encode, MaxEncodedLen};
26use pezframe_support::weights::Weight;
27use pezpallet_revive_uapi::ReturnFlags;
28use pezsp_core::Get;
29use pezsp_runtime::{
30 traits::{One, Saturating, Zero},
31 DispatchError, RuntimeDebug,
32};
33use scale_info::TypeInfo;
34
35#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
46pub struct ContractResult<R, Balance> {
47 pub gas_consumed: Weight,
49 pub gas_required: Weight,
60 pub storage_deposit: StorageDeposit<Balance>,
67 pub result: Result<R, DispatchError>,
69}
70
71#[derive(Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug, TypeInfo)]
73pub struct EthTransactInfo<Balance> {
74 pub gas_required: Weight,
76 pub storage_deposit: Balance,
78 pub eth_gas: U256,
80 pub data: Vec<u8>,
82}
83
84#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
86pub enum EthTransactError {
87 Data(Vec<u8>),
88 Message(String),
89}
90
91#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
92pub enum BalanceConversionError {
94 Value,
96 Dust,
98}
99
100#[derive(Default, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
103pub struct BalanceWithDust<Balance> {
104 value: Balance,
106 dust: u32,
109}
110
111impl<Balance> From<Balance> for BalanceWithDust<Balance> {
112 fn from(value: Balance) -> Self {
113 Self { value, dust: 0 }
114 }
115}
116
117impl<Balance> BalanceWithDust<Balance> {
118 pub fn deconstruct(self) -> (Balance, u32) {
120 (self.value, self.dust)
121 }
122
123 pub fn new_unchecked<T: Config>(value: Balance, dust: u32) -> Self {
125 debug_assert!(dust < T::NativeToEthRatio::get());
126 Self { value, dust }
127 }
128
129 pub fn from_value<T: Config>(
131 value: U256,
132 ) -> Result<BalanceWithDust<BalanceOf<T>>, BalanceConversionError> {
133 if value.is_zero() {
134 return Ok(Default::default());
135 }
136
137 let (quotient, remainder) = value.div_mod(T::NativeToEthRatio::get().into());
138 let value = quotient.try_into().map_err(|_| BalanceConversionError::Value)?;
139 let dust = remainder.try_into().map_err(|_| BalanceConversionError::Dust)?;
140
141 Ok(BalanceWithDust { value, dust })
142 }
143}
144
145impl<Balance: Zero + One + Saturating> BalanceWithDust<Balance> {
146 pub fn is_zero(&self) -> bool {
148 self.value.is_zero() && self.dust == 0
149 }
150
151 pub fn into_rounded_balance(self) -> Balance {
153 if self.dust == 0 {
154 self.value
155 } else {
156 self.value.saturating_add(Balance::one())
157 }
158 }
159}
160
161pub type CodeUploadResult<Balance> = Result<CodeUploadReturnValue<Balance>, DispatchError>;
163
164pub type GetStorageResult = Result<Option<Vec<u8>>, ContractAccessError>;
166
167pub type SetStorageResult = Result<WriteOutcome, ContractAccessError>;
169
170#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, MaxEncodedLen, RuntimeDebug, TypeInfo)]
172pub enum ContractAccessError {
173 DoesntExist,
175 KeyDecodingFailed,
177 StorageWriteFailed(DispatchError),
179}
180
181#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo, Default)]
183pub struct ExecReturnValue {
184 pub flags: ReturnFlags,
186 pub data: Vec<u8>,
188}
189
190impl ExecReturnValue {
191 pub fn did_revert(&self) -> bool {
193 self.flags.contains(ReturnFlags::REVERT)
194 }
195}
196
197#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
199pub struct InstantiateReturnValue {
200 pub result: ExecReturnValue,
202 pub addr: H160,
204}
205
206#[derive(Clone, PartialEq, Eq, Encode, Decode, MaxEncodedLen, RuntimeDebug, TypeInfo)]
208pub struct CodeUploadReturnValue<Balance> {
209 pub code_hash: pezsp_core::H256,
211 pub deposit: Balance,
213}
214
215#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
217pub enum Code {
218 Upload(Vec<u8>),
220 Existing(pezsp_core::H256),
222}
223
224#[derive(
226 Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, MaxEncodedLen, RuntimeDebug, TypeInfo,
227)]
228pub enum StorageDeposit<Balance> {
229 Refund(Balance),
234 Charge(Balance),
239}
240
241impl<T, Balance> ContractResult<T, Balance> {
242 pub fn map_result<V>(self, map_fn: impl FnOnce(T) -> V) -> ContractResult<V, Balance> {
243 ContractResult {
244 gas_consumed: self.gas_consumed,
245 gas_required: self.gas_required,
246 storage_deposit: self.storage_deposit,
247 result: self.result.map(map_fn),
248 }
249 }
250}
251
252impl<Balance: Zero> Default for StorageDeposit<Balance> {
253 fn default() -> Self {
254 Self::Charge(Zero::zero())
255 }
256}
257
258impl<Balance: Zero + Copy> StorageDeposit<Balance> {
259 pub fn charge_or_zero(&self) -> Balance {
261 match self {
262 Self::Charge(amount) => *amount,
263 Self::Refund(_) => Zero::zero(),
264 }
265 }
266
267 pub fn is_zero(&self) -> bool {
268 match self {
269 Self::Charge(amount) => amount.is_zero(),
270 Self::Refund(amount) => amount.is_zero(),
271 }
272 }
273}
274
275impl<Balance> StorageDeposit<Balance>
276where
277 Balance: Saturating + Ord + Copy,
278{
279 pub fn saturating_add(&self, rhs: &Self) -> Self {
281 use StorageDeposit::*;
282 match (self, rhs) {
283 (Charge(lhs), Charge(rhs)) => Charge(lhs.saturating_add(*rhs)),
284 (Refund(lhs), Refund(rhs)) => Refund(lhs.saturating_add(*rhs)),
285 (Charge(lhs), Refund(rhs)) => {
286 if lhs >= rhs {
287 Charge(lhs.saturating_sub(*rhs))
288 } else {
289 Refund(rhs.saturating_sub(*lhs))
290 }
291 },
292 (Refund(lhs), Charge(rhs)) => {
293 if lhs > rhs {
294 Refund(lhs.saturating_sub(*rhs))
295 } else {
296 Charge(rhs.saturating_sub(*lhs))
297 }
298 },
299 }
300 }
301
302 pub fn saturating_sub(&self, rhs: &Self) -> Self {
304 use StorageDeposit::*;
305 match (self, rhs) {
306 (Charge(lhs), Refund(rhs)) => Charge(lhs.saturating_add(*rhs)),
307 (Refund(lhs), Charge(rhs)) => Refund(lhs.saturating_add(*rhs)),
308 (Charge(lhs), Charge(rhs)) => {
309 if lhs >= rhs {
310 Charge(lhs.saturating_sub(*rhs))
311 } else {
312 Refund(rhs.saturating_sub(*lhs))
313 }
314 },
315 (Refund(lhs), Refund(rhs)) => {
316 if lhs > rhs {
317 Refund(lhs.saturating_sub(*rhs))
318 } else {
319 Charge(rhs.saturating_sub(*lhs))
320 }
321 },
322 }
323 }
324
325 pub fn available(&self, limit: &Balance) -> Balance {
332 use StorageDeposit::*;
333 match self {
334 Charge(amount) => limit.saturating_sub(*amount),
335 Refund(amount) => limit.saturating_add(*amount),
336 }
337 }
338}
339
340pub struct ExecConfig<T: Config> {
342 pub bump_nonce: bool,
359 pub collect_deposit_from_hold: Option<(u32, Weight)>,
364 pub effective_gas_price: Option<U256>,
368 pub is_dry_run: Option<DryRunConfig<<<T as Config>::Time as Time>::Moment>>,
371 pub mock_handler: Option<Box<dyn MockHandler<T>>>,
375}
376
377impl<T: Config> ExecConfig<T> {
378 pub fn new_bizinikiwi_tx() -> Self {
380 Self {
381 bump_nonce: true,
382 collect_deposit_from_hold: None,
383 effective_gas_price: None,
384 is_dry_run: None,
385 mock_handler: None,
386 }
387 }
388
389 pub fn new_bizinikiwi_tx_without_bump() -> Self {
390 Self {
391 bump_nonce: false,
392 collect_deposit_from_hold: None,
393 effective_gas_price: None,
394 mock_handler: None,
395 is_dry_run: None,
396 }
397 }
398
399 pub fn new_eth_tx(effective_gas_price: U256, encoded_len: u32, base_weight: Weight) -> Self {
401 Self {
402 bump_nonce: false,
403 collect_deposit_from_hold: Some((encoded_len, base_weight)),
404 effective_gas_price: Some(effective_gas_price),
405 mock_handler: None,
406 is_dry_run: None,
407 }
408 }
409
410 pub fn with_dry_run(
412 mut self,
413 dry_run_config: DryRunConfig<<<T as Config>::Time as Time>::Moment>,
414 ) -> Self {
415 self.is_dry_run = Some(dry_run_config);
416 self
417 }
418}
419
420#[must_use = "You must handle whether the code was removed or not."]
422pub enum CodeRemoved {
423 No,
425 Yes,
427}