decred.org/dcrdex@v1.0.5/dex/networks/erc20/txdata.go (about)

     1  // This code is available on the terms of the project LICENSE.md file,
     2  // also available online at https://blueoakcouncil.org/license/1.0.0.
     3  
     4  package erc20
     5  
     6  import (
     7  	"fmt"
     8  	"math/big"
     9  
    10  	dexeth "decred.org/dcrdex/dex/networks/eth"
    11  	"github.com/ethereum/go-ethereum/common"
    12  )
    13  
    14  func parseCallData(method string, data []byte, expArgs int) ([]any, error) {
    15  	decoded, err := dexeth.ParseCallData(data, ERC20ABI)
    16  	if err != nil {
    17  		return nil, fmt.Errorf("unable to parse call data: %v", err)
    18  	}
    19  	if decoded.Name != method {
    20  		return nil, fmt.Errorf("expected %v function but got %v", method, decoded.Name)
    21  	}
    22  	if len(decoded.Args) != expArgs {
    23  		return nil, fmt.Errorf("wrong number of arguments. wanted %d, got %d", expArgs, len(decoded.Args))
    24  	}
    25  	return decoded.Args, nil
    26  }
    27  
    28  // ParseTransferFromData parses the calldata used to call the transferFrom
    29  // method of an ERC20 contract.
    30  func ParseTransferFromData(data []byte) (sender, recipient common.Address, amount *big.Int, err error) {
    31  	args, err := parseCallData("transferFrom", data, 3)
    32  	if err != nil {
    33  		return common.Address{}, common.Address{}, nil, fmt.Errorf("unable to parse call data: %v", err)
    34  	}
    35  
    36  	sender, ok := args[0].(common.Address)
    37  	if !ok {
    38  		return common.Address{}, common.Address{}, nil, fmt.Errorf("expected first arg of type common.Address but got %T", args[0])
    39  	}
    40  
    41  	recipient, ok = args[1].(common.Address)
    42  	if !ok {
    43  		return common.Address{}, common.Address{}, nil, fmt.Errorf("expected second arg of type common.Address but got %T", args[1])
    44  	}
    45  
    46  	amount, ok = args[2].(*big.Int)
    47  	if !ok {
    48  		return common.Address{}, common.Address{}, nil, fmt.Errorf("expected third arg of type *big.Int but got %T", args[2])
    49  	}
    50  
    51  	return sender, recipient, amount, nil
    52  }
    53  
    54  // ParseTransferData parses the calldata used to call the transfer method of an
    55  // ERC20 contract.
    56  func ParseTransferData(data []byte) (common.Address, *big.Int, error) {
    57  	args, err := parseCallData("transfer", data, 2)
    58  	if err != nil {
    59  		return common.Address{}, nil, fmt.Errorf("unable to parse call data: %v", err)
    60  	}
    61  
    62  	recipient, ok := args[0].(common.Address)
    63  	if !ok {
    64  		return common.Address{}, nil, fmt.Errorf("expected first arg of type common.Address but got %T", args[0])
    65  	}
    66  	value, ok := args[1].(*big.Int)
    67  	if !ok {
    68  		return common.Address{}, nil, fmt.Errorf("expected second arg of type *big.Int but got %T", args[1])
    69  	}
    70  
    71  	return recipient, value, nil
    72  }