“APIConsumer”在部署时遇到了无效的操作码 - Chainlink with Polygon in Truffle

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

我在使用 Truffle、VS Code 和 Metamask 在 Polygon 测试网上部署智能合约时遇到问题。合约在 Sepolia testnet 和 Remix IDE(Polygon) 上成功部署,但在 Polygon 上部署时抛出以下错误

"APIConsumer" hit an invalid opcode while deploying. Try:
   * Verifying that your constructor params satisfy all assert conditions.
   * Verifying your constructor code doesn't access an array out of bounds.
   * Adding reason strings to your assert statements.

我的智能合约代码如下:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol";

/**
 * @title The APIConsumer contract
 * @notice An API Consumer contract that makes GET requests to obtain 24h trading volume of ETH in USD
 */
contract APIConsumer is ChainlinkClient {
    using Chainlink for Chainlink.Request;

    string public volume;
    address private immutable oracle;
    string private jobId;
    uint256 private immutable fee;

    event DataFullfilled(string volume);

    
    constructor(
    ) {
        setChainlinkToken(0x326C977E6efc84E512bB9C30f76E30c160eD06FB);
        setChainlinkOracle(0xB7E946A727090285a2d5BC5A2D837bD45539d4c8);
        oracle = 0xB7E946A727090285a2d5BC5A2D837bD45539d4c8;
        jobId = "70717430666f4c0d8452ca6ceec0b656";
        fee = (1 * LINK_DIVISIBILITY) / 10; 
    }

    /**
     * @notice Creates a Chainlink request to retrieve API response, find the target
     * data, then multiply by 1000000000000000000 (to remove decimal places from data).
     *
     * @return requestId - id of the request
     */
    function requestVolumeData() public returns (bytes32 requestId) {
        Chainlink.Request memory request = buildChainlinkRequest(
            stringToBytes32(jobId),
            address(this),
            this.fulfill.selector
        );

        // Set the URL to perform the GET request on
       
        // Multiply the result by 1000000000000000000 to remove decimals
 

        // Sends the request
        return sendChainlinkRequestTo(oracle, request, fee);
    }

    function stringToBytes32(
        string memory source
    ) private pure returns (bytes32 result) {
        bytes memory tempEmptyStringTest = bytes(source);
        if (tempEmptyStringTest.length == 0) {
            return 0x0;
        }

        assembly {
            // solhint-disable-line no-inline-assembly
            result := mload(add(source, 32))
        }
    }

    /**
     * @notice Receives the response in the form of uint256
     *
     * @param _requestId - id of the request
     * @param _volume - response; requested 24h trading volume of ETH in USD
     */
    function fulfill(
        bytes32 _requestId,
        string memory _volume
    ) public recordChainlinkFulfillment(_requestId) {
        volume = _volume;
        emit DataFullfilled(volume);
    }

    function read() public view returns (string memory) {
        return volume;
    }

    /**
     * @notice Witdraws LINK from the contract
     * @dev Implement a withdraw function to avoid locking your LINK in the contract
     */
    function withdrawLink() external {}
}

我的迁移文件 - 1_deploy_simple_storage.js 文件

const APIConsumer = artifacts.require("APIConsumer")
const LinkToken = artifacts.require("LinkToken")
const MockOracle = artifacts.require("MockOracle")
const web3 = require("web3")

const { networkConfig, developmentChains } = require("../helper-truffle-config")
const { fundContractWithLink } = require("../scripts/utils/fundContract")

module.exports = async function (deployer, network, accounts) {
    let oracle, linkTokenAddress

    if (developmentChains.includes(network)) {
        const linkToken = await LinkToken.deployed()
        const mockOracle = await MockOracle.deployed()
        linkTokenAddress = linkToken.address
        oracle = mockOracle.address
    } else {
        console.log(networkConfig[network])
        linkTokenAddress = networkConfig[network]["linkToken"]
        oracle = networkConfig[network]["oracle"]
    }
    const jobId = web3.utils.toHex(networkConfig[network]["jobId"])
    const fee = networkConfig[network]["fee"]

    await deployer.deploy(APIConsumer)
    console.log("API Consumer Deployed!")

    console.log("Let's fund the contract with Link...")
    const apiConsumer = await APIConsumer.deployed()

    await fundContractWithLink(apiConsumer.address, network)
}

