admin管理员组

文章数量:1332872

I have this contract:

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

contract CampaignFactory {
    address[] public deployedCampaigns;

    function createCampaign(uint minimum) public {
        address newCampaign = address(new Campaign(minimum, msg.sender));
        deployedCampaigns.push(newCampaign);
    }

    function getDeployedCampaigns() public view returns(address[] memory) {
        return deployedCampaigns;
    }
}

contract Campaign {
    struct Request {
        string description;
        uint value;
        address recipient;
        bool plete;
        uint approvalCount;
        mapping(address => bool) approvals;
    }

    Request[] public requests;
    address public manager;
    uint public minimumContribution;
    mapping(address => bool) public approvers;
    uint public approversCount;

    modifier restricted() {
        require(msg.sender == manager);
        _;
    }

    constructor(uint minimum, address creator) {
        manager = creator;
        minimumContribution = minimum;
    }

    function contribute() public payable {
        require(msg.value > minimumContribution);

        approvers[msg.sender] = true;
        approversCount++;
    }

    function createRequest(string calldata description, uint value, address recipient) public restricted {
        Request storage newRequest = requests.push();
        newRequest.description = description;
        newRequest.value = value;
        newRequest.recipient = recipient;
        newRequestplete = false;
        newRequest.approvalCount = 0;
    }

    function approveRequest(uint index) public {
        Request storage request = requests[index];

        require(approvers[msg.sender]);
        require(!request.approvals[msg.sender]);

        request.approvals[msg.sender] = true;
        request.approvalCount++;
    }

    function finalizeRequest(uint index) public restricted {
        Request storage request = requests[index];

        require(request.approvalCount > (approversCount / 2));
        require(!requestplete);

        payable(request.recipient).transfer(request.value); 
        requestplete = true;
    }
}

And test:

const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider());

const piledFactory = require('../ethereum/build/CampaignFactory.json');
const piledCampaign = require('../ethereum/build/Campaign.json');

let accounts;
let factory;
let campaignAddress;
let campaign;

beforeEach(async() => {
    accounts = await web3.eth.getAccounts();

    web3.eth.getBalance(accounts[0]).then(result => console.log(result));

    factory = await new web3.eth.Contract(piledFactory.abi)
        .deploy({ data: piledFactory.evm.bytecode.object })
        .send({ from: accounts[0], gas: '1000000' });

    await factory.methods.createCampaign('100').send({
        from: accounts[0],
        gas: '1000000'
    });

    [campaignAddress] = await factory.methods.getDeployedCampaigns().call();
    campaign = await new web3.eth.Contract(
        JSON.parse(piledCampaign.interface),
        campaignAddress
    );
});

describe('Campaigns', () => {
    it('deploys a factory and a campaign', () => {
        assert.ok(factory.options.address);
        assert.ok(campaign.options.address);
    });
});

When I run the test, I get VM Exception while processing transaction: out of gas, but it logs that accounts[0] balance is 100000000000000000000. The problem occurs where the factory is assigned a new contract instance saying there isn't enough gas, while there clearly is.

I have this contract:

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

contract CampaignFactory {
    address[] public deployedCampaigns;

    function createCampaign(uint minimum) public {
        address newCampaign = address(new Campaign(minimum, msg.sender));
        deployedCampaigns.push(newCampaign);
    }

    function getDeployedCampaigns() public view returns(address[] memory) {
        return deployedCampaigns;
    }
}

contract Campaign {
    struct Request {
        string description;
        uint value;
        address recipient;
        bool plete;
        uint approvalCount;
        mapping(address => bool) approvals;
    }

    Request[] public requests;
    address public manager;
    uint public minimumContribution;
    mapping(address => bool) public approvers;
    uint public approversCount;

    modifier restricted() {
        require(msg.sender == manager);
        _;
    }

    constructor(uint minimum, address creator) {
        manager = creator;
        minimumContribution = minimum;
    }

    function contribute() public payable {
        require(msg.value > minimumContribution);

        approvers[msg.sender] = true;
        approversCount++;
    }

    function createRequest(string calldata description, uint value, address recipient) public restricted {
        Request storage newRequest = requests.push();
        newRequest.description = description;
        newRequest.value = value;
        newRequest.recipient = recipient;
        newRequest.plete = false;
        newRequest.approvalCount = 0;
    }

    function approveRequest(uint index) public {
        Request storage request = requests[index];

        require(approvers[msg.sender]);
        require(!request.approvals[msg.sender]);

        request.approvals[msg.sender] = true;
        request.approvalCount++;
    }

    function finalizeRequest(uint index) public restricted {
        Request storage request = requests[index];

        require(request.approvalCount > (approversCount / 2));
        require(!request.plete);

        payable(request.recipient).transfer(request.value); 
        request.plete = true;
    }
}

