使用编译器

使用命令行编译器

注解

本节不适用于 solcjs ,即使在命令行模式下使用也是如此。

基本用法

固定性存储库的构建目标之一是 solc ,固态命令行编译器。使用 solc --help 为您提供所有选项的说明。编译器可以产生各种输出,从简单的二进制文件和抽象语法树(解析树)上的汇编到气体使用量的估计。如果您只想编译单个文件,则可以按如下方式运行该文件 solc --bin sourceFile.sol 它将打印二进制文件。如果您想要获得一些更高级的输出变体 solc ,告诉它使用以下命令将所有内容输出到单独的文件可能更好 solc -o outputDirectory --bin --ast-compact-json --asm sourceFile.sol

优化器选项

在部署协定之前,请在编译时使用 solc --optimize --bin sourceFile.sol .默认情况下,优化器将优化契约,前提是在其生命周期内调用它200次(更具体地说,它假定每个操作码执行大约200次)。如果希望初始合同部署更便宜,以后的函数执行更昂贵,请将其设置为 --optimize-runs=1 .如果您期望许多事务,而不关心更高的部署成本和输出大小,请设置 --optimize-runs 一个很高的数字。此参数对以下内容有影响(将来可能会更改):

  • 函数调度例程中二进制搜索的大小

  • 像大数字或字符串这样的常量的存储方式

基本路径和导入重映射

命令行编译器将自动从文件系统读取导入的文件,但也可以提供 path redirects 使用 prefix=path 采用以下方式:

solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ file.sol

这实质上是指示编译器搜索任何以 github.com/ethereum/dapp-bin/ 在……下面 /usr/local/lib/dapp-bin

当访问文件系统以搜索导入时, paths that do not start with ./ or ../ 被视为相对于使用 --base-path--include-path 选项(如果未指定基本路径,则为当前工作目录)。此外,通过这些选项添加的路径部分不会出现在合同元数据中。

出于安全原因,编译器具有 restrictions on what directories it can access 。文件读取器自动允许文件读取器访问在命令行上指定的源文件目录和重新映射的目标路径,但默认情况下拒绝其他所有内容。其他路径(及其子目录)可以通过 --allow-paths /sample/path,/another/sample/path 换个位置。指定的路径内的所有内容 --base-path 总是被允许的。

以上只是编译器处理导入路径方式的简化。有关示例的详细说明和转角案例的讨论,请参阅 path resolution

库链接

如果你的合同使用 libraries ,您将注意到字节码包含表单的子字符串。 __$53aea86b7d70b31448b230b20ae141a537$__. These are placeholders for the actual library addresses. The placeholder is a 34 character prefix of the hex encoding of the keccak256 hash of the fully qualified library name. The bytecode file will also contain lines of the form // <placeholder> -> <fq library name> at the end to help identify which libraries the placeholders represent. Note that the fully qualified library name is the path of its source file and the library name separated by :. You can use `` solc``作为链接器,意味着它将在这些点为您插入库地址:

要么添加 --libraries "file.sol:Math=0x1234567890123456789012345678901234567890 file.sol:Heap=0xabCD567890123456789012345678901234567890" 添加到命令以提供每个库的地址(使用逗号或空格作为分隔符)或将字符串存储在文件中(每行一个库),然后运行 solc 使用 --libraries fileName

注解

起始实心度0.8.1接受 = as separator between library and address, and : as a separator is deprecated. It will be removed in the future. Currently `` --库“file.sol:Math:0x1234567890123456789012345678901234567890 file.sol:Heap:0xabCD567890123456789012345678901234567890”``也可以工作。

如果 solc 用选项调用 --standard-json ,它将期望在标准输入上有一个JSON输入(如下所述),并在标准输出上返回一个JSON输出。尤其是对于更复杂的应用,建议使用自动化和更复杂的界面。进程将始终以“成功”状态终止,并通过JSON输出报告任何错误。选择权 --base-path 也是在标准json模式下处理的。

如果 solc 用选项调用 --link ,所有输入文件都被解释为在 __$53aea86b7d70b31448b230b20ae141a537$__ -上面给出的格式并在适当位置链接(如果从stdin读取输入,则将其写入stdout)。所有选项,除了 --libraries 被忽略(包括 -o )在这种情况下。

