github.com/ava-labs/subnet-evm@v0.6.4/accounts/abi/method.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2015 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 package abi 28 29 import ( 30 "fmt" 31 "strings" 32 33 "github.com/ethereum/go-ethereum/crypto" 34 ) 35 36 // FunctionType represents different types of functions a contract might have. 37 type FunctionType int 38 39 const ( 40 // Constructor represents the constructor of the contract. 41 // The constructor function is called while deploying a contract. 42 Constructor FunctionType = iota 43 // Fallback represents the fallback function. 44 // This function is executed if no other function matches the given function 45 // signature and no receive function is specified. 46 Fallback 47 // Receive represents the receive function. 48 // This function is executed on plain Ether transfers. 49 Receive 50 // Function represents a normal function. 51 Function 52 ) 53 54 // Method represents a callable given a `Name` and whether the method is a constant. 55 // If the method is `Const` no transaction needs to be created for this 56 // particular Method call. It can easily be simulated using a local VM. 57 // For example a `Balance()` method only needs to retrieve something 58 // from the storage and therefore requires no Tx to be sent to the 59 // network. A method such as `Transact` does require a Tx and thus will 60 // be flagged `false`. 61 // Input specifies the required input parameters for this gives method. 62 type Method struct { 63 // Name is the method name used for internal representation. It's derived from 64 // the raw name and a suffix will be added in the case of a function overload. 65 // 66 // e.g. 67 // These are two functions that have the same name: 68 // * foo(int,int) 69 // * foo(uint,uint) 70 // The method name of the first one will be resolved as foo while the second one 71 // will be resolved as foo0. 72 Name string 73 RawName string // RawName is the raw method name parsed from ABI 74 75 // Type indicates whether the method is a 76 // special fallback introduced in solidity v0.6.0 77 Type FunctionType 78 79 // StateMutability indicates the mutability state of method, 80 // the default value is nonpayable. It can be empty if the abi 81 // is generated by legacy compiler. 82 StateMutability string 83 84 // Legacy indicators generated by compiler before v0.6.0 85 Constant bool 86 Payable bool 87 88 Inputs Arguments 89 Outputs Arguments 90 str string 91 // Sig returns the methods string signature according to the ABI spec. 92 // e.g. function foo(uint32 a, int b) = "foo(uint32,int256)" 93 // Please note that "int" is substitute for its canonical representation "int256" 94 Sig string 95 // ID returns the canonical representation of the method's signature used by the 96 // abi definition to identify method names and types. 97 ID []byte 98 } 99 100 // NewMethod creates a new Method. 101 // A method should always be created using NewMethod. 102 // It also precomputes the sig representation and the string representation 103 // of the method. 104 func NewMethod(name string, rawName string, funType FunctionType, mutability string, isConst, isPayable bool, inputs Arguments, outputs Arguments) Method { 105 var ( 106 types = make([]string, len(inputs)) 107 inputNames = make([]string, len(inputs)) 108 outputNames = make([]string, len(outputs)) 109 ) 110 for i, input := range inputs { 111 inputNames[i] = fmt.Sprintf("%v %v", input.Type, input.Name) 112 types[i] = input.Type.String() 113 } 114 for i, output := range outputs { 115 outputNames[i] = output.Type.String() 116 if len(output.Name) > 0 { 117 outputNames[i] += fmt.Sprintf(" %v", output.Name) 118 } 119 } 120 // calculate the signature and method id. Note only function 121 // has meaningful signature and id. 122 var ( 123 sig string 124 id []byte 125 ) 126 if funType == Function { 127 sig = fmt.Sprintf("%v(%v)", rawName, strings.Join(types, ",")) 128 id = crypto.Keccak256([]byte(sig))[:4] 129 } 130 // Extract meaningful state mutability of solidity method. 131 // If it's default value, never print it. 132 state := mutability 133 if state == "nonpayable" { 134 state = "" 135 } 136 if state != "" { 137 state = state + " " 138 } 139 identity := fmt.Sprintf("function %v", rawName) 140 switch funType { 141 case Fallback: 142 identity = "fallback" 143 case Receive: 144 identity = "receive" 145 case Constructor: 146 identity = "constructor" 147 } 148 str := fmt.Sprintf("%v(%v) %sreturns(%v)", identity, strings.Join(inputNames, ", "), state, strings.Join(outputNames, ", ")) 149 150 return Method{ 151 Name: name, 152 RawName: rawName, 153 Type: funType, 154 StateMutability: mutability, 155 Constant: isConst, 156 Payable: isPayable, 157 Inputs: inputs, 158 Outputs: outputs, 159 str: str, 160 Sig: sig, 161 ID: id, 162 } 163 } 164 165 func (method Method) String() string { 166 return method.str 167 } 168 169 // IsConstant returns the indicator whether the method is read-only. 170 func (method Method) IsConstant() bool { 171 return method.StateMutability == "view" || method.StateMutability == "pure" || method.Constant 172 } 173 174 // IsPayable returns the indicator whether the method can process 175 // plain ether transfers. 176 func (method Method) IsPayable() bool { 177 return method.StateMutability == "payable" || method.Payable 178 }