Solidity 智能合约的编程编译不起作用

问题描述 投票:0回答:1

使用我的feess后端,我想以编程方式编译用户在我的nextjs前端中输入的Solidity智能合约。

由于我使用的是 TypeScript 并且它包含自动编译器版本识别等高级功能,因此我使用的是 ConsenSys 的 solc-typed-ast 包。

编译(看起来)有效,但返回的字节码与我使用 Remix 手动编译合约时收到的字节码略有不同。当我在前端收到结果并尝试在以太坊上部署字节码时,交易似乎已完成,但在浏览器中查看交易已失败,状态为:

Warning! Error encountered during contract execution [invalid opcode: opcode 0x5f not defined]

这个错误的原因可能是什么(但是,看看字节码“几乎正确”的编译?

这是我的后端服务进行编译:

import { Application } from '../../declarations'; import { compileSol } from 'solc-typed-ast'; /** * A mapping from several Smart Contracts' Name to their Solidity Code or ABI * @typedef {Object} CodeMap * @property {string} key - The name of the Smart Contract * @property {string} value - The Solidity Code or ABI of the Smart Contract * @example * { * "Contract1": "contract Contract1 { ... }", * "Contract2": "contract Contract2 { ... }", * } */ export type CodeMap = { [key: string]: string }; /** * Solidity Compiler Service * This service compiles the Solidity code for a given Project using the solc-typed-ast library. */ export class SolidityCompiler { ... async find(params?: Params | undefined): Promise<CompilationResult[]> { ... // Fetch the code from the database const codeToCompile = JSON.parse(template.code) as CodeMap; // Initialize the compileResults array const compileResults: CompilationResult[] = []; try { // Iterate over each contract in the codeToCompile map for (const [contractName, contractCode] of Object.entries(codeToCompile)) { // Create a temporary directory and file path for each contract const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'solidity-')); const filePath = path.join(tempDir, `${contractName}.sol`); // Write the contract's Solidity code to a file fs.writeFileSync(filePath, contractCode); try { // Compile the Solidity code const result = await compileSol(filePath, 'auto'); // Extract the compiled contract names const compiledContractNames = Object.keys(result.data.contracts[filePath]); // Iterate through compiled contracts compiledContractNames.forEach((compiledContractName) => { const compiledContract = result.data.contracts[filePath][compiledContractName]; // Store the result together with the compiled contract name compileResults.push({ contractName: compiledContractName, success: true, abi: compiledContract.abi, bytecode: compiledContract.evm.bytecode.object, error: undefined, compilerVersion: result.compilerVersion, }); console.log(`Solidity Compiler Service: ${compiledContractName} compiled successfully`); }); } catch (compileError: any) { // Store possible errors together with the contract name compileResults.push({ contractName, success: false, abi: undefined, bytecode: undefined, error: compileError.message, }); console.error(`Solidity Compiler Service: ${contractName}`, compileError.message); } // Clean up the temporary file and directory fs.unlinkSync(filePath); fs.rmdirSync(tempDir); } } catch (error: any) { throw new Error(`Solidity Compilation Error: ${error.message}`); } return compileResults; } }

template.code
来自我的数据库,看起来像这样:

"{\"ERC20\":\"pragma solidity ^0.5.0;\\n\\n// Flat ERC20\\n// Updated Jun 7 2019\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * 

安全数学

restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's

+
operator.\\n *\\n * Requirements:\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's
-
operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's
*
operator.\\n *\\n * Requirements:\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n

    

typescript compilation ethereum solidity solc
1个回答
0
投票
是solidity 0.8.20中引入的新PUSH0操作码,并非所有链都支持。将编译器回滚到早期版本或在编译中以非上海 evm 为目标,错误就会消失。

© www.soinside.com 2019 - 2024. All rights reserved.