accounts/abi,accounts/abi/bind: add payable features into contract bindings

Signed-off-by: RJ Catalano <rj@monax.io>
This commit is contained in:
RJ Catalano 2017-07-24 12:14:12 -05:00
parent 1802682f65
commit 6766b4bd96
No known key found for this signature in database
GPG key ID: D4AB109D9B5D6386
5 changed files with 21 additions and 2 deletions

View file

@ -33,6 +33,7 @@ type ABI struct {
Constructor Method Constructor Method
Methods map[string]Method Methods map[string]Method
Events map[string]Event Events map[string]Event
Fallback Method
} }
// JSON returns a parsed ABI interface and error if it failed. // JSON returns a parsed ABI interface and error if it failed.
@ -185,6 +186,7 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
Constant bool Constant bool
Indexed bool Indexed bool
Anonymous bool Anonymous bool
Payable bool
Inputs []Argument Inputs []Argument
Outputs []Argument Outputs []Argument
} }
@ -202,12 +204,13 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
Inputs: field.Inputs, Inputs: field.Inputs,
} }
// empty defaults to function according to the abi spec // empty defaults to function according to the abi spec
case "function", "": case "function":
abi.Methods[field.Name] = Method{ abi.Methods[field.Name] = Method{
Name: field.Name, Name: field.Name,
Const: field.Constant, Const: field.Constant,
Inputs: field.Inputs, Inputs: field.Inputs,
Outputs: field.Outputs, Outputs: field.Outputs,
Payable: field.Payable,
} }
case "event": case "event":
abi.Events[field.Name] = Event{ abi.Events[field.Name] = Event{
@ -215,6 +218,10 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
Anonymous: field.Anonymous, Anonymous: field.Anonymous,
Inputs: field.Inputs, Inputs: field.Inputs,
} }
case "fallback":
abi.Fallback = Method{
Payable: field.Payable,
}
} }
} }

View file

@ -152,6 +152,11 @@ func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...in
if err != nil { if err != nil {
return nil, err return nil, err
} }
// check to make sure method is payable and if not, make sure that there is no
// value being transported with this transaction
if !c.abi.Methods[method].Payable && 0 != opts.Value.Cmp(common.Big0) {
return nil, fmt.Errorf("bind: value %v sent to non payable method %v", opts.Value.String(), method)
}
return c.transact(opts, &c.address, input) return c.transact(opts, &c.address, input)
} }

View file

@ -67,6 +67,7 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La
var ( var (
calls = make(map[string]*tmplMethod) calls = make(map[string]*tmplMethod)
transacts = make(map[string]*tmplMethod) transacts = make(map[string]*tmplMethod)
writes = make(map[string]*tmplMethod)
) )
for _, original := range evmABI.Methods { for _, original := range evmABI.Methods {
// Normalize the method for capital cases and non-anonymous inputs/outputs // Normalize the method for capital cases and non-anonymous inputs/outputs
@ -90,8 +91,10 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La
// Append the methods to the call or transact lists // Append the methods to the call or transact lists
if original.Const { if original.Const {
calls[original.Name] = &tmplMethod{Original: original, Normalized: normalized, Structured: structured(original)} calls[original.Name] = &tmplMethod{Original: original, Normalized: normalized, Structured: structured(original)}
} else { } else if original.Payable {
transacts[original.Name] = &tmplMethod{Original: original, Normalized: normalized, Structured: structured(original)} transacts[original.Name] = &tmplMethod{Original: original, Normalized: normalized, Structured: structured(original)}
} else {
writes[original.Name] = &tmplMethod{Original: original, Normalized: normalized, Structured: structured(original)}
} }
} }
contracts[types[i]] = &tmplContract{ contracts[types[i]] = &tmplContract{
@ -99,8 +102,10 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La
InputABI: strings.Replace(strippedABI, "\"", "\\\"", -1), InputABI: strings.Replace(strippedABI, "\"", "\\\"", -1),
InputBin: strings.TrimSpace(bytecodes[i]), InputBin: strings.TrimSpace(bytecodes[i]),
Constructor: evmABI.Constructor, Constructor: evmABI.Constructor,
Fallback: evmABI.Fallback,
Calls: calls, Calls: calls,
Transacts: transacts, Transacts: transacts,
Writes: writes,
} }
} }
// Generate the contract template data content and render it // Generate the contract template data content and render it

View file

@ -30,6 +30,7 @@ type tmplContract struct {
InputABI string // JSON ABI used as the input to generate the binding from InputABI string // JSON ABI used as the input to generate the binding from
InputBin string // Optional EVM bytecode used to denetare deploy code from InputBin string // Optional EVM bytecode used to denetare deploy code from
Constructor abi.Method // Contract constructor for deploy parametrization Constructor abi.Method // Contract constructor for deploy parametrization
Fallback abi.Method // Contract fallback method for direct interaction with contract
Calls map[string]*tmplMethod // Contract calls that only read state data Calls map[string]*tmplMethod // Contract calls that only read state data
Transacts map[string]*tmplMethod // Contract calls that write state data Transacts map[string]*tmplMethod // Contract calls that write state data
} }

View file

@ -34,6 +34,7 @@ import (
// Input specifies the required input parameters for this gives method. // Input specifies the required input parameters for this gives method.
type Method struct { type Method struct {
Name string Name string
Payable bool
Const bool Const bool
Inputs []Argument Inputs []Argument
Outputs []Argument Outputs []Argument