Пример #1
0
        public TransactionTracer(string from, string transactionHash, string toAddress, string contractAddress, BigInteger value)
        {
            _allTransfers   = new List <TransferValue>();
            ContractAddress = contractAddress;
            _addressUtil    = new AddressUtil();
            TransactionHash = transactionHash;
            Stack           = new List <CallStackFrame>();
            FromAddress     = from;
            ToAddress       = Constants.EmptyAddress;
            Type            = TransferValueType.CREATION;
            if (toAddress != null)
            {
                ToAddress = toAddress;
                Type      = TransferValueType.TRANSACTION;
            }

            string destinationAddress      = toAddress ?? ContractAddress ?? Constants.EmptyAddress;
            List <TransferValue> transfers = new List <TransferValue>();

            if (value != 0)
            {
                transfers.Add(new TransferValue()
                {
                    Depth           = 0,
                    TransactionHash = transactionHash,
                    FromAddress     = from,
                    ToAddress       = destinationAddress,
                    Value           = value,
                    Type            = this.Type
                });
            }

            var initialCallStack = new CallStackFrame()
            {
                Address   = destinationAddress,
                OpCode    = Type == TransferValueType.CREATION ? OpCodes.CREATE : null,
                Transfers = transfers.ToArray()
            };

            Stack.Add(initialCallStack);

            _callTree    = new TreeNode <CallStackFrame>(initialCallStack, 0);
            _currentNode = _callTree;
        }
Пример #2
0
        public async Task ProcessLog(StructLogItem structLog)
        {
            _currentDepth = structLog.Depth;
            CallStackFrame addedOnCurrentProcessing = null;

            if (structLog.Error != null)
            {
                this.Error = structLog.Error?.ToString();

                return;
            }

            if (structLog.Depth == _currentNode.Depth)
            {
                var returnFrame = _currentNode.Data;
                _currentNode = _currentNode.Parent;
                var topFrame = _currentNode.Data;

                if ((topFrame.OpCode == OpCodes.CREATE || returnFrame.OpCode == OpCodes.CREATE))
                {
                    string lastAddress = structLog.Stack.Last();
                    returnFrame.Address = FormatAddress(lastAddress);
                    if (returnFrame.Transfers != null && returnFrame.Transfers.Count() != 0)
                    {
                        await Fixup(returnFrame.Transfers, returnFrame.Address);
                    }
                }
            }

            switch (structLog.Opcode)
            {
            case OpCodes.CREATE:
            {
                var    value = new HexBigInteger(structLog.Stack.Last());
                string src   = _currentDepth - 1 == _currentNode.Depth ? _currentNode.Data.Address : _currentNode.Parent?.Data.Address;

                TransferValue[] transfers = null;
                //if (value.Value != 0)
                //{
                transfers = new TransferValue[] { new TransferValue()
                                                  {
                                                      Depth           = structLog.Depth,
                                                      ToAddress       = Constants.EmptyAddress,
                                                      Value           = value.Value,
                                                      FromAddress     = src,
                                                      TransactionHash = TransactionHash,
                                                      Type            = TransferValueType.CREATION
                                                  } };
                //}

                addedOnCurrentProcessing = new CallStackFrame()
                {
                    Address   = Constants.EmptyAddress,
                    OpCode    = structLog.Opcode,
                    Transfers = transfers ?? new TransferValue[] { }
                };
            }
            break;

            case OpCodes.CALL:
            {
                var    value = new HexBigInteger(structLog.Stack[structLog.Stack.Count - 3]);
                var    dest  = FormatAddress(structLog.Stack[structLog.Stack.Count - 2]);
                string src   = _currentNode.Data.Address;

                TransferValue[] transfers = null;
                if (value.Value != 0)
                {
                    transfers = new TransferValue[] { new TransferValue()
                                                      {
                                                          Depth           = structLog.Depth,//this.Stack.Count,
                                                          ToAddress       = dest,
                                                          Value           = value.Value,
                                                          FromAddress     = src,
                                                          TransactionHash = TransactionHash,
                                                          Type            = TransferValueType.TRANSFER
                                                      } };
                }

                addedOnCurrentProcessing = new CallStackFrame()
                {
                    Address   = dest,
                    OpCode    = structLog.Opcode,
                    Transfers = transfers ?? new TransferValue[] { }
                };
            }
            break;

            case OpCodes.CALLCODE:
            case OpCodes.DELEGATECALL:
            {
                string src = _currentNode.Data.Address;
                addedOnCurrentProcessing = new CallStackFrame()
                {
                    Address = src,
                    OpCode  = structLog.Opcode,
                };
            }
            break;

            case OpCodes.SUICIDE:
                // SUICIDE results in a transfer back to the calling address.
                //TODO: Find a way to calculate such TransferValue
            {
            }
            break;

            default:
                break;
            }

            if (addedOnCurrentProcessing != null)
            {
                this.Stack.Add(addedOnCurrentProcessing);
                TreeNode <CallStackFrame> newNode = new TreeNode <CallStackFrame>(addedOnCurrentProcessing, _currentDepth);
                if (_currentDepth == _currentNode.Depth)
                {
                    _currentNode.Parent.AddChild(newNode);
                }
                else
                {
                    _currentNode.AddChild(newNode);
                }

                _currentNode = newNode;
            }
        }