Remix: 返回错误: {“jsonrpc”:”2.0″,”error”:”无效的操作码: PUSH0″, “id”:2405507186007008}

huangapple go评论72阅读模式
英文:

Remix: Returned error: {"jsonrpc":"2.0","error":"invalid opcode: PUSH0", "id":2405507186007008}

问题

在运行私有链节点(geth)和 Ubuntu 上的 Chainlink 节点后,我想测试 Chainlink Any API 的功能(https://docs.chain.link/any-api/get-request/examples/single-word-response,Single Word Response)。

我运行了以下命令来启动节点:

## 终端1
cd ~/myChain/localChain/node1 && geth --datadir data --gcmode "archive" --syncmode=full --networkid 4190 --http --http.addr 0.0.0.0 --http.port 6789 --http.corsdomain "*" --ws --port 30305 --allow-insecure-unlock --unlock edd96278959aA8B27DdC14FD70ACb31f7e7beC2F --keystore ./keystore console

## 终端2
cd ~/myChain/chainlink/.chainlink && docker run --net host -u=root -p 6688:6688 -v ~/.chainlink:/chainlink -it --env-file=.env smartcontract/chainlink:1.11.0 local n

我成功部署了我的 LinkToken 合约,operator 合约,并在我的 Chainlink 节点 UI 操作员中创建了一个新的任务(GET>uint256)。它们如下所示:

LinkToken.sol

pragma solidity ^0.4.11;

import "https://github.com/smartcontractkit/chainlink/contracts/src/v0.4/ERC677Token.sol";
import { StandardToken as linkStandardToken } from "https://github.com/smartcontractkit/chainlink/contracts/src/v0.4/vendor/StandardToken.sol";

contract LinkToken is linkStandardToken, ERC677Token {
  uint public constant totalSupply = 10**27;
  string public constant name = "ChainLink Token";
  uint8 public constant decimals = 18;
  string public constant symbol = "LINK";

  function LinkToken() public {
    balances[msg.sender] = totalSupply;
  }

  // 其他函数...
}

operator.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
import "@chainlink/contracts/src/v0.7/Operator.sol";

job GET>uint256(我已经将 "YOUR_ORACLE_CONTRACT_ADDRESS" 更改为我的 operator 合约地址)

type = "directrequest"
schemaVersion = 1
name = "Get > Uint256 - (TOML)"
maxTaskDuration = "0s"
contractAddress = "YOUR_ORACLE_CONTRACT_ADDRESS"
minIncomingConfirmations = 0
observationSource = """
    decode_log   [type="ethabidecodelog"
                  abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)"
                  data="$(jobRun.logData)"
                  topics="$(jobRun.logTopics)"]

    decode_cbor  [type="cborparse" data="$(decode_log.data)"]
    fetch        [type="http" method=GET url="$(decode_cbor.get)" allowUnrestrictedNetworkAccess="true"]
    parse        [type="jsonparse" path="$(decode_cbor.path)" data="$(fetch)"]

    multiply     [type="multiply" input="$(parse)" times="$(decode_cbor.times)"]

    encode_data  [type="ethabiencode" abi="(bytes32 requestId, uint256 value)" data="{ \"requestId\": $(decode_log.requestId), \"value\": $(multiply) }"]
    encode_tx    [type="ethabiencode"
                  abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)"
                  data="{\"requestId\": $(decode_log.requestId), \"payment\":   $(decode_log.payment), \"callbackAddress\": $(decode_log.callbackAddr), \"callbackFunctionId\": $(decode_log.callbackFunctionId), \"expiration\": $(decode_log.cancelExpiration), \"data\": $(encode_data)}"]
    submit_tx    [type="ethtx" to="YOUR_ORACLE_CONTRACT_ADDRESS" data="$(encode_tx)"]

    decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx
"""

LinkToken 合约用于将 LINK 代币转移到其他地址,而 Operator 合约用于与我的 Chainlink 节点交互。按照 Chainlink 文档的说明,我将部署 ATestnetConsumer 合约,然后请求 API 数据。

但是,在 Remix 中我收到了以下错误:

Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending? Returned error: {"jsonrpc":"2.0","error":"invalid opcode: PUSH0","id":2405507186007008}

Remix 中的 PUSH0 错误
而我的 geth 控制台也出现了此错误:Geth 中的 PUSH0 错误

我尝试重置我的 geth 节点和 Chainlink 节点,并重复相同的步骤。但是它们似乎没有解决问题。

英文:

After runing my private chain node in geth and Chainlink node in my Ubuntu, I would like to test the function of Chainlink Any API(https://docs.chain.link/any-api/get-request/examples/single-word-response, Single Word Response).

I ran these commands to run nodes:

## SHELL1
cd ~/myChain/localChain/node1 && geth --datadir data --gcmode "archive" --syncmode=full --networkid 4190 --http --http.addr 0.0.0.0 --http.port 6789 --http.corsdomain "*" --ws --port 30305 --allow-insecure-unlock --unlock edd96278959aA8B27DdC14FD70ACb31f7e7beC2F --keystore ./keystore console

## SHELL2
cd ~/myChain/chainlink/.chainlink && docker run --net host -u=root  -p 6688:6688 -v ~/.chainlink:/chainlink -it --env-file=.env smartcontract/chainlink:1.11.0 local n

I successfully deployed my LinkToken contract, operator contract and created a new job(GET>uint256) in my Chainlink node UI Operator. They are as followed:

LinkToken.sol

pragma solidity ^0.4.11;

import "https://github.com/smartcontractkit/chainlink/contracts/src/v0.4/ERC677Token.sol";
import { StandardToken as linkStandardToken } from "https://github.com/smartcontractkit/chainlink/contracts/src/v0.4/vendor/StandardToken.sol";


contract LinkToken is linkStandardToken, ERC677Token {

  uint public constant totalSupply = 10**27;
  string public constant name = "ChainLink Token";
  uint8 public constant decimals = 18;
  string public constant symbol = "LINK";

  function LinkToken()
    public
  {
    balances[msg.sender] = totalSupply;
  }

  /**
  * @dev transfer token to a specified address with additional data if the recipient is a contract.
  * @param _to The address to transfer to.
  * @param _value The amount to be transferred.
  * @param _data The extra data to be passed to the receiving contract.
  */
  function transferAndCall(address _to, uint _value, bytes _data)
    public
    validRecipient(_to)
    returns (bool success)
  {
    return super.transferAndCall(_to, _value, _data);
  }

  /**
  * @dev transfer token to a specified address.
  * @param _to The address to transfer to.
  * @param _value The amount to be transferred.
  */
  function transfer(address _to, uint _value)
    public
    validRecipient(_to)
    returns (bool success)
  {
    return super.transfer(_to, _value);
  }

  /**
   * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
   * @param _spender The address which will spend the funds.
   * @param _value The amount of tokens to be spent.
   */
  function approve(address _spender, uint256 _value)
    public
    validRecipient(_spender)
    returns (bool)
  {
    return super.approve(_spender,  _value);
  }

  /**
   * @dev Transfer tokens from one address to another
   * @param _from address The address which you want to send tokens from
   * @param _to address The address which you want to transfer to
   * @param _value uint256 the amount of tokens to be transferred
   */
  function transferFrom(address _from, address _to, uint256 _value)
    public
    validRecipient(_to)
    returns (bool)
  {
    return super.transferFrom(_from, _to, _value);
  }


  // MODIFIERS

  modifier validRecipient(address _recipient) {
    require(_recipient != address(0) && _recipient != address(this));
    _;
  }

}

operator.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
import "@chainlink/contracts/src/v0.7/Operator.sol";

job GET>uint256 (I have already change the "YOUR_ORACLE_CONTRACT_ADDRESS" with my operator contract address)

type = "directrequest"
schemaVersion = 1
name = "Get > Uint256 - (TOML)"
maxTaskDuration = "0s"
contractAddress = "YOUR_ORACLE_CONTRACT_ADDRESS"
minIncomingConfirmations = 0
observationSource = """
    decode_log   [type="ethabidecodelog"
                  abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)"
                  data="$(jobRun.logData)"
                  topics="$(jobRun.logTopics)"]

    decode_cbor  [type="cborparse" data="$(decode_log.data)"]
    fetch        [type="http" method=GET url="$(decode_cbor.get)" allowUnrestrictedNetworkAccess="true"]
    parse        [type="jsonparse" path="$(decode_cbor.path)" data="$(fetch)"]

    multiply     [type="multiply" input="$(parse)" times="$(decode_cbor.times)"]

    encode_data  [type="ethabiencode" abi="(bytes32 requestId, uint256 value)" data="{ \\"requestId\\": $(decode_log.requestId), \\"value\\": $(multiply) }"]
    encode_tx    [type="ethabiencode"
                  abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)"
                  data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\":   $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}"
                  ]
    submit_tx    [type="ethtx" to="YOUR_ORACLE_CONTRACT_ADDRESS" data="$(encode_tx)"]

    decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx
"""

LinkToken contract is used to transfer LINK token to other address, and Operator contract is used to interact with my Chainlink node. By following the document of Chainlink, I will deploy ATestnetConsumer contract then request the API data.

However, I got an error in Remix like this:

Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending? Returned error: {"jsonrpc":"2.0","error":"invalid opcode: PUSH0", "id":2405507186007008}

PUSH0 Error in Remix
And my geth console also got this error: PUSH0 Error in Geth

I tried to reset my geth node and Chainlink node and redo all the same steps. However, they don't make sense.

答案1

得分: 4

使用Solc版本0.8.20,默认的EVM版本设置为"Shanghai"。在上海升级中,向以太坊虚拟机添加了一个新的操作码PUSHO。这意味着PUSH0操作码现在可以成为合约的字节码的一部分。如果您的私有链不支持它,将会出现"Invalid opcode"错误。

解决方案是手动将EVM版本设置为以前的某个版本,例如"Paris"(之前的版本,也被称为The Merge),而不是现在的默认值"Shanghai"。

Remix:

  • 转到编译选项卡
  • 切换到"高级配置"下拉菜单
  • 切换到"EVM版本"下拉菜单,选择"paris"而不是"default"

Solc:

  • 运行solc --evm-version <版本> <合约>
  • 例如,运行solc --evm-version paris contract.sol

Hardhat:

  • 调整Hardhat配置文件如下
// hardhat.config.ts
solidity: {
    compilers: [
        {
            version: '0.8.20',
            settings: {
                evmVersion: 'paris'
            }
        }
    ]
}

Foundry:

  • 调整foundry.toml文件如下
evm_version = 'paris'
英文:

With Solc version 0.8.20, the default EVM version is set to "Shanghai". A new opcode, PUSHO, was added to the Ethereum Virtual Machine in the Shanghai upgrade. That means the PUSH0 opcode can now be part of the contract's bytecode. If your private chain does not support it, it will error with the "Invalid opcode" error.

The solution is to manually set the EVM version to some previous version, for example, "Paris" (the version before, also known as The Merge), instead of "Shanghai", which is the default now.

Remix:

  • Go to the compilation tab
  • Toggle the "Advanced Configurations" dropdown
  • Toggle the "EVM VERSION" dropdown menu and select "paris" instead of "default"

Solc:

  • Run solc --evm-version &lt;VERSION&gt; &lt;CONTRACT&gt;
  • for example solc --evm-version paris contract.sol

Hardhat:

  • Adjust the hardhat config file like this
// hardhat.config.ts
solidity: {
    compilers: [
        {
            version: &#39;0.8.20&#39;,
            settings: {
                evmVersion: &#39;paris&#39;
            }
        }
    ]
}

Foundry:

  • Adjust the foundry.toml file like this
evm_version = &#39;paris&#39;

huangapple
  • 本文由 发表于 2023年5月25日 11:14:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76328677.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定