From 6766b4bd96b833f57097a80cfbc6ecba600a6bb1 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Mon, 24 Jul 2017 12:14:12 -0500 Subject: [PATCH] accounts/abi,accounts/abi/bind: add payable features into contract bindings Signed-off-by: RJ Catalano --- accounts/abi/abi.go | 9 ++++++++- accounts/abi/bind/base.go | 5 +++++ accounts/abi/bind/bind.go | 7 ++++++- accounts/abi/bind/template.go | 1 + accounts/abi/method.go | 1 + 5 files changed, 21 insertions(+), 2 deletions(-) diff --git a/accounts/abi/abi.go b/accounts/abi/abi.go index 2a06d474b8..1cb22abe36 100644 --- a/accounts/abi/abi.go +++ b/accounts/abi/abi.go @@ -33,6 +33,7 @@ type ABI struct { Constructor Method Methods map[string]Method Events map[string]Event + Fallback Method } // JSON returns a parsed ABI interface and error if it failed. @@ -185,6 +186,7 @@ func (abi *ABI) UnmarshalJSON(data []byte) error { Constant bool Indexed bool Anonymous bool + Payable bool Inputs []Argument Outputs []Argument } @@ -202,12 +204,13 @@ func (abi *ABI) UnmarshalJSON(data []byte) error { Inputs: field.Inputs, } // empty defaults to function according to the abi spec - case "function", "": + case "function": abi.Methods[field.Name] = Method{ Name: field.Name, Const: field.Constant, Inputs: field.Inputs, Outputs: field.Outputs, + Payable: field.Payable, } case "event": abi.Events[field.Name] = Event{ @@ -215,6 +218,10 @@ func (abi *ABI) UnmarshalJSON(data []byte) error { Anonymous: field.Anonymous, Inputs: field.Inputs, } + case "fallback": + abi.Fallback = Method{ + Payable: field.Payable, + } } } diff --git a/accounts/abi/bind/base.go b/accounts/abi/bind/base.go index b40bd65e80..3828a96647 100644 --- a/accounts/abi/bind/base.go +++ b/accounts/abi/bind/base.go @@ -152,6 +152,11 @@ func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...in if err != nil { 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) } diff --git a/accounts/abi/bind/bind.go b/accounts/abi/bind/bind.go index 73e95e02a1..57331665bf 100644 --- a/accounts/abi/bind/bind.go +++ b/accounts/abi/bind/bind.go @@ -67,6 +67,7 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La var ( calls = make(map[string]*tmplMethod) transacts = make(map[string]*tmplMethod) + writes = make(map[string]*tmplMethod) ) for _, original := range evmABI.Methods { // 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 if original.Const { 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)} + } else { + writes[original.Name] = &tmplMethod{Original: original, Normalized: normalized, Structured: structured(original)} } } 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), InputBin: strings.TrimSpace(bytecodes[i]), Constructor: evmABI.Constructor, + Fallback: evmABI.Fallback, Calls: calls, Transacts: transacts, + Writes: writes, } } // Generate the contract template data content and render it diff --git a/accounts/abi/bind/template.go b/accounts/abi/bind/template.go index 64dd598c0b..e85524ae89 100644 --- a/accounts/abi/bind/template.go +++ b/accounts/abi/bind/template.go @@ -30,6 +30,7 @@ type tmplContract struct { InputABI string // JSON ABI used as the input to generate the binding from InputBin string // Optional EVM bytecode used to denetare deploy code from 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 Transacts map[string]*tmplMethod // Contract calls that write state data } diff --git a/accounts/abi/method.go b/accounts/abi/method.go index 62b3d29575..805f7c2337 100644 --- a/accounts/abi/method.go +++ b/accounts/abi/method.go @@ -34,6 +34,7 @@ import ( // Input specifies the required input parameters for this gives method. type Method struct { Name string + Payable bool Const bool Inputs []Argument Outputs []Argument