注意
本节不适用于solcjs,即使在命令行模式下使用也不适用。
Solidity存储库的构建目标之一是solidity solc命令行编译器。使用为您提供所有选项的说明。编译器可以生成各种输出,范围从简单的二进制文件和抽象语法树(解析树)上的汇编到气体使用的估计。如果您只想编译单个文件,则将其运行为打印二进制文件。如果你想获得一些更高级的输出变体,最好告诉它使用输出所有内容来分离文件。solc --helpsolc --bin sourceFile.solsolcsolc -o outputDirectory --bin --ast --asm sourceFile.sol
在部署合约之前,请在编译时激活优化程序。默认情况下,优化器将优化合约,假设在其生命周期内调用了200次。如果您希望初始合约部署更便宜并且后期功能执行更昂贵,请将其设置为。如果您期望许多事务并且不关心更高的部署成本和输出大小,请设置为较大的数字。solc --optimize --bin sourceFile.sol–runs=1–runs
命令行编译器将自动从文件系统读取导入的文件,但也可以通过prefix=path以下方式提供路径重定向:
solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ file.sol
这实质上指示编译器搜索以github.com/ethereum/dapp-bin/under 开头的任何内容/usr/local/lib/dapp-bin。 solc不会读取位于重映射目标之外的文件系统中以及显式指定的源文件所在目录之外的文件,因此只有在添加为重新映射时才会起作用。import “/etc/passwd”;/=/
不允许使用空重映射前缀。
如果由于重映射而存在多个匹配,则选择具有最长公共前缀的匹配。
出于安全原因,编译器限制了它可以访问的目录。在命令行上指定的源文件的路径(及其子目录)和由重映射定义的路径允许用于导入语句,但其他所有内容都被拒绝。可以通过交换机允许其他路径(及其子目录)。–allow-paths /sample/path,/another/sample/path
如果您的合约使用库,您会注意到字节码包含表单的子字符串__ 53 a e a 86 b 7 d 70 b 31448 b 230 b 20 a e 141 a 537 53aea86b7d70b31448b230b20ae141a537 53aea86b7d70b31448b230b20ae141a537__。这些是实际库地址的占位符。占位符是完全限定库名称的keccak256哈希值的十六进制编码的34个字符前缀。字节码文件还将在末尾包含表单行,以帮助识别占位符表示的库。请注意,完全限定的库名称是其源文件的路径和由之隔开的库名称。您可以将其用作链接器,这意味着它将在以下位置为您插入库地址:// -> :solc
可以添加到命令中为每个库提供地址,也可以将字符串存储在文件中(每行一个库)并使用。–libraries "file.sol:Math:0x1234567890123456789012345678901234567890 file.sol:Heap:0xabCD567890123456789012345678901234567890"solc–libraries fileName
如果solc使用该选项调用,则–link所有输入文件在__ 53 a e a 86 b 7 d 70 b 31448 b 230 b 20 a e 141 a 537 53aea86b7d70b31448b230b20ae141a537 53aea86b7d70b31448b230b20ae141a537__上面给出的-format中被解释为未链接的二进制文件(十六进制编码)并且就地链接(如果从stdin读取输入,则将其写入stdout)。在这种情况下,除了–libraries忽略所有选项(包括-o)。
如果solc使用该选项调用–standard-json,则它将在标准输入上获得JSON输入(如下所述),并在标准输出上返回JSON输出。这是更复杂且特别是自动化用途的推荐界面。
注意
库占位符曾经是库本身的完全限定名称,而不是它的哈希值。仍然支持此格式,但编译器将不再输出它。这种更改是为了降低库之间发生冲突的可能性,因为只能使用完全限定库名的前36个字符。solc --link
将EVM版本设置为目标
编译合约代码时,可以指定要编译的以太坊虚拟机版本,以避免特定的功能或行为。
警告
编译错误的EVM版本可能会导致错误,奇怪和失败的行为。请确保(尤其是在运行专用链时)使用匹配的EVM版本。
在命令行上,您可以选择EVM版本,如下所示:
solc --evm-version contract.sol
在标准JSON界面中,使用字段中的"evmVersion" 键"settings":
{
“sources”: { … },
“settings”: {
“optimizer”: { … },
“evmVersion”: “”
}
}
目标选项
下面列出了目标EVM版本以及每个版本中引入的与编译器相关的更改。不保证每个版本之间的向后兼容性。
• homestead (最旧的版本)
• tangerineWhistle
o 进入其他账户的天然气成本增加,与天然气估算和优化者相关。
o 默认情况下为外部调用发送的所有气体,以前必须保留一定数量的气体。
• spuriousDragon
o exp操作码的气体成本增加,与气体估算和优化器相关。
• byzantium(默认)
o 操作码returndatacopy,returndatasize并staticcall在组装功能。
o 所述staticcall主叫非库视图或纯函数,这防止功能从在EVM级修改状态时,即当操作码被使用,当使用无效类型转换甚至适用。
o 可以访问从函数调用返回的动态数据。
o revert操作码介绍,这意味着revert()不会浪费气体。
• constantinople (仍在进行中)
o 操作码shl,shr并sar在组装功能。
o 换档操作员使用换档操作码,因此需要更少的气体。
编译器输入输出JSON描述
与Solidity编译器接口的推荐方法,尤其是对于更复杂和自动化的设置,是所谓的JSON输入输出接口。编译器的所有发行版都提供相同的接口。
这些字段通常会有变化,有些是可选的(如上所述),但我们只尝试进行向后兼容的更改。
编译器API需要JSON格式的输入,并以JSON格式的输出输出编译结果。
以下小节通过示例描述了格式。当然不允许发表评论,此处仅用于解释目的。
输入描述
{
//必需:源代码语言,例如“Solidity”,“Vyper”,“lll”,“assembly”等。
语言:“Solidity”,
需要
sources:
{
// 这里的键是源文件的“全局”名称,
导入可以通过重映射使用其他文件(见下文)。
"myFile.sol":
{
//可选:源文件的keccak256哈希值
如果通过URL导入,它用于验证检索到的内容。
"keccak256": "0x123...",
//必需(除非使用“内容”,见下文):源文件的URL。
//应按此顺序导入URL,并根据结果检查结果
//keccak256哈希(如果可用)。 如果哈希不匹配或者没有匹配
//URL(s)导致成功,应该引发错误。
"urls":
[
"bzzr://56ab...",
"ipfs://Qma...",
//如果使用文件,则应将其目录添加到命令行中
//`--allow-paths `。
"file:///tmp/path/to/file.sol"
]
},
"mortal":
{
//可选:源文件的keccak256哈希值
"keccak256": "0x234...",
//必需(除非使用“urls”):源文件的文字内容
"content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }"
}
},
//可选的
settings:
{
//可选:已重新排序的已排序列表
remappings: [ ":g/dir" ],
//可选:优化工具设置
optimizer: {
//默认情况下禁用
enabled: true,
// 优化您打算运行代码的次数。
// 较低的值将针对初始部署成本进行更多优化,较高的值将针对高频率使用进行更多优化。
runs: 200
},
evmVersion: "byzantium", //要编译的EVM版本。影响类型检查和代码生成。可以是宅基地,橘哨,伪狂龙,拜占庭或君士坦丁堡
// 元数据设置(可选)
metadata: {
//仅使用文字内容而非URL(默认为false)
useLiteralContent: true
},
// 库的地址。如果此处未给出所有库,则可能导致输出数据不同的未链接对象。
libraries: {
// 顶级键是使用库的源文件的名称
//如果使用重映射,则此源文件应与应用重映射后的全局路径匹配
// 如果此键是空字符串,则表示全局级别
"myFile.sol": {
"MyLib": "0x123123..."
}
}
//以下内容可用于选择所需的输出。
//如果省略此字段,则编译器会加载并执行类型检查,但除了错误之外不会生成任何输出。
//第一级键是文件名,第二级是合约名,空合约名是指文件本身,
//而星星指的是所有合约。
//
//可用的输出类型如下:
// abi - ABI
// ast - 所有源文件的AST
// legacyAST - 所有源文件的旧AST
// devdoc - 开发人员文档(natspec)
// userdoc - 用户文档(natspec)
//元数据 - 元数据
// ir - desugaring之前的新程序集格式
// evm.assembly - desugaring之后的新程序集格式
// evm.legacyAssembly - JSON中的旧式汇编格式
// evm.bytecode.object - 字节码对象
// evm.bytecode.opcodes - 操作码列表
// evm.bytecode.sourceMap - 源映射(对调试很有用)
// evm.bytecode.linkReferences - 链接引用(如果未链接的对象)
// evm.deployedBytecode * - 已部署的字节码(与evm.bytecode具有相同的选项)
// evm.methodIdentifiers - 函数哈希列表
// evm.gasEstimates - 功能气体估算
// ewasm.wast - eWASM S表达式格式(不支持atm)
// ewasm.wasm - eWASM二进制格式(不支持atm)
//
//注意使用`evm`,`evm.bytecode`,`ewasm`等会选择每一个
//目标输出的一部分。另外,`*`可以用作通配符来请求所有内容。
//
outputSelection: {
//启用每个合约的元数据和字节码输出。
"*": {
"*": [ "metadata", "evm.bytecode" ]
},
//启用文件def中定义的MyContract的abi和opcodes输出。
"def": {
"MyContract": [ "abi", "evm.bytecode.opcodes" ]
},
//启用每个合约的源地图输出。
"*": {
"*": [ "evm.bytecode.sourceMap" ]
},
//启用每个文件的旧AST输出。
"*": {
"": [ "legacyAST" ]
}
}
}
}
输出描述
{
//可选:如果未遇到错误/警告,则不存在
errors: [
{
// 可选:源文件中的位置
sourceLocation: {
file: "sourceFile.sol",
start: 0,
end: 100
],
//强制:错误类型,例如“TypeError”,“InternalCompilerError”,“Exception”等。
//请参阅下面的完整类型列表。
type: "TypeError",
//强制:发生错误的组件,例如“general”,“ewasm”等。
component: "general",
//强制(“错误”或“警告”)
severity: "error",
//强制性
message: "Invalid keyword"
//可选:使用源位置格式化的消息
formattedMessage: "sourceFile.sol:100: Invalid keyword"
}
],
//这包含文件级输出。 In可以通过outputSelection设置进行限制/过滤。
sources: {
"sourceFile.sol": {
//标识符(用于源映射)
id: 1,
// The AST 对象
ast: {},
//遗留的 AST 对象
legacyAST: {}
}
},
//这包含合约级输出。它可以通过outputSelection设置进行限制/过滤。
contracts: {
"sourceFile.sol": {
//如果使用的语言没有合约名称,则此字段应等于空字符串。
"ContractName": {
//以太坊合约ABI。如果为空,则表示为空数组。
abi: [],
//请参阅元数据输出文档(序列化的JSON字符串)
metadata: "{...}",
//用户文档(natspec)
userdoc: {},
//开发者文档(natspec)
devdoc: {},
//中间表示(字符串)
ir: "",
//与EVM相关的输出
evm: {
//汇编(字符串)
assembly: "",
//旧式程序集(对象)
legacyAssembly: {},
//字节码和相关细节。
bytecode: {
//字节码为十六进制字符串。
object: "00fe",
//操作码列表(字符串)
opcodes: "",
//源映射为字符串。请参阅源映射定义。
sourceMap: "",
//如果给定,这是一个未链接的对象。
linkReferences: {
"libraryFile.sol": {
//字节偏移到字节码。链接替换位于那里的20个字节。
"Library1": [
{ start: 0, length: 20 },
{ start: 200, length: 20 }
]
}
}
},
//与上面相同的布局。
deployedBytecode: { },
//函数哈希列表
methodIdentifiers: {
"delegate(address)": "5c19a95c"
},
//功能气体估算
gasEstimates: {
creation: {
codeDepositCost: "420000",
executionCost: "infinite",
totalCost: "infinite"
},
external: {
"delegate(address)": "25000"
},
internal: {
"heavyLifting()": "infinite"
}
}
},
// eWASM相关输出
ewasm: {
// S表达式格式
wast: "",
//二进制格式(十六进制字符串)
wasm: ""
}
}
}
}
}
错误类型