accounts/abi: accounts/abi/bind: Move topics to abi package (#21057)
* accounts/abi/bind: added test cases for waitDeployed * accounts/abi/bind: added test case for boundContract * accounts/abi/bind: removed unnecessary resolve methods * accounts/abi: moved topics from /bind to /abi * accounts/abi/bind: cleaned up format... functions * accounts/abi: improved log message * accounts/abi: added type tests * accounts/abi/bind: remove superfluous template methods
This commit is contained in:
parent
7b7e5921a4
commit
b8ea9042e5
@ -275,7 +275,7 @@ func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
|
|||||||
retval := make([]interface{}, 0, len(nonIndexedArgs))
|
retval := make([]interface{}, 0, len(nonIndexedArgs))
|
||||||
virtualArgs := 0
|
virtualArgs := 0
|
||||||
for index, arg := range nonIndexedArgs {
|
for index, arg := range nonIndexedArgs {
|
||||||
marshalledValue, err := ToGoType((index+virtualArgs)*32, arg.Type, data)
|
marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data)
|
||||||
if arg.Type.T == ArrayTy && !isDynamicType(arg.Type) {
|
if arg.Type.T == ArrayTy && !isDynamicType(arg.Type) {
|
||||||
// If we have a static array, like [3]uint256, these are coded as
|
// If we have a static array, like [3]uint256, these are coded as
|
||||||
// just like uint256,uint256,uint256.
|
// just like uint256,uint256,uint256.
|
||||||
@ -312,7 +312,7 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
|
|||||||
// Make sure arguments match up and pack them
|
// Make sure arguments match up and pack them
|
||||||
abiArgs := arguments
|
abiArgs := arguments
|
||||||
if len(args) != len(abiArgs) {
|
if len(args) != len(abiArgs) {
|
||||||
return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(abiArgs))
|
return nil, fmt.Errorf("argument count mismatch: got %d for %d", len(args), len(abiArgs))
|
||||||
}
|
}
|
||||||
// variable input is the output appended at the end of packed
|
// variable input is the output appended at the end of packed
|
||||||
// output. This is used for strings and bytes types input.
|
// output. This is used for strings and bytes types input.
|
||||||
|
@ -266,7 +266,7 @@ func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]int
|
|||||||
// Append the event selector to the query parameters and construct the topic set
|
// Append the event selector to the query parameters and construct the topic set
|
||||||
query = append([][]interface{}{{c.abi.Events[name].ID}}, query...)
|
query = append([][]interface{}{{c.abi.Events[name].ID}}, query...)
|
||||||
|
|
||||||
topics, err := makeTopics(query...)
|
topics, err := abi.MakeTopics(query...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -315,7 +315,7 @@ func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]inter
|
|||||||
// Append the event selector to the query parameters and construct the topic set
|
// Append the event selector to the query parameters and construct the topic set
|
||||||
query = append([][]interface{}{{c.abi.Events[name].ID}}, query...)
|
query = append([][]interface{}{{c.abi.Events[name].ID}}, query...)
|
||||||
|
|
||||||
topics, err := makeTopics(query...)
|
topics, err := abi.MakeTopics(query...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -349,7 +349,7 @@ func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log)
|
|||||||
indexed = append(indexed, arg)
|
indexed = append(indexed, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return parseTopics(out, indexed, log.Topics[1:])
|
return abi.ParseTopics(out, indexed, log.Topics[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnpackLogIntoMap unpacks a retrieved log into the provided map.
|
// UnpackLogIntoMap unpacks a retrieved log into the provided map.
|
||||||
@ -365,7 +365,7 @@ func (c *BoundContract) UnpackLogIntoMap(out map[string]interface{}, event strin
|
|||||||
indexed = append(indexed, arg)
|
indexed = append(indexed, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return parseTopicsIntoMap(out, indexed, log.Topics[1:])
|
return abi.ParseTopicsIntoMap(out, indexed, log.Topics[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensureContext is a helper method to ensure a context is not nil, even if the
|
// ensureContext is a helper method to ensure a context is not nil, even if the
|
||||||
|
@ -34,8 +34,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type mockCaller struct {
|
type mockCaller struct {
|
||||||
codeAtBlockNumber *big.Int
|
codeAtBlockNumber *big.Int
|
||||||
callContractBlockNumber *big.Int
|
callContractBlockNumber *big.Int
|
||||||
|
pendingCodeAtCalled bool
|
||||||
|
pendingCallContractCalled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *mockCaller) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) {
|
func (mc *mockCaller) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) {
|
||||||
@ -47,6 +49,16 @@ func (mc *mockCaller) CallContract(ctx context.Context, call ethereum.CallMsg, b
|
|||||||
mc.callContractBlockNumber = blockNumber
|
mc.callContractBlockNumber = blockNumber
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mc *mockCaller) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) {
|
||||||
|
mc.pendingCodeAtCalled = true
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *mockCaller) PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) {
|
||||||
|
mc.pendingCallContractCalled = true
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
func TestPassingBlockNumber(t *testing.T) {
|
func TestPassingBlockNumber(t *testing.T) {
|
||||||
|
|
||||||
mc := &mockCaller{}
|
mc := &mockCaller{}
|
||||||
@ -82,6 +94,16 @@ func TestPassingBlockNumber(t *testing.T) {
|
|||||||
if mc.codeAtBlockNumber != nil {
|
if mc.codeAtBlockNumber != nil {
|
||||||
t.Fatalf("CodeAt() was passed a block number when it should not have been")
|
t.Fatalf("CodeAt() was passed a block number when it should not have been")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bc.Call(&bind.CallOpts{BlockNumber: blockNumber, Pending: true}, &ret, "something")
|
||||||
|
|
||||||
|
if !mc.pendingCallContractCalled {
|
||||||
|
t.Fatalf("CallContract() was not passed the block number")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !mc.pendingCodeAtCalled {
|
||||||
|
t.Fatalf("CodeAt() was not passed the block number")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const hexData = "0x000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158"
|
const hexData = "0x000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158"
|
||||||
|
@ -220,8 +220,6 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
|||||||
"bindtype": bindType[lang],
|
"bindtype": bindType[lang],
|
||||||
"bindtopictype": bindTopicType[lang],
|
"bindtopictype": bindTopicType[lang],
|
||||||
"namedtype": namedType[lang],
|
"namedtype": namedType[lang],
|
||||||
"formatmethod": formatMethod,
|
|
||||||
"formatevent": formatEvent,
|
|
||||||
"capitalise": capitalise,
|
"capitalise": capitalise,
|
||||||
"decapitalise": decapitalise,
|
"decapitalise": decapitalise,
|
||||||
}
|
}
|
||||||
@ -537,9 +535,7 @@ var methodNormalizer = map[Lang]func(string) string{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// capitalise makes a camel-case string which starts with an upper case character.
|
// capitalise makes a camel-case string which starts with an upper case character.
|
||||||
func capitalise(input string) string {
|
var capitalise = abi.ToCamelCase
|
||||||
return abi.ToCamelCase(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
// decapitalise makes a camel-case string which starts with a lower case character.
|
// decapitalise makes a camel-case string which starts with a lower case character.
|
||||||
func decapitalise(input string) string {
|
func decapitalise(input string) string {
|
||||||
@ -588,74 +584,3 @@ func hasStruct(t abi.Type) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolveArgName converts a raw argument representation into a user friendly format.
|
|
||||||
func resolveArgName(arg abi.Argument, structs map[string]*tmplStruct) string {
|
|
||||||
var (
|
|
||||||
prefix string
|
|
||||||
embedded string
|
|
||||||
typ = &arg.Type
|
|
||||||
)
|
|
||||||
loop:
|
|
||||||
for {
|
|
||||||
switch typ.T {
|
|
||||||
case abi.SliceTy:
|
|
||||||
prefix += "[]"
|
|
||||||
case abi.ArrayTy:
|
|
||||||
prefix += fmt.Sprintf("[%d]", typ.Size)
|
|
||||||
default:
|
|
||||||
embedded = typ.TupleRawName + typ.String()
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
typ = typ.Elem
|
|
||||||
}
|
|
||||||
if s, exist := structs[embedded]; exist {
|
|
||||||
return prefix + s.Name
|
|
||||||
} else {
|
|
||||||
return arg.Type.String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// formatMethod transforms raw method representation into a user friendly one.
|
|
||||||
func formatMethod(method abi.Method, structs map[string]*tmplStruct) string {
|
|
||||||
inputs := make([]string, len(method.Inputs))
|
|
||||||
for i, input := range method.Inputs {
|
|
||||||
inputs[i] = fmt.Sprintf("%v %v", resolveArgName(input, structs), input.Name)
|
|
||||||
}
|
|
||||||
outputs := make([]string, len(method.Outputs))
|
|
||||||
for i, output := range method.Outputs {
|
|
||||||
outputs[i] = resolveArgName(output, structs)
|
|
||||||
if len(output.Name) > 0 {
|
|
||||||
outputs[i] += fmt.Sprintf(" %v", output.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Extract meaningful state mutability of solidity method.
|
|
||||||
// If it's default value, never print it.
|
|
||||||
state := method.StateMutability
|
|
||||||
if state == "nonpayable" {
|
|
||||||
state = ""
|
|
||||||
}
|
|
||||||
if state != "" {
|
|
||||||
state = state + " "
|
|
||||||
}
|
|
||||||
identity := fmt.Sprintf("function %v", method.RawName)
|
|
||||||
if method.Type == abi.Fallback {
|
|
||||||
identity = "fallback"
|
|
||||||
} else if method.Type == abi.Receive {
|
|
||||||
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.
|
|
||||||
func formatEvent(event abi.Event, structs map[string]*tmplStruct) string {
|
|
||||||
inputs := make([]string, len(event.Inputs))
|
|
||||||
for i, input := range event.Inputs {
|
|
||||||
if input.Indexed {
|
|
||||||
inputs[i] = fmt.Sprintf("%v indexed %v", resolveArgName(input, structs), input.Name)
|
|
||||||
} else {
|
|
||||||
inputs[i] = fmt.Sprintf("%v %v", resolveArgName(input, structs), input.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("event %v(%v)", event.RawName, strings.Join(inputs, ", "))
|
|
||||||
}
|
|
||||||
|
@ -297,7 +297,7 @@ var (
|
|||||||
{{range .Calls}}
|
{{range .Calls}}
|
||||||
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
|
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatmethod .Original $structs}}
|
// Solidity: {{.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Caller) {{.Normalized.Name}}(opts *bind.CallOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} },{{else}}{{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}}{{end}} error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}Caller) {{.Normalized.Name}}(opts *bind.CallOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} },{{else}}{{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}}{{end}} error) {
|
||||||
{{if .Structured}}ret := new(struct{
|
{{if .Structured}}ret := new(struct{
|
||||||
{{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}}
|
{{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}}
|
||||||
@ -316,14 +316,14 @@ var (
|
|||||||
|
|
||||||
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
|
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatmethod .Original $structs}}
|
// Solidity: {{.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Session) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} }, {{else}} {{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}} {{end}} error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}Session) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} }, {{else}} {{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}} {{end}} error) {
|
||||||
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.CallOpts {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.CallOpts {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
||||||
}
|
}
|
||||||
|
|
||||||
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
|
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatmethod .Original $structs}}
|
// Solidity: {{.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}CallerSession) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} }, {{else}} {{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}} {{end}} error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}CallerSession) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} }, {{else}} {{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}} {{end}} error) {
|
||||||
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.CallOpts {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.CallOpts {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
||||||
}
|
}
|
||||||
@ -332,21 +332,21 @@ var (
|
|||||||
{{range .Transacts}}
|
{{range .Transacts}}
|
||||||
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}.
|
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatmethod .Original $structs}}
|
// Solidity: {{.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Transactor) {{.Normalized.Name}}(opts *bind.TransactOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}Transactor) {{.Normalized.Name}}(opts *bind.TransactOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) {
|
||||||
return _{{$contract.Type}}.contract.Transact(opts, "{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
return _{{$contract.Type}}.contract.Transact(opts, "{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
||||||
}
|
}
|
||||||
|
|
||||||
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}.
|
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatmethod .Original $structs}}
|
// Solidity: {{.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Session) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}Session) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) {
|
||||||
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.TransactOpts {{range $i, $_ := .Normalized.Inputs}}, {{.Name}}{{end}})
|
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.TransactOpts {{range $i, $_ := .Normalized.Inputs}}, {{.Name}}{{end}})
|
||||||
}
|
}
|
||||||
|
|
||||||
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}.
|
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatmethod .Original $structs}}
|
// Solidity: {{.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) {
|
||||||
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.TransactOpts {{range $i, $_ := .Normalized.Inputs}}, {{.Name}}{{end}})
|
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.TransactOpts {{range $i, $_ := .Normalized.Inputs}}, {{.Name}}{{end}})
|
||||||
}
|
}
|
||||||
@ -355,21 +355,21 @@ var (
|
|||||||
{{if .Fallback}}
|
{{if .Fallback}}
|
||||||
// Fallback is a paid mutator transaction binding the contract fallback function.
|
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatmethod .Fallback.Original $structs}}
|
// Solidity: {{.Fallback.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Transactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}Transactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) {
|
||||||
return _{{$contract.Type}}.contract.RawTransact(opts, calldata)
|
return _{{$contract.Type}}.contract.RawTransact(opts, calldata)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback is a paid mutator transaction binding the contract fallback function.
|
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatmethod .Fallback.Original $structs}}
|
// Solidity: {{.Fallback.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Session) Fallback(calldata []byte) (*types.Transaction, error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}Session) Fallback(calldata []byte) (*types.Transaction, error) {
|
||||||
return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata)
|
return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback is a paid mutator transaction binding the contract fallback function.
|
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatmethod .Fallback.Original $structs}}
|
// Solidity: {{.Fallback.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Fallback(calldata []byte) (*types.Transaction, error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Fallback(calldata []byte) (*types.Transaction, error) {
|
||||||
return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata)
|
return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata)
|
||||||
}
|
}
|
||||||
@ -378,21 +378,21 @@ var (
|
|||||||
{{if .Receive}}
|
{{if .Receive}}
|
||||||
// Receive is a paid mutator transaction binding the contract receive function.
|
// Receive is a paid mutator transaction binding the contract receive function.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatmethod .Receive.Original $structs}}
|
// Solidity: {{.Receive.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Transactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) {
|
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
|
return _{{$contract.Type}}.contract.RawTransact(opts, nil) // calldata is disallowed for receive function
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receive is a paid mutator transaction binding the contract receive function.
|
// Receive is a paid mutator transaction binding the contract receive function.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatmethod .Receive.Original $structs}}
|
// Solidity: {{.Receive.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Session) Receive() (*types.Transaction, error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}Session) Receive() (*types.Transaction, error) {
|
||||||
return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts)
|
return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receive is a paid mutator transaction binding the contract receive function.
|
// Receive is a paid mutator transaction binding the contract receive function.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatmethod .Receive.Original $structs}}
|
// Solidity: {{.Receive.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Receive() (*types.Transaction, error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Receive() (*types.Transaction, error) {
|
||||||
return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts)
|
return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts)
|
||||||
}
|
}
|
||||||
@ -471,7 +471,7 @@ var (
|
|||||||
|
|
||||||
// Filter{{.Normalized.Name}} is a free log retrieval operation binding the contract event 0x{{printf "%x" .Original.ID}}.
|
// Filter{{.Normalized.Name}} is a free log retrieval operation binding the contract event 0x{{printf "%x" .Original.ID}}.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatevent .Original $structs}}
|
// Solidity: {{.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Filter{{.Normalized.Name}}(opts *bind.FilterOpts{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}} []{{bindtype .Type $structs}}{{end}}{{end}}) (*{{$contract.Type}}{{.Normalized.Name}}Iterator, error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Filter{{.Normalized.Name}}(opts *bind.FilterOpts{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}} []{{bindtype .Type $structs}}{{end}}{{end}}) (*{{$contract.Type}}{{.Normalized.Name}}Iterator, error) {
|
||||||
{{range .Normalized.Inputs}}
|
{{range .Normalized.Inputs}}
|
||||||
{{if .Indexed}}var {{.Name}}Rule []interface{}
|
{{if .Indexed}}var {{.Name}}Rule []interface{}
|
||||||
@ -488,7 +488,7 @@ var (
|
|||||||
|
|
||||||
// Watch{{.Normalized.Name}} is a free log subscription operation binding the contract event 0x{{printf "%x" .Original.ID}}.
|
// Watch{{.Normalized.Name}} is a free log subscription operation binding the contract event 0x{{printf "%x" .Original.ID}}.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatevent .Original $structs}}
|
// Solidity: {{.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Watch{{.Normalized.Name}}(opts *bind.WatchOpts, sink chan<- *{{$contract.Type}}{{.Normalized.Name}}{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}} []{{bindtype .Type $structs}}{{end}}{{end}}) (event.Subscription, error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Watch{{.Normalized.Name}}(opts *bind.WatchOpts, sink chan<- *{{$contract.Type}}{{.Normalized.Name}}{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}} []{{bindtype .Type $structs}}{{end}}{{end}}) (event.Subscription, error) {
|
||||||
{{range .Normalized.Inputs}}
|
{{range .Normalized.Inputs}}
|
||||||
{{if .Indexed}}var {{.Name}}Rule []interface{}
|
{{if .Indexed}}var {{.Name}}Rule []interface{}
|
||||||
@ -530,7 +530,7 @@ var (
|
|||||||
|
|
||||||
// Parse{{.Normalized.Name}} is a log parse operation binding the contract event 0x{{printf "%x" .Original.ID}}.
|
// Parse{{.Normalized.Name}} is a log parse operation binding the contract event 0x{{printf "%x" .Original.ID}}.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatevent .Original $structs}}
|
// Solidity: {{.Original.String}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Parse{{.Normalized.Name}}(log types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Parse{{.Normalized.Name}}(log types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
|
||||||
event := new({{$contract.Type}}{{.Normalized.Name}})
|
event := new({{$contract.Type}}{{.Normalized.Name}})
|
||||||
if err := _{{$contract.Type}}.contract.UnpackLog(event, "{{.Original.Name}}", log); err != nil {
|
if err := _{{$contract.Type}}.contract.UnpackLog(event, "{{.Original.Name}}", log); err != nil {
|
||||||
@ -662,7 +662,7 @@ import java.util.*;
|
|||||||
{{if .Fallback}}
|
{{if .Fallback}}
|
||||||
// Fallback is a paid mutator transaction binding the contract fallback function.
|
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatmethod .Fallback.Original $structs}}
|
// Solidity: {{.Fallback.Original.String}}
|
||||||
public Transaction Fallback(TransactOpts opts, byte[] calldata) throws Exception {
|
public Transaction Fallback(TransactOpts opts, byte[] calldata) throws Exception {
|
||||||
return this.Contract.rawTransact(opts, calldata);
|
return this.Contract.rawTransact(opts, calldata);
|
||||||
}
|
}
|
||||||
@ -671,7 +671,7 @@ import java.util.*;
|
|||||||
{{if .Receive}}
|
{{if .Receive}}
|
||||||
// Receive is a paid mutator transaction binding the contract receive function.
|
// Receive is a paid mutator transaction binding the contract receive function.
|
||||||
//
|
//
|
||||||
// Solidity: {{formatmethod .Receive.Original $structs}}
|
// Solidity: {{.Receive.Original.String}}
|
||||||
public Transaction Receive(TransactOpts opts) throws Exception {
|
public Transaction Receive(TransactOpts opts) throws Exception {
|
||||||
return this.Contract.rawTransact(opts, null);
|
return this.Contract.rawTransact(opts, null);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ package bind
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -56,14 +56,14 @@ func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*ty
|
|||||||
// contract address when it is mined. It stops waiting when ctx is canceled.
|
// contract address when it is mined. It stops waiting when ctx is canceled.
|
||||||
func WaitDeployed(ctx context.Context, b DeployBackend, tx *types.Transaction) (common.Address, error) {
|
func WaitDeployed(ctx context.Context, b DeployBackend, tx *types.Transaction) (common.Address, error) {
|
||||||
if tx.To() != nil {
|
if tx.To() != nil {
|
||||||
return common.Address{}, fmt.Errorf("tx is not contract creation")
|
return common.Address{}, errors.New("tx is not contract creation")
|
||||||
}
|
}
|
||||||
receipt, err := WaitMined(ctx, b, tx)
|
receipt, err := WaitMined(ctx, b, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Address{}, err
|
return common.Address{}, err
|
||||||
}
|
}
|
||||||
if receipt.ContractAddress == (common.Address{}) {
|
if receipt.ContractAddress == (common.Address{}) {
|
||||||
return common.Address{}, fmt.Errorf("zero address")
|
return common.Address{}, errors.New("zero address")
|
||||||
}
|
}
|
||||||
// Check that code has indeed been deployed at the address.
|
// Check that code has indeed been deployed at the address.
|
||||||
// This matters on pre-Homestead chains: OOG in the constructor
|
// This matters on pre-Homestead chains: OOG in the constructor
|
||||||
|
@ -18,6 +18,7 @@ package bind_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -84,7 +85,7 @@ func TestWaitDeployed(t *testing.T) {
|
|||||||
select {
|
select {
|
||||||
case <-mined:
|
case <-mined:
|
||||||
if err != test.wantErr {
|
if err != test.wantErr {
|
||||||
t.Errorf("test %q: error mismatch: got %q, want %q", name, err, test.wantErr)
|
t.Errorf("test %q: error mismatch: want %q, got %q", name, test.wantErr, err)
|
||||||
}
|
}
|
||||||
if address != test.wantAddress {
|
if address != test.wantAddress {
|
||||||
t.Errorf("test %q: unexpected contract address %s", name, address.Hex())
|
t.Errorf("test %q: unexpected contract address %s", name, address.Hex())
|
||||||
@ -94,3 +95,40 @@ func TestWaitDeployed(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWaitDeployedCornerCases(t *testing.T) {
|
||||||
|
backend := backends.NewSimulatedBackend(
|
||||||
|
core.GenesisAlloc{
|
||||||
|
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000)},
|
||||||
|
},
|
||||||
|
10000000,
|
||||||
|
)
|
||||||
|
defer backend.Close()
|
||||||
|
|
||||||
|
// Create a transaction to an account.
|
||||||
|
code := "6060604052600a8060106000396000f360606040526008565b00"
|
||||||
|
tx := types.NewTransaction(0, common.HexToAddress("0x01"), big.NewInt(0), 3000000, big.NewInt(1), common.FromHex(code))
|
||||||
|
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
backend.SendTransaction(ctx, tx)
|
||||||
|
backend.Commit()
|
||||||
|
notContentCreation := errors.New("tx is not contract creation")
|
||||||
|
if _, err := bind.WaitDeployed(ctx, backend, tx); err.Error() != notContentCreation.Error() {
|
||||||
|
t.Errorf("error missmatch: want %q, got %q, ", notContentCreation, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a transaction that is not mined.
|
||||||
|
tx = types.NewContractCreation(1, big.NewInt(0), 3000000, big.NewInt(1), common.FromHex(code))
|
||||||
|
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
contextCanceled := errors.New("context canceled")
|
||||||
|
if _, err := bind.WaitDeployed(ctx, backend, tx); err.Error() != contextCanceled.Error() {
|
||||||
|
t.Errorf("error missmatch: want %q, got %q, ", contextCanceled, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
backend.SendTransaction(ctx, tx)
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package bind
|
package abi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
@ -23,13 +23,12 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// makeTopics converts a filter query argument list into a filter topic set.
|
// MakeTopics converts a filter query argument list into a filter topic set.
|
||||||
func makeTopics(query ...[]interface{}) ([][]common.Hash, error) {
|
func MakeTopics(query ...[]interface{}) ([][]common.Hash, error) {
|
||||||
topics := make([][]common.Hash, len(query))
|
topics := make([][]common.Hash, len(query))
|
||||||
for i, filter := range query {
|
for i, filter := range query {
|
||||||
for _, rule := range filter {
|
for _, rule := range filter {
|
||||||
@ -112,19 +111,19 @@ func genIntType(rule int64, size uint) []byte {
|
|||||||
return topic[:]
|
return topic[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseTopics converts the indexed topic fields into actual log field values.
|
// ParseTopics converts the indexed topic fields into actual log field values.
|
||||||
func parseTopics(out interface{}, fields abi.Arguments, topics []common.Hash) error {
|
func ParseTopics(out interface{}, fields Arguments, topics []common.Hash) error {
|
||||||
return parseTopicWithSetter(fields, topics,
|
return parseTopicWithSetter(fields, topics,
|
||||||
func(arg abi.Argument, reconstr interface{}) {
|
func(arg Argument, reconstr interface{}) {
|
||||||
field := reflect.ValueOf(out).Elem().FieldByName(capitalise(arg.Name))
|
field := reflect.ValueOf(out).Elem().FieldByName(ToCamelCase(arg.Name))
|
||||||
field.Set(reflect.ValueOf(reconstr))
|
field.Set(reflect.ValueOf(reconstr))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseTopicsIntoMap converts the indexed topic field-value pairs into map key-value pairs
|
// ParseTopicsIntoMap converts the indexed topic field-value pairs into map key-value pairs
|
||||||
func parseTopicsIntoMap(out map[string]interface{}, fields abi.Arguments, topics []common.Hash) error {
|
func ParseTopicsIntoMap(out map[string]interface{}, fields Arguments, topics []common.Hash) error {
|
||||||
return parseTopicWithSetter(fields, topics,
|
return parseTopicWithSetter(fields, topics,
|
||||||
func(arg abi.Argument, reconstr interface{}) {
|
func(arg Argument, reconstr interface{}) {
|
||||||
out[arg.Name] = reconstr
|
out[arg.Name] = reconstr
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -134,7 +133,7 @@ func parseTopicsIntoMap(out map[string]interface{}, fields abi.Arguments, topics
|
|||||||
//
|
//
|
||||||
// Note, dynamic types cannot be reconstructed since they get mapped to Keccak256
|
// Note, dynamic types cannot be reconstructed since they get mapped to Keccak256
|
||||||
// hashes as the topic value!
|
// hashes as the topic value!
|
||||||
func parseTopicWithSetter(fields abi.Arguments, topics []common.Hash, setter func(abi.Argument, interface{})) error {
|
func parseTopicWithSetter(fields Arguments, topics []common.Hash, setter func(Argument, interface{})) error {
|
||||||
// Sanity check that the fields and topics match up
|
// Sanity check that the fields and topics match up
|
||||||
if len(fields) != len(topics) {
|
if len(fields) != len(topics) {
|
||||||
return errors.New("topic/field count mismatch")
|
return errors.New("topic/field count mismatch")
|
||||||
@ -146,13 +145,13 @@ func parseTopicWithSetter(fields abi.Arguments, topics []common.Hash, setter fun
|
|||||||
}
|
}
|
||||||
var reconstr interface{}
|
var reconstr interface{}
|
||||||
switch arg.Type.T {
|
switch arg.Type.T {
|
||||||
case abi.TupleTy:
|
case TupleTy:
|
||||||
return errors.New("tuple type in topic reconstruction")
|
return errors.New("tuple type in topic reconstruction")
|
||||||
case abi.StringTy, abi.BytesTy, abi.SliceTy, abi.ArrayTy:
|
case StringTy, BytesTy, SliceTy, ArrayTy:
|
||||||
// Array types (including strings and bytes) have their keccak256 hashes stored in the topic- not a hash
|
// Array types (including strings and bytes) have their keccak256 hashes stored in the topic- not a hash
|
||||||
// whose bytes can be decoded to the actual value- so the best we can do is retrieve that hash
|
// whose bytes can be decoded to the actual value- so the best we can do is retrieve that hash
|
||||||
reconstr = topics[i]
|
reconstr = topics[i]
|
||||||
case abi.FunctionTy:
|
case FunctionTy:
|
||||||
if garbage := binary.BigEndian.Uint64(topics[i][0:8]); garbage != 0 {
|
if garbage := binary.BigEndian.Uint64(topics[i][0:8]); garbage != 0 {
|
||||||
return fmt.Errorf("bind: got improperly encoded function type, got %v", topics[i].Bytes())
|
return fmt.Errorf("bind: got improperly encoded function type, got %v", topics[i].Bytes())
|
||||||
}
|
}
|
||||||
@ -161,7 +160,7 @@ func parseTopicWithSetter(fields abi.Arguments, topics []common.Hash, setter fun
|
|||||||
reconstr = tmp
|
reconstr = tmp
|
||||||
default:
|
default:
|
||||||
var err error
|
var err error
|
||||||
reconstr, err = abi.ToGoType(0, arg.Type, topics[i].Bytes())
|
reconstr, err = toGoType(0, arg.Type, topics[i].Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
@ -14,14 +14,13 @@
|
|||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package bind
|
package abi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
)
|
)
|
||||||
@ -119,7 +118,7 @@ func TestMakeTopics(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
got, err := makeTopics(tt.args.query...)
|
got, err := MakeTopics(tt.args.query...)
|
||||||
if (err != nil) != tt.wantErr {
|
if (err != nil) != tt.wantErr {
|
||||||
t.Errorf("makeTopics() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("makeTopics() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
return
|
return
|
||||||
@ -135,7 +134,7 @@ type args struct {
|
|||||||
createObj func() interface{}
|
createObj func() interface{}
|
||||||
resultObj func() interface{}
|
resultObj func() interface{}
|
||||||
resultMap func() map[string]interface{}
|
resultMap func() map[string]interface{}
|
||||||
fields abi.Arguments
|
fields Arguments
|
||||||
topics []common.Hash
|
topics []common.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,6 +148,14 @@ type int256Struct struct {
|
|||||||
Int256Value *big.Int
|
Int256Value *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type hashStruct struct {
|
||||||
|
HashValue common.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
type funcStruct struct {
|
||||||
|
FuncValue [24]byte
|
||||||
|
}
|
||||||
|
|
||||||
type topicTest struct {
|
type topicTest struct {
|
||||||
name string
|
name string
|
||||||
args args
|
args args
|
||||||
@ -156,10 +163,12 @@ type topicTest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setupTopicsTests() []topicTest {
|
func setupTopicsTests() []topicTest {
|
||||||
bytesType, _ := abi.NewType("bytes5", "", nil)
|
bytesType, _ := NewType("bytes5", "", nil)
|
||||||
int8Type, _ := abi.NewType("int8", "", nil)
|
int8Type, _ := NewType("int8", "", nil)
|
||||||
int256Type, _ := abi.NewType("int256", "", nil)
|
int256Type, _ := NewType("int256", "", nil)
|
||||||
tupleType, _ := abi.NewType("tuple(int256,int8)", "", nil)
|
tupleType, _ := NewType("tuple(int256,int8)", "", nil)
|
||||||
|
stringType, _ := NewType("string", "", nil)
|
||||||
|
funcType, _ := NewType("function", "", nil)
|
||||||
|
|
||||||
tests := []topicTest{
|
tests := []topicTest{
|
||||||
{
|
{
|
||||||
@ -170,7 +179,7 @@ func setupTopicsTests() []topicTest {
|
|||||||
resultMap: func() map[string]interface{} {
|
resultMap: func() map[string]interface{} {
|
||||||
return map[string]interface{}{"staticBytes": [5]byte{1, 2, 3, 4, 5}}
|
return map[string]interface{}{"staticBytes": [5]byte{1, 2, 3, 4, 5}}
|
||||||
},
|
},
|
||||||
fields: abi.Arguments{abi.Argument{
|
fields: Arguments{Argument{
|
||||||
Name: "staticBytes",
|
Name: "staticBytes",
|
||||||
Type: bytesType,
|
Type: bytesType,
|
||||||
Indexed: true,
|
Indexed: true,
|
||||||
@ -189,7 +198,7 @@ func setupTopicsTests() []topicTest {
|
|||||||
resultMap: func() map[string]interface{} {
|
resultMap: func() map[string]interface{} {
|
||||||
return map[string]interface{}{"int8Value": int8(-1)}
|
return map[string]interface{}{"int8Value": int8(-1)}
|
||||||
},
|
},
|
||||||
fields: abi.Arguments{abi.Argument{
|
fields: Arguments{Argument{
|
||||||
Name: "int8Value",
|
Name: "int8Value",
|
||||||
Type: int8Type,
|
Type: int8Type,
|
||||||
Indexed: true,
|
Indexed: true,
|
||||||
@ -209,7 +218,7 @@ func setupTopicsTests() []topicTest {
|
|||||||
resultMap: func() map[string]interface{} {
|
resultMap: func() map[string]interface{} {
|
||||||
return map[string]interface{}{"int256Value": big.NewInt(-1)}
|
return map[string]interface{}{"int256Value": big.NewInt(-1)}
|
||||||
},
|
},
|
||||||
fields: abi.Arguments{abi.Argument{
|
fields: Arguments{Argument{
|
||||||
Name: "int256Value",
|
Name: "int256Value",
|
||||||
Type: int256Type,
|
Type: int256Type,
|
||||||
Indexed: true,
|
Indexed: true,
|
||||||
@ -222,12 +231,55 @@ func setupTopicsTests() []topicTest {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tuple(int256, int8)",
|
name: "hash type",
|
||||||
|
args: args{
|
||||||
|
createObj: func() interface{} { return &hashStruct{} },
|
||||||
|
resultObj: func() interface{} { return &hashStruct{crypto.Keccak256Hash([]byte("stringtopic"))} },
|
||||||
|
resultMap: func() map[string]interface{} {
|
||||||
|
return map[string]interface{}{"hashValue": crypto.Keccak256Hash([]byte("stringtopic"))}
|
||||||
|
},
|
||||||
|
fields: Arguments{Argument{
|
||||||
|
Name: "hashValue",
|
||||||
|
Type: stringType,
|
||||||
|
Indexed: true,
|
||||||
|
}},
|
||||||
|
topics: []common.Hash{
|
||||||
|
crypto.Keccak256Hash([]byte("stringtopic")),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "function type",
|
||||||
|
args: args{
|
||||||
|
createObj: func() interface{} { return &funcStruct{} },
|
||||||
|
resultObj: func() interface{} {
|
||||||
|
return &funcStruct{[24]byte{255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}}
|
||||||
|
},
|
||||||
|
resultMap: func() map[string]interface{} {
|
||||||
|
return map[string]interface{}{"funcValue": [24]byte{255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}}
|
||||||
|
},
|
||||||
|
fields: Arguments{Argument{
|
||||||
|
Name: "funcValue",
|
||||||
|
Type: funcType,
|
||||||
|
Indexed: true,
|
||||||
|
}},
|
||||||
|
topics: []common.Hash{
|
||||||
|
{0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "error on topic/field count mismatch",
|
||||||
args: args{
|
args: args{
|
||||||
createObj: func() interface{} { return nil },
|
createObj: func() interface{} { return nil },
|
||||||
resultObj: func() interface{} { return nil },
|
resultObj: func() interface{} { return nil },
|
||||||
resultMap: func() map[string]interface{} { return make(map[string]interface{}) },
|
resultMap: func() map[string]interface{} { return make(map[string]interface{}) },
|
||||||
fields: abi.Arguments{abi.Argument{
|
fields: Arguments{Argument{
|
||||||
Name: "tupletype",
|
Name: "tupletype",
|
||||||
Type: tupleType,
|
Type: tupleType,
|
||||||
Indexed: true,
|
Indexed: true,
|
||||||
@ -236,6 +288,59 @@ func setupTopicsTests() []topicTest {
|
|||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "error on unindexed arguments",
|
||||||
|
args: args{
|
||||||
|
createObj: func() interface{} { return &int256Struct{} },
|
||||||
|
resultObj: func() interface{} { return &int256Struct{} },
|
||||||
|
resultMap: func() map[string]interface{} { return make(map[string]interface{}) },
|
||||||
|
fields: Arguments{Argument{
|
||||||
|
Name: "int256Value",
|
||||||
|
Type: int256Type,
|
||||||
|
Indexed: false,
|
||||||
|
}},
|
||||||
|
topics: []common.Hash{
|
||||||
|
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "error on tuple in topic reconstruction",
|
||||||
|
args: args{
|
||||||
|
createObj: func() interface{} { return &tupleType },
|
||||||
|
resultObj: func() interface{} { return &tupleType },
|
||||||
|
resultMap: func() map[string]interface{} { return make(map[string]interface{}) },
|
||||||
|
fields: Arguments{Argument{
|
||||||
|
Name: "tupletype",
|
||||||
|
Type: tupleType,
|
||||||
|
Indexed: true,
|
||||||
|
}},
|
||||||
|
topics: []common.Hash{{0}},
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "error on improper encoded function",
|
||||||
|
args: args{
|
||||||
|
createObj: func() interface{} { return &funcStruct{} },
|
||||||
|
resultObj: func() interface{} { return &funcStruct{} },
|
||||||
|
resultMap: func() map[string]interface{} {
|
||||||
|
return make(map[string]interface{})
|
||||||
|
},
|
||||||
|
fields: Arguments{Argument{
|
||||||
|
Name: "funcValue",
|
||||||
|
Type: funcType,
|
||||||
|
Indexed: true,
|
||||||
|
}},
|
||||||
|
topics: []common.Hash{
|
||||||
|
{0, 0, 0, 0, 0, 0, 0, 128, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return tests
|
return tests
|
||||||
@ -247,7 +352,7 @@ func TestParseTopics(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
createObj := tt.args.createObj()
|
createObj := tt.args.createObj()
|
||||||
if err := parseTopics(createObj, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr {
|
if err := ParseTopics(createObj, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr {
|
||||||
t.Errorf("parseTopics() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("parseTopics() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
}
|
}
|
||||||
resultObj := tt.args.resultObj()
|
resultObj := tt.args.resultObj()
|
||||||
@ -264,7 +369,7 @@ func TestParseTopicsIntoMap(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
outMap := make(map[string]interface{})
|
outMap := make(map[string]interface{})
|
||||||
if err := parseTopicsIntoMap(outMap, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr {
|
if err := ParseTopicsIntoMap(outMap, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr {
|
||||||
t.Errorf("parseTopicsIntoMap() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("parseTopicsIntoMap() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
}
|
}
|
||||||
resultMap := tt.args.resultMap()
|
resultMap := tt.args.resultMap()
|
@ -144,7 +144,7 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
|
|||||||
elemSize := getTypeSize(*t.Elem)
|
elemSize := getTypeSize(*t.Elem)
|
||||||
|
|
||||||
for i, j := start, 0; j < size; i, j = i+elemSize, j+1 {
|
for i, j := start, 0; j < size; i, j = i+elemSize, j+1 {
|
||||||
inter, err := ToGoType(i, *t.Elem, output)
|
inter, err := toGoType(i, *t.Elem, output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ func forTupleUnpack(t Type, output []byte) (interface{}, error) {
|
|||||||
retval := reflect.New(t.getType()).Elem()
|
retval := reflect.New(t.getType()).Elem()
|
||||||
virtualArgs := 0
|
virtualArgs := 0
|
||||||
for index, elem := range t.TupleElems {
|
for index, elem := range t.TupleElems {
|
||||||
marshalledValue, err := ToGoType((index+virtualArgs)*32, *elem, output)
|
marshalledValue, err := toGoType((index+virtualArgs)*32, *elem, output)
|
||||||
if elem.T == ArrayTy && !isDynamicType(*elem) {
|
if elem.T == ArrayTy && !isDynamicType(*elem) {
|
||||||
// If we have a static array, like [3]uint256, these are coded as
|
// If we have a static array, like [3]uint256, these are coded as
|
||||||
// just like uint256,uint256,uint256.
|
// just like uint256,uint256,uint256.
|
||||||
@ -187,9 +187,9 @@ func forTupleUnpack(t Type, output []byte) (interface{}, error) {
|
|||||||
return retval.Interface(), nil
|
return retval.Interface(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToGoType parses the output bytes and recursively assigns the value of these bytes
|
// toGoType parses the output bytes and recursively assigns the value of these bytes
|
||||||
// into a go type with accordance with the ABI spec.
|
// into a go type with accordance with the ABI spec.
|
||||||
func ToGoType(index int, t Type, output []byte) (interface{}, error) {
|
func toGoType(index int, t Type, output []byte) (interface{}, error) {
|
||||||
if index+32 > len(output) {
|
if index+32 > len(output) {
|
||||||
return nil, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %d require %d", len(output), index+32)
|
return nil, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %d require %d", len(output), index+32)
|
||||||
}
|
}
|
||||||
@ -218,9 +218,8 @@ func ToGoType(index int, t Type, output []byte) (interface{}, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return forTupleUnpack(t, output[begin:])
|
return forTupleUnpack(t, output[begin:])
|
||||||
} else {
|
|
||||||
return forTupleUnpack(t, output[index:])
|
|
||||||
}
|
}
|
||||||
|
return forTupleUnpack(t, output[index:])
|
||||||
case SliceTy:
|
case SliceTy:
|
||||||
return forEachUnpack(t, output[begin:], 0, length)
|
return forEachUnpack(t, output[begin:], 0, length)
|
||||||
case ArrayTy:
|
case ArrayTy:
|
||||||
|
Loading…
Reference in New Issue
Block a user