solidity.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. // Package compiler wraps the ABI compilation outputs.
  17. package compiler
  18. import (
  19. "encoding/json"
  20. "fmt"
  21. )
  22. // --combined-output format
  23. type solcOutput struct {
  24. Contracts map[string]struct {
  25. BinRuntime string `json:"bin-runtime"`
  26. SrcMapRuntime string `json:"srcmap-runtime"`
  27. Bin, SrcMap, Abi, Devdoc, Userdoc, Metadata string
  28. Hashes map[string]string
  29. }
  30. Version string
  31. }
  32. // solidity v.0.8 changes the way ABI, Devdoc and Userdoc are serialized
  33. type solcOutputV8 struct {
  34. Contracts map[string]struct {
  35. BinRuntime string `json:"bin-runtime"`
  36. SrcMapRuntime string `json:"srcmap-runtime"`
  37. Bin, SrcMap, Metadata string
  38. Abi interface{}
  39. Devdoc interface{}
  40. Userdoc interface{}
  41. Hashes map[string]string
  42. }
  43. Version string
  44. }
  45. // ParseCombinedJSON takes the direct output of a solc --combined-output run and
  46. // parses it into a map of string contract name to Contract structs. The
  47. // provided source, language and compiler version, and compiler options are all
  48. // passed through into the Contract structs.
  49. //
  50. // The solc output is expected to contain ABI, source mapping, user docs, and dev docs.
  51. //
  52. // Returns an error if the JSON is malformed or missing data, or if the JSON
  53. // embedded within the JSON is malformed.
  54. func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion string, compilerVersion string, compilerOptions string) (map[string]*Contract, error) {
  55. var output solcOutput
  56. if err := json.Unmarshal(combinedJSON, &output); err != nil {
  57. // Try to parse the output with the new solidity v.0.8.0 rules
  58. return parseCombinedJSONV8(combinedJSON, source, languageVersion, compilerVersion, compilerOptions)
  59. }
  60. // Compilation succeeded, assemble and return the contracts.
  61. contracts := make(map[string]*Contract)
  62. for name, info := range output.Contracts {
  63. // Parse the individual compilation results.
  64. var abi, userdoc, devdoc interface{}
  65. if err := json.Unmarshal([]byte(info.Abi), &abi); err != nil {
  66. return nil, fmt.Errorf("solc: error reading abi definition (%v)", err)
  67. }
  68. if err := json.Unmarshal([]byte(info.Userdoc), &userdoc); err != nil {
  69. return nil, fmt.Errorf("solc: error reading userdoc definition (%v)", err)
  70. }
  71. if err := json.Unmarshal([]byte(info.Devdoc), &devdoc); err != nil {
  72. return nil, fmt.Errorf("solc: error reading devdoc definition (%v)", err)
  73. }
  74. contracts[name] = &Contract{
  75. Code: "0x" + info.Bin,
  76. RuntimeCode: "0x" + info.BinRuntime,
  77. Hashes: info.Hashes,
  78. Info: ContractInfo{
  79. Source: source,
  80. Language: "Solidity",
  81. LanguageVersion: languageVersion,
  82. CompilerVersion: compilerVersion,
  83. CompilerOptions: compilerOptions,
  84. SrcMap: info.SrcMap,
  85. SrcMapRuntime: info.SrcMapRuntime,
  86. AbiDefinition: abi,
  87. UserDoc: userdoc,
  88. DeveloperDoc: devdoc,
  89. Metadata: info.Metadata,
  90. },
  91. }
  92. }
  93. return contracts, nil
  94. }
  95. // parseCombinedJSONV8 parses the direct output of solc --combined-output
  96. // and parses it using the rules from solidity v.0.8.0 and later.
  97. func parseCombinedJSONV8(combinedJSON []byte, source string, languageVersion string, compilerVersion string, compilerOptions string) (map[string]*Contract, error) {
  98. var output solcOutputV8
  99. if err := json.Unmarshal(combinedJSON, &output); err != nil {
  100. return nil, err
  101. }
  102. // Compilation succeeded, assemble and return the contracts.
  103. contracts := make(map[string]*Contract)
  104. for name, info := range output.Contracts {
  105. contracts[name] = &Contract{
  106. Code: "0x" + info.Bin,
  107. RuntimeCode: "0x" + info.BinRuntime,
  108. Hashes: info.Hashes,
  109. Info: ContractInfo{
  110. Source: source,
  111. Language: "Solidity",
  112. LanguageVersion: languageVersion,
  113. CompilerVersion: compilerVersion,
  114. CompilerOptions: compilerOptions,
  115. SrcMap: info.SrcMap,
  116. SrcMapRuntime: info.SrcMapRuntime,
  117. AbiDefinition: info.Abi,
  118. UserDoc: info.Userdoc,
  119. DeveloperDoc: info.Devdoc,
  120. Metadata: info.Metadata,
  121. },
  122. }
  123. }
  124. return contracts, nil
  125. }