aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgary rong <garyrong0905@gmail.com>2019-08-02 15:20:46 +0800
committerMartin Holst Swende <martin@swende.se>2019-08-02 15:20:46 +0800
commit947f5f2b152e18dfab2bec72c99ef76e1d851764 (patch)
tree7656fcf2546bf6955003472af4dc9c60949ae7ff
parente46a01d56c190badd6b71a4fba6c886fcee1059b (diff)
downloadgo-tangerine-947f5f2b152e18dfab2bec72c99ef76e1d851764.tar
go-tangerine-947f5f2b152e18dfab2bec72c99ef76e1d851764.tar.gz
go-tangerine-947f5f2b152e18dfab2bec72c99ef76e1d851764.tar.bz2
go-tangerine-947f5f2b152e18dfab2bec72c99ef76e1d851764.tar.lz
go-tangerine-947f5f2b152e18dfab2bec72c99ef76e1d851764.tar.xz
go-tangerine-947f5f2b152e18dfab2bec72c99ef76e1d851764.tar.zst
go-tangerine-947f5f2b152e18dfab2bec72c99ef76e1d851764.zip
accounts/abi, signer/fourbyte: fix incorrect signature (#19881)
The abi package already supports function overload by adding a suffix to the overloaded function name, but it uses the function name with suffix to calculate signature(both for the event and method). This PR fixes it by adding a new field named RawName, which can be used to calcuate all signatures but use Name to distinguish different overloaded function.
-rw-r--r--accounts/abi/abi.go10
-rw-r--r--accounts/abi/abi_test.go47
-rw-r--r--accounts/abi/bind/base.go4
-rw-r--r--accounts/abi/bind/bind.go4
-rw-r--r--accounts/abi/bind/bind_test.go93
-rw-r--r--accounts/abi/bind/template.go22
-rw-r--r--accounts/abi/event.go38
-rw-r--r--accounts/abi/event_test.go4
-rw-r--r--accounts/abi/method.go23
-rw-r--r--accounts/abi/pack_test.go14
-rw-r--r--signer/fourbyte/abi.go2
11 files changed, 204 insertions, 57 deletions
diff --git a/accounts/abi/abi.go b/accounts/abi/abi.go
index 97a3a98bd..7831a5ed3 100644
--- a/accounts/abi/abi.go
+++ b/accounts/abi/abi.go
@@ -70,7 +70,7 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
return nil, err
}
// Pack up the method ID too if not a constructor and return
- return append(method.Id(), arguments...), nil
+ return append(method.ID(), arguments...), nil
}
// Unpack output in v according to the abi specification
@@ -121,11 +121,9 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
Inputs []Argument
Outputs []Argument
}
-
if err := json.Unmarshal(data, &fields); err != nil {
return err
}
-
abi.Methods = make(map[string]Method)
abi.Events = make(map[string]Event)
for _, field := range fields {
@@ -144,6 +142,7 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
}
abi.Methods[name] = Method{
Name: name,
+ RawName: field.Name,
Const: field.Constant,
Inputs: field.Inputs,
Outputs: field.Outputs,
@@ -157,6 +156,7 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
}
abi.Events[name] = Event{
Name: name,
+ RawName: field.Name,
Anonymous: field.Anonymous,
Inputs: field.Inputs,
}
@@ -173,7 +173,7 @@ func (abi *ABI) MethodById(sigdata []byte) (*Method, error) {
return nil, fmt.Errorf("data too short (%d bytes) for abi method lookup", len(sigdata))
}
for _, method := range abi.Methods {
- if bytes.Equal(method.Id(), sigdata[:4]) {
+ if bytes.Equal(method.ID(), sigdata[:4]) {
return &method, nil
}
}
@@ -184,7 +184,7 @@ func (abi *ABI) MethodById(sigdata []byte) (*Method, error) {
// ABI and returns nil if none found.
func (abi *ABI) EventByID(topic common.Hash) (*Event, error) {
for _, event := range abi.Events {
- if bytes.Equal(event.Id().Bytes(), topic.Bytes()) {
+ if bytes.Equal(event.ID().Bytes(), topic.Bytes()) {
return &event, nil
}
}
diff --git a/accounts/abi/abi_test.go b/accounts/abi/abi_test.go
index 09d3c94a0..7a795e052 100644
--- a/accounts/abi/abi_test.go
+++ b/accounts/abi/abi_test.go
@@ -61,10 +61,10 @@ func TestReader(t *testing.T) {
exp := ABI{
Methods: map[string]Method{
"balance": {
- "balance", true, nil, nil,
+ "balance", "balance", true, nil, nil,
},
"send": {
- "send", false, []Argument{
+ "send", "send", false, []Argument{
{"amount", Uint256, false},
}, nil,
},
@@ -162,12 +162,10 @@ func TestTestSlice(t *testing.T) {
if err != nil {
t.Fatal(err)
}
-
slice := make([]uint64, 2)
if _, err := abi.Pack("uint64[2]", slice); err != nil {
t.Error(err)
}
-
if _, err := abi.Pack("uint64[]", slice); err != nil {
t.Error(err)
}
@@ -175,19 +173,19 @@ func TestTestSlice(t *testing.T) {
func TestMethodSignature(t *testing.T) {
String, _ := NewType("string", nil)
- m := Method{"foo", false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil}
+ m := Method{"foo", "foo", false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil}
exp := "foo(string,string)"
if m.Sig() != exp {
t.Error("signature mismatch", exp, "!=", m.Sig())
}
idexp := crypto.Keccak256([]byte(exp))[:4]
- if !bytes.Equal(m.Id(), idexp) {
- t.Errorf("expected ids to match %x != %x", m.Id(), idexp)
+ if !bytes.Equal(m.ID(), idexp) {
+ t.Errorf("expected ids to match %x != %x", m.ID(), idexp)
}
uintt, _ := NewType("uint256", nil)
- m = Method{"foo", false, []Argument{{"bar", uintt, false}}, nil}
+ m = Method{"foo", "foo", false, []Argument{{"bar", uintt, false}}, nil}
exp = "foo(uint256)"
if m.Sig() != exp {
t.Error("signature mismatch", exp, "!=", m.Sig())
@@ -206,13 +204,36 @@ func TestMethodSignature(t *testing.T) {
{Name: "y", Type: "int256"},
}},
})
- m = Method{"foo", false, []Argument{{"s", s, false}, {"bar", String, false}}, nil}
+ m = Method{"foo", "foo", false, []Argument{{"s", s, false}, {"bar", String, false}}, nil}
exp = "foo((int256,int256[],(int256,int256)[],(int256,int256)[2]),string)"
if m.Sig() != exp {
t.Error("signature mismatch", exp, "!=", m.Sig())
}
}
+func TestOverloadedMethodSignature(t *testing.T) {
+ json := `[{"constant":true,"inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"i","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"}],"name":"bar","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"},{"indexed":false,"name":"j","type":"uint256"}],"name":"bar","type":"event"}]`
+ abi, err := JSON(strings.NewReader(json))
+ if err != nil {
+ t.Fatal(err)
+ }
+ check := func(name string, expect string, method bool) {
+ if method {
+ if abi.Methods[name].Sig() != expect {
+ t.Fatalf("The signature of overloaded method mismatch, want %s, have %s", expect, abi.Methods[name].Sig())
+ }
+ } else {
+ if abi.Events[name].Sig() != expect {
+ t.Fatalf("The signature of overloaded event mismatch, want %s, have %s", expect, abi.Events[name].Sig())
+ }
+ }
+ }
+ check("foo", "foo(uint256,uint256)", true)
+ check("foo0", "foo(uint256)", true)
+ check("bar", "bar(uint256)", false)
+ check("bar0", "bar(uint256,uint256)", false)
+}
+
func TestMultiPack(t *testing.T) {
abi, err := JSON(strings.NewReader(jsondata2))
if err != nil {
@@ -900,13 +921,13 @@ func TestABI_MethodById(t *testing.T) {
}
for name, m := range abi.Methods {
a := fmt.Sprintf("%v", m)
- m2, err := abi.MethodById(m.Id())
+ m2, err := abi.MethodById(m.ID())
if err != nil {
t.Fatalf("Failed to look up ABI method: %v", err)
}
b := fmt.Sprintf("%v", m2)
if a != b {
- t.Errorf("Method %v (id %v) not 'findable' by id in ABI", name, common.ToHex(m.Id()))
+ t.Errorf("Method %v (id %v) not 'findable' by id in ABI", name, common.ToHex(m.ID()))
}
}
// Also test empty
@@ -974,8 +995,8 @@ func TestABI_EventById(t *testing.T) {
t.Errorf("We should find a event for topic %s, test #%d", topicID.Hex(), testnum)
}
- if event.Id() != topicID {
- t.Errorf("Event id %s does not match topic %s, test #%d", event.Id().Hex(), topicID.Hex(), testnum)
+ if event.ID() != topicID {
+ t.Errorf("Event id %s does not match topic %s, test #%d", event.ID().Hex(), topicID.Hex(), testnum)
}
unknowntopicID := crypto.Keccak256Hash([]byte("unknownEvent"))
diff --git a/accounts/abi/bind/base.go b/accounts/abi/bind/base.go
index f70f911d3..f74a0af21 100644
--- a/accounts/abi/bind/base.go
+++ b/accounts/abi/bind/base.go
@@ -252,7 +252,7 @@ func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]int
opts = new(FilterOpts)
}
// 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...)
if err != nil {
@@ -301,7 +301,7 @@ func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]inter
opts = new(WatchOpts)
}
// 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...)
if err != nil {
diff --git a/accounts/abi/bind/bind.go b/accounts/abi/bind/bind.go
index cd8c942b5..dc51e2a7e 100644
--- a/accounts/abi/bind/bind.go
+++ b/accounts/abi/bind/bind.go
@@ -541,7 +541,7 @@ func formatMethod(method abi.Method, structs map[string]*tmplStruct) string {
if method.Const {
constant = "constant "
}
- return fmt.Sprintf("function %v(%v) %sreturns(%v)", method.Name, strings.Join(inputs, ", "), constant, strings.Join(outputs, ", "))
+ return fmt.Sprintf("function %v(%v) %sreturns(%v)", method.RawName, strings.Join(inputs, ", "), constant, strings.Join(outputs, ", "))
}
// formatEvent transforms raw event representation into a user friendly one.
@@ -554,5 +554,5 @@ func formatEvent(event abi.Event, structs map[string]*tmplStruct) string {
inputs[i] = fmt.Sprintf("%v %v", resolveArgName(input, structs), input.Name)
}
}
- return fmt.Sprintf("event %v(%v)", event.Name, strings.Join(inputs, ", "))
+ return fmt.Sprintf("event %v(%v)", event.RawName, strings.Join(inputs, ", "))
}
diff --git a/accounts/abi/bind/bind_test.go b/accounts/abi/bind/bind_test.go
index 5588b2431..7dca3547c 100644
--- a/accounts/abi/bind/bind_test.go
+++ b/accounts/abi/bind/bind_test.go
@@ -1280,6 +1280,99 @@ var bindTests = []struct {
"b98c933f0a6ececcd167bd4f9d3299b1a0": "Math",
},
[]string{"UseLibrary", "Math"},
+ }, {
+ "Overload",
+ `
+ pragma solidity ^0.5.10;
+
+ contract overload {
+ mapping(address => uint256) balances;
+
+ event bar(uint256 i);
+ event bar(uint256 i, uint256 j);
+
+ function foo(uint256 i) public {
+ emit bar(i);
+ }
+ function foo(uint256 i, uint256 j) public {
+ emit bar(i, j);
+ }
+ }
+ `,
+ []string{`608060405234801561001057600080fd5b50610153806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806304bc52f81461003b5780632fbebd3814610073575b600080fd5b6100716004803603604081101561005157600080fd5b8101908080359060200190929190803590602001909291905050506100a1565b005b61009f6004803603602081101561008957600080fd5b81019080803590602001909291905050506100e4565b005b7fae42e9514233792a47a1e4554624e83fe852228e1503f63cd383e8a431f4f46d8282604051808381526020018281526020019250505060405180910390a15050565b7f0423a1321222a0a8716c22b92fac42d85a45a612b696a461784d9fa537c81e5c816040518082815260200191505060405180910390a15056fea265627a7a72305820e22b049858b33291cbe67eeaece0c5f64333e439d27032ea8337d08b1de18fe864736f6c634300050a0032`},
+ []string{`[{"constant":false,"inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"i","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"}],"name":"bar","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"},{"indexed":false,"name":"j","type":"uint256"}],"name":"bar","type":"event"}]`},
+ `
+ "math/big"
+ "time"
+
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/crypto"
+ `,
+ `
+ // Initialize test accounts
+ key, _ := crypto.GenerateKey()
+ auth := bind.NewKeyedTransactor(key)
+ sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000)
+ defer sim.Close()
+
+ // deploy the test contract
+ _, _, contract, err := DeployOverload(auth, sim)
+ if err != nil {
+ t.Fatalf("Failed to deploy contract: %v", err)
+ }
+ // Finish deploy.
+ sim.Commit()
+
+ resCh, stopCh := make(chan uint64), make(chan struct{})
+
+ go func() {
+ barSink := make(chan *OverloadBar)
+ sub, _ := contract.WatchBar(nil, barSink)
+ defer sub.Unsubscribe()
+
+ bar0Sink := make(chan *OverloadBar0)
+ sub0, _ := contract.WatchBar0(nil, bar0Sink)
+ defer sub0.Unsubscribe()
+
+ for {
+ select {
+ case ev := <-barSink:
+ resCh <- ev.I.Uint64()
+ case ev := <-bar0Sink:
+ resCh <- ev.I.Uint64() + ev.J.Uint64()
+ case <-stopCh:
+ return
+ }
+ }
+ }()
+ contract.Foo(auth, big.NewInt(1), big.NewInt(2))
+ sim.Commit()
+ select {
+ case n := <-resCh:
+ if n != 3 {
+ t.Fatalf("Invalid bar0 event")
+ }
+ case <-time.NewTimer(100 * time.Millisecond).C:
+ t.Fatalf("Wait bar0 event timeout")
+ }
+
+ contract.Foo0(auth, big.NewInt(1))
+ sim.Commit()
+ select {
+ case n := <-resCh:
+ if n != 1 {
+ t.Fatalf("Invalid bar event")
+ }
+ case <-time.NewTimer(100 * time.Millisecond).C:
+ t.Fatalf("Wait bar event timeout")
+ }
+ close(stopCh)
+ `,
+ nil,
+ nil,
+ nil,
},
}
diff --git a/accounts/abi/bind/template.go b/accounts/abi/bind/template.go
index 3683a1eb4..4ec65474b 100644
--- a/accounts/abi/bind/template.go
+++ b/accounts/abi/bind/template.go
@@ -294,7 +294,7 @@ var (
{{end}}
{{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}}
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) {
@@ -313,14 +313,14 @@ var (
return {{if .Structured}}*ret,{{else}}{{range $i, $_ := .Normalized.Outputs}}*ret{{$i}},{{end}}{{end}} err
}
- // {{.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}}
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}})
}
- // {{.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}}
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) {
@@ -329,21 +329,21 @@ var (
{{end}}
{{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}}
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}})
}
- // {{.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}}
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}})
}
- // {{.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}}
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) {
@@ -422,7 +422,7 @@ var (
Raw types.Log // Blockchain specific contextual infos
}
- // 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}}
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) {
@@ -439,7 +439,7 @@ var (
return &{{$contract.Type}}{{.Normalized.Name}}Iterator{contract: _{{$contract.Type}}.contract, event: "{{.Original.Name}}", logs: logs, sub: sub}, nil
}
- // 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}}
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) {
@@ -481,7 +481,7 @@ var (
}), nil
}
- // 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: {{.Original.String}}
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Parse{{.Normalized.Name}}(log types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
@@ -574,7 +574,7 @@ import java.util.*;
}
{{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: {{.Original.String}}
public {{if gt (len .Normalized.Outputs) 1}}{{capitalise .Normalized.Name}}Results{{else}}{{range .Normalized.Outputs}}{{bindtype .Type $structs}}{{end}}{{end}} {{.Normalized.Name}}(CallOpts opts{{range .Normalized.Inputs}}, {{bindtype .Type $structs}} {{.Name}}{{end}}) throws Exception {
@@ -601,7 +601,7 @@ import java.util.*;
{{end}}
{{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: {{.Original.String}}
public Transaction {{.Normalized.Name}}(TransactOpts opts{{range .Normalized.Inputs}}, {{bindtype .Type $structs}} {{.Name}}{{end}}) throws Exception {
diff --git a/accounts/abi/event.go b/accounts/abi/event.go
index 9392c1990..f1474813a 100644
--- a/accounts/abi/event.go
+++ b/accounts/abi/event.go
@@ -28,7 +28,18 @@ import (
// holds type information (inputs) about the yielded output. Anonymous events
// don't get the signature canonical representation as the first LOG topic.
type Event struct {
- Name string
+ // Name is the event name used for internal representation. It's derived from
+ // the raw name and a suffix will be added in the case of a event overload.
+ //
+ // e.g.
+ // There are two events have same name:
+ // * foo(int,int)
+ // * foo(uint,uint)
+ // The event name of the first one wll be resolved as foo while the second one
+ // will be resolved as foo0.
+ Name string
+ // RawName is the raw event name parsed from ABI.
+ RawName string
Anonymous bool
Inputs Arguments
}
@@ -41,17 +52,26 @@ func (e Event) String() string {
inputs[i] = fmt.Sprintf("%v indexed %v", input.Type, input.Name)
}
}
- return fmt.Sprintf("event %v(%v)", e.Name, strings.Join(inputs, ", "))
+ return fmt.Sprintf("event %v(%v)", e.RawName, strings.Join(inputs, ", "))
}
-// Id returns the canonical representation of the event's signature used by the
-// abi definition to identify event names and types.
-func (e Event) Id() common.Hash {
+// Sig returns the event string signature according to the ABI spec.
+//
+// Example
+//
+// event foo(uint32 a, int b) = "foo(uint32,int256)"
+//
+// Please note that "int" is substitute for its canonical representation "int256"
+func (e Event) Sig() string {
types := make([]string, len(e.Inputs))
- i := 0
- for _, input := range e.Inputs {
+ for i, input := range e.Inputs {
types[i] = input.Type.String()
- i++
}
- return common.BytesToHash(crypto.Keccak256([]byte(fmt.Sprintf("%v(%v)", e.Name, strings.Join(types, ",")))))
+ return fmt.Sprintf("%v(%v)", e.RawName, strings.Join(types, ","))
+}
+
+// ID returns the canonical representation of the event's signature used by the
+// abi definition to identify event names and types.
+func (e Event) ID() common.Hash {
+ return common.BytesToHash(crypto.Keccak256([]byte(e.Sig())))
}
diff --git a/accounts/abi/event_test.go b/accounts/abi/event_test.go
index e735cceb8..792e26762 100644
--- a/accounts/abi/event_test.go
+++ b/accounts/abi/event_test.go
@@ -104,8 +104,8 @@ func TestEventId(t *testing.T) {
}
for name, event := range abi.Events {
- if event.Id() != test.expectations[name] {
- t.Errorf("expected id to be %x, got %x", test.expectations[name], event.Id())
+ if event.ID() != test.expectations[name] {
+ t.Errorf("expected id to be %x, got %x", test.expectations[name], event.ID())
}
}
}
diff --git a/accounts/abi/method.go b/accounts/abi/method.go
index d3c02599f..7da2e18fc 100644
--- a/accounts/abi/method.go
+++ b/accounts/abi/method.go
@@ -32,7 +32,18 @@ import (
// be flagged `false`.
// Input specifies the required input parameters for this gives method.
type Method struct {
- Name string
+ // Name is the method name used for internal representation. It's derived from
+ // the raw name and a suffix will be added in the case of a function overload.
+ //
+ // e.g.
+ // There are two functions have same name:
+ // * foo(int,int)
+ // * foo(uint,uint)
+ // The method name of the first one will be resolved as foo while the second one
+ // will be resolved as foo0.
+ Name string
+ // RawName is the raw method name parsed from ABI.
+ RawName string
Const bool
Inputs Arguments
Outputs Arguments
@@ -42,7 +53,7 @@ type Method struct {
//
// Example
//
-// function foo(uint32 a, int b) = "foo(uint32,int256)"
+// function foo(uint32 a, int b) = "foo(uint32,int256)"
//
// Please note that "int" is substitute for its canonical representation "int256"
func (method Method) Sig() string {
@@ -50,7 +61,7 @@ func (method Method) Sig() string {
for i, input := range method.Inputs {
types[i] = input.Type.String()
}
- return fmt.Sprintf("%v(%v)", method.Name, strings.Join(types, ","))
+ return fmt.Sprintf("%v(%v)", method.RawName, strings.Join(types, ","))
}
func (method Method) String() string {
@@ -69,9 +80,11 @@ func (method Method) String() string {
if method.Const {
constant = "constant "
}
- return fmt.Sprintf("function %v(%v) %sreturns(%v)", method.Name, strings.Join(inputs, ", "), constant, strings.Join(outputs, ", "))
+ return fmt.Sprintf("function %v(%v) %sreturns(%v)", method.RawName, strings.Join(inputs, ", "), constant, strings.Join(outputs, ", "))
}
-func (method Method) Id() []byte {
+// ID returns the canonical representation of the method's signature used by the
+// abi definition to identify method names and types.
+func (method Method) ID() []byte {
return crypto.Keccak256([]byte(method.Sig()))[:4]
}
diff --git a/accounts/abi/pack_test.go b/accounts/abi/pack_test.go
index 10cd3a396..f43e39056 100644
--- a/accounts/abi/pack_test.go
+++ b/accounts/abi/pack_test.go
@@ -634,7 +634,7 @@ func TestMethodPack(t *testing.T) {
t.Fatal(err)
}
- sig := abi.Methods["slice"].Id()
+ sig := abi.Methods["slice"].ID()
sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...)
sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...)
@@ -648,7 +648,7 @@ func TestMethodPack(t *testing.T) {
}
var addrA, addrB = common.Address{1}, common.Address{2}
- sig = abi.Methods["sliceAddress"].Id()
+ sig = abi.Methods["sliceAddress"].ID()
sig = append(sig, common.LeftPadBytes([]byte{32}, 32)...)
sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...)
sig = append(sig, common.LeftPadBytes(addrA[:], 32)...)
@@ -663,7 +663,7 @@ func TestMethodPack(t *testing.T) {
}
var addrC, addrD = common.Address{3}, common.Address{4}
- sig = abi.Methods["sliceMultiAddress"].Id()
+ sig = abi.Methods["sliceMultiAddress"].ID()
sig = append(sig, common.LeftPadBytes([]byte{64}, 32)...)
sig = append(sig, common.LeftPadBytes([]byte{160}, 32)...)
sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...)
@@ -681,7 +681,7 @@ func TestMethodPack(t *testing.T) {
t.Errorf("expected %x got %x", sig, packed)
}
- sig = abi.Methods["slice256"].Id()
+ sig = abi.Methods["slice256"].ID()
sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...)
sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...)
@@ -695,7 +695,7 @@ func TestMethodPack(t *testing.T) {
}
a := [2][2]*big.Int{{big.NewInt(1), big.NewInt(1)}, {big.NewInt(2), big.NewInt(0)}}
- sig = abi.Methods["nestedArray"].Id()
+ sig = abi.Methods["nestedArray"].ID()
sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...)
sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...)
sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...)
@@ -712,7 +712,7 @@ func TestMethodPack(t *testing.T) {
t.Errorf("expected %x got %x", sig, packed)
}
- sig = abi.Methods["nestedArray2"].Id()
+ sig = abi.Methods["nestedArray2"].ID()
sig = append(sig, common.LeftPadBytes([]byte{0x20}, 32)...)
sig = append(sig, common.LeftPadBytes([]byte{0x40}, 32)...)
sig = append(sig, common.LeftPadBytes([]byte{0x80}, 32)...)
@@ -728,7 +728,7 @@ func TestMethodPack(t *testing.T) {
t.Errorf("expected %x got %x", sig, packed)
}
- sig = abi.Methods["nestedSlice"].Id()
+ sig = abi.Methods["nestedSlice"].ID()
sig = append(sig, common.LeftPadBytes([]byte{0x20}, 32)...)
sig = append(sig, common.LeftPadBytes([]byte{0x02}, 32)...)
sig = append(sig, common.LeftPadBytes([]byte{0x40}, 32)...)
diff --git a/signer/fourbyte/abi.go b/signer/fourbyte/abi.go
index ba3af6225..585eae1cd 100644
--- a/signer/fourbyte/abi.go
+++ b/signer/fourbyte/abi.go
@@ -140,7 +140,7 @@ func parseCallData(calldata []byte, abidata string) (*decodedCallData, error) {
return nil, err
}
// Everything valid, assemble the call infos for the signer
- decoded := decodedCallData{signature: method.Sig(), name: method.Name}
+ decoded := decodedCallData{signature: method.Sig(), name: method.RawName}
for i := 0; i < len(method.Inputs); i++ {
decoded.inputs = append(decoded.inputs, decodedArgument{
soltype: method.Inputs[i],