accounts/abi: implement new fallback functions (#20764)
* accounts/abi: implement new fackball functions In Solidity v0.6.0, the original fallback is separated into two different sub types: fallback and receive. This PR addes the support for parsing new format abi and the relevant abigen functionalities. * accounts/abi: fix unit tests * accounts/abi: minor fixes * accounts/abi, mobile: support jave binding * accounts/abi: address marius's comment * accounts/abi: Work around the uin64 conversion issue Co-authored-by: Guillaume Ballet <gballet@gmail.com>
This commit is contained in:
@ -171,12 +171,24 @@ func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...in
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// todo(rjl493456442) check the method is payable or not,
|
||||
// reject invalid transaction at the first place
|
||||
return c.transact(opts, &c.address, input)
|
||||
}
|
||||
|
||||
// RawTransact initiates a transaction with the given raw calldata as the input.
|
||||
// It's usually used to initiates transaction for invoking **Fallback** function.
|
||||
func (c *BoundContract) RawTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error) {
|
||||
// todo(rjl493456442) check the method is payable or not,
|
||||
// reject invalid transaction at the first place
|
||||
return c.transact(opts, &c.address, calldata)
|
||||
}
|
||||
|
||||
// Transfer initiates a plain transaction to move funds to the contract, calling
|
||||
// its default method if one is available.
|
||||
func (c *BoundContract) Transfer(opts *TransactOpts) (*types.Transaction, error) {
|
||||
// todo(rjl493456442) check the payable fallback or receive is defined
|
||||
// or not, reject invalid transaction at the first place
|
||||
return c.transact(opts, &c.address, nil)
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,8 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||
calls = make(map[string]*tmplMethod)
|
||||
transacts = make(map[string]*tmplMethod)
|
||||
events = make(map[string]*tmplEvent)
|
||||
fallback *tmplMethod
|
||||
receive *tmplMethod
|
||||
|
||||
// identifiers are used to detect duplicated identifier of function
|
||||
// and event. For all calls, transacts and events, abigen will generate
|
||||
@ -92,7 +94,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||
normalizedName := methodNormalizer[lang](alias(aliases, original.Name))
|
||||
// Ensure there is no duplicated identifier
|
||||
var identifiers = callIdentifiers
|
||||
if !original.Const {
|
||||
if !original.IsConstant() {
|
||||
identifiers = transactIdentifiers
|
||||
}
|
||||
if identifiers[normalizedName] {
|
||||
@ -121,7 +123,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||
}
|
||||
}
|
||||
// Append the methods to the call or transact lists
|
||||
if original.Const {
|
||||
if original.IsConstant() {
|
||||
calls[original.Name] = &tmplMethod{Original: original, Normalized: normalized, Structured: structured(original.Outputs)}
|
||||
} else {
|
||||
transacts[original.Name] = &tmplMethod{Original: original, Normalized: normalized, Structured: structured(original.Outputs)}
|
||||
@ -156,7 +158,13 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||
// Append the event to the accumulator list
|
||||
events[original.Name] = &tmplEvent{Original: original, Normalized: normalized}
|
||||
}
|
||||
|
||||
// Add two special fallback functions if they exist
|
||||
if evmABI.HasFallback() {
|
||||
fallback = &tmplMethod{Original: evmABI.Fallback}
|
||||
}
|
||||
if evmABI.HasReceive() {
|
||||
receive = &tmplMethod{Original: evmABI.Receive}
|
||||
}
|
||||
// There is no easy way to pass arbitrary java objects to the Go side.
|
||||
if len(structs) > 0 && lang == LangJava {
|
||||
return "", errors.New("java binding for tuple arguments is not supported yet")
|
||||
@ -169,6 +177,8 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||
Constructor: evmABI.Constructor,
|
||||
Calls: calls,
|
||||
Transacts: transacts,
|
||||
Fallback: fallback,
|
||||
Receive: receive,
|
||||
Events: events,
|
||||
Libraries: make(map[string]string),
|
||||
}
|
||||
@ -619,11 +629,22 @@ func formatMethod(method abi.Method, structs map[string]*tmplStruct) string {
|
||||
outputs[i] += fmt.Sprintf(" %v", output.Name)
|
||||
}
|
||||
}
|
||||
constant := ""
|
||||
if method.Const {
|
||||
constant = "constant "
|
||||
// Extract meaningful state mutability of solidity method.
|
||||
// If it's default value, never print it.
|
||||
state := method.StateMutability
|
||||
if state == "nonpayable" {
|
||||
state = ""
|
||||
}
|
||||
return fmt.Sprintf("function %v(%v) %sreturns(%v)", method.RawName, strings.Join(inputs, ", "), constant, strings.Join(outputs, ", "))
|
||||
if state != "" {
|
||||
state = state + " "
|
||||
}
|
||||
identity := fmt.Sprintf("function %v", method.RawName)
|
||||
if method.IsFallback {
|
||||
identity = "fallback"
|
||||
} else if method.IsReceive {
|
||||
identity = "receive"
|
||||
}
|
||||
return fmt.Sprintf("%s(%v) %sreturns(%v)", identity, strings.Join(inputs, ", "), state, strings.Join(outputs, ", "))
|
||||
}
|
||||
|
||||
// formatEvent transforms raw event representation into a user friendly one.
|
||||
|
File diff suppressed because one or more lines are too long
@ -35,6 +35,8 @@ type tmplContract struct {
|
||||
Constructor abi.Method // Contract constructor for deploy parametrization
|
||||
Calls map[string]*tmplMethod // Contract calls that only read state data
|
||||
Transacts map[string]*tmplMethod // Contract calls that write state data
|
||||
Fallback *tmplMethod // Additional special fallback function
|
||||
Receive *tmplMethod // Additional special receive function
|
||||
Events map[string]*tmplEvent // Contract events accessors
|
||||
Libraries map[string]string // Same as tmplData, but filtered to only keep what the contract needs
|
||||
Library bool // Indicator whether the contract is a library
|
||||
@ -351,6 +353,52 @@ var (
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .Fallback}}
|
||||
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||
//
|
||||
// Solidity: {{formatmethod .Fallback.Original $structs}}
|
||||
func (_{{$contract.Type}} *{{$contract.Type}}Transactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) {
|
||||
return _{{$contract.Type}}.contract.RawTransact(opts, calldata)
|
||||
}
|
||||
|
||||
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||
//
|
||||
// Solidity: {{formatmethod .Fallback.Original $structs}}
|
||||
func (_{{$contract.Type}} *{{$contract.Type}}Session) Fallback(calldata []byte) (*types.Transaction, error) {
|
||||
return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata)
|
||||
}
|
||||
|
||||
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||
//
|
||||
// Solidity: {{formatmethod .Fallback.Original $structs}}
|
||||
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Fallback(calldata []byte) (*types.Transaction, error) {
|
||||
return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .Receive}}
|
||||
// Receive is a paid mutator transaction binding the contract receive function.
|
||||
//
|
||||
// Solidity: {{formatmethod .Receive.Original $structs}}
|
||||
func (_{{$contract.Type}} *{{$contract.Type}}Transactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) {
|
||||
return _{{$contract.Type}}.contract.RawTransact(opts, nil) // calldata is disallowed for receive function
|
||||
}
|
||||
|
||||
// Receive is a paid mutator transaction binding the contract receive function.
|
||||
//
|
||||
// Solidity: {{formatmethod .Receive.Original $structs}}
|
||||
func (_{{$contract.Type}} *{{$contract.Type}}Session) Receive() (*types.Transaction, error) {
|
||||
return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts)
|
||||
}
|
||||
|
||||
// Receive is a paid mutator transaction binding the contract receive function.
|
||||
//
|
||||
// Solidity: {{formatmethod .Receive.Original $structs}}
|
||||
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Receive() (*types.Transaction, error) {
|
||||
return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{range .Events}}
|
||||
// {{$contract.Type}}{{.Normalized.Name}}Iterator is returned from Filter{{.Normalized.Name}} and is used to iterate over the raw logs and unpacked data for {{.Normalized.Name}} events raised by the {{$contract.Type}} contract.
|
||||
type {{$contract.Type}}{{.Normalized.Name}}Iterator struct {
|
||||
@ -611,6 +659,24 @@ import java.util.*;
|
||||
return this.Contract.transact(opts, "{{.Original.Name}}" , args);
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .Fallback}}
|
||||
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||
//
|
||||
// Solidity: {{formatmethod .Fallback.Original $structs}}
|
||||
public Transaction Fallback(TransactOpts opts, byte[] calldata) throws Exception {
|
||||
return this.Contract.rawTransact(opts, calldata);
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .Receive}}
|
||||
// Receive is a paid mutator transaction binding the contract receive function.
|
||||
//
|
||||
// Solidity: {{formatmethod .Receive.Original $structs}}
|
||||
public Transaction Receive(TransactOpts opts) throws Exception {
|
||||
return this.Contract.rawTransact(opts, null);
|
||||
}
|
||||
{{end}}
|
||||
}
|
||||
{{end}}
|
||||
`
|
||||
|
Reference in New Issue
Block a user