And test:

const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider());

const piledFactory = require('../ethereum/build/CampaignFactory.json');
const piledCampaign = require('../ethereum/build/Campaign.json');

let accounts;
let factory;
let campaignAddress;
let campaign;

beforeEach(async() => {
    accounts = await web3.eth.getAccounts();

    web3.eth.getBalance(accounts[0]).then(result => console.log(result));

    factory = await new web3.eth.Contract(piledFactory.abi)
        .deploy({ data: piledFactory.evm.bytecode.object })
        .send({ from: accounts[0], gas: '1000000' });

    await factory.methods.createCampaign('100').send({
        from: accounts[0],
        gas: '1000000'
    });

    [campaignAddress] = await factory.methods.getDeployedCampaigns().call();
    campaign = await new web3.eth.Contract(
        JSON.parse(piledCampaign.interface),
        campaignAddress
    );
});

describe('Campaigns', () => {
    it('deploys a factory and a campaign', () => {
        assert.ok(factory.options.address);
        assert.ok(campaign.options.address);
    });
});

When I run the test, I get VM Exception while processing transaction: out of gas, but it logs that accounts[0] balance is 100000000000000000000. The problem occurs where the factory is assigned a new contract instance saying there isn't enough gas, while there clearly is.

Share edited Aug 23, 2022 at 17:32 TylerH 21.1k78 gold badges79 silver badges112 bronze badges asked Jan 11, 2022 at 10:07 Andrija GajicAndrija Gajic 3824 silver badges17 bronze badges 3
  • Double check how you provide gas and/or gas fees. It sounds like the problem lies there, not in your contract implementation. – Marko Popovic Commented Jan 11, 2022 at 13:17
  • @MarkoPopovic what do you mean how do I provide gas? I am using web3 account that you get with web3 library. So far I haven't had any issues with writing my tests this way. – Andrija Gajic Commented Jan 11, 2022 at 20:52
  • Does this answer your question? VM Exception while processing transaction: out of gas – TylerH Commented Aug 23, 2022 at 17:33
Add a ment  | 

2 Answers 2

Reset to default 8

Where you have .send({ from: accounts[0], gas: '1000000' }), you are specifying that a maximum of 1000000 gas can be used to process that transaction, regardless of the balance of the from account.

If you're deploying a large enough contract, this amount will be too small. Increasing this amount should resolve the issue.

Note, if the number you specify for gas is larger than the amount actually used, the difference will be refunded.

Please update the gasLimit.

test/Campaign.test.js

const assert = require("assert");
const ganache = require("ganache-cli");
const Web3 = require("web3");

const options = {
  gasLimit: 10000000,
};
const web3 = new Web3(ganache.provider(options));

const piledFactory = require("../build/CampaignFactory.json");
const piledCampaign = require("../build/Campaign.json");

let accounts;
let factory;
let campaignAddress;
let campaign;

beforeEach(async () => {
  accounts = await web3.eth.getAccounts();

  factory = await new web3.eth.Contract(piledFactory.abi)
    .deploy({ data: piledFactory.evm.bytecode.object })
    .send({ from: accounts[0], gas: "10000000" });

  await factory.methods.createCampaign("100").send({
    from: accounts[0],
    gas: "10000000",
  });

  [campaignAddress] = await factory.methods.getDeployedCampaigns().call();

  campaign = await new web3.eth.Contract(piledCampaign.abi, campaignAddress);
});

describe("Campaigns", () => {
  it("deploys a factory and a campaign", () => {
    assert.ok(factory.options.address);
    assert.ok(campaign.options.address);
  });
});

It works for me!

本文标签: javascriptweb3VM Exception while processing transaction out of gasStack Overflow