Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Package bind (via abigen) doesn't create structs used only as constructor parameters #23939

Closed
ARR4N opened this issue Nov 20, 2021 · 1 comment

Comments

@ARR4N
Copy link
Contributor

ARR4N commented Nov 20, 2021

System information

Geth v1.10.12
Should be OS-independent but only tested on Ubuntu
solc 0.8.10+commit.fc410830.Linux.g++

Expected behaviour

Foo.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

contract Foo {
    struct StructType {
        uint256 field;
    }

    constructor(StructType memory st) {}
}

This should produce a valid binding:
$ solc Foo.sol --combined-json abi,bin | abigen --combined-json /dev/stdin --pkg foo --out foo.go

Actual behaviour

Fatal: Failed to generate ABI binding: template: :71:120: executing "" at <bindtype .Type $structs>: error calling bindtype: runtime error: invalid memory address or nil pointer dereference

Steps to reproduce the behaviour

This test case in bind_test.go:

	{
		name: `constructor with struct param`,
		contract: `
		pragma solidity >=0.8.0 <0.9.0;
		
		contract Foo {
			struct StructType {
				uint256 field;
			}
		
			constructor(StructType memory st) {}
		}
		`,
		bytecode: []string{`0x608060405234801561001057600080fd5b506040516101c43803806101c48339818101604052810190610032919061014a565b50610177565b6000604051905090565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6100958261004c565b810181811067ffffffffffffffff821117156100b4576100b361005d565b5b80604052505050565b60006100c7610038565b90506100d3828261008c565b919050565b6000819050919050565b6100eb816100d8565b81146100f657600080fd5b50565b600081519050610108816100e2565b92915050565b60006020828403121561012457610123610047565b5b61012e60206100bd565b9050600061013e848285016100f9565b60008301525092915050565b6000602082840312156101605761015f610042565b5b600061016e8482850161010e565b91505092915050565b603f806101856000396000f3fe6080604052600080fdfea2646970667358221220cdffa667affecefac5561f65f4a4ba914204a8d4eb859d8cd426fb306e5c12a364736f6c634300080a0033`},
		abi:      []string{`[{"inputs":[{"components":[{"internalType":"uint256","name":"field","type":"uint256"}],"internalType":"struct Foo.StructType","name":"st","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"}]`},
	},

Suspected cause

The nil-pointer dereference is caused by this line not checking if StructType is in the structs map:

return structs[kind.TupleRawName+kind.String()].Name

I suspect that the root cause is because structs are detected by this loop over all methods, which excludes the constructor:

for _, original := range evmABI.Methods {

@ARR4N ARR4N added the type:bug label Nov 20, 2021
divergencetech pushed a commit to divergencetech/go-ethereum that referenced this issue Nov 20, 2021
…arams

Fixes issue ethereum#23939

The `structs` map is populated by iterating over all methods except the constructor,
which results in a nil-pointer dereference.

I've first reproduced the problem with a new test and then implemented the fix.
@holiman
Copy link
Contributor

holiman commented Dec 2, 2021

Fixed by #23940

@holiman holiman closed this as completed Dec 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants