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