web3 - 处理事务时出现 VM 异常:gas 耗尽
web3 - VM Exception while processing transaction: out of gas
我有这份合同:
// 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 complete;
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.complete = 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.complete);
payable(request.recipient).transfer(request.value);
request.complete = true;
}
}
并测试:
const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider());
const compiledFactory = require('../ethereum/build/CampaignFactory.json');
const compiledCampaign = 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(compiledFactory.abi)
.deploy({ data: compiledFactory.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(compiledCampaign.interface),
campaignAddress
);
});
describe('Campaigns', () => {
it('deploys a factory and a campaign', () => {
assert.ok(factory.options.address);
assert.ok(campaign.options.address);
});
});
当我 运行 测试时,我在处理交易时遇到 VM 异常:gas 耗尽,但它记录帐户[0] 余额为 100000000000000000000。问题发生在工厂被分配了新合同的地方例如说没有足够的汽油,而显然有。
在你有 .send({ from: accounts[0], gas: '1000000' })
的地方,你指定最多 1000000
gas 可用于处理该交易,而不管 from
帐户的余额如何。
如果您要部署足够大的合约,这个数量就会太小。增加此数量应该可以解决问题。
请注意,如果您指定的gas数量大于实际使用的数量,将退还差额。
我有这份合同:
// 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 complete;
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.complete = 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.complete);
payable(request.recipient).transfer(request.value);
request.complete = true;
}
}
并测试:
const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider());
const compiledFactory = require('../ethereum/build/CampaignFactory.json');
const compiledCampaign = 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(compiledFactory.abi)
.deploy({ data: compiledFactory.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(compiledCampaign.interface),
campaignAddress
);
});
describe('Campaigns', () => {
it('deploys a factory and a campaign', () => {
assert.ok(factory.options.address);
assert.ok(campaign.options.address);
});
});
当我 运行 测试时,我在处理交易时遇到 VM 异常:gas 耗尽,但它记录帐户[0] 余额为 100000000000000000000。问题发生在工厂被分配了新合同的地方例如说没有足够的汽油,而显然有。
在你有 .send({ from: accounts[0], gas: '1000000' })
的地方,你指定最多 1000000
gas 可用于处理该交易,而不管 from
帐户的余额如何。
如果您要部署足够大的合约,这个数量就会太小。增加此数量应该可以解决问题。
请注意,如果您指定的gas数量大于实际使用的数量,将退还差额。