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