helper-truffle-config

const networkConfig = {
    test: {
        fee: "100000000000000000",
        keyHash: "0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc",
        jobId: "29fa9aa13bf1468788b7cc4a500a45b8",
        fundAmount: "1000000000000000000",
        keepersUpdateInterval: "30",
        ethUsdPriceFeed: "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419",
    },
    ganache: {
        fee: "100000000000000000",
        keyHash: "0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc",
        jobId: "29fa9aa13bf1468788b7cc4a500a45b8",
        fundAmount: "1000000000000000000",
        keepersUpdateInterval: "30",
        ethUsdPriceFeed: "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419",
    },
    goerli: {
        chainId: "5",
        linkToken: "0x326C977E6efc84E512bB9C30f76E30c160eD06FB",
        ethUsdPriceFeed: "0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e",
        keyHash: "0x79d3d8832d904592c0bf9818b621522c988bb8b0c05cdc3b15aea1b6e8db0c15",
        vrfCoordinator: "0x2Ca8E0C643bDe4C2E08ab1fA0da3401AdAD7734D",
        oracle: "0xCC79157eb46F5624204f47AB42b3906cAA40eaB7",
        jobId: "ca98366cc7314957b8c012c72f05aeeb",
        fee:        "11000000000000000",
        fundAmount: "11000000000000000", // 0.1
        keepersUpdateInterval: "30",
        subId: "52", // add your subscription Id here!
    },
    sepolia: {
        chainId: "11155111",
        linkToken: "0x779877A7B0D9E8603169DdbD7836e478b4624789",
        ethUsdPriceFeed: "0x694AA1769357215DE4FAC081bf1f309aDC325306",
        keyHash: "0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c",
        vrfCoordinator: "0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625",
        oracle: "0x3016e3b55bF31cC50E78933Fb536efD2B29ed3bE",
        jobId: "c3c788ba52ba4ee387eeef344d77c793",
        fee:        "11000000000000000",
        fundAmount: "11000000000000000", // 0.1
        keepersUpdateInterval: "30",
        subId: "52", // add your subscription Id here!
    },
    polygon: {
        chainId: "80001",
        linkToken: "0x326C977E6efc84E512bB9C30f76E30c160eD06FB",
        ethUsdPriceFeed: "0xF9680D99D6C9589e2a93a78A04A279e509205945",
        keyHash: "0x4b09e658ed251bcafeebbc69400383d49f344ace09b9576fe248bb02c003fe9f",
        oracle: "0x40193c8518BB267228Fc409a613bDbD8eC5a97b3",
        jobId: "7d80a6386ef543a3abb52817f6707e3b",
        fee: "2500000",
        fundAmount: "100000000000000000", // 0.1
        keepersUpdateInterval: "30",
        // subId: "52", // add your subscription Id here!
    },
    rinkeby: {
        chainId: "4",
        linkToken: "0x01be23585060835e02b77ef475b0cc51aa1e0709",
        ethUsdPriceFeed: "0x8A753747A1Fa494EC906cE90E9f37563A8AF630e",
        keyHash: "0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc",
        vrfCoordinator: "0x6168499c0cFfCaCD319c818142124B7A15E857ab",
        oracle: "0xc57b33452b4f7bb189bb5afae9cc4aba1f7a4fd8",
        jobId: "6b88e0402e5d415eb946e528b8e0c7ba",
        fee: "100000000000000000",
        fundAmount: "100000000000000000", // 0.1
        keepersUpdateInterval: "30",
        subId: "0", // add your subscription Id here!
    },
}

const developmentChains = ["test", "development", "ganache"]

