Description
System information
Geth version: geth version
Solidity version: 0.8.0
OS & Version: Windows/Linux/OSX
Commit hash : (if develop
)
Expected behaviour
https://github.com/ethereum/go-ethereum/blob/3c46f5570bd674cf49c0113352ff79a4e026a5b8/common/compiler/solidity.go#L143
When executing this line, the json string is expected to marshal in the output struct where abi is of type string. The abi string will be further marshalled into another struct and the process should report no error if compiled with solc
command(which is solidity compiler).
Actual behaviour
When compiled with solidity v0.8.0, it will produce the following unmarshal error:
json: cannot unmarshal array into Go struct field .Contracts.Abi of type string
Steps to reproduce the behaviour
Try deploy the smart contracts with compiler, execute this line of code:
contracts, err := compiler.CompileSolidity("./solc-macos", path...)
The following is a deploy example:
t.Log("test deploy contract")
// Configure and generate a sample block chain
var (
memDb = memorydb.New()
db = rawdb.NewDatabase(memDb)
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey)
gspec = &core.Genesis{
GasLimit: 800000000,
Config: ¶ms.ChainConfig{
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
},
Alloc: core.GenesisAlloc{
address: {Balance: big.NewInt(9000000000000000000)},
},
}
)
engine := ethash.NewFaker()
chainConfig, _, err := core.SetupGenesisBlock(db, gspec)
if err != nil {
t.Fatal(err)
}
blockchain, err := core.NewBlockChain(db, &core.CacheConfig{
TrieDirtyDisabled: true,
}, chainConfig, engine, vm.Config{}, nil)
if err != nil {
t.Fatal(err)
}
_ = blockchain.StateCache().TrieDB()
// construct the first diff
contractBackend := backends.NewSimulatedBackend(gspec.Alloc, gspec.GasLimit)
transactOpts := bind.NewKeyedTransactor(key)
transactOpts.GasPrice = big.NewInt(1)
_ = transactOpts
_ = contractBackend
source := []string{"/Users/bytedance/Documents/codes/bsol/WeatherStorage.sol"}
contracts, err := compiler.CompileSolidity("./solc-macos", path...)
if err != nil {
return nil, err
}
var data []ContractData
for contractName, contract := range contracts {
fmt.Println(contractName)
if strings.Index(strings.Split(contractName, ":")[1], "Benchmark") != 0 {
continue
}
var names []string
abiData, err := json.Marshal(contract.Info.AbiDefinition.([]interface{}))
if err != nil {
return nil, err
}
abi, err := abi.JSON(bytes.NewBuffer(abiData))
if err != nil {
return nil, err
}
// fmt.Printf("abi: %+v\nabiData:%+v\n", abi, abiData)
for _, method := range contract.Info.AbiDefinition.([]interface{}) {
mapped := method.(map[string]interface{})
if mapped["name"] == nil {
if len(mapped["inputs"].([]interface{})) != 0 {
return nil, errors.New("Invalid Benchmark: constructor should require 0 arguments")
}
continue
}
name := mapped["name"].(string)
if strings.Index(name, "Benchmark") != 0 {
continue
}
if len(mapped["inputs"].([]interface{})) != 0 {
return nil, errors.New("Invalid Benchmark: %s: function should require 0 arguments, but it requires %d")
}
names = append(names, name)
}
if err != nil {
return nil, err
}
data = append(data, ContractData{abi, contract.Code, names, strings.Split(contractName, ":")[1]})
}
contractBackend.Commit()
return data, nil
Suggestion
For developers, please try to modify the output behavior of solidity 0.8.0 compiler from outputing array to string, or try to modify the https://github.com/ethereum/go-ethereum/blob/3c46f5570bd674cf49c0113352ff79a4e026a5b8/common/compiler/solidity.go#L141 function to make it compatible with the new solidity compiler version.