如何通过solc编译solidity编写的以太坊智能合约

hubwiz · · 4007 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

# solc:solidity的编译器 solidity编写的以太坊智能合约可通过命令行编译工具solc来进行编译,成为以太坊虚拟机中的代码。solc编译后最终部署到链上形成我们所见到的各种智能合约。 作为一个solidity命令行编译工具,我们来看看官网都怎么说solc。 solc的安装很简单: ``` npm install -g solc //或者 npm install -g solc-cli //或者 sudo apt-get install solc ``` 安装完成后我们来看,```solc --help```,solc --help命令显示所有的solc命令选项。编译器可以生成各种输出,比如最终的二进制合约文件、语法树的汇编或者需要预计的要花费的gas等。```solc --bin sourceFile.sol```,可以编译后输出一个名为sourceFile.sol的智能合约文件。如果你想从```solc```获得更丰富的一些输出变量,你可以使用```solc -o outputDirectory --bin --ast --asm sourceFile.sol```。 你在部署[以太坊智能合约](http://xc.hubwiz.com/course/5a952991adb3847553d205d1)之前可以用```solc --optimize --bin sourceFile.sol```优化一下。默认情况下solc编译器会帮你优化200次。你也可以设置 ```--runs=1```,这样就按照最小化的方式进行编译,如果你希望多次交易不太在乎成本,那你可以设置成你想要的次数:)。 命令行编译器会自动读取需要导入的文件,也可以通过使用```prefix = path```来指定路径,例如: >```solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ =/usr/local/lib/fallback file.sol``` 这样编译器就会从指定目录```github.com/ethereum/dapp-bin/```下的```/usr/local/lib/dapp-bin/```目录开始搜索,如果没有找到文件,它将查看```/usr/local/lib/fallback```。solc将只读取你指定的这两个路径的,因此像```import "/etc/passwd";```必须要通过```/=```重新映射才起作用。如果有多个匹配,则选择具有最长公共前缀的进行匹配。 出于安全上的考虑,编译器限制了它可以访问的一些目录。在命令行中指定的源文件的路径(及其子目录)和命令行指定的路径外其他所有内容都会被拒绝。```--allow-paths /sample/path,/another/sample/path```来切换。 如果智能合约使用了[libraries](https://solidity.readthedocs.io/en/v0.4.24/contracts.html#libraries),你会注意到字节码包含了```__LibraryName______```的子字符串。您可以使用solc作为链接器,这意味着它将在这些点为您插入库地址。 可以通过添加库```--libraries "Math:0x12345678901234567890 Heap:0xabcdef0123456"```到您的命令,以提供每个库的地址,或者使用文件中的说明字符串(每行一个库),并使用```--libraries fileName```运行solc。 如果用选项```--link```调用Solc,则所有输入文件都被解释为未链接的二进制文件(HEX编码),在上面给出的```__LibraryName____```格式中,将其链接到适当地址(如果从stdin读取输入,则将其写入stdout)。在这种情况下,除了库外,所有选项都被忽略(包括```-o```)。 如果用```--standard-json```调用SOLC,它就将标准的JSON输入(如下所述),并返回JSON输出。 #solc编译器输入输出JSON描述 这些JSON格式通过编译器API使用,可以通过SOLC获得。内容都是可以修改的,一些对象是可选的(如前所述),其目的是向后兼容。 编译器的API需要一个JSON格式的输入,然后以JSON格式输出编译结果。 **注意不允许注释**。下面示例中的注释,是官网为了学习者更好的理解标注的。 * 输入格式说明: ``` { // Required: Source code language, such as "Solidity", "serpent", "lll", "assembly", etc. 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. "urls": [ "bzzr://56ab...", "ipfs://Qma...", "file:///tmp/path/to/file.sol" ] }, "mortal": { // Optional: keccak256 hash of the source file "keccak256": "0x234...", // Required (unless "urls" is used): literal contents of the source file "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }" } }, // Optional settings: { // Optional: Sorted list of remappings remappings: [ ":g/dir" ], // Optional: Optimizer settings optimizer: { // disabled by default 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 }, evmVersion: "byzantium", // Version of the EVM to compile for. Affects type checking and code generation. Can be homestead, tangerineWhistle, spuriousDragon, byzantium or constantinople // Metadata settings (optional) metadata: { // Use only literal content and not URLs (false by default) useLiteralContent: true }, // 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. // 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 is the contract name, where empty contract name refers to the file itself, // while the star refers to all of the contracts. // // The available output types are as follows: // abi - ABI // ast - AST of all source files // legacyAST - legacy AST of all source files // devdoc - Developer documentation (natspec) // userdoc - User documentation (natspec) // metadata - Metadata // ir - New assembly format before desugaring // evm.assembly - New assembly format after desugaring // evm.legacyAssembly - Old-style assembly format in JSON // 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.deployedBytecode* - Deployed bytecode (has the same options as evm.bytecode) // evm.methodIdentifiers - The list of function hashes // evm.gasEstimates - Function gas estimates // ewasm.wast - eWASM S-expressions format (not supported atm) // ewasm.wasm - eWASM binary format (not supported atm) // // 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: { // Enable the metadata and bytecode outputs of every single contract. "*": { "*": [ "metadata", "evm.bytecode" ] }, // Enable the abi and opcodes output of MyContract defined in file def. "def": { "MyContract": [ "abi", "evm.bytecode.opcodes" ] }, // Enable the source map output of every single contract. "*": { "*": [ "evm.bytecode.sourceMap" ] }, // Enable the legacy AST output of every single file. "*": { "": [ "legacyAST" ] } } } } ``` * 输出格式说明 ``` { // Optional: not present if no errors/warnings were encountered errors: [ { // Optional: Location within the source file. sourceLocation: { file: "sourceFile.sol", start: 0, end: 100 ], // 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" or "warning") severity: "error", // Mandatory message: "Invalid keyword" // Optional: the message formatted with source location formattedMessage: "sourceFile.sol:100: Invalid keyword" } ], // This contains the file-level outputs. In can be limited/filtered by the outputSelection settings. sources: { "sourceFile.sol": { // Identifier (used in source maps) id: 1, // The AST object ast: {}, // The legacy AST object legacyAST: {} } }, // 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://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI abi: [], // See the Metadata Output documentation (serialised JSON string) metadata: "{...}", // User documentation (natspec) userdoc: {}, // Developer documentation (natspec) devdoc: {}, // Intermediate representation (string) ir: "", // EVM-related outputs evm: { // Assembly (string) assembly: "", // Old-style assembly (object) legacyAssembly: {}, // Bytecode and related details. bytecode: { // The bytecode as a hex string. object: "00fe", // Opcodes list (string) opcodes: "", // The source mapping as a string. See the source mapping definition. sourceMap: "", // 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 } ] } } }, // The same layout as above. deployedBytecode: { }, // 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输入不符合要求的格式,例如输入不是JSON对象,不支持语言,等等。 2. IOError:IO错误,IO和导入处理错误,如提供的源中的不可解析URL或hash不匹配。 3. ParserError:语法f分析错误,源代码不符合语言规则。 4. DocstringParsingError:文档解析错误,无法解析注释块中的NATSPEC标记。 5. SytRealError:语法错误,如```continue ```在```for```循环之外使用。 6. DeclarationError:声明错误,无效、不可解析或冲突的标识符名称。例如未找到标识符 7. TypeError:类型错误,如无效类型转换、无效赋值等。 8. UnimplementedFeatureError:编译器不支持该特性,但希望在将来的版本中得到支持。 9. InternalCompilerError:编译器中触发内部错误,这应该作为一个问题来反馈。 10. Exception:例外,编译过程中未知的故障,这应该作为一个问题反馈。 11. CompilerError:编译错误,编译器堆栈的使用无效,这应该作为一个问题来反馈。 12. FatalError:致命错误,这应该作为一个问题来反馈。 13. Warning:警告并没有停止编译,但如果可能的话,应该加以处理。 原文请访问:[solc](http://blog.hubwiz.com/2018/06/14/solc-compiler/) 如果你希望马上开始学习以太坊DApp开发,推荐访问一个在线教程: * [以太坊智能合约](http://xc.hubwiz.com/course/5a952991adb3847553d205d1?affid=studygolang616),主要介绍智能合约与dapp应用开发,适合入门。 * [以太坊开发](http://xc.hubwiz.com/course/5abbb7acc02e6b6a59171dd6?affid=studygolang616),主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4007 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传