Skip to content

Commit df1c5c7

Browse files
committed
wip3
1 parent 5008d60 commit df1c5c7

1 file changed

Lines changed: 89 additions & 54 deletions

File tree

  • runtime-sdk/modules/evm-new/src

runtime-sdk/modules/evm-new/src/lib.rs

Lines changed: 89 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub mod types;
1111

1212
use base64::prelude::*;
1313
use revm::{
14-
primitives::{ExecutionResult, Output, TxKind},
14+
primitives::{ExecutionResult, TxEnv, TxKind},
1515
Evm,
1616
};
1717

@@ -370,28 +370,19 @@ impl<Cfg: Config> API for Module<Cfg> {
370370
}
371371
}
372372

373-
// TODO: Most of evm_create and evm_call is the same, group the common code into one method as in the old implementation.
374373
impl<Cfg: Config> Module<Cfg> {
375-
fn evm_create<C: Context>(
374+
fn evm_execute<C: Context, F: FnOnce(&mut TxEnv)>(
376375
ctx: &C,
377-
caller: H160,
378-
value: U256,
379-
init_code: Vec<u8>,
380376
estimate_gas: bool,
377+
f: F,
381378
) -> Result<Vec<u8>, Error> {
382-
let mut db = db::OasisDB::<'_, C, Cfg>::new(ctx);
379+
// TODO: precompiles
383380

384-
let mut evm = Evm::builder()
385-
.with_db(db)
386-
.modify_tx_env(|tx| {
387-
tx.transact_to = TxKind::Create;
388-
tx.caller = caller.0.into();
389-
tx.value = revm::primitives::U256::from_be_bytes(value.into()); // XXX: is BE ok?
390-
tx.data = init_code.into();
391-
})
392-
.build();
381+
let is_query = CurrentState::with_env(|env| !env.is_execute());
393382

394-
let tx = evm.transact().unwrap(); // XXX: transact_commit? + err checking
383+
let mut db = db::OasisDB::<'_, C, Cfg>::new(ctx);
384+
let mut evm = Evm::builder().with_db(db).modify_tx_env(f).build();
385+
let tx = evm.transact().unwrap(); // XXX: err checking
395386

396387
let ret = match tx.result {
397388
ExecutionResult::Success {
@@ -400,20 +391,86 @@ impl<Cfg: Config> Module<Cfg> {
400391
gas_refunded,
401392
logs,
402393
output,
403-
} => Ok(output.into_data().to_vec()),
394+
} => {
395+
// Clamp data based on maximum allowed result size.
396+
let data = output.into_data();
397+
let data = if !is_query && data.len() > Cfg::MAX_RESULT_SIZE {
398+
data[..Cfg::MAX_RESULT_SIZE].to_vec()
399+
} else {
400+
data.to_vec()
401+
};
402+
403+
// Use gas and refund unused gas.
404+
// XXX: check
405+
<C::Runtime as Runtime>::Core::use_tx_gas(gas_used)?;
406+
<C::Runtime as Runtime>::Accounts::set_refund_unused_tx_fee(Cfg::REFUND_UNUSED_FEE);
407+
408+
// Emit logs as events.
409+
CurrentState::with(|state| {
410+
for log in logs {
411+
state.emit_event(crate::Event::Log {
412+
address: H160::from_slice(&log.address.into_array()),
413+
topics: log
414+
.topics()
415+
.iter()
416+
.map(|&topic| H256::from_slice(&topic.as_slice()))
417+
.collect(),
418+
data: log.data.data.to_vec(),
419+
});
420+
}
421+
});
422+
423+
Ok(data)
424+
}
404425
ExecutionResult::Revert { gas_used, output } => {
405-
Err(Error::Reverted(BASE64_STANDARD.encode(output.to_vec()))) // XXX: to_vec maybe not needed (check encoding)
426+
// Clamp data based on maximum allowed result size.
427+
// XXX: to_vec maybe not needed (check encoding)
428+
let data = if !is_query && output.len() > Cfg::MAX_RESULT_SIZE {
429+
output[..Cfg::MAX_RESULT_SIZE].to_vec()
430+
} else {
431+
output.to_vec()
432+
};
433+
434+
// Use gas and refund unused gas.
435+
// XXX: check
436+
<C::Runtime as Runtime>::Core::use_tx_gas(gas_used)?;
437+
<C::Runtime as Runtime>::Accounts::set_refund_unused_tx_fee(Cfg::REFUND_UNUSED_FEE);
438+
439+
Err(Error::Reverted(BASE64_STANDARD.encode(data)))
406440
}
407441
ExecutionResult::Halt { reason, gas_used } => {
442+
// Use gas and refund unused gas.
443+
// XXX: check
444+
<C::Runtime as Runtime>::Core::use_tx_gas(gas_used)?;
445+
<C::Runtime as Runtime>::Accounts::set_refund_unused_tx_fee(Cfg::REFUND_UNUSED_FEE);
446+
408447
Err(crate::Error::ExecutionFailed(format!("{:?}", reason)))
409448
}
410449
};
411-
// TODO: logs? also clamp data.
412-
// TODO: gas...
413450

414451
ret
415452
}
416453

454+
fn evm_create<C: Context>(
455+
ctx: &C,
456+
caller: H160,
457+
value: U256,
458+
init_code: Vec<u8>,
459+
estimate_gas: bool,
460+
) -> Result<Vec<u8>, Error> {
461+
Self::evm_execute(ctx, estimate_gas, |tx| {
462+
tx.gas_limit = <C::Runtime as Runtime>::Core::remaining_tx_gas();
463+
tx.gas_price = CurrentState::with_env(|env| env.tx_auth_info().fee.gas_price())
464+
.try_into()
465+
.unwrap(); // XXX: err checking
466+
467+
tx.caller = caller.0.into();
468+
tx.transact_to = TxKind::Create;
469+
tx.value = revm::primitives::U256::from_be_bytes(value.into()); // XXX: is BE ok?
470+
tx.data = init_code.into();
471+
})
472+
}
473+
417474
fn evm_call<C: Context>(
418475
ctx: &C,
419476
caller: H160,
@@ -422,39 +479,17 @@ impl<Cfg: Config> Module<Cfg> {
422479
data: Vec<u8>,
423480
estimate_gas: bool,
424481
) -> Result<Vec<u8>, Error> {
425-
let mut db = db::OasisDB::<'_, C, Cfg>::new(ctx);
426-
427-
let mut evm = Evm::builder()
428-
.with_db(db)
429-
.modify_tx_env(|tx| {
430-
tx.transact_to = TxKind::Call(address.0.into());
431-
tx.caller = caller.0.into();
432-
tx.value = revm::primitives::U256::from_be_bytes(value.into()); // XXX: is BE ok?
433-
tx.data = data.into();
434-
})
435-
.build();
436-
437-
let tx = evm.transact().unwrap(); // XXX: transact_commit? + err checking
438-
439-
let ret = match tx.result {
440-
ExecutionResult::Success {
441-
reason,
442-
gas_used,
443-
gas_refunded,
444-
logs,
445-
output,
446-
} => Ok(output.into_data().to_vec()),
447-
ExecutionResult::Revert { gas_used, output } => {
448-
Err(Error::Reverted(BASE64_STANDARD.encode(output.to_vec()))) // XXX: to_vec maybe not needed (check encoding)
449-
}
450-
ExecutionResult::Halt { reason, gas_used } => {
451-
Err(crate::Error::ExecutionFailed(format!("{:?}", reason)))
452-
}
453-
};
454-
// TODO: logs? also clamp data.
455-
// TODO: gas...
456-
457-
ret
482+
Self::evm_execute(ctx, estimate_gas, |tx| {
483+
tx.gas_limit = <C::Runtime as Runtime>::Core::remaining_tx_gas();
484+
tx.gas_price = CurrentState::with_env(|env| env.tx_auth_info().fee.gas_price())
485+
.try_into()
486+
.unwrap(); // XXX: err checking
487+
488+
tx.caller = caller.0.into();
489+
tx.transact_to = TxKind::Call(address.0.into());
490+
tx.value = revm::primitives::U256::from_be_bytes(value.into()); // XXX: is BE ok?
491+
tx.data = data.into();
492+
})
458493
}
459494

460495
fn derive_caller() -> Result<H160, Error> {

0 commit comments

Comments
 (0)