警告

不鼓励在生成的字节码上手动链接库,因为它不会更新合同元数据。由于元数据包含编译时指定的库列表,而字节码包含元数据散列,因此您将获得不同的二进制文件,具体取决于执行链接的时间。

您应该要求编译器在编译协定时链接库,方法是使用 --libraries 选项: solc 或者 libraries 键,如果您使用编译器的标准JSON接口。

注解

库占位符以前是库本身的完全限定名,而不是其哈希。此格式仍受支持 solc --link 但是编译器将不再输出它。进行此更改是为了减少库之间发生冲突的可能性,因为只能使用完全限定的库名称的前36个字符。

将EVM版本设置为目标

当您编译合同代码时,可以指定要编译的以太坊虚拟机版本,以避免特定的功能或行为。

警告

为错误的EVM版本编译可能会导致错误、奇怪和失败的行为。请确保使用匹配的EVM版本,尤其是在运行私有链时。

在命令行上,您可以选择EVM版本,如下所示:

solc --evm-version <VERSION> contract.sol

standard JSON interface 使用 "evmVersion" 关键在 "settings" 领域:

{
  "sources": {/* ... */},
  "settings": {
    "optimizer": {/* ... */},
    "evmVersion": "<VERSION>"
  }
}

目标选项

下面是目标EVM版本的列表,以及在每个版本中引入的与编译器相关的更改。不能保证每个版本之间的向后兼容性。

  • homestead
    • (最旧版本)

  • tangerineWhistle
    • 接入其他账户的天然气成本增加,与天然气估算和优化器相关。

    • 所有因外线呼叫而默认发送的气体,以前必须保留一定数量。

  • spuriousDragon
    • 天然气成本 exp 操作码增加,与气体估计和优化器相关。

  • byzantium
    • 机器码 returndatacopyreturndatasizestaticcall 在组件中可用。

    • 这个 staticcall 在调用非库视图或纯函数时使用opcode,这会阻止函数在evm级别修改状态,即,甚至在使用无效类型转换时也会应用opcode。

    • 可以访问从函数调用返回的动态数据。

    • revert 引入了操作码,这意味着 revert() 不会浪费气体。

  • constantinople
    • 机器码 create2`, `` extcodehashshlshrsar 在组件中可用。

    • 移位操作员使用移位操作码,因此需要更少的气体。

  • petersburg
    • 编译器的行为与君士坦丁堡相同。

  • istanbul
    • 机器码 chainidselfbalance 在组件中可用。

  • berlin
    • 煤气费 SLOAD*CALLBALANCEEXT*SELFDESTRUCT 增加了。编译器假定此类操作的冷气成本。这与气体估计和优化器相关。

  • london ( 默认设置 )
    • 挡路的基准费 (EIP-3198EIP-1559 )可以通过全局 block.basefeebasefee() 在内联汇编中。

编译器输入和输出JSON描述

与Solidity编译器接口的推荐方法是所谓的JSON输入输出接口,特别是对于更复杂和自动化的设置。编译器的所有发行版都提供相同的接口。

字段通常会发生变化,有些字段是可选的(如前所述),但我们只尝试进行向后兼容的更改。

编译器API需要JSON格式的输入,并将编译结果输出到JSON格式的输出中。不使用标准的错误输出,即使存在错误,进程也将始终以“成功”状态终止。错误总是作为JSON输出的一部分报告。

下面的小节通过一个例子来描述这种格式。当然,此处不允许使用注释,仅用于解释目的。

输入说明

{
  // Required: Source code language. Currently supported are "Solidity" and "Yul".
  "language": "Solidity",
  // Required
  "sources":
  {
    // The keys here are the "global" names of the source files,
    // imports can use other files via remappings (see below).
    "myFile.sol":
    {
      // Optional: keccak256 hash of the source file
      // It is used to verify the retrieved content if imported via URLs.
      "keccak256": "0x123...",
      // Required (unless "content" is used, see below): URL(s) to the source file.
      // URL(s) should be imported in this order and the result checked against the
      // keccak256 hash (if available). If the hash doesn't match or none of the
      // URL(s) result in success, an error should be raised.
      // Using the commandline interface only filesystem paths are supported.
      // With the JavaScript interface the URL will be passed to the user-supplied
      // read callback, so any URL supported by the callback can be used.
      "urls":
      [
        "bzzr://56ab...",
        "ipfs://Qma...",
        "/tmp/path/to/file.sol"
        // If files are used, their directories should be added to the command line via
        // `--allow-paths <path>`.
      ]
    },
    "destructible":
    {
      // Optional: keccak256 hash of the source file
      "keccak256": "0x234...",
      // Required (unless "urls" is used): literal contents of the source file
      "content": "contract destructible is owned { function shutdown() { if (msg.sender == owner) selfdestruct(owner); } }"
    }
  },
  // Optional
  "settings":
  {
    // Optional: Stop compilation after the given stage. Currently only "parsing" is valid here
    "stopAfter": "parsing",
    // Optional: Sorted list of remappings
    "remappings": [ ":g=/dir" ],
    // Optional: Optimizer settings
    "optimizer": {
      // Disabled by default.
      // NOTE: enabled=false still leaves some optimizations on. See comments below.
      // WARNING: Before version 0.8.6 omitting the 'enabled' key was not equivalent to setting
      // it to false and would actually disable all the optimizations.
      "enabled": true,
      // Optimize for how many times you intend to run the code.
      // Lower values will optimize more for initial deployment cost, higher
      // values will optimize more for high-frequency usage.
      "runs": 200,
      // Switch optimizer components on or off in detail.
      // The "enabled" switch above provides two defaults which can be
      // tweaked here. If "details" is given, "enabled" can be omitted.
      "details": {
        // The peephole optimizer is always on if no details are given,
        // use details to switch it off.
        "peephole": true,
        // The inliner is always on if no details are given,
        // use details to switch it off.
        "inliner": true,
        // The unused jumpdest remover is always on if no details are given,
        // use details to switch it off.
        "jumpdestRemover": true,
        // Sometimes re-orders literals in commutative operations.
        "orderLiterals": false,
        // Removes duplicate code blocks
        "deduplicate": false,
        // Common subexpression elimination, this is the most complicated step but
        // can also provide the largest gain.
        "cse": false,
        // Optimize representation of literal numbers and strings in code.
        "constantOptimizer": false,
        // The new Yul optimizer. Mostly operates on the code of ABI coder v2
        // and inline assembly.
        // It is activated together with the global optimizer setting
        // and can be deactivated here.
        // Before Solidity 0.6.0 it had to be activated through this switch.
        "yul": false,
        // Tuning options for the Yul optimizer.
        "yulDetails": {
          // Improve allocation of stack slots for variables, can free up stack slots early.
          // Activated by default if the Yul optimizer is activated.
          "stackAllocation": true,
          // Select optimization steps to be applied.
          // Optional, the optimizer will use the default sequence if omitted.
          "optimizerSteps": "dhfoDgvulfnTUtnIf..."
        }
      }
    },
    // Version of the EVM to compile for.
    // Affects type checking and code generation. Can be homestead,
    // tangerineWhistle, spuriousDragon, byzantium, constantinople, petersburg, istanbul or berlin
    "evmVersion": "byzantium",
    // Optional: Change compilation pipeline to go through the Yul intermediate representation.
    // This is a highly EXPERIMENTAL feature, not to be used for production. This is false by default.
    "viaIR": true,
    // Optional: Debugging settings
    "debug": {
      // How to treat revert (and require) reason strings. Settings are
      // "default", "strip", "debug" and "verboseDebug".
      // "default" does not inject compiler-generated revert strings and keeps user-supplied ones.
      // "strip" removes all revert strings (if possible, i.e. if literals are used) keeping side-effects
      // "debug" injects strings for compiler-generated internal reverts, implemented for ABI encoders V1 and V2 for now.
      // "verboseDebug" even appends further information to user-supplied revert strings (not yet implemented)
      "revertStrings": "default",
      // Optional: How much extra debug information to include in comments in the produced EVM
      // assembly and Yul code. Available components are:
      // - `location`: Annotations of the form `@src <index>:<start>:<end>` indicating the
      //    location of the corresponding element in the original Solidity file, where:
      //     - `<index>` is the file index matching the `@use-src` annotation,
      //     - `<start>` is the index of the first byte at that location,
      //     - `<end>` is the index of the first byte after that location.
      // - `snippet`: A single-line code snippet from the location indicated by `@src`.
      //     The snippet is quoted and follows the corresponding `@src` annotation.
      // - `*`: Wildcard value that can be used to request everything.
      "debugInfo": ["location", "snippet"]
    },
    // Metadata settings (optional)
    "metadata": {
      // Use only literal content and not URLs (false by default)
      "useLiteralContent": true,
      // Use the given hash method for the metadata hash that is appended to the bytecode.
      // The metadata hash can be removed from the bytecode via option "none".
      // The other options are "ipfs" and "bzzr1".
      // If the option is omitted, "ipfs" is used by default.
      "bytecodeHash": "ipfs"
    },
    // Addresses of the libraries. If not all libraries are given here,
    // it can result in unlinked objects whose output data is different.
    "libraries": {
      // The top level key is the the name of the source file where the library is used.
      // If remappings are used, this source file should match the global path
      // after remappings were applied.
      // If this key is an empty string, that refers to a global level.
      "myFile.sol": {
        "MyLib": "0x123123..."
      }
    },
    // The following can be used to select desired outputs based
    // on file and contract names.
    // If this field is omitted, then the compiler loads and does type checking,
    // but will not generate any outputs apart from errors.
    // The first level key is the file name and the second level key is the contract name.
    // An empty contract name is used for outputs that are not tied to a contract
    // but to the whole source file like the AST.
    // A star as contract name refers to all contracts in the file.
    // Similarly, a star as a file name matches all files.
    // To select all outputs the compiler can possibly generate, use
    // "outputSelection: { "*": { "*": [ "*" ], "": [ "*" ] } }"
    // but note that this might slow down the compilation process needlessly.
    //
    // The available output types are as follows:
    //
    // File level (needs empty string as contract name):
    //   ast - AST of all source files
    //
    // Contract level (needs the contract name or "*"):
    //   abi - ABI
    //   devdoc - Developer documentation (natspec)
    //   userdoc - User documentation (natspec)
    //   metadata - Metadata
    //   ir - Yul intermediate representation of the code before optimization
    //   irOptimized - Intermediate representation after optimization
    //   storageLayout - Slots, offsets and types of the contract's state variables.
    //   evm.assembly - New assembly format
    //   evm.legacyAssembly - Old-style assembly format in JSON
    //   evm.bytecode.functionDebugData - Debugging information at function level
    //   evm.bytecode.object - Bytecode object
    //   evm.bytecode.opcodes - Opcodes list
    //   evm.bytecode.sourceMap - Source mapping (useful for debugging)
    //   evm.bytecode.linkReferences - Link references (if unlinked object)
    //   evm.bytecode.generatedSources - Sources generated by the compiler
    //   evm.deployedBytecode* - Deployed bytecode (has all the options that evm.bytecode has)
    //   evm.deployedBytecode.immutableReferences - Map from AST ids to bytecode ranges that reference immutables
    //   evm.methodIdentifiers - The list of function hashes
    //   evm.gasEstimates - Function gas estimates
    //   ewasm.wast - Ewasm in WebAssembly S-expressions format
    //   ewasm.wasm - Ewasm in WebAssembly binary format
    //
    // Note that using a using `evm`, `evm.bytecode`, `ewasm`, etc. will select every
    // target part of that output. Additionally, `*` can be used as a wildcard to request everything.
    //
    "outputSelection": {
      "*": {
        "*": [
          "metadata", "evm.bytecode" // Enable the metadata and bytecode outputs of every single contract.
          , "evm.bytecode.sourceMap" // Enable the source map output of every single contract.
        ],
        "": [
          "ast" // Enable the AST output of every single file.
        ]
      },
      // Enable the abi and opcodes output of MyContract defined in file def.
      "def": {
        "MyContract": [ "abi", "evm.bytecode.opcodes" ]
      }
    },
    // The modelChecker object is experimental and subject to changes.
    "modelChecker":
    {
      // Chose which contracts should be analyzed as the deployed one.
      "contracts":
      {
        "source1.sol": ["contract1"],
        "source2.sol": ["contract2", "contract3"]
      },
      // Choose whether division and modulo operations should be replaced by
      // multiplication with slack variables. Default is `true`.
      // Using `false` here is recommended if you are using the CHC engine
      // and not using Spacer as the Horn solver (using Eldarica, for example).
      // See the Formal Verification section for a more detailed explanation of this option.
      "divModWithSlacks": true,
      // Choose which model checker engine to use: all (default), bmc, chc, none.
      "engine": "chc",
      // Choose whether to output all unproved targets. The default is `false`.
      "showUnproved": true,
      // Choose which solvers should be used, if available.
      // See the Formal Verification section for the solvers description.
      "solvers": ["cvc4", "smtlib2", "z3"],
      // Choose which targets should be checked: constantCondition,
      // underflow, overflow, divByZero, balance, assert, popEmptyArray, outOfBounds.
      // If the option is not given all targets are checked by default,
      // except underflow/overflow for Solidity >=0.8.7.
      // See the Formal Verification section for the targets description.
      "targets": ["underflow", "overflow", "assert"],
      // Timeout for each SMT query in milliseconds.
      // If this option is not given, the SMTChecker will use a deterministic
      // resource limit by default.
      // A given timeout of 0 means no resource/time restrictions for any query.
      "timeout": 20000
    }
  }
}

输出描述

{
  // Optional: not present if no errors/warnings/infos were encountered
  "errors": [
    {
      // Optional: Location within the source file.
      "sourceLocation": {
        "file": "sourceFile.sol",
        "start": 0,
        "end": 100
      },
      // Optional: Further locations (e.g. places of conflicting declarations)
      "secondarySourceLocations": [
        {
          "file": "sourceFile.sol",
          "start": 64,
          "end": 92,
          "message": "Other declaration is here:"
        }
      ],
      // Mandatory: Error type, such as "TypeError", "InternalCompilerError", "Exception", etc.
      // See below for complete list of types.
      "type": "TypeError",
      // Mandatory: Component where the error originated, such as "general", "ewasm", etc.
      "component": "general",
      // Mandatory ("error", "warning" or "info", but please note that this may be extended in the future)
      "severity": "error",
      // Optional: unique code for the cause of the error
      "errorCode": "3141",
      // Mandatory
      "message": "Invalid keyword",
      // Optional: the message formatted with source location
      "formattedMessage": "sourceFile.sol:100: Invalid keyword"
    }
  ],
  // This contains the file-level outputs.
  // It can be limited/filtered by the outputSelection settings.
  "sources": {
    "sourceFile.sol": {
      // Identifier of the source (used in source maps)
      "id": 1,
      // The AST object
      "ast": {}
    }
  },
  // This contains the contract-level outputs.
  // It can be limited/filtered by the outputSelection settings.
  "contracts": {
    "sourceFile.sol": {
      // If the language used has no contract names, this field should equal to an empty string.
      "ContractName": {
        // The Ethereum Contract ABI. If empty, it is represented as an empty array.
        // See https://docs.soliditylang.org/en/develop/abi-spec.html
        "abi": [],
        // See the Metadata Output documentation (serialised JSON string)
        "metadata": "{/* ... */}",
        // User documentation (natspec)
        "userdoc": {},
        // Developer documentation (natspec)
        "devdoc": {},
        // Intermediate representation (string)
        "ir": "",
        // See the Storage Layout documentation.
        "storageLayout": {"storage": [/* ... */], "types": {/* ... */} },
        // EVM-related outputs
        "evm": {
          // Assembly (string)
          "assembly": "",
          // Old-style assembly (object)
          "legacyAssembly": {},
          // Bytecode and related details.
          "bytecode": {
            // Debugging data at the level of functions.
            "functionDebugData": {
              // Now follows a set of functions including compiler-internal and
              // user-defined function. The set does not have to be complete.
              "@mint_13": { // Internal name of the function
                "entryPoint": 128, // Byte offset into the bytecode where the function starts (optional)
                "id": 13, // AST ID of the function definition or null for compiler-internal functions (optional)
                "parameterSlots": 2, // Number of EVM stack slots for the function parameters (optional)
                "returnSlots": 1 // Number of EVM stack slots for the return values (optional)
              }
            },
            // The bytecode as a hex string.
            "object": "00fe",
            // Opcodes list (string)
            "opcodes": "",
            // The source mapping as a string. See the source mapping definition.
            "sourceMap": "",
            // Array of sources generated by the compiler. Currently only
            // contains a single Yul file.
            "generatedSources": [{
              // Yul AST
              "ast": {/* ... */},
              // Source file in its text form (may contain comments)
              "contents":"{ function abi_decode(start, end) -> data { data := calldataload(start) } }",
              // Source file ID, used for source references, same "namespace" as the Solidity source files
              "id": 2,
              "language": "Yul",
              "name": "#utility.yul"
            }],
            // If given, this is an unlinked object.
            "linkReferences": {
              "libraryFile.sol": {
                // Byte offsets into the bytecode.
                // Linking replaces the 20 bytes located there.
                "Library1": [
                  { "start": 0, "length": 20 },
                  { "start": 200, "length": 20 }
                ]
              }
            }
          },
          "deployedBytecode": {
            /* ..., */ // The same layout as above.
            "immutableReferences": {
              // There are two references to the immutable with AST ID 3, both 32 bytes long. One is
              // at bytecode offset 42, the other at bytecode offset 80.
              "3": [{ "start": 42, "length": 32 }, { "start": 80, "length": 32 }]
            }
          },
          // The list of function hashes
          "methodIdentifiers": {
            "delegate(address)": "5c19a95c"
          },
          // Function gas estimates
          "gasEstimates": {
            "creation": {
              "codeDepositCost": "420000",
              "executionCost": "infinite",
              "totalCost": "infinite"
            },
            "external": {
              "delegate(address)": "25000"
            },
            "internal": {
              "heavyLifting()": "infinite"
            }
          }
        },
        // Ewasm related outputs
        "ewasm": {
          // S-expressions format
          "wast": "",
          // Binary format (hex string)
          "wasm": ""
        }
      }
    }
  }
}

错误类型

  1. JSONError :json输入不符合要求的格式,例如输入不是json对象,不支持该语言等。

  2. IOError :IO和导入处理错误,例如提供的源中无法解析的URL或哈希不匹配。

  3. ParserError :源代码不符合语言规则。

  4. DocstringParsingError :无法分析注释块中的natspec标记。

  5. SyntaxError :语法错误,例如 continue 在外部使用 for 循环。

  6. DeclarationError: Invalid, unresolvable or clashing identifier names. e.g. Identifier not found

  7. TypeError :类型系统中的错误,例如类型转换无效、分配无效等。

  8. UnimplementedFeatureError :编译器不支持功能,但在将来的版本中应该支持功能。

  9. InternalCompilerError :编译器中触发的内部错误-这应作为问题报告。

  10. Exception :编译过程中出现未知故障-应将此报告为问题。

  11. CompilerError :编译器堆栈的使用无效-应将其报告为问题。

  12. FatalError :未正确处理致命错误-应将此报告为问题。

  13. Warning :一个警告,它没有停止编译,但应该在可能的情况下加以处理。

  14. Info :编译器认为用户可能会发现有用但不危险且不一定需要处理的信息。

编译器工具

坚固性升级

solidity-upgrade 可以帮助您半自动升级您的合同,以打破语言变化。虽然它不能也不能为每个中断的版本实现所有必需的更改,但它仍然支持那些需要大量重复的手动调整的更改。

注解

solidity-upgrade 执行大部分工作,但您的合同很可能需要进一步的人工调整。我们建议对文件使用版本控制系统。这有助于检查并最终回滚所做的更改。

警告

solidity-upgrade 不完整或没有错误,请小心使用。

它是如何工作的

您可以将(a)Solidity源文件传递给 solidity-upgrade [files] . 如果这些利用了 import 语句引用当前源文件目录之外的文件,则需要指定允许从中读取和导入文件的目录,方法是 --allow-paths [directory] . 您可以通过传递忽略丢失的文件 --ignore-missing .

solidity-upgrade 基于 libsolidity 并且可以解析、编译和分析源文件,并可能在其中找到适用的源代码升级。

源代码升级被认为是对源代码的小的文本更改。它们应用于给定源文件的内存表示形式。默认情况下会更新相应的源文件,但您可以通过 --dry-run 模拟整个升级过程而不写入任何文件。

升级过程本身有两个阶段。在第一阶段,源文件被解析,由于不可能在该级别升级源代码,所以会收集错误并通过传递记录下来 --verbose . 目前没有可用的源升级。

在第二阶段,编译所有源代码,并在编译的同时运行所有激活的升级分析模块。默认情况下,将激活所有可用模块。请阅读 available modules 更多详情。

这可能导致编译错误,这些错误可以通过源代码升级来修复。如果没有发生错误,则不会报告源升级,并且您已经完成了升级。如果发生错误,并且某个升级模块报告了源升级,则应用第一个报告的升级,并对所有给定的源文件再次触发编译。只要报告源代码升级,就重复上一步。如果仍然发生错误,可以通过传递 --verbose . 如果没有出现错误,则合同是最新的,可以使用最新版本的编译器进行编译。

可用的升级模块

模块

版本

描述

constructor

0.5.0

现在必须使用 constructor 关键字。

visibility

0.5.0

显式函数可见性现在是必需的,默认为 public .

abstract

0.6.0

关键词 abstract 如果合同没有实现其所有功能,则必须使用。

virtual

0.6.0

必须标记接口外没有实现的函数 virtual .

override

0.6.0

重写函数或修饰符时,new关键字 override 必须使用。

dotsyntax

0.7.0

不推荐使用以下语法: f.gas(...)()f.value(...)()(new C).value(...)() . 将这些呼叫替换为 f{{gas: ..., value: ...}}()(new C){{value: ...}}() .

now

0.7.0

这个 now 关键字已弃用。使用 block.timestamp 相反。

constructor-visibility

0.7.0

移除构造函数的可见性。

请阅读 0.5.0 release notes0.6.0 release notes0.7.0 release notes0.8.0 release notes 了解更多详细信息。

简介

Usage: solidity-upgrade [options] contract.sol

Allowed options:
    --help               Show help message and exit.
    --version            Show version and exit.
    --allow-paths path(s)
                         Allow a given path for imports. A list of paths can be
                         supplied by separating them with a comma.
    --ignore-missing     Ignore missing files.
    --modules module(s)  Only activate a specific upgrade module. A list of
                         modules can be supplied by separating them with a comma.
    --dry-run            Apply changes in-memory only and don't write to input
                         file.
    --verbose            Print logs, errors and changes. Shortens output of
                         upgrade patches.
    --unsafe             Accept *unsafe* changes.

错误报告/功能请求

如果你发现了一个错误或者你有一个功能请求,请 file an issue 在Github上。

例子

假设您在 Source.sol

pragma solidity >=0.6.0 <0.6.4;
// This will not compile after 0.7.0
// SPDX-License-Identifier: GPL-3.0
contract C {
    // FIXME: remove constructor visibility and make the contract abstract
    constructor() internal {}
}

contract D {
    uint time;

    function f() public payable {
        // FIXME: change now to block.timestamp
        time = now;
    }
}

contract E {
    D d;

    // FIXME: remove constructor visibility
    constructor() public {}

    function g() public {
        // FIXME: change .value(5) =>  {value: 5}
        d.f.value(5)();
    }
}
所需更改

从0.7.0开始,上述合同将无法编译。为使合同与当前Solidity版本保持一致,必须执行以下升级模块: constructor-visibilitynowdotsyntax . 请阅读 available modules 更多详情。

运行升级

建议使用 --modules 争论。

solidity-upgrade --modules constructor-visibility,now,dotsyntax Source.sol

上面的命令应用所有更改,如下所示。请仔细检查(pragma必须手动更新)

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
abstract contract C {
    // FIXME: remove constructor visibility and make the contract abstract
    constructor() {}
}

contract D {
    uint time;

    function f() public payable {
        // FIXME: change now to block.timestamp
        time = block.timestamp;
    }
}

contract E {
    D d;

    // FIXME: remove constructor visibility
    constructor() {}

    function g() public {
        // FIXME: change .value(5) =>  {value: 5}
        d.f{value: 5}();
    }
}