@@ -11,7 +11,7 @@ pub mod types;
1111
1212use base64:: prelude:: * ;
1313use 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.
374373impl < 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