diff --git a/accounts/abi/bind.go b/accounts/abi/bind.go
new file mode 100644
index 0000000000..b5f414fa5f
--- /dev/null
+++ b/accounts/abi/bind.go
@@ -0,0 +1,269 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package abi
+
+import (
+ "bytes"
+ "fmt"
+ "sort"
+ "strings"
+
+ "golang.org/x/tools/imports"
+)
+
+// Bind generates a Go wrapper around a contract ABI. This wrapper isn't meant
+// to be used as is in client code, but rather as an intermediate struct which
+// enforces compile time type safety and naming convention opposed to having to
+// manually maintain hard coded strings that break on runtime.
+func Bind(jsonABI string, pkg string, kind string) (string, error) {
+ // Parse the actual ABI to generate the binding for
+ abi, err := JSON(strings.NewReader(jsonABI))
+ if err != nil {
+ return "", err
+ }
+ // Generate the contract type, fields and methods
+ code := new(bytes.Buffer)
+ kind = strings.ToUpper(kind[:1]) + kind[1:]
+ fmt.Fprintf(code, "%s\n", bindContract(kind, jsonABI))
+
+ methods := make([]string, 0, len(abi.Methods))
+ for name, _ := range abi.Methods {
+ methods = append(methods, name)
+ }
+ sort.Strings(methods)
+
+ for _, method := range methods {
+ fmt.Fprintf(code, "%s\n", bindMethod(kind, abi.Methods[method]))
+ }
+ // Format the code with goimports and return
+ buffer := new(bytes.Buffer)
+
+ fmt.Fprintf(buffer, "package %s\n\n", pkg)
+ fmt.Fprintf(buffer, "%s\n\n", string(code.Bytes()))
+
+ blob, err := imports.Process("", buffer.Bytes(), nil)
+ if err != nil {
+ fmt.Println(string(buffer.Bytes()))
+ return "", err
+ }
+ return string(blob), nil
+}
+
+// bindContract generates the basic wrapper code for interacting with an Ethereum
+// contract via the abi package. All contract methods will call into the generic
+// ones generated here.
+func bindContract(kind string, abi string) string {
+ code := ""
+
+ // Generate the hard coded ABI used for Ethereum interaction
+ code += fmt.Sprintf("// Ethereum ABI used to generate the binding from.\nconst %sABI = `%s`\n\n", kind, strings.TrimSpace(abi))
+
+ // Generate the Go struct with all the maintenance fields
+ code += fmt.Sprintf("// %s is an auto generated Go binding around an Ethereum contract.\n", kind)
+ code += fmt.Sprintf("type %s struct {\n", kind)
+ code += fmt.Sprintf("contract *abi.BoundContract // Generic contract wrapper for the low level calls\n")
+ code += fmt.Sprintf("}\n\n")
+
+ // Generate the constructor to create a bound contract
+ code += fmt.Sprintf("// New%s creates a new instance of %s, bound to a specific deployed contract.\n", kind, kind)
+ code += fmt.Sprintf("func New%s(address common.Address, blockchain *core.BlockChain, opts abi.ContractOpts) (*%s, error) {\n", kind, kind)
+ code += fmt.Sprintf(" parsed, err := abi.JSON(strings.NewReader(%sABI))\n", kind)
+ code += fmt.Sprintf(" if err != nil {\n")
+ code += fmt.Sprintf(" return nil, err\n")
+ code += fmt.Sprintf(" }\n")
+ code += fmt.Sprintf(" return &%s{\n", kind)
+ code += fmt.Sprintf(" contract: abi.NewBoundContract(address, parsed, blockchain, opts),\n")
+ code += fmt.Sprintf(" }, nil\n")
+ code += fmt.Sprintf("}")
+
+ return code
+}
+
+// bindMethod
+func bindMethod(kind string, method Method) string {
+ var (
+ name = strings.ToUpper(method.Name[:1]) + method.Name[1:]
+ prologue = new(bytes.Buffer)
+ )
+ // Generate the argument and return list for the function
+ args := make([]string, 0, len(method.Inputs))
+ for i, arg := range method.Inputs {
+ param := arg.Name
+ if param == "" {
+ param = fmt.Sprintf("arg%d", i)
+ }
+ args = append(args, fmt.Sprintf("%s %s", param, bindType(arg.Type)))
+ }
+ returns, _ := bindReturn(prologue, name, method.Outputs)
+
+ // Generate the docs to help with coding against the binding
+ callTypeDoc := "free data retrieval call"
+ if !method.Const {
+ callTypeDoc = "paid mutator transaction"
+ }
+ docs := fmt.Sprintf("// %s is a %s binding the contract method 0x%x.\n", name, callTypeDoc, method.Id())
+ docs += fmt.Sprintf("// \n")
+ docs += fmt.Sprintf("// Solidity: %s", strings.TrimPrefix(method.String(), "function "))
+
+ // Generate the method itself and return
+ if method.Const {
+ return fmt.Sprintf("%s\n%s\nfunc (_%s *%s) %s(%s) (%s) {\n%s\n}\n", prologue, docs, kind, kind, name, strings.Join(args, ","), strings.Join(returns, ","), bindCallBody(kind, method.Name, args, returns))
+ } else {
+ args = append([]string{"auth *abi.AuthOpts"}, args...)
+ return fmt.Sprintf("%s\n%s\nfunc (_%s *%s) %s(%s) (*types.Transaction, error) {\n%s\n}\n", prologue, docs, kind, kind, name, strings.Join(args, ","), bindTransactionBody(kind, method.Name, args))
+ }
+}
+
+// bindType converts a Solidity type to a Go one. Since there is no clear mapping
+// from all Solidity types to Go ones (e.g. uint17), those that cannot be exactly
+// mapped will use an upscaled type (e.g. *big.Int).
+func bindType(kind Type) string {
+ switch {
+ case kind.stringKind == "address":
+ return "common.Address"
+
+ case kind.stringKind == "hash":
+ return "common.Hash"
+
+ case strings.HasPrefix(kind.stringKind, "bytes"):
+ if kind.stringKind == "bytes" {
+ return "[]byte"
+ }
+ return fmt.Sprintf("[%s]byte", kind.stringKind[5:])
+
+ case strings.HasPrefix(kind.stringKind, "int"):
+ switch kind.stringKind[:3] {
+ case "8", "16", "32", "64":
+ return kind.stringKind
+ }
+ return "*big.Int"
+
+ case strings.HasPrefix(kind.stringKind, "uint"):
+ switch kind.stringKind[:4] {
+ case "8", "16", "32", "64":
+ return kind.stringKind
+ }
+ return "*big.Int"
+
+ default:
+ return kind.stringKind
+ }
+}
+
+// bindReturn creates the list of return parameters for a method invocation. If
+// all the fields of the return type are named, and there is more than one value
+// being returned, the returns are wrapped in a result struct.
+func bindReturn(prologue *bytes.Buffer, method string, outputs []Argument) ([]string, string) {
+ // Generate the anonymous return list for when a struct is not needed/possible
+ var (
+ returns = make([]string, 0, len(outputs)+1)
+ anonymous = false
+ )
+ for _, ret := range outputs {
+ returns = append(returns, bindType(ret.Type))
+ if ret.Name == "" {
+ anonymous = true
+ }
+ }
+ if anonymous || len(returns) < 2 {
+ returns = append(returns, "error")
+ return returns, ""
+ }
+ // If the returns are named and numerous, wrap in a result struct
+ wrapper, impl := bindReturnStruct(method, outputs)
+ prologue.WriteString(impl + "\n")
+ return []string{"*" + wrapper, "error"}, wrapper
+}
+
+// bindReturnStruct creates a Go structure with the specified fields to be used
+// as the return type from a method call.
+func bindReturnStruct(method string, returns []Argument) (string, string) {
+ fields := make([]string, 0, len(returns))
+ for _, ret := range returns {
+ fields = append(fields, fmt.Sprintf("%s %s", strings.ToUpper(ret.Name[:1])+ret.Name[1:], bindType(ret.Type)))
+ }
+ kind := fmt.Sprintf("%sResult", method)
+ docs := fmt.Sprintf("// %s is the result of the %s invocation.", kind, method)
+
+ return kind, fmt.Sprintf("%s\ntype %s struct {\n%s\n}", docs, kind, strings.Join(fields, "\n"))
+}
+
+// bindCallBody creates the Go code to declare a batch of return values, invoke
+// an Ethereum method call with the requested parameters, parse the binary output
+// into the return values and return them.
+func bindCallBody(kind string, method string, params []string, returns []string) string {
+ body := ""
+
+ // Allocate memory for each of the return values
+ rets := make([]string, 0, len(returns)-1)
+ if len(returns) > 1 {
+ body += "var ("
+ for i, kind := range returns[:len(returns)-1] { // Omit the final error
+ name := fmt.Sprintf("ret%d", i)
+
+ rets = append(rets, name)
+ body += fmt.Sprintf("%s = new(%s)\n", name, strings.TrimPrefix(kind, "*"))
+ }
+ body += ")\n"
+ }
+ // Assemble a single collector variable for the result ABI initialization
+ result := strings.Join(rets, ",")
+ if len(returns) > 2 {
+ result = "[]interface{}{" + result + "}"
+ }
+ // Extract the parameter list into a flat variable name list
+ inputs := make([]string, len(params))
+ for i, param := range params {
+ inputs[i] = strings.Split(param, " ")[0]
+ }
+ input := ""
+ if len(inputs) > 0 {
+ input = "," + strings.Join(inputs, ",")
+ }
+ // Request executing the contract call and return the results with the errors
+ body += fmt.Sprintf("err := _%s.contract.Call(%s, \"%s\" %s)\n", kind, result, method, input)
+
+ outs := make([]string, 0, len(returns))
+ for i, ret := range returns[:len(returns)-1] { // Handle th final error separately
+ if strings.HasPrefix(ret, "*") {
+ outs = append(outs, rets[i])
+ } else {
+ outs = append(outs, "*"+rets[i])
+ }
+ }
+ outs = append(outs, "err")
+
+ body += fmt.Sprintf("return %s", strings.Join(outs, ","))
+
+ return body
+}
+
+// bindTransactionBody creates the Go code to invoke an Ethereum transaction call
+// with the requested parameters, and return the assembled transaction object.
+func bindTransactionBody(kind string, method string, params []string) string {
+ // Extract the parameter list into a flat variable name list
+ inputs := make([]string, len(params)-1) // Omit the auth options
+ for i, param := range params[1:] {
+ inputs[i] = strings.Split(param, " ")[0]
+ }
+ input := ""
+ if len(inputs) > 0 {
+ input = "," + strings.Join(inputs, ",")
+ }
+ // Request executing the contract call and return the results with the errors
+ return fmt.Sprintf("return _%s.contract.Transact(auth, \"%s\" %s)", kind, method, input)
+}
diff --git a/accounts/abi/bind_base.go b/accounts/abi/bind_base.go
new file mode 100644
index 0000000000..36c69609f1
--- /dev/null
+++ b/accounts/abi/bind_base.go
@@ -0,0 +1,236 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package abi
+
+import (
+ "errors"
+ "fmt"
+ "math/big"
+
+ "github.com/barakmich/glog"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm/runtime"
+ "github.com/ethereum/go-ethereum/eth/filters"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/logger"
+)
+
+// GasOracleFn is a gas price oracle function callback to request the suggestion
+// of an estimated gas price that should be used to execute a paid transaction.
+type GasOracleFn func() *big.Int
+
+// MinerStateFn is a callback method to retrieve the currently pending state
+// according ti our local mining instance.
+type MinerStateFn func() (*types.Block, *state.StateDB)
+
+// TxScheduleFn is a callback method to schedule a transaction for execution.
+type TxScheduleFn func(*types.Transaction) error
+
+// ContractOpts is the set of contract parameters that can be used to fine tune
+// behavior tailoring to a specific use case.
+type ContractOpts struct {
+ Database ethdb.Database // Chain and state database needed to access past logs
+ EventMux *event.TypeMux // Event multiplexer to publish log events merged with others
+ GasOracle GasOracleFn // Gas price oracle to allow not specifying transaction prices
+ MinerState MinerStateFn // Pending state retriever to allow nonce and gas limit estimation
+ TxSchedule TxScheduleFn // Transaction scheduler to inject a transaction into the pool
+}
+
+// SignerFn is a signer function callback when a contract requires a method to
+// sign the transaction before submission.
+type SignerFn func(common.Address, *types.Transaction) (*types.Transaction, error)
+
+// AuthOpts is the authorization data required to create a valid Ethereum transaction.
+type AuthOpts struct {
+ Account common.Address // Ethereum account to send the transaction from
+ Nonce *big.Int // Nonce to use for the transaction execution (nil = use pending state)
+ Signer SignerFn // Method to use for signing the transaction (mandatory)
+
+ Value *big.Int // Funds to transfer along along the transaction (nil = 0 = no funds)
+ GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle)
+ GasLimit *big.Int // Gas limit to set for the transaction execution (nil = estimate + 10%)
+}
+
+// BoundContract is the base wrapper object that reflects a contract on the
+// Ethereum network. It contains a collection of methods that are used by the
+// higher level contract bindings to operate.
+type BoundContract struct {
+ address common.Address // Deployment address of the contract on the Ethereum blockchain
+ abi ABI // Reflect based ABI to access the correct Ethereum methods
+
+ blockchain *core.BlockChain // Ethereum blockchain to use for state retrieval
+ options *ContractOpts // Options fine tuning contract behaviour
+ filters *filters.FilterSystem // Filter system to handle the contract events
+}
+
+// NewBoundContract initialises a new ABI and returns the contract. It does not
+// deploy the contract, hence the name.
+func NewBoundContract(address common.Address, abi ABI, blockchain *core.BlockChain, opts ContractOpts) *BoundContract {
+ // Initialize any needed values for the contract options
+ if opts.EventMux == nil {
+ opts.EventMux = new(event.TypeMux)
+ }
+ // Create and return the contract base
+ return &BoundContract{
+ address: address,
+ abi: abi,
+ blockchain: blockchain,
+ options: &opts,
+ filters: filters.NewFilterSystem(opts.EventMux),
+ }
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (c *BoundContract) Call(result interface{}, method string, params ...interface{}) error {
+ return c.abi.Call(c.execute, result, method, params...)
+}
+
+// execute runs the contract code for the given input value and returns the output.
+func (c *BoundContract) execute(input []byte) []byte {
+ state, _ := c.blockchain.State()
+
+ output, err := runtime.Call(c.address, input, &runtime.Config{
+ GetHashFn: core.GetHashFn(c.blockchain.CurrentBlock().ParentHash(), c.blockchain),
+ State: state,
+ })
+ if err != nil {
+ glog.V(logger.Warn).Infof("contract call failed: %v", err)
+ return nil
+ }
+ return output
+}
+
+// Transact invokes the (paid) contract method with params as input values and
+// value as the fund transfer to the contract.
+func (c *BoundContract) Transact(opts *AuthOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ // Pack up the method and arguments into an input data blob
+ input, err := c.abi.Pack(method, params...)
+ if err != nil {
+ return nil, err
+ }
+ // Ensure a valid value field and resolve the account nonce
+ value := opts.Value
+ if value == nil {
+ value = new(big.Int)
+ }
+ nonce := opts.Nonce
+ if nonce == nil {
+ if c.options.MinerState == nil {
+ return nil, errors.New("account nonce nil and no miner state retriever specified to estimate")
+ }
+ _, statedb := c.options.MinerState()
+ if statedb == nil {
+ return nil, errors.New("miner state retriever returned nil")
+ }
+ nonce = new(big.Int).SetUint64(statedb.GetNonce(opts.Account))
+ }
+ // Figure out the gas allowance and gas price values
+ gasPrice := opts.GasPrice
+ if gasPrice == nil {
+ if c.options.GasOracle == nil {
+ return nil, errors.New("gas price nil and no price oracle set")
+ }
+ if gasPrice = c.options.GasOracle(); gasPrice == nil {
+ return nil, errors.New("gas oracle suggested nil price")
+ }
+ }
+ gasLimit := opts.GasLimit
+ if gasLimit == nil {
+ limit, err := c.estimate(opts.Account, value, gasPrice, input)
+ if err != nil {
+ return nil, fmt.Errorf("gas estimation failed: %v", err)
+ }
+ if gasLimit = limit; gasLimit == nil {
+ return nil, errors.New("gas estimator suggested nil limit")
+ }
+ }
+ // Create the transaction, sign it and schedule it for execution
+ rawTx := types.NewTransaction(nonce.Uint64(), c.address, value, gasLimit, gasPrice, input)
+ if opts.Signer == nil {
+ return nil, errors.New("no signer to authorize the transaction with")
+ }
+ signedTx, err := opts.Signer(opts.Account, rawTx)
+ if err != nil {
+ return nil, err
+ }
+ if c.options.TxSchedule == nil {
+ return nil, errors.New("no transaction scheduler configured")
+ }
+ if err := c.options.TxSchedule(signedTx); err != nil {
+ return nil, err
+ }
+ return signedTx, nil
+}
+
+// estimate tries to calculate the approximate gas required by a transaction.
+func (c *BoundContract) estimate(sender common.Address, value, price *big.Int, input []byte) (*big.Int, error) {
+ // Create a copy of the current state db to screw around with
+ if c.options.MinerState == nil {
+ return nil, errors.New("no miner state retriever configured")
+ }
+ block, statedb := c.options.MinerState()
+ if block == nil || statedb == nil {
+ return nil, errors.New("pending miner state nil")
+ }
+ statedb = statedb.Copy()
+
+ // Set infinite balance to the sender account
+ from := statedb.GetOrNewStateObject(sender)
+ from.SetBalance(common.MaxBig)
+
+ // Assemble the call invocation to measure the gas usage
+ msg := callmsg{
+ from: from,
+ to: &c.address,
+ gasLimit: block.GasLimit(),
+ gasPrice: price,
+ value: value,
+ data: input,
+ }
+ // Execute the call and return
+ vmenv := core.NewEnv(statedb, c.blockchain, msg, block.Header())
+ gaspool := new(core.GasPool).AddGas(common.MaxBig)
+
+ _, gas, err := core.ApplyMessage(vmenv, msg, gaspool)
+ return gas, err
+}
+
+// callmsg implements core.Message to allow passing it as a transaction simulator.
+type callmsg struct {
+ from *state.StateObject
+ to *common.Address
+ gasLimit *big.Int
+ gasPrice *big.Int
+ value *big.Int
+ data []byte
+}
+
+func (m callmsg) From() (common.Address, error) { return m.from.Address(), nil }
+func (m callmsg) FromFrontier() (common.Address, error) { return m.from.Address(), nil }
+func (m callmsg) Nonce() uint64 { return m.from.Nonce() }
+func (m callmsg) To() *common.Address { return m.to }
+func (m callmsg) GasPrice() *big.Int { return m.gasPrice }
+func (m callmsg) Gas() *big.Int { return m.gasLimit }
+func (m callmsg) Value() *big.Int { return m.value }
+func (m callmsg) Data() []byte { return m.data }
diff --git a/accounts/abi/bind_test.go b/accounts/abi/bind_test.go
new file mode 100644
index 0000000000..1c6eec985a
--- /dev/null
+++ b/accounts/abi/bind_test.go
@@ -0,0 +1,23 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package abi
+
+/*
+// Tests that packages generated by the binder can be successfully compiled.
+func TestBindValidity(t *testing.T) {
+
+}*/
diff --git a/cmd/goabi/main.go b/cmd/goabi/main.go
new file mode 100644
index 0000000000..e1ce08fcf2
--- /dev/null
+++ b/cmd/goabi/main.go
@@ -0,0 +1,71 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+)
+
+var (
+ abiFlag = flag.String("abi", "", "Path to the Ethereum contract ABI json to bind")
+ pkgFlag = flag.String("pkg", "", "Go package name to generate the binding into")
+ typFlag = flag.String("type", "", "Go struct name for the binding (default = package name)")
+ outFlag = flag.String("out", "", "Output path for the generated binding")
+)
+
+func main() {
+ // Parse and validate the command line flags
+ flag.Parse()
+
+ if *abiFlag == "" {
+ fmt.Printf("No contract ABI path specified (--abi)\n")
+ os.Exit(-1)
+ }
+ if *pkgFlag == "" {
+ fmt.Printf("No destination Go package specified (--pkg)\n")
+ os.Exit(-1)
+ }
+ // Generate the contract binding
+ in, err := ioutil.ReadFile(*abiFlag)
+ if err != nil {
+ fmt.Printf("Failed to read input ABI: %v\n", err)
+ os.Exit(-1)
+ }
+ kind := *typFlag
+ if kind == "" {
+ kind = *pkgFlag
+ }
+ bind, err := abi.Bind(string(in), *pkgFlag, kind)
+ if err != nil {
+ fmt.Printf("Failed to generate ABI binding: %v\n", err)
+ os.Exit(-1)
+ }
+ // Either flush it out to a file or display on the standard output
+ if *outFlag == "" {
+ fmt.Printf("%s\n", bind)
+ return
+ }
+ if err := ioutil.WriteFile(*outFlag, []byte(bind), 0600); err != nil {
+ fmt.Printf("Failed to write ABI binding: %v\n", err)
+ os.Exit(-1)
+ }
+}