I'm trying to test my contract but I'm receiving this error:
Events
✔ deploys a factory and an event
✔ marks caller as the event manager
1) allows the user to buy a ticket and stores their details
2 passing (1s)
1 failing
1) Events
allows the user to buy a ticket and stores their details:
c: VM Exception while processing transaction: out of gas
at Function.c.fromResults (node_modules/ganache-cli/build/ganache-core.node.cli.js:4:192416)
at w.processBlock (node_modules/ganache-cli/build/ganache-core.node.cli.js:42:50915)
at processTicksAndRejections (internal/process/task_queues.js:94:5)
However, when looking over my code I believe I have more than enough gas and perhaps this error has to do with something else.
Here is the code for my test:
const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider({ gasLimit: 10000000 }));
const compiledFactory = require("../ethereum/build/EventFactory.json");
const compiledCampaign = require("../ethereum/build/Event.json");
let accounts;
let factory;
let eventAddress;
let event;
beforeEach(async () => {
accounts = await web3.eth.getAccounts();
factory = await new web3.eth.Contract(JSON.parse(compiledFactory.interface))
.deploy({ data: compiledFactory.bytecode })
.send({ from: accounts[0], gas: "10000000" });
await factory.methods.createEvent("test event", 2, 1, "Elton John's world tour", "Faketown auditorium", 100).send({
from: accounts[0],
gas: "10000000",
});
[eventAddress] = await factory.methods.getDeployedEvents().call();
event = await new web3.eth.Contract(
JSON.parse(compiledCampaign.interface),
eventAddress
);
});
describe("Events", () => {
it("deploys a factory and an event", () => {
assert.ok(factory.options.address);
assert.ok(event.options.address);
});
it("marks caller as the event manager", async () => {
const manager = await event.methods.manager().call();
assert.equal(accounts[0], manager);
});
it("allows the user to buy a ticket and stores their details", async () => {
await event.methods.buyTicket('Louie').send({
value: '1',
from: accounts[1]
});
const isContributor = await event.methods.attendees(account[1]).call();
assert(isContributor);
});
});
As you can see, my first two tests pass. However the third does not work. I believe I am providing enough gas. Here is my contract so you can look at the functions:
pragma solidity ^0.4.17;
contract EventFactory {
address[] public deployedEvents;
function createEvent(string title, uint max, uint cost, string description, string location, uint date) public {
address newEvent = new Event(title, msg.sender, max, cost, description, location, date);
deployedEvents.push(newEvent);
}
function getDeployedEvents() public view returns (address[]) {
return deployedEvents;
}
}
contract Event {
struct Attendee {
bool valid;
string name;
uint ticketNumber;
bool confirmed;
uint amountPaid;
uint confirmationCode;
}
address public manager;
string public title;
uint public maxAttendees;
uint public ticketsSold;
mapping(address=>Attendee) public attendees;
uint public ticketCost;
string public eventDescription;
string public eventLocation;
uint public eventDate;
mapping(address=>bool) public blacklist;
modifier restricted() {
require(msg.sender == manager);
_;
}
function random(uint seed) private view returns (uint) {
uint tmp = uint(block.blockhash(block.number - 1));
return uint(keccak256(tmp,seed)) % 1000000000;
}
function Event(string eventTitle, address creator, uint max, uint cost, string description, string location, uint date) public {
title = eventTitle;
manager = creator;
maxAttendees = max;
ticketsSold = 0;
ticketCost = cost;
eventDescription = description;
eventLocation = location;
eventDate = date;
}
function buyTicket(string name) public payable {
require(blacklist[msg.sender] != true);
require(ticketsSold != maxAttendees);
require(attendees[msg.sender].valid == false);
require(msg.value == ticketCost);
Attendee memory attendee = Attendee({
valid: true,
name: name,
ticketNumber: (maxAttendees - ticketsSold),
confirmed: false,
amountPaid: ticketCost,
confirmationCode: 0
});
ticketsSold++;
attendees[msg.sender] = attendee;
}
function challengeAttendee(address attendee, uint seed) public restricted returns (uint) {
require(attendees[attendee].valid == true);
uint code = random(seed);
attendees[attendee].confirmationCode = code;
return code;
}
function confirmTicketOwnerShip(uint code) public {
require(attendees[msg.sender].confirmationCode != 0);
attendees[msg.sender].confirmed = attendees[msg.sender].confirmationCode == code;
}
function confirmResponse(address attendee) public restricted view returns (bool) {
return attendees[attendee].confirmed;
}
function addToBlackList(address blockedAddress) public restricted {
blacklist[blockedAddress] = true;
}
function getEventDetails() public view returns (string, uint, uint, uint, string, string, uint) {
return (
title,
maxAttendees,
ticketsSold,
ticketCost,
eventDescription,
eventLocation,
eventDate
);
}
}
I've found the error, unfortunately, it's simply a typo. On the sixth line down I use account[1] not accounts[1]. Also I had to specify the gas as the default amount was not enough.
My code now looks like:
it("allows the user to buy a ticket and stores their details", async () => {
await event.methods.buyTicket("Louie").send({
from: accounts[1],
value: '1',
gas: '20000000'
});
const isContributor = await event.methods.attendees(accounts[1]).call();
assert(isContributor.valid);
});