Skip to content

Commit b26eedf

Browse files
rjl493456442gballet
authored andcommitted
accounts/abi/bind: avoid reclaring structs (#20381)
1 parent 44b4164 commit b26eedf

File tree

3 files changed

+103
-18
lines changed

3 files changed

+103
-18
lines changed

accounts/abi/bind/bind.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,16 @@ const (
4848
// enforces compile time type safety and naming convention opposed to having to
4949
// manually maintain hard coded strings that break on runtime.
5050
func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]string, pkg string, lang Lang, libs map[string]string, aliases map[string]string) (string, error) {
51-
// Process each individual contract requested binding
52-
contracts := make(map[string]*tmplContract)
51+
var (
52+
// contracts is the map of each individual contract requested binding
53+
contracts = make(map[string]*tmplContract)
5354

54-
// Map used to flag each encountered library as such
55-
isLib := make(map[string]struct{})
55+
// structs is the map of all reclared structs shared by passed contracts.
56+
structs = make(map[string]*tmplStruct)
5657

58+
// isLib is the map used to flag each encountered library as such
59+
isLib = make(map[string]struct{})
60+
)
5761
for i := 0; i < len(types); i++ {
5862
// Parse the actual ABI to generate the binding for
5963
evmABI, err := abi.JSON(strings.NewReader(abis[i]))
@@ -73,7 +77,6 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
7377
calls = make(map[string]*tmplMethod)
7478
transacts = make(map[string]*tmplMethod)
7579
events = make(map[string]*tmplEvent)
76-
structs = make(map[string]*tmplStruct)
7780

7881
// identifiers are used to detect duplicated identifier of function
7982
// and event. For all calls, transacts and events, abigen will generate
@@ -168,7 +171,6 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
168171
Transacts: transacts,
169172
Events: events,
170173
Libraries: make(map[string]string),
171-
Structs: structs,
172174
}
173175
// Function 4-byte signatures are stored in the same sequence
174176
// as types, if available.
@@ -200,6 +202,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
200202
Package: pkg,
201203
Contracts: contracts,
202204
Libraries: libs,
205+
Structs: structs,
203206
}
204207
buffer := new(bytes.Buffer)
205208

accounts/abi/bind/bind_test.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,88 @@ var bindTests = []struct {
14481448
map[string]string{"_myVar": "pubVar"}, // alias MyVar to PubVar
14491449
nil,
14501450
},
1451+
{
1452+
"MultiContracts",
1453+
`
1454+
pragma solidity ^0.5.11;
1455+
pragma experimental ABIEncoderV2;
1456+
1457+
library ExternalLib {
1458+
struct SharedStruct{
1459+
uint256 f1;
1460+
bytes32 f2;
1461+
}
1462+
}
1463+
1464+
contract ContractOne {
1465+
function foo(ExternalLib.SharedStruct memory s) pure public {
1466+
// Do stuff
1467+
}
1468+
}
1469+
1470+
contract ContractTwo {
1471+
function bar(ExternalLib.SharedStruct memory s) pure public {
1472+
// Do stuff
1473+
}
1474+
}
1475+
`,
1476+
[]string{
1477+
`60806040523480156100115760006000fd5b50610017565b6101b5806100266000396000f3fe60806040523480156100115760006000fd5b50600436106100305760003560e01c80639d8a8ba81461003657610030565b60006000fd5b610050600480360361004b91908101906100d1565b610052565b005b5b5056610171565b6000813590506100698161013d565b92915050565b6000604082840312156100825760006000fd5b61008c60406100fb565b9050600061009c848285016100bc565b60008301525060206100b08482850161005a565b60208301525092915050565b6000813590506100cb81610157565b92915050565b6000604082840312156100e45760006000fd5b60006100f28482850161006f565b91505092915050565b6000604051905081810181811067ffffffffffffffff8211171561011f5760006000fd5b8060405250919050565b6000819050919050565b6000819050919050565b61014681610129565b811415156101545760006000fd5b50565b61016081610133565b8114151561016e5760006000fd5b50565bfea365627a7a72315820749274eb7f6c01010d5322af4e1668b0a154409eb7968bd6cae5524c7ed669bb6c6578706572696d656e74616cf564736f6c634300050c0040`,
1478+
`60806040523480156100115760006000fd5b50610017565b6101b5806100266000396000f3fe60806040523480156100115760006000fd5b50600436106100305760003560e01c8063db8ba08c1461003657610030565b60006000fd5b610050600480360361004b91908101906100d1565b610052565b005b5b5056610171565b6000813590506100698161013d565b92915050565b6000604082840312156100825760006000fd5b61008c60406100fb565b9050600061009c848285016100bc565b60008301525060206100b08482850161005a565b60208301525092915050565b6000813590506100cb81610157565b92915050565b6000604082840312156100e45760006000fd5b60006100f28482850161006f565b91505092915050565b6000604051905081810181811067ffffffffffffffff8211171561011f5760006000fd5b8060405250919050565b6000819050919050565b6000819050919050565b61014681610129565b811415156101545760006000fd5b50565b61016081610133565b8114151561016e5760006000fd5b50565bfea365627a7a723158209bc28ee7ea97c131a13330d77ec73b4493b5c59c648352da81dd288b021192596c6578706572696d656e74616cf564736f6c634300050c0040`,
1479+
`606c6026600b82828239805160001a6073141515601857fe5b30600052607381538281f350fe73000000000000000000000000000000000000000030146080604052600436106023575b60006000fdfea365627a7a72315820518f0110144f5b3de95697d05e456a064656890d08e6f9cff47f3be710cc46a36c6578706572696d656e74616cf564736f6c634300050c0040`,
1480+
},
1481+
[]string{
1482+
`[{"constant":true,"inputs":[{"components":[{"internalType":"uint256","name":"f1","type":"uint256"},{"internalType":"bytes32","name":"f2","type":"bytes32"}],"internalType":"struct ExternalLib.SharedStruct","name":"s","type":"tuple"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"}]`,
1483+
`[{"constant":true,"inputs":[{"components":[{"internalType":"uint256","name":"f1","type":"uint256"},{"internalType":"bytes32","name":"f2","type":"bytes32"}],"internalType":"struct ExternalLib.SharedStruct","name":"s","type":"tuple"}],"name":"bar","outputs":[],"payable":false,"stateMutability":"pure","type":"function"}]`,
1484+
`[]`,
1485+
},
1486+
`
1487+
"math/big"
1488+
1489+
"github.com/ethereum/go-ethereum/accounts/abi/bind"
1490+
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
1491+
"github.com/ethereum/go-ethereum/crypto"
1492+
"github.com/ethereum/go-ethereum/core"
1493+
`,
1494+
`
1495+
key, _ := crypto.GenerateKey()
1496+
addr := crypto.PubkeyToAddress(key.PublicKey)
1497+
1498+
// Deploy registrar contract
1499+
sim := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}}, 10000000)
1500+
defer sim.Close()
1501+
1502+
transactOpts := bind.NewKeyedTransactor(key)
1503+
_, _, c1, err := DeployContractOne(transactOpts, sim)
1504+
if err != nil {
1505+
t.Fatal("Failed to deploy contract")
1506+
}
1507+
sim.Commit()
1508+
err = c1.Foo(nil, ExternalLibSharedStruct{
1509+
F1: big.NewInt(100),
1510+
F2: [32]byte{0x01, 0x02, 0x03},
1511+
})
1512+
if err != nil {
1513+
t.Fatal("Failed to invoke function")
1514+
}
1515+
_, _, c2, err := DeployContractTwo(transactOpts, sim)
1516+
if err != nil {
1517+
t.Fatal("Failed to deploy contract")
1518+
}
1519+
sim.Commit()
1520+
err = c2.Bar(nil, ExternalLibSharedStruct{
1521+
F1: big.NewInt(100),
1522+
F2: [32]byte{0x01, 0x02, 0x03},
1523+
})
1524+
if err != nil {
1525+
t.Fatal("Failed to invoke function")
1526+
}
1527+
`,
1528+
nil,
1529+
nil,
1530+
nil,
1531+
[]string{"ContractOne", "ContractTwo", "ExternalLib"},
1532+
},
14511533
}
14521534

