When sending a transaction using web3 I recive EIP1559FeeMarketTransaction.fillFromResult error

198 views Asked by At

I am using a ganache local blockchain and truffle to test my smart contracts, this problem started to occur all of a sudden, since before I wasn't running into this problem. So when I call the mintItems function using web3 js I get the EIP1559FeeMarketTransaction.fillFromResult error. Can anyone please help

This is the full error message:

    ResponseError: Returned error: [ethjs-query] while formatting outputs from RPC '{"value":{"code":-32603,"data":{"message":"VM Exception while processing transaction: revert","stack":"RuntimeError: VM Exception while processing transaction: revert\n    at EIP1559FeeMarketTransaction.fillFromResult (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:12745)\n    at Miner.<anonymous> (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:36703)\n    at async Miner.<anonymous> (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:35116)\n    at async Miner.mine (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:39680)\n    at async Blockchain.mine (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:60063)\n    at async Promise.all (index 0)\n    at async TransactionPool.emit (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\node_modules\\emittery\\index.js:303:3)","code":-32000,"name":"RuntimeError","data":{"hash":"0x4ea759cfd57e77e10baf6eb1d762f86a19580af73867b4e43e192cff8d369725","programCounter":238,"result":"0x4ea759cfd57e77e10baf6eb1d762f86a19580af73867b4e43e192cff8d369725","reason":null,"message":"revert"}}}}'
    at Web3RequestManager.<anonymous> (web3_request_manager.ts:163:1)
    at Generator.next (<anonymous>)
    at fulfilled (web3_request_manager.ts:1:1)

This is the smart contract I am calling:

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

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "./Interfaces/ISaleTokens.sol";

contract SaleTokens is ERC1155, ISaleTokens {
    constructor() ERC1155("doesn't matter") {}

    struct Token {
        string _tokenURI;
        address _tokenMinter;
    }
    mapping(uint256 => Token) private _tokens;
    uint256 tokenId = 0;

    function setTokenURI(uint256 _tokenId, string memory _uri) private {
        _tokens[_tokenId]._tokenURI = _uri;
    }

    function mintItems(uint256 numItems, string memory metadataURI)
        public
        override
    {
        bool isNew = true;
        uint256 currentTokenId = 0;
        for (uint256 i = 1; i <= tokenId; i++) {
            if (stringsEquals(_tokens[i]._tokenURI, metadataURI)) {
                isNew = false;
                currentTokenId = i;
                break;
            }
        }
        bytes memory byteMetadata = bytes(metadataURI);
        if (isNew || _tokens[currentTokenId]._tokenMinter != msg.sender) {
            tokenId++;
            currentTokenId = tokenId;
            setTokenURI(currentTokenId, metadataURI);
            _tokens[currentTokenId]._tokenMinter = msg.sender;
            _mint(msg.sender, currentTokenId, numItems, byteMetadata);
        } else if (
            !isNew && _tokens[currentTokenId]._tokenMinter == msg.sender
        ) {
            setTokenURI(currentTokenId, metadataURI);
            _mint(msg.sender, currentTokenId, numItems, byteMetadata);
        }
    }

    function stringsEquals(string memory s1, string memory s2)
        private
        pure
        returns (bool)
    {
        bytes memory b1 = bytes(s1);
        bytes memory b2 = bytes(s2);
        uint256 l1 = b1.length;
        if (l1 != b2.length) return false;

        return keccak256(b1) == keccak256(b2);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount
    ) public virtual override {
        require(
            from == _msgSender() || isApprovedForAll(from, _msgSender()),
            "ERC1155: caller is not token owner or approved"
        );
        _safeTransferFrom(from, to, id, amount, "");
    }

    function editToken(uint256 _tokenId, string calldata newURI) public override {
        require(_tokenId <= tokenId && _tokenId > 0, "Invalid token, or token does not exist.");
        require(_tokens[_tokenId]._tokenMinter == msg.sender, "Only token minter can edit token.");
        require(keccak256(abi.encodePacked(_tokens[_tokenId]._tokenURI)) != keccak256(abi.encodePacked(newURI)), "New URI must be different to oroginal URI");

        _tokens[_tokenId]._tokenURI = newURI;
    }

    function uri(uint256 tokenNum)
        public
        view
        override
        returns (string memory)
    {
        return _tokens[tokenNum]._tokenURI;
    }

    function getLastTokenId() public view override returns (uint256) {
        return tokenId;
    }

    function burn(uint256 _tokenId, uint256 amount) public override {
        _burn(msg.sender, _tokenId, amount);
    }

    function getMinter(uint256 _tokenId) public view returns (address) {
        return _tokens[_tokenId]._tokenMinter;
    }
}

This is the js code that handles the web3 transactions

import Web3 from "web3";
import SaleTokenContract from "contracts/SaleTokens.json"
import MarketContract from "contracts/Market.json"


let selectedAccount;
let SaleTokenAddress;
let SaleToken;
let Market;
let MarketAddress;
export const init = async () => {
    let provider = window.ethereum;

    if(typeof provider !== 'undefined'){
      //metamask is installed

      provider.request({method: "eth_requestAccounts"})
      .then(accounts => {
        selectedAccount = accounts[0]
        // console.log(`Selected account is ${selectedAccount}`);
      })
      .catch(err => {
        console.log(err);
      })
      window.ethereum.on('accountsChanged', function(accounts){
        selectedAccount = accounts[0]
        // console.log(`Selected changed to ${selectedAccount}`);
      })
    }

    const web3 = new Web3(provider);

    const networkId = await web3.eth.net.getId();
    SaleTokenAddress = SaleTokenContract.networks[networkId].address
    MarketAddress = MarketContract.networks[networkId].address
    SaleToken = new web3.eth.Contract(SaleTokenContract.abi, SaleTokenAddress)
    Market = new web3.eth.Contract(MarketContract.abi, MarketAddress)
};

export const mintItems = (itemNum, tokenURI) => {
    return SaleToken.methods.mintItems(itemNum, tokenURI).send({ from: selectedAccount });
}

export const editToken = (tokenNumber, tokenURI) => {
  return SaleToken.methods.mintItems(tokenNumber, tokenURI).send({from: selectedAccount })
}

export const approve = (doAllow) => {
  return SaleToken.methods.setApprovalForAll(MarketAddress, doAllow).send({ from: selectedAccount });
}
export const getTokenURI = (tokenID) => {
  return SaleToken.methods.uri(tokenID).call();
}
export const getTokenCounter = () => {
    return SaleToken.methods.getLastTokenId().call();
}
export const getItemMinter = (tokenID) => {
    return SaleToken.methods.getMinter(tokenID).call();
}

export const editProductToken = (tokenID, newURI) => {
  return SaleToken.methods.editToken(tokenID, newURI).send({ from: selectedAccount });
}

export const listingNum = () =>{
  return Market.methods.getNumOfListings().call();
}

export const listingPrice = (_listingId) =>{
  return Market.methods.getTokenPrice(_listingId).call();
}

export const listingStock = (_listingId) =>{
  return Market.methods.getTokenStock(_listingId).call();
}

export const listingSearchTerms = (_listingId) =>{
  return Market.methods.getTokenSearchTerms(_listingId).call();
}

export const getListingTokenURI = (_listingId) =>{
  return Market.methods.getListingTokenURI(_listingId).call();
}

export const getListingTokenId = (_listingId) =>{
  return Market.methods.getTokenId(_listingId).call();
}

export const getListingTokenSeller = (_listingId) =>{
  return Market.methods.getTokenSeller(_listingId).call();
}

export const listToken = (tokenID, price, stock, searchTerms) => {
    return Market.methods.listEditProduct(tokenID, stock, price, SaleTokenAddress, searchTerms, 0).send({ from: selectedAccount });
}

export const editListedToken = (tokenID, price, stock, searchTerms, tokenToEdit) => {
  return Market.methods.listEditProduct(tokenID, stock, price, SaleTokenAddress, searchTerms, tokenToEdit).send({ from: selectedAccount });
}

export const buyToken = (listingID, amountToBuy, amountToPay) => {
  return Market.methods.buyProduct(listingID, amountToBuy).send({ from: selectedAccount, value: amountToPay });
}

And this is my truffle-config

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>
   */

  networks: {
    // 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: 7545,            // Standard Ethereum port (default: none)
     network_id: "5777",       // 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.
    // mumbai: {
    //   provider: () => new HDWalletProvider(MNEMONIC, `https://polygon-mumbai.infura.io/v3/${PROJECT_ID}`),
    //   network_id: 80001,       // 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: "0.8.18" // Fetch exact version from solc-bin (default: truffle's version)
      // docker: true,        // Use "0.5.1" you've installed locally with docker (default: false)
      // settings: {          // See the solidity docs for advice about optimization and evmVersion
      //  optimizer: {
      //    enabled: false,
      //    runs: 200
      //  },
      //  evmVersion: "byzantium"
      // }
    }
  }

  // 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"
  //     }
  //   }
  // }
};

I tried running the contract on remix using metamask and ganache (for it to be consistent with web3 implementation) and found it works on remix, so I think this is a problem with my truffle config or js implementation.

0

There are 0 answers