Skip to content

Commit 05cbc41

Browse files
pallet-evm: refactor duplicate code in call/create/create2 (#4922)
* pallet-evm: refactor duplicate code in call/create/create2 * Bump runtime version
1 parent 4342a4b commit 05cbc41

File tree

1 file changed

+100
-141
lines changed

1 file changed

+100
-141
lines changed

src/lib.rs

Lines changed: 100 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -232,54 +232,22 @@ decl_module! {
232232
nonce: Option<U256>,
233233
) -> DispatchResult {
234234
let sender = ensure_signed(origin)?;
235-
ensure!(gas_price >= T::FeeCalculator::min_gas_price(), Error::<T>::GasPriceTooLow);
236235
let source = T::ConvertAccountId::convert_account_id(&sender);
237236

238-
let vicinity = Vicinity {
239-
gas_price,
240-
origin: source,
241-
};
242-
243-
let mut backend = Backend::<T>::new(&vicinity);
244-
let mut executor = StackExecutor::new_with_precompile(
245-
&backend,
246-
gas_limit as usize,
247-
&backend::GASOMETER_CONFIG,
248-
T::Precompiles::execute,
249-
);
250-
251-
let total_fee = gas_price.checked_mul(U256::from(gas_limit))
252-
.ok_or(Error::<T>::FeeOverflow)?;
253-
let total_payment = value.checked_add(total_fee).ok_or(Error::<T>::PaymentOverflow)?;
254-
let source_account = Accounts::get(&source);
255-
ensure!(source_account.balance >= total_payment, Error::<T>::BalanceLow);
256-
executor.withdraw(source, total_fee).map_err(|_| Error::<T>::WithdrawFailed)?;
257-
258-
if let Some(nonce) = nonce {
259-
ensure!(source_account.nonce == nonce, Error::<T>::InvalidNonce);
260-
}
261-
262-
let reason = executor.transact_call(
237+
Self::execute_evm(
263238
source,
264-
target,
265239
value,
266-
input,
267-
gas_limit as usize,
268-
);
269-
270-
let ret = match reason {
271-
ExitReason::Succeed(_) => Ok(()),
272-
ExitReason::Error(_) => Err(Error::<T>::ExitReasonFailed),
273-
ExitReason::Revert(_) => Err(Error::<T>::ExitReasonRevert),
274-
ExitReason::Fatal(_) => Err(Error::<T>::ExitReasonFatal),
275-
};
276-
let actual_fee = executor.fee(gas_price);
277-
executor.deposit(source, total_fee.saturating_sub(actual_fee));
278-
279-
let (values, logs) = executor.deconstruct();
280-
backend.apply(values, logs, true);
281-
282-
ret.map_err(Into::into)
240+
gas_limit,
241+
gas_price,
242+
nonce,
243+
|executor| ((), executor.transact_call(
244+
source,
245+
target,
246+
value,
247+
input,
248+
gas_limit as usize,
249+
)),
250+
).map_err(Into::into)
283251
}
284252

285253
/// Issue an EVM create operation. This is similar to a contract creation transaction in
@@ -294,60 +262,28 @@ decl_module! {
294262
nonce: Option<U256>,
295263
) -> DispatchResult {
296264
let sender = ensure_signed(origin)?;
297-
ensure!(gas_price >= T::FeeCalculator::min_gas_price(), Error::<T>::GasPriceTooLow);
298-
299265
let source = T::ConvertAccountId::convert_account_id(&sender);
300266

301-
let vicinity = Vicinity {
302-
gas_price,
303-
origin: source,
304-
};
305-
306-
let mut backend = Backend::<T>::new(&vicinity);
307-
let mut executor = StackExecutor::new_with_precompile(
308-
&backend,
309-
gas_limit as usize,
310-
&backend::GASOMETER_CONFIG,
311-
T::Precompiles::execute,
312-
);
313-
314-
let total_fee = gas_price.checked_mul(U256::from(gas_limit))
315-
.ok_or(Error::<T>::FeeOverflow)?;
316-
let total_payment = value.checked_add(total_fee).ok_or(Error::<T>::PaymentOverflow)?;
317-
let source_account = Accounts::get(&source);
318-
ensure!(source_account.balance >= total_payment, Error::<T>::BalanceLow);
319-
executor.withdraw(source, total_fee).map_err(|_| Error::<T>::WithdrawFailed)?;
320-
321-
if let Some(nonce) = nonce {
322-
ensure!(source_account.nonce == nonce, Error::<T>::InvalidNonce);
323-
}
324-
325-
let create_address = executor.create_address(
326-
evm::CreateScheme::Legacy { caller: source }
327-
);
328-
let reason = executor.transact_create(
267+
let create_address = Self::execute_evm(
329268
source,
330269
value,
331-
init,
332-
gas_limit as usize,
333-
);
334-
335-
let ret = match reason {
336-
ExitReason::Succeed(_) => {
337-
Module::<T>::deposit_event(Event::Created(create_address));
338-
Ok(())
270+
gas_limit,
271+
gas_price,
272+
nonce,
273+
|executor| {
274+
(executor.create_address(
275+
evm::CreateScheme::Legacy { caller: source },
276+
), executor.transact_create(
277+
source,
278+
value,
279+
init,
280+
gas_limit as usize,
281+
))
339282
},
340-
ExitReason::Error(_) => Err(Error::<T>::ExitReasonFailed),
341-
ExitReason::Revert(_) => Err(Error::<T>::ExitReasonRevert),
342-
ExitReason::Fatal(_) => Err(Error::<T>::ExitReasonFatal),
343-
};
344-
let actual_fee = executor.fee(gas_price);
345-
executor.deposit(source, total_fee.saturating_sub(actual_fee));
346-
347-
let (values, logs) = executor.deconstruct();
348-
backend.apply(values, logs, true);
283+
)?;
349284

350-
ret.map_err(Into::into)
285+
Module::<T>::deposit_event(Event::Created(create_address));
286+
Ok(())
351287
}
352288

353289
/// Issue an EVM create2 operation.
@@ -362,62 +298,30 @@ decl_module! {
362298
nonce: Option<U256>,
363299
) -> DispatchResult {
364300
let sender = ensure_signed(origin)?;
365-
ensure!(gas_price >= T::FeeCalculator::min_gas_price(), Error::<T>::GasPriceTooLow);
366-
367301
let source = T::ConvertAccountId::convert_account_id(&sender);
368302

369-
let vicinity = Vicinity {
370-
gas_price,
371-
origin: source,
372-
};
373-
374-
let mut backend = Backend::<T>::new(&vicinity);
375-
let mut executor = StackExecutor::new_with_precompile(
376-
&backend,
377-
gas_limit as usize,
378-
&backend::GASOMETER_CONFIG,
379-
T::Precompiles::execute,
380-
);
381-
382-
let total_fee = gas_price.checked_mul(U256::from(gas_limit))
383-
.ok_or(Error::<T>::FeeOverflow)?;
384-
let total_payment = value.checked_add(total_fee).ok_or(Error::<T>::PaymentOverflow)?;
385-
let source_account = Accounts::get(&source);
386-
ensure!(source_account.balance >= total_payment, Error::<T>::BalanceLow);
387-
executor.withdraw(source, total_fee).map_err(|_| Error::<T>::WithdrawFailed)?;
388-
389-
if let Some(nonce) = nonce {
390-
ensure!(source_account.nonce == nonce, Error::<T>::InvalidNonce);
391-
}
392-
393303
let code_hash = H256::from_slice(Keccak256::digest(&init).as_slice());
394-
let create_address = executor.create_address(
395-
evm::CreateScheme::Create2 { caller: source, code_hash, salt }
396-
);
397-
let reason = executor.transact_create2(
304+
let create_address = Self::execute_evm(
398305
source,
399306
value,
400-
init,
401-
salt,
402-
gas_limit as usize,
403-
);
404-
405-
let ret = match reason {
406-
ExitReason::Succeed(_) => {
407-
Module::<T>::deposit_event(Event::Created(create_address));
408-
Ok(())
307+
gas_limit,
308+
gas_price,
309+
nonce,
310+
|executor| {
311+
(executor.create_address(
312+
evm::CreateScheme::Create2 { caller: source, code_hash, salt },
313+
), executor.transact_create2(
314+
source,
315+
value,
316+
init,
317+
salt,
318+
gas_limit as usize,
319+
))
409320
},
410-
ExitReason::Error(_) => Err(Error::<T>::ExitReasonFailed),
411-
ExitReason::Revert(_) => Err(Error::<T>::ExitReasonRevert),
412-
ExitReason::Fatal(_) => Err(Error::<T>::ExitReasonFatal),
413-
};
414-
let actual_fee = executor.fee(gas_price);
415-
executor.deposit(source, total_fee.saturating_sub(actual_fee));
416-
417-
let (values, logs) = executor.deconstruct();
418-
backend.apply(values, logs, true);
321+
)?;
419322

420-
ret.map_err(Into::into)
323+
Module::<T>::deposit_event(Event::Created(create_address));
324+
Ok(())
421325
}
422326
}
423327
}
@@ -454,4 +358,59 @@ impl<T: Trait> Module<T> {
454358
AccountCodes::remove(address);
455359
AccountStorages::remove_prefix(address);
456360
}
361+
362+
/// Execute an EVM operation.
363+
fn execute_evm<F, R>(
364+
source: H160,
365+
value: U256,
366+
gas_limit: u32,
367+
gas_price: U256,
368+
nonce: Option<U256>,
369+
f: F,
370+
) -> Result<R, Error<T>> where
371+
F: FnOnce(&mut StackExecutor<Backend<T>>) -> (R, ExitReason),
372+
{
373+
ensure!(gas_price >= T::FeeCalculator::min_gas_price(), Error::<T>::GasPriceTooLow);
374+
375+
let vicinity = Vicinity {
376+
gas_price,
377+
origin: source,
378+
};
379+
380+
let mut backend = Backend::<T>::new(&vicinity);
381+
let mut executor = StackExecutor::new_with_precompile(
382+
&backend,
383+
gas_limit as usize,
384+
&backend::GASOMETER_CONFIG,
385+
T::Precompiles::execute,
386+
);
387+
388+
let total_fee = gas_price.checked_mul(U256::from(gas_limit))
389+
.ok_or(Error::<T>::FeeOverflow)?;
390+
let total_payment = value.checked_add(total_fee).ok_or(Error::<T>::PaymentOverflow)?;
391+
let source_account = Accounts::get(&source);
392+
ensure!(source_account.balance >= total_payment, Error::<T>::BalanceLow);
393+
executor.withdraw(source, total_fee).map_err(|_| Error::<T>::WithdrawFailed)?;
394+
395+
if let Some(nonce) = nonce {
396+
ensure!(source_account.nonce == nonce, Error::<T>::InvalidNonce);
397+
}
398+
399+
let (retv, reason) = f(&mut executor);
400+
401+
let ret = match reason {
402+
ExitReason::Succeed(_) => Ok(retv),
403+
ExitReason::Error(_) => Err(Error::<T>::ExitReasonFailed),
404+
ExitReason::Revert(_) => Err(Error::<T>::ExitReasonRevert),
405+
ExitReason::Fatal(_) => Err(Error::<T>::ExitReasonFatal),
406+
};
407+
408+
let actual_fee = executor.fee(gas_price);
409+
executor.deposit(source, total_fee.saturating_sub(actual_fee));
410+
411+
let (values, logs) = executor.deconstruct();
412+
backend.apply(values, logs, true);
413+
414+
ret
415+
}
457416
}

0 commit comments

Comments
 (0)