14531535
// Tests that packages generated by the binder can be successfully compiled and

accounts/abi/bind/template.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type tmplData struct {
2323
Package string // Name of the package to place the generated file in
2424
Contracts map[string]*tmplContract // List of contracts to generate into this file
2525
Libraries map[string]string // Map the bytecode's link pattern to the library name
26+
Structs map[string]*tmplStruct // Contract struct type definitions
2627
}
2728

2829
// tmplContract contains the data needed to generate an individual contract binding.
@@ -36,8 +37,7 @@ type tmplContract struct {
3637
Transacts map[string]*tmplMethod // Contract calls that write state data
3738
Events map[string]*tmplEvent // Contract events accessors
3839
Libraries map[string]string // Same as tmplData, but filtered to only keep what the contract needs
39-
Structs map[string]*tmplStruct // Contract struct type definitions
40-
Library bool
40+
Library bool // Indicator whether the contract is a library
4141
}
4242

4343
// tmplMethod is a wrapper around an abi.Method that contains a few preprocessed
@@ -108,8 +108,16 @@ var (
108108
_ = event.NewSubscription
109109
)
110110
111+
{{$structs := .Structs}}
112+
{{range $structs}}
113+
// {{.Name}} is an auto generated low-level Go binding around an user-defined struct.
114+
type {{.Name}} struct {
115+
{{range $field := .Fields}}
116+
{{$field.Name}} {{$field.Type}}{{end}}
117+
}
118+
{{end}}
119+
111120
{{range $contract := .Contracts}}
112-
{{$structs := $contract.Structs}}
113121
// {{.Type}}ABI is the input ABI used to generate the binding from.
114122
const {{.Type}}ABI = "{{.InputABI}}"
115123
@@ -285,14 +293,6 @@ var (
285293
return _{{$contract.Type}}.Contract.contract.Transact(opts, method, params...)
286294
}
287295
288-
{{range .Structs}}
289-
// {{.Name}} is an auto generated low-level Go binding around an user-defined struct.
290-
type {{.Name}} struct {
291-
{{range $field := .Fields}}
292-
{{$field.Name}} {{$field.Type}}{{end}}
293-
}
294-
{{end}}
295-
296296
{{range .Calls}}
297297
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
298298
//
@@ -507,8 +507,8 @@ package {{.Package}};
507507
import org.ethereum.geth.*;
508508
import java.util.*;
509509
510+
{{$structs := .Structs}}
510511
{{range $contract := .Contracts}}
511-
{{$structs := $contract.Structs}}
512512
{{if not .Library}}public {{end}}class {{.Type}} {
513513
// ABI is the input ABI used to generate the binding from.
514514
public final static String ABI = "{{.InputABI}}";

0 commit comments

Comments
 (0)