Skip to content

Commit 3340b3e

Browse files
committed
customize CallContract
1 parent 5943fae commit 3340b3e

File tree

585 files changed

+259088
-962
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

585 files changed

+259088
-962
lines changed

accounts/abi/abi.go

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Copyright 2015 The go-ethereum Authors
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package abi
18+
19+
import (
20+
"bytes"
21+
"encoding/json"
22+
"fmt"
23+
"io"
24+
)
25+
26+
// The ABI holds information about a contract's context and available
27+
// invokable methods. It will allow you to type check function calls and
28+
// packs data accordingly.
29+
type ABI struct {
30+
Constructor Method
31+
Methods map[string]Method
32+
Events map[string]Event
33+
}
34+
35+
// JSON returns a parsed ABI interface and error if it failed.
36+
func JSON(reader io.Reader) (ABI, error) {
37+
dec := json.NewDecoder(reader)
38+
39+
var abi ABI
40+
if err := dec.Decode(&abi); err != nil {
41+
return ABI{}, err
42+
}
43+
44+
return abi, nil
45+
}
46+
47+
// Pack the given method name to conform the ABI. Method call's data
48+
// will consist of method_id, args0, arg1, ... argN. Method id consists
49+
// of 4 bytes and arguments are all 32 bytes.
50+
// Method ids are created from the first 4 bytes of the hash of the
51+
// methods string signature. (signature = baz(uint32,string32))
52+
func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
53+
// Fetch the ABI of the requested method
54+
if name == "" {
55+
// constructor
56+
arguments, err := abi.Constructor.Inputs.Pack(args...)
57+
if err != nil {
58+
return nil, err
59+
}
60+
return arguments, nil
61+
62+
}
63+
method, exist := abi.Methods[name]
64+
if !exist {
65+
return nil, fmt.Errorf("method '%s' not found", name)
66+
}
67+
68+
arguments, err := method.Inputs.Pack(args...)
69+
if err != nil {
70+
return nil, err
71+
}
72+
// Pack up the method ID too if not a constructor and return
73+
return append(method.Id(), arguments...), nil
74+
}
75+
76+
// Unpack output in v according to the abi specification
77+
func (abi ABI) Unpack(v interface{}, name string, output []byte) (err error) {
78+
if len(output) == 0 {
79+
return fmt.Errorf("abi: unmarshalling empty output")
80+
}
81+
// since there can't be naming collisions with contracts and events,
82+
// we need to decide whether we're calling a method or an event
83+
if method, ok := abi.Methods[name]; ok {
84+
if len(output)%32 != 0 {
85+
return fmt.Errorf("abi: improperly formatted output")
86+
}
87+
return method.Outputs.Unpack(v, output)
88+
} else if event, ok := abi.Events[name]; ok {
89+
return event.Inputs.Unpack(v, output)
90+
}
91+
return fmt.Errorf("abi: could not locate named method or event")
92+
}
93+
94+
// UnmarshalJSON implements json.Unmarshaler interface
95+
func (abi *ABI) UnmarshalJSON(data []byte) error {
96+
var fields []struct {
97+
Type string
98+
Name string
99+
Constant bool
100+
Anonymous bool
101+
Inputs []Argument
102+
Outputs []Argument
103+
}
104+
105+
if err := json.Unmarshal(data, &fields); err != nil {
106+
return err
107+
}
108+
109+
abi.Methods = make(map[string]Method)
110+
abi.Events = make(map[string]Event)
111+
for _, field := range fields {
112+
switch field.Type {
113+
case "constructor":
114+
abi.Constructor = Method{
115+
Inputs: field.Inputs,
116+
}
117+
// empty defaults to function according to the abi spec
118+
case "function", "":
119+
abi.Methods[field.Name] = Method{
120+
Name: field.Name,
121+
Const: field.Constant,
122+
Inputs: field.Inputs,
123+
Outputs: field.Outputs,
124+
}
125+
case "event":
126+
abi.Events[field.Name] = Event{
127+
Name: field.Name,
128+
Anonymous: field.Anonymous,
129+
Inputs: field.Inputs,
130+
}
131+
}
132+
}
133+
134+
return nil
135+
}
136+
137+
// MethodById looks up a method by the 4-byte id
138+
// returns nil if none found
139+
func (abi *ABI) MethodById(sigdata []byte) (*Method, error) {
140+
for _, method := range abi.Methods {
141+
if bytes.Equal(method.Id(), sigdata[:4]) {
142+
return &method, nil
143+
}
144+
}
145+
return nil, fmt.Errorf("no method with id: %#x", sigdata[:4])
146+
}

0 commit comments

Comments
 (0)