8
8
//! ## Handler <- EVM Context Handler
9
9
//! ## StackState<'config>
10
10
//!
11
+ use crate :: {
12
+ precompiles:: Precompiles ,
13
+ state:: { Account , Balance , ByteCode , Key } ,
14
+ } ;
11
15
use ethereum_types:: { H160 , H256 , U256 } ;
12
16
use evm:: {
13
17
backend:: { Backend , Basic } ,
14
18
executor:: stack:: { Accessed , StackExecutor , StackState , StackSubstateMetadata } ,
15
- Context , ExitError , ExitFatal , ExitReason , ExitRevert , Transfer ,
19
+ Context , ExitFatal , ExitReason , ExitRevert , Transfer ,
16
20
} ;
17
21
use std:: collections:: { BTreeMap , BTreeSet } ;
18
-
19
22
use thiserror:: Error ;
20
23
21
- use crate :: {
22
- precompiles:: Precompiles ,
23
- state:: { Account , Balance , ByteCode , Key } ,
24
- } ;
25
-
26
24
/// Export EVM types
27
25
pub use evm:: backend:: Log ;
26
+ pub use evm:: ExitError ;
28
27
29
28
/// An address of an EVM account.
30
29
pub type Address = H160 ;
@@ -125,11 +124,11 @@ pub enum Error {
125
124
pub trait EvmState {
126
125
fn environment ( & self ) -> & Environment ;
127
126
128
- fn account ( & self , address : Address ) -> Option < Account > ;
127
+ fn account ( & self , address : & Address ) -> Option < Account > ;
129
128
130
- fn contains ( & self , address : Address ) -> bool ;
129
+ fn contains ( & self , address : & Address ) -> bool ;
131
130
132
- fn modify_account < F > ( & mut self , address : Address , f : F )
131
+ fn modify_account < F > ( & mut self , address : Address , f : F ) -> Result < ( ) , ExitError >
133
132
where
134
133
F : FnOnce ( Account ) -> Option < Account > ;
135
134
@@ -181,7 +180,7 @@ impl<'a> VirtualMachineSubstate<'a> {
181
180
let account = self
182
181
. known_account ( & address)
183
182
. cloned ( )
184
- . unwrap_or_else ( || state. account ( address) . unwrap_or_default ( ) ) ;
183
+ . unwrap_or_else ( || state. account ( & address) . unwrap_or_default ( ) ) ;
185
184
self . accounts . entry ( address) . or_insert ( account)
186
185
}
187
186
}
@@ -245,12 +244,18 @@ where
245
244
let vm = executor. into_state ( ) ;
246
245
247
246
// pay gas fees
248
- if let Some ( mut account) = vm. state . account ( vm. origin ) {
247
+ if let Some ( mut account) = vm. state . account ( & vm. origin ) {
249
248
account. balance = account
250
249
. balance
251
- . checked_sub ( gas_fees)
250
+ . checked_sub (
251
+ gas_fees
252
+ . try_into ( )
253
+ . map_err ( |_| Error :: TransactionError ( ExitError :: OutOfFund ) ) ?,
254
+ )
252
255
. ok_or ( Error :: TransactionError ( ExitError :: OutOfFund ) ) ?;
253
- vm. state . modify_account ( vm. origin , |_| Some ( account) ) ;
256
+ vm. state
257
+ . modify_account ( vm. origin , |_| Some ( account) )
258
+ . map_err ( Error :: TransactionError ) ?;
254
259
}
255
260
256
261
// exit_reason
@@ -369,50 +374,64 @@ impl<'a, State: EvmState> Backend for VirtualMachine<'a, State> {
369
374
self . state . environment ( ) . chain_id
370
375
}
371
376
fn exists ( & self , address : H160 ) -> bool {
372
- self . substate . known_account ( & address) . is_some ( ) || self . state . contains ( address)
377
+ self . substate . known_account ( & address) . is_some ( ) || self . state . contains ( & address)
373
378
}
374
379
fn basic ( & self , address : H160 ) -> Basic {
375
380
self . substate
376
381
. known_account ( & address)
377
382
. map ( |account| Basic {
378
383
balance : account. balance . into ( ) ,
379
- nonce : account. nonce ,
384
+ nonce : account. state . nonce ,
380
385
} )
381
386
. unwrap_or_else ( || {
382
387
self . state
383
- . account ( address)
388
+ . account ( & address)
384
389
. map ( |account| Basic {
385
390
balance : account. balance . into ( ) ,
386
- nonce : account. nonce ,
391
+ nonce : account. state . nonce ,
387
392
} )
388
393
. unwrap_or_default ( )
389
394
} )
390
395
}
391
396
fn code ( & self , address : H160 ) -> Vec < u8 > {
392
397
self . substate
393
398
. known_account ( & address)
394
- . map ( |account| account. code . clone ( ) )
399
+ . map ( |account| account. state . code . clone ( ) )
395
400
. unwrap_or_else ( || {
396
401
self . state
397
- . account ( address)
398
- . map ( |account| account. code )
402
+ . account ( & address)
403
+ . map ( |account| account. state . code )
399
404
. unwrap_or_default ( )
400
405
} )
401
406
}
402
407
fn storage ( & self , address : H160 , index : H256 ) -> H256 {
403
408
self . substate
404
409
. known_account ( & address)
405
- . map ( |account| account. storage . get ( & index) . cloned ( ) . unwrap_or_default ( ) )
410
+ . map ( |account| {
411
+ account
412
+ . state
413
+ . storage
414
+ . get ( & index)
415
+ . cloned ( )
416
+ . unwrap_or_default ( )
417
+ } )
406
418
. unwrap_or_else ( || {
407
419
self . state
408
- . account ( address)
409
- . map ( |account| account. storage . get ( & index) . cloned ( ) . unwrap_or_default ( ) )
420
+ . account ( & address)
421
+ . map ( |account| {
422
+ account
423
+ . state
424
+ . storage
425
+ . get ( & index)
426
+ . cloned ( )
427
+ . unwrap_or_default ( )
428
+ } )
410
429
. unwrap_or_default ( )
411
430
} )
412
431
}
413
432
fn original_storage ( & self , address : H160 , index : H256 ) -> Option < H256 > {
414
- match self . state . account ( address) {
415
- Some ( account) => account. storage . get ( & index) . cloned ( ) ,
433
+ match self . state . account ( & address) {
434
+ Some ( account) => account. state . storage . get ( & index) . cloned ( ) ,
416
435
None => None ,
417
436
}
418
437
}
@@ -461,7 +480,8 @@ impl<'a, State: EvmState> StackState<'a> for VirtualMachine<'a, State> {
461
480
let mut account = account. clone ( ) ;
462
481
// cleanup storage from zero values
463
482
// ref: https://github.com/rust-blockchain/evm/blob/8b1875c83105f47b74d3d7be7302f942e92eb374/src/backend/memory.rs#L185
464
- account. storage = account
483
+ account. state . storage = account
484
+ . state
465
485
. storage
466
486
. iter ( )
467
487
. filter ( |( _, v) | v != & & Default :: default ( ) )
@@ -474,12 +494,12 @@ impl<'a, State: EvmState> StackState<'a> for VirtualMachine<'a, State> {
474
494
} else {
475
495
Some ( account)
476
496
}
477
- } ) ;
497
+ } ) ? ;
478
498
}
479
499
480
500
// delete account
481
501
for address in self . substate . deletes . iter ( ) {
482
- self . state . modify_account ( * address, |_| None ) ;
502
+ self . state . modify_account ( * address, |_| None ) ? ;
483
503
}
484
504
485
505
// save the logs
@@ -515,7 +535,7 @@ impl<'a, State: EvmState> StackState<'a> for VirtualMachine<'a, State> {
515
535
fn is_empty ( & self , address : H160 ) -> bool {
516
536
match self . substate . known_account ( & address) {
517
537
Some ( account) => account. is_empty ( ) ,
518
- None => match self . state . account ( address) {
538
+ None => match self . state . account ( & address) {
519
539
Some ( account) => account. is_empty ( ) ,
520
540
None => true ,
521
541
} ,
@@ -537,16 +557,16 @@ impl<'a, State: EvmState> StackState<'a> for VirtualMachine<'a, State> {
537
557
}
538
558
539
559
fn inc_nonce ( & mut self , address : H160 ) {
540
- self . substate . account_mut ( address, self . state ) . nonce += U256 :: one ( ) ;
560
+ self . substate . account_mut ( address, self . state ) . state . nonce += U256 :: one ( ) ;
541
561
}
542
562
543
563
fn set_storage ( & mut self , address : H160 , key : H256 , value : H256 ) {
544
564
let account = self . substate . account_mut ( address, self . state ) ;
545
- account. storage = account. storage . clone ( ) . put ( key, value) ;
565
+ account. state . storage = account. state . storage . clone ( ) . put ( key, value) ;
546
566
}
547
567
548
568
fn reset_storage ( & mut self , address : H160 ) {
549
- self . substate . account_mut ( address, self . state ) . storage = Default :: default ( ) ;
569
+ self . substate . account_mut ( address, self . state ) . state . storage = Default :: default ( ) ;
550
570
}
551
571
552
572
fn log ( & mut self , address : H160 , topics : Vec < H256 > , data : Vec < u8 > ) {
@@ -562,19 +582,29 @@ impl<'a, State: EvmState> StackState<'a> for VirtualMachine<'a, State> {
562
582
}
563
583
564
584
fn set_code ( & mut self , address : H160 , code : Vec < u8 > ) {
565
- self . substate . account_mut ( address, self . state ) . code = code;
585
+ self . substate . account_mut ( address, self . state ) . state . code = code;
566
586
}
567
587
568
588
fn transfer ( & mut self , transfer : Transfer ) -> Result < ( ) , ExitError > {
569
589
let source = self . substate . account_mut ( transfer. source , self . state ) ;
570
590
571
- source. balance = match source. balance . checked_sub ( transfer. value ) {
591
+ source. balance = match source. balance . checked_sub (
592
+ transfer
593
+ . value
594
+ . try_into ( )
595
+ . map_err ( |_| ExitError :: OutOfFund ) ?,
596
+ ) {
572
597
Some ( res) => res,
573
- None => return Err ( ExitError :: OutOfGas ) ,
598
+ None => return Err ( ExitError :: OutOfFund ) ,
574
599
} ;
575
600
576
601
let target = self . substate . account_mut ( transfer. target , self . state ) ;
577
- target. balance = match target. balance . checked_add ( transfer. value ) {
602
+ target. balance = match target. balance . checked_add (
603
+ transfer
604
+ . value
605
+ . try_into ( )
606
+ . map_err ( |_| ExitError :: Other ( "Balance overflow" . into ( ) ) ) ?,
607
+ ) {
578
608
Some ( res) => res,
579
609
None => return Err ( ExitError :: Other ( "Balance overflow" . into ( ) ) ) ,
580
610
} ;
@@ -609,19 +639,20 @@ pub mod test {
609
639
& self . environment
610
640
}
611
641
612
- fn account ( & self , address : Address ) -> Option < Account > {
613
- self . accounts . get ( & address) . cloned ( )
642
+ fn account ( & self , address : & Address ) -> Option < Account > {
643
+ self . accounts . get ( address) . cloned ( )
614
644
}
615
645
616
- fn contains ( & self , address : Address ) -> bool {
617
- self . accounts . contains ( & address)
646
+ fn contains ( & self , address : & Address ) -> bool {
647
+ self . accounts . contains ( address)
618
648
}
619
649
620
- fn modify_account < F > ( & mut self , address : Address , f : F )
650
+ fn modify_account < F > ( & mut self , address : Address , f : F ) -> Result < ( ) , ExitError >
621
651
where
622
652
F : FnOnce ( Account ) -> Option < Account > ,
623
653
{
624
654
self . accounts = self . accounts . clone ( ) . modify_account ( address, f) ;
655
+ Ok ( ( ) )
625
656
}
626
657
627
658
fn update_logs ( & mut self , block_hash : H256 , logs : Vec < Log > ) {
0 commit comments