module.exports = {
    networkConfig,
    developmentChains,
}

truffle-config.js

/**
 * Use this file to configure your truffle project. It's seeded with some
 * common settings for different networks and features like migrations,
 * compilation, and testing. Uncomment the ones you need or modify
 * them to suit your project as necessary.
 *
 * More information about configuration can be found at:
 *
 * https://trufflesuite.com/docs/truffle/reference/configuration
 *
 * Hands-off deployment with Infura
 * --------------------------------
 *
 * Do you have a complex application that requires lots of transactions to deploy?
 * Use this approach to make deployment a breeze 🏖️:
 *
 * Infura deployment needs a wallet provider (like @truffle/hdwallet-provider)
 * to sign transactions before they're sent to a remote public node.
 * Infura accounts are available for free at 🔍: https://infura.io/register
 *
 * You'll need a mnemonic - the twelve word phrase the wallet uses to generate
 * public/private key pairs. You can store your secrets 🤐 in a .env file.
 * In your project root, run `$ npm install dotenv`.
 * Create .env (which should be .gitignored) and declare your MNEMONIC
 * and Infura PROJECT_ID variables inside.
 * For example, your .env file will have the following structure:
 *
 * MNEMONIC = <Your 12 phrase mnemonic>
 * PROJECT_ID = <Your Infura project id>
 *
 * Deployment with Truffle Dashboard (Recommended for best security practice)
 * --------------------------------------------------------------------------
 *
 * Are you concerned about security and minimizing rekt status 🤔?
 * Use this method for best security:
 *
 * Truffle Dashboard lets you review transactions in detail, and leverages
 * MetaMask for signing, so there's no need to copy-paste your mnemonic.
 * More details can be found at 🔎:
 *
 * https://trufflesuite.com/docs/truffle/getting-started/using-the-truffle-dashboard/
 */

// require('dotenv').config();
// const { MNEMONIC, PROJECT_ID } = process.env;

// const HDWalletProvider = require('@truffle/hdwallet-provider');

const HDWalletProvider = require("@truffle/hdwallet-provider")
require("dotenv").config()

const privateKey = process.env.PRIVATE_KEY
// These are the keys auto-generated from running `ganache -d`
const GOERLI_RPC_URL =
    process.env.GOERLI_RPC_URL || "https://eth-goerli.alchemyapi.io/v2/your-api-key"
const SEPOLIA_RPC_URL =
    process.env.SEPOLIA_RPC_URL || "https://eth-goerli.alchemyapi.io/v2/your-api-key"
    console.log(process.env.GOERLI_RPC_URL);
const POLYGON_RPC_URL =
    process.env.POLYGON_RPC_URL

module.exports = {
  /**
   * Networks define how you connect to your ethereum client and let you set the
   * defaults web3 uses to send transactions. If you don't specify one truffle
   * will spin up a managed Ganache instance for you on port 9545 when you
   * run `develop` or `test`. You can ask a truffle command to use a specific
   * network from the command line, e.g
   *
   * $ truffle test --network <network-name>
   */

  contracts_build_directory: "../client/src/contracts",
  networks: {
    ganache: {
      // provider: () => new HDWalletProvider(ganachePrivateKeys, "http://127.0.0.1:7545"),
      host: "127.0.0.1", // Localhost (default: none)
      port: 7545, // Standard Ethereum port (default: none)
      network_id: "5777", // Any network (default: none)
      // confirmations: 0,
  },
  goerli: {
    provider: () => new HDWalletProvider(privateKey, GOERLI_RPC_URL),
    network_id: 5, // Goerli's id
    confirmations: 1, // # of confirmations to wait between deployments. (default: 0)
    timeoutBlocks: 20000000000, // # of blocks before a deployment times out  (minimum/default: 50)
    skipDryRun: true, // Skip dry run before migrations? (default: false for public nets ),
    networkCheckTimeout: 100000000,
    timeoutBlocks: 2000000000
},
polygon: {
  provider: () => new HDWalletProvider(privateKey, POLYGON_RPC_URL),
  network_id: 80001,
      confirmations: 2,
      timeoutBlocks: 200,
      skipDryRun: true,
      networkCheckTimeout: 9000000,
      pollingInterval: 1800000,
      disableConfirmationListener: true
},
  sepolia: {
    provider: () => new HDWalletProvider(privateKey, SEPOLIA_RPC_URL),
    network_id: 11155111, // Goerli's id
    confirmations: 1, // # of confirmations to wait between deployments. (default: 0)
    timeoutBlocks: 20000000000, // # of blocks before a deployment times out  (minimum/default: 50)
    skipDryRun: true, // Skip dry run before migrations? (default: false for public nets ),
    networkCheckTimeout: 100000000,
    timeoutBlocks: 2000000000
},
    // Useful for testing. The `development` name is special - truffle uses it by default
    // if it's defined here and no other network is specified at the command line.
    // You should run a client (like ganache, geth, or parity) in a separate terminal
    // tab if you use this network and you must also set the `host`, `port` and `network_id`
    // options below to some value.
    //
    // development: {
    //  host: "127.0.0.1",     // Localhost (default: none)
    //  port: 8545,            // Standard Ethereum port (default: none)
    //  network_id: "*",       // Any network (default: none)
    // },
    //
    // An additional network, but with some advanced options…
    // advanced: {
    //   port: 8777,             // Custom port
    //   network_id: 1342,       // Custom network
    //   gas: 8500000,           // Gas sent with each transaction (default: ~6700000)
    //   gasPrice: 20000000000,  // 20 gwei (in wei) (default: 100 gwei)
    //   from: <address>,        // Account to send transactions from (default: accounts[0])
    //   websocket: true         // Enable EventEmitter interface for web3 (default: false)
    // },
    //
    // Useful for deploying to a public network.
    // Note: It's important to wrap the provider as a function to ensure truffle uses a new provider every time.
    // goerli: {
    //   provider: () => new HDWalletProvider(MNEMONIC, `https://goerli.infura.io/v3/${PROJECT_ID}`),
    //   network_id: 5,       // Goerli's id
    //   confirmations: 2,    // # of confirmations to wait between deployments. (default: 0)
    //   timeoutBlocks: 200,  // # of blocks before a deployment times out  (minimum/default: 50)
    //   skipDryRun: true     // Skip dry run before migrations? (default: false for public nets )
    // },
    //
    // Useful for private networks
    // private: {
    //   provider: () => new HDWalletProvider(MNEMONIC, `https://network.io`),
    //   network_id: 2111,   // This network is yours, in the cloud.
    //   production: true    // Treats this network as if it was a public net. (default: false)
    // }
  },

  // Set default mocha options here, use special reporters, etc.
  mocha: {
    // timeout: 100000
  },

  // Configure your compilers
  compilers: {
    solc: {
        version: "pragma", // Fetch exact version from solc-bin (default: truffle's version)
        settings: {
            optimizer: {
                enabled: false,
                runs: 200,
            },
        },
    },
},

  // Truffle DB is currently disabled by default; to enable it, change enabled:
  // false to enabled: true. The default storage location can also be
  // overridden by specifying the adapter settings, as shown in the commented code below.
  //
  // NOTE: It is not possible to migrate your contracts to truffle DB and you should
  // make a backup of your artifacts to a safe location before enabling this feature.
  //
  // After you backed up your artifacts you can utilize db by running migrate as follows:
  // $ truffle migrate --reset --compile-all
  //
  // db: {
  //   enabled: false,
  //   host: "127.0.0.1",
  //   adapter: {
  //     name: "indexeddb",
  //     settings: {
  //       directory: ".db"
  //     }
  //   }
  // }
};
  

我尝试删除所有构造函数参数和断言语句,但似乎没有任何效果。任何形式的帮助表示赞赏。谢谢!

polygon smartcontracts truffle chainlink
© www.soinside.com 2019 - 2024. All rights reserved.