github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/state/runtime/instrumentation/js/internal/tracers/prestate_tracer_legacy.js (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // prestateTracer outputs sufficient information to create a local execution of 18 // the transaction from a custom assembled genesis block. 19 { 20 // prestate is the genesis that we're building. 21 prestate: null, 22 23 // lookupAccount injects the specified account into the prestate object. 24 lookupAccount: function(addr, db){ 25 var acc = toHex(addr); 26 if (this.prestate[acc] === undefined) { 27 this.prestate[acc] = { 28 balance: '0x' + db.getBalance(addr).toString(16), 29 nonce: db.getNonce(addr), 30 code: toHex(db.getCode(addr)), 31 storage: {} 32 }; 33 } 34 }, 35 36 // lookupStorage injects the specified storage entry of the given account into 37 // the prestate object. 38 lookupStorage: function(addr, key, db){ 39 var acc = toHex(addr); 40 var idx = toHex(key); 41 42 if (this.prestate[acc].storage[idx] === undefined) { 43 this.prestate[acc].storage[idx] = toHex(db.getState(addr, key)); 44 } 45 }, 46 47 // result is invoked when all the opcodes have been iterated over and returns 48 // the final result of the tracing. 49 result: function(ctx, db) { 50 if (this.prestate === null) { 51 this.prestate = {}; 52 // If tx is transfer-only, the recipient account 53 // hasn't been populated. 54 this.lookupAccount(ctx.to, db); 55 } 56 57 // At this point, we need to deduct the 'value' from the 58 // outer transaction, and move it back to the origin 59 this.lookupAccount(ctx.from, db); 60 61 var fromBal = bigInt(this.prestate[toHex(ctx.from)].balance.slice(2), 16); 62 var toBal = bigInt(this.prestate[toHex(ctx.to)].balance.slice(2), 16); 63 64 this.prestate[toHex(ctx.to)].balance = '0x'+toBal.subtract(ctx.value).toString(16); 65 this.prestate[toHex(ctx.from)].balance = '0x'+fromBal.add(ctx.value).add((ctx.gasUsed + ctx.intrinsicGas) * ctx.gasPrice).toString(16); 66 67 // Decrement the caller's nonce, and remove empty create targets 68 this.prestate[toHex(ctx.from)].nonce--; 69 if (ctx.type == 'CREATE') { 70 // We can blibdly delete the contract prestate, as any existing state would 71 // have caused the transaction to be rejected as invalid in the first place. 72 delete this.prestate[toHex(ctx.to)]; 73 } 74 // Return the assembled allocations (prestate) 75 return this.prestate; 76 }, 77 78 // step is invoked for every opcode that the VM executes. 79 step: function(log, db) { 80 // Add the current account if we just started tracing 81 if (this.prestate === null){ 82 this.prestate = {}; 83 // Balance will potentially be wrong here, since this will include the value 84 // sent along with the message. We fix that in 'result()'. 85 this.lookupAccount(log.contract.getAddress(), db); 86 } 87 // Whenever new state is accessed, add it to the prestate 88 switch (log.op.toString()) { 89 case "EXTCODECOPY": case "EXTCODESIZE": case "EXTCODEHASH": case "BALANCE": 90 this.lookupAccount(toAddress(log.stack.peek(0).toString(16)), db); 91 break; 92 case "CREATE": 93 var from = log.contract.getAddress(); 94 this.lookupAccount(toContract(from, db.getNonce(from)), db); 95 break; 96 case "CREATE2": 97 var from = log.contract.getAddress(); 98 // stack: salt, size, offset, endowment 99 var offset = log.stack.peek(1).valueOf() 100 var size = log.stack.peek(2).valueOf() 101 var end = offset + size 102 this.lookupAccount(toContract2(from, log.stack.peek(3).toString(16), log.memory.slice(offset, end)), db); 103 break; 104 case "CALL": case "CALLCODE": case "DELEGATECALL": case "STATICCALL": 105 this.lookupAccount(toAddress(log.stack.peek(1).toString(16)), db); 106 break; 107 case 'SSTORE':case 'SLOAD': 108 this.lookupStorage(log.contract.getAddress(), toWord(log.stack.peek(0).toString(16)), db); 109 break; 110 } 111 }, 112 113 // fault is invoked when the actual execution of an opcode fails. 114 fault: function(log, db) {} 115 }