[tracer] fix format of contract create action

[tracer] add revert message
pull/3686/head
peekpi 4 years ago
parent 9ee88f45f7
commit 300e03f207
  1. 75
      hmy/tracers/block_tracer.go

@ -42,6 +42,7 @@ type action struct {
outLen int64
value *big.Int
err error
revert []byte
subCalls []*action
}
@ -53,29 +54,25 @@ func (c action) toJsonStr() (string, *string, *string) {
callType := strings.ToLower(c.op.String())
if c.op == vm.CREATE || c.op == vm.CREATE2 {
action := fmt.Sprintf(
`{"callType":"%s","value":"0x%s","address":"0x%x","gas":"0x%x","from":"0x%x","init":"0x%x"}`,
callType, c.value.Text(16), c.to, c.gas, c.from, c.input,
`{"from":"0x%x","gas":"0x%x","init":"0x%x","value":"0x%s"}`,
c.from, c.gas, c.input, c.value.Text(16),
)
output := fmt.Sprintf(
`{"code":"0x%x","gasUsed":"0x%x"}`,
c.output, c.gasUsed,
`{"address":"0x%x","code":"0x%x","gasUsed":"0x%x"}`,
c.to, c.output, c.gasUsed,
)
return "create", &action, &output
}
if c.op == vm.CALL || c.op == vm.CALLCODE || c.op == vm.DELEGATECALL || c.op == vm.STATICCALL {
var action string
if c.value != nil {
action = fmt.Sprintf(
`{"callType":"%s","value":"0x%s","to":"0x%x","gas":"0x%x","from":"0x%x","input":"0x%x"}`,
callType, c.value.Text(16), c.to, c.gas, c.from, c.input,
)
} else {
action = fmt.Sprintf(
`{"callType":"%s","to":"0x%x","gas":"0x%x","from":"0x%x","input":"0x%x"}`,
callType, c.to, c.gas, c.from, c.input,
)
if c.value == nil {
c.value = big.NewInt(0)
}
action := fmt.Sprintf(
`{"callType":"%s","value":"0x%s","to":"0x%x","gas":"0x%x","from":"0x%x","input":"0x%x"}`,
callType, c.value.Text(16), c.to, c.gas, c.from, c.input,
)
output := fmt.Sprintf(
`{"output":"0x%x","gasUsed":"0x%x"}`,
c.output, c.gasUsed,
@ -113,6 +110,14 @@ func (jst *ParityBlockTracer) pop() *action {
return ac
}
func (jst *ParityBlockTracer) last() *action {
return jst.calls[len(jst.calls)-1]
}
func (jst *ParityBlockTracer) len() int {
return len(jst.calls)
}
// CaptureStart implements the ParityBlockTracer interface to initialize the tracing operation.
func (jst *ParityBlockTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error {
jst.op = vm.CALL // vritual call
@ -169,7 +174,7 @@ func (jst *ParityBlockTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode,
return retErr
}
if op == vm.SELFDESTRUCT {
ac := jst.calls[len(jst.calls)-1]
ac := jst.last()
ac.push(&action{
op: op,
from: contract.Address(),
@ -211,15 +216,19 @@ func (jst *ParityBlockTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode,
}
if jst.descended {
jst.descended = false
if depth >= len(jst.calls) { // >= to >
jst.calls[len(jst.calls)-1].gas = gas
if depth >= jst.len() { // >= to >
jst.last().gas = gas
}
}
if op == vm.REVERT {
jst.calls[len(jst.calls)-1].err = errors.New("execution reverted")
last := jst.last()
last.err = errors.New("execution reverted")
revertOff := stackPeek(0).Int64()
revertLen := stackPeek(1).Int64()
last.revert = memoryCopy(revertOff, revertLen)
return retErr
}
if depth == len(jst.calls)-1 { // depth == len - 1
if depth == jst.len()-1 { // depth == len - 1
call := jst.pop()
if call.op == vm.CREATE || call.op == vm.CREATE2 {
call.gasUsed = call.gasIn - call.gasCost - gas
@ -242,8 +251,7 @@ func (jst *ParityBlockTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode,
call.err = errors.New("internal failure")
}
}
size := len(jst.calls)
jst.calls[size-1].push(call)
jst.last().push(call)
}
return retErr
}
@ -251,7 +259,23 @@ func (jst *ParityBlockTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode,
// CaptureFault implements the ParityBlockTracer interface to trace an execution fault
// while running an opcode.
func (jst *ParityBlockTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error {
jst.err = err
if op == vm.REVERT {
return nil
}
call := jst.pop()
if call.err == nil {
// Consume all available gas and clean any leftovers
if call.gas != 0 {
call.gasUsed = call.gas
}
// Flatten the failed call into its parent
if jst.len() > 0 {
jst.last().push(call)
return nil
}
}
jst.push(call)
return nil
}
@ -288,8 +312,9 @@ func (jst *ParityBlockTracer) GetResult() ([]json.RawMessage, error) {
len(ac.subCalls), string(traceStr), typStr, *acStr,
)
var resultPiece string
if jst.err != nil {
resultPiece = `"error": "Reverted"`
if ac.err != nil {
resultPiece = fmt.Sprintf(`"error":"Reverted","revert":"0x%x"`, ac.revert)
} else if outStr != nil {
resultPiece = fmt.Sprintf(`"result":%s`, *outStr)
}

Loading…
Cancel
Save