github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/pkg/articulate/trace.go (about)

     1  package articulate
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/abi"
     7  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/rpc"
     8  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types"
     9  	goEthAbi "github.com/ethereum/go-ethereum/accounts/abi"
    10  )
    11  
    12  func (abiCache *AbiCache) ArticulateTrace(trace *types.Trace) (err error) {
    13  	found, err := articulateTrace(trace, &abiCache.AbiMap)
    14  	if err != nil {
    15  		return err
    16  
    17  	} else if found != nil {
    18  		trace.ArticulatedTrace = found
    19  		return nil
    20  
    21  	} else {
    22  		address := trace.Action.To
    23  		if !abiCache.loadedMap.GetValue(address) && !abiCache.skipMap.GetValue(address) {
    24  			if err = abi.LoadAbi(abiCache.Conn, address, &abiCache.AbiMap); err != nil {
    25  				abiCache.skipMap.SetValue(address, true)
    26  				if !errors.Is(err, rpc.ErrNotAContract) {
    27  					// Not being a contract is not an error because we want to articulate the input in case it's a message
    28  					return err
    29  				}
    30  			} else {
    31  				abiCache.loadedMap.SetValue(address, true)
    32  			}
    33  		}
    34  
    35  		if !abiCache.skipMap.GetValue(address) {
    36  			if trace.ArticulatedTrace, err = articulateTrace(trace, &abiCache.AbiMap); err != nil {
    37  				return err
    38  			}
    39  		}
    40  
    41  		return nil
    42  	}
    43  }
    44  
    45  func articulateTrace(trace *types.Trace, abiMap *abi.SelectorSyncMap) (articulated *types.Function, err error) {
    46  	input := trace.Action.Input
    47  	if len(input) < 10 {
    48  		return
    49  	}
    50  
    51  	encoding := input[:10]
    52  	articulated = abiMap.GetValue(encoding)
    53  
    54  	if trace.Result == nil || articulated == nil {
    55  		return
    56  	}
    57  
    58  	var abiMethod *goEthAbi.Method
    59  
    60  	if len(trace.Action.Input) >= 10 {
    61  		abiMethod, err = articulated.GetAbiMethod()
    62  		if err != nil {
    63  			return nil, err
    64  		}
    65  		err = articulateArguments(
    66  			abiMethod.Inputs,
    67  			trace.Action.Input[10:],
    68  			nil,
    69  			articulated.Inputs,
    70  		)
    71  		if err != nil {
    72  			return
    73  		}
    74  	}
    75  
    76  	abiMethod, err = articulated.GetAbiMethod()
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	if len(trace.Result.Output) >= 2 {
    81  		err = articulateArguments(
    82  			abiMethod.Outputs,
    83  			trace.Result.Output[2:],
    84  			nil,
    85  			articulated.Outputs,
    86  		)
    87  	}
    88  
    89  	return
    90  }