github.com/simplechain-org/go-simplechain@v1.0.6/accounts/abi/method.go (about)

     1  package abi
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/simplechain-org/go-simplechain/crypto"
     8  )
     9  
    10  // FunctionType represents different types of functions a contract might have.
    11  type FunctionType int
    12  
    13  const (
    14  	// Constructor represents the constructor of the contract.
    15  	// The constructor function is called while deploying a contract.
    16  	Constructor FunctionType = iota
    17  	// Fallback represents the fallback function.
    18  	// This function is executed if no other function matches the given function
    19  	// signature and no receive function is specified.
    20  	Fallback
    21  	// Receive represents the receive function.
    22  	// This function is executed on plain Ether transfers.
    23  	Receive
    24  	// Function represents a normal function.
    25  	Function
    26  )
    27  
    28  // Method represents a callable given a `Name` and whether the method is a constant.
    29  // If the method is `Const` no transaction needs to be created for this
    30  // particular Method call. It can easily be simulated using a local VM.
    31  // For example a `Balance()` method only needs to retrieve something
    32  // from the storage and therefore requires no Tx to be sent to the
    33  // network. A method such as `Transact` does require a Tx and thus will
    34  // be flagged `false`.
    35  // Input specifies the required input parameters for this gives method.
    36  type Method struct {
    37  	// Name is the method name used for internal representation. It's derived from
    38  	// the raw name and a suffix will be added in the case of a function overload.
    39  	//
    40  	// e.g.
    41  	// These are two functions that have the same name:
    42  	// * foo(int,int)
    43  	// * foo(uint,uint)
    44  	// The method name of the first one will be resolved as foo while the second one
    45  	// will be resolved as foo0.
    46  	Name    string
    47  	RawName string // RawName is the raw method name parsed from ABI
    48  
    49  	// Type indicates whether the method is a
    50  	// special fallback introduced in solidity v0.6.0
    51  	Type FunctionType
    52  
    53  	// StateMutability indicates the mutability state of method,
    54  	// the default value is nonpayable. It can be empty if the abi
    55  	// is generated by legacy compiler.
    56  	StateMutability string
    57  
    58  	// Legacy indicators generated by compiler before v0.6.0
    59  	Constant bool
    60  	Payable  bool
    61  
    62  	Inputs  Arguments
    63  	Outputs Arguments
    64  	str     string
    65  	// Sig returns the methods string signature according to the ABI spec.
    66  	// e.g.		function foo(uint32 a, int b) = "foo(uint32,int256)"
    67  	// Please note that "int" is substitute for its canonical representation "int256"
    68  	Sig string
    69  	// ID returns the canonical representation of the method's signature used by the
    70  	// abi definition to identify method names and types.
    71  	ID []byte
    72  }
    73  
    74  // NewMethod creates a new Method.
    75  // A method should always be created using NewMethod.
    76  // It also precomputes the sig representation and the string representation
    77  // of the method.
    78  func NewMethod(name string, rawName string, funType FunctionType, mutability string, isConst, isPayable bool, inputs Arguments, outputs Arguments) Method {
    79  	var (
    80  		types       = make([]string, len(inputs))
    81  		inputNames  = make([]string, len(inputs))
    82  		outputNames = make([]string, len(outputs))
    83  	)
    84  	for i, input := range inputs {
    85  		inputNames[i] = fmt.Sprintf("%v %v", input.Type, input.Name)
    86  		types[i] = input.Type.String()
    87  	}
    88  	for i, output := range outputs {
    89  		outputNames[i] = output.Type.String()
    90  		if len(output.Name) > 0 {
    91  			outputNames[i] += fmt.Sprintf(" %v", output.Name)
    92  		}
    93  	}
    94  	// calculate the signature and method id. Note only function
    95  	// has meaningful signature and id.
    96  	var (
    97  		sig string
    98  		id  []byte
    99  	)
   100  	if funType == Function {
   101  		sig = fmt.Sprintf("%v(%v)", rawName, strings.Join(types, ","))
   102  		id = crypto.Keccak256([]byte(sig))[:4]
   103  	}
   104  	// Extract meaningful state mutability of solidity method.
   105  	// If it's default value, never print it.
   106  	state := mutability
   107  	if state == "nonpayable" {
   108  		state = ""
   109  	}
   110  	if state != "" {
   111  		state = state + " "
   112  	}
   113  	identity := fmt.Sprintf("function %v", rawName)
   114  	if funType == Fallback {
   115  		identity = "fallback"
   116  	} else if funType == Receive {
   117  		identity = "receive"
   118  	} else if funType == Constructor {
   119  		identity = "constructor"
   120  	}
   121  	str := fmt.Sprintf("%v(%v) %sreturns(%v)", identity, strings.Join(inputNames, ", "), state, strings.Join(outputNames, ", "))
   122  
   123  	return Method{
   124  		Name:            name,
   125  		RawName:         rawName,
   126  		Type:            funType,
   127  		StateMutability: mutability,
   128  		Constant:        isConst,
   129  		Payable:         isPayable,
   130  		Inputs:          inputs,
   131  		Outputs:         outputs,
   132  		str:             str,
   133  		Sig:             sig,
   134  		ID:              id,
   135  	}
   136  }
   137  
   138  func (method Method) String() string {
   139  	return method.str
   140  }
   141  
   142  // IsConstant returns the indicator whether the method is read-only.
   143  func (method Method) IsConstant() bool {
   144  	return method.StateMutability == "view" || method.StateMutability == "pure" || method.Constant
   145  }
   146  
   147  // IsPayable returns the indicator whether the method can process
   148  // plain ether transfers.
   149  func (method Method) IsPayable() bool {
   150  	return method.StateMutability == "payable" || method.Payable
   151  }