I am trying to test addition of an object to an array of struct like so:
describe("Create Horse", async function() {
it("horses struct array initialized with 0 horses", async function() {
expect(await stallionRace.horses.length).to.equal(0)
})
it.only("creates a horse and adds it to the struct array", async function() {
await stallionRace.createHorse("pony", 1, 1000000000)
expect(stallionRace.horses.length).to.be.greaterThan(0)
})
})
The function in the contract file looks like this:
function createHorse(string memory _name, uint8 _level, uint256 _price) public onlyOwner {
if(horses.length > 0) {
require(keccak256(bytes(horses[horses.length - 1].name)) != keccak256(bytes(_name)), "Another horse with this name already exists");
}
s_horseId = s_horseId + 1;
horses.push(Horse(s_horseId, _price, _level, _name));
emit HorseCreated(s_horseId, _price, _level, _name);
}
I am getting this error while testing with Chai:
AssertionError: expected +0 to be above +0
What could be the issue? Why is it not adding it to the array? Does it have something to do with the 'onlyOwner' modifier?
I tried this too:
const result = await stallionRace.createHorse("pony", 1, 1000000000, {from: this.currentOwner})
await result.wait(1)
But still failed.
Related
I am using ethers.js to call the mint function in my smart contract but it fails with this error:
Error: transaction failed [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ].
I am able to call the view functions this error only occurs when I call functions which make transactions. So, I know that I have connected to the same network as the contract.
My smart contract:
pragma solidity ^0.8.12;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract FutNFT is ERC721, ERC721Enumerable, Ownable {
struct Player {
string name;
string preferredPosition;
uint256 id;
uint8 age;
uint8 level;
uint64 lastUpgrade;
string[] suitablePositions;
string imageURI;
}
struct History {
uint256 winCount;
uint256 lossCount;
}
mapping(address => History) ownerHistory;
mapping(uint256 => Player) players;
mapping(uint256 => address) public playerToOwner;
mapping(uint256 => uint256) listedPlayerIndex;
uint256[] public listedPlayers;
event PlayerAdded(uint256 playerId);
modifier owned(uint256 id) {
require(getPlayerExists(id), "Player does not exist");
require(msg.sender == ownerOf(id), "Not the owner!");
_;
}
constructor() ERC721("FutNFT", "FNFT") {}
function getListedPlayers() public view returns (uint256[] memory) {
return listedPlayers;
}
function getPlayer(uint256 _id) public view returns (Player memory) {
return players[_id];
}
function ownerOf(uint256 tokenId)
public
view
override(ERC721, IERC721)
returns (address)
{
return super.ownerOf(tokenId);
}
function getPlayerExists(uint256 _id) public view returns (bool) {
return playerToOwner[_id] != address(0);
}
function mint(Player memory _player) public onlyOwner {
require(playerToOwner[_player.id] == address(0), "Player Exists!");
players[_player.id] = _player;
playerToOwner[_player.id] = msg.sender;
_mint(msg.sender, _player.id);
emit PlayerAdded(_player.id);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal override(ERC721, ERC721Enumerable) {
super._beforeTokenTransfer(from, to, tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
my frontend code:
const player: PlayerInterface = {
name: "Lionel Messi",
preferredPosition: "RWF",
id: 1,
age: 34,
level: 20,
lastUpgrade: new Date().getTime(),
suitablePositions: ["ST", "CF", "RMF", "CAM"],
imageURI:
"https://bafybeicfhmevzs4aso7rqvx7l5ndb2ly7gudjyj5xjkztvohpwxw2za7iy.ipfs.dweb.link/nft.png",
};
const provider = new ethers.providers.Web3Provider(
(window as any).ethereum
);
const signer = provider.getSigner();
const tx = await futNFT.connect(signer).mint(player, {
gasPrice: 30000000000,
gasLimit: 2000000,
});
await tx.wait();
console.log("minted");
const player1 = await futNFT.getPlayer(1);
console.log(player1);
test.js file. I've tried installing/ uninstalling all different/previous versions of solidity but nothing is working properly. I am getting this TypeError: Cannot destructure property 'interface' of 'require(...)' as it is undefined. repeatedly. Please help me regarding this problem
const assert = require("assert");
const ganache = require("ganache-cli");
const Web3 = require("web3");
const web3 = new Web3(ganache.provider());
const { interface, bytecode } = require('../compile');
let lottery;
let accounts;
beforeEach(async () => {
accounts = await web3.eth.getAccounts();
lottery = await new web3.eth.Contract(JSON.parse(interface))
.deploy({ data: bytecode })
.send({ from: accounts[0], gas: "1000000" });
});
describe('Lottery Contract', () => {
it('deploys a contract', () => {
assert.ok(lottery.options.address);
});
});
compile.js file. Error while I try to run my compile.js file. Using command "npm run test". Please help me regarding this problem.
const path = require("path");
const fs = require("fs");
const solc = require("solc");
const lotteryPath = path.resolve(__dirname, "contracts", "Lottery.sol");
const source = fs.readFileSync(lotteryPath, "utf8");
// console.log(solc.compile(source, 1));
module.exports = solc.compile(source, 1).contracts[":Lottery"];
deploy.js file
const HDWalletProvider = require("#truffle/hdwallet-provider");
const Web3 = require("web3");
const { interface, bytecode } = require("./compile");
const provider = new HDWalletProvider(
"**************************************************",
"https://rinkeby.infura.io**************************"
);
const web3 = new Web3(provider);
const deploy = async () => {
const accounts = await web3.eth.getAccounts();
console.log("Attempting to deploy from accoutns", accounts[0]);
const result = await new web3.eth.Contract(JSON.parse(interface))
.deploy({ data: bytecode})
.send({ gas: "1000000", from: accounts[0] });
console.log("Contract deployed to", result.options.address);
};
lottery.sol file
pragma solidity ^0.8.7; // latest solidity version...
contract Lottery
{
address public manager;
address[] public players;
constructor()
{
manager = msg.sender;
}
function enter() public payable
{
require(msg.value > .01 ether);
players.push(msg.sender);
}
function random() private view returns (uint256)
{
return
uint256(keccak256(abi.encodePacked(block.difficulty, block.timestamp, players)));
}
function pickWinner() public restricted
{
require(msg.sender == manager);
uint256 index = random() % players.length;
uint256 amount = address(this).balance;
payable(players[index]).transfer(amount);
players = new address[](0);
}
modifier restricted()
{
require(msg.sender == manager);
_;
}
function getPlayers() public view returns (address[] memory)
{
return players;
}
}
I'm using Solidity/Truffle. I have two contracts called Category and Post. Post is inherited from Category (Post is Category ).
Contract Category has an array called categories. I have a function in contract Category called isCategoryExists.
When I try to call this function from contract Category, everything is ok. But when I want to call this function from contract Post, I receive false because categories.length is 0.
Category.sol:
ragma solidity >=0.4.22 <0.9.0;
import "./ICategory.sol";
/// #title Create, edit and manage categories
contract Category is ICategory {
// State variables
uint256 currentIndex;
CategoryStruct[] private categories;
mapping(address => CategoryStruct[]) categoriesByUser;
// Modifiers
modifier onlyValidInput(CategoryInputStruct memory _input) {
bytes memory errCode;
bytes memory title = bytes(_input.title);
if (title.length == 0) {
errCode = bytes("invalidTitle");
}
if (errCode.length > 0) {
revert(string(errCode));
}
_;
}
modifier onlyValidIndex(uint256 index) {
if (isCategoryExists(index)) {
_;
} else {
revert("Invalid index.");
}
}
// Constructor
constructor() {
currentIndex = categories.length;
}
// Functions
/// #notice Check if category exists
function isCategoryExists(uint256 index) public view returns (bool) {
if (index >= categories.length) {
return false;
}
return categories[index].isExist;
}
/// #notice This function creates a category.
/// #dev Before this function, the entered data is validated with onlyValidInput modifier.
function createCategory(
CategoryInputStruct memory _input,
LocationStruct memory _location
) external onlyValidInput(_input) returns (bool) {
CategoryStruct memory newCategory = CategoryStruct({
id: currentIndex,
user: msg.sender,
title: _input.title,
isExist: true
});
categories.push(newCategory);
categoriesByUser[msg.sender].push(newCategory);
emit CategoryCreated(currentIndex);
currentIndex++;
return true;
}
}
Post.sol:
pragma solidity >=0.4.22 <0.9.0;
import "../category/Category.sol";
/// #title Create, edit and manage posts
contract Post is Category {
// State variables
uint256 currentPostIndex;
struct PostStruct {
uint256 id;
address user;
string title;
string body;
uint256 categoryId;
}
struct PostInputStruct {
string title;
string body;
uint256 categoryId;
}
PostStruct[] private posts;
mapping(address => uint256[]) postIndexesByUser; // example: 0x01234 => [3, 5, 24, 112, 448]
// Modifiers
modifier onlyValidPostInput(PostInputStruct memory _input) {
bytes memory errCode;
bytes memory title = bytes(_input.title);
bytes memory body = bytes(_input.body);
uint256 categoryId = uint256(_input.categoryId);
if (title.length == 0) {
errCode = bytes("invalidTitle");
} else if (body.length == 0) {
errCode = bytes("invalidBody");
}
if (errCode.length > 0) {
revert(string(errCode));
}
_;
}
// Constructor
constructor() {
currentPostIndex = posts.length;
}
// Functions
/// #notice This function creates a post.
/// #dev Before this function, the entered data is validated with onlyValidPostInput modifier.
function createPost(PostInputStruct memory _input)
external
onlyValidPostInput(_input)
returns (bool)
{
bool isExist = isCategoryExists(_input.categoryId);
PostStruct memory newPost = PostStruct({
id: currentPostIndex,
user: msg.sender,
title: _input.title,
body: _input.body,
categoryId: _input.categoryId
});
posts.push(newPost);
postIndexesByUser[msg.sender].push(currentPostIndex);
currentPostIndex++;
return true;
}
}
I make this call from the JS test environment in Truffle.
What I guess:
I think everything resets every time I run the tests. I'm not sure yet. This is a bit strange and has wasted a few days of my time.
Category.test.js:
const Chance = require("chance");
const Category = artifacts.require("Category");
const chance = new Chance();
contract("Category", (accounts) => {
// Setup 1 account.
const accountOne = accounts[0];
const accountTwo = accounts[1];
let categoryInstance;
before(async () => {
categoryInstance = await Category.deployed();
});
it("should create a category", async () => {
const title = chance.sentence();
// Create category
const categoryCreated = await categoryInstance.createCategory([title], {
from: accountOne,
});
// Get a category by array index
const category = await categoryInstance.getCategoryByIndex(0);
assert.equal(category.id, 0, "There is no data for this index");
assert.equal(category.title, title, "title is not equal");
});
it("Should return true because a category exists", async () => {
const isExists = await categoryInstance.isCategoryExists(0, {
from: accountOne,
});
assert.equal(isExists, true, "Category exists but result is false.");
});
});
Post.test.js
const Chance = require("chance");
const Category = artifacts.require("Category");
const Post = artifacts.require("post");
const chance = new Chance();
contract("Post", (accounts) => {
// Setup 1 account.
const accountOne = accounts[0];
const accountTwo = accounts[1];
let categoryInstance;
let postInstance;
before(async () => {
// Create a sample category
categoryInstance = await Category.deployed();
const title = chance.sentence();
// Create category
const categoryCreated = await categoryInstance.createCategory(
[title, purpose, area],
[polygon],
{
from: accountOne,
}
);
postInstance = await Post.deployed();
});
it("should create a post", async () => {
// Generate sample data
const title = chance.sentence();
const body = chance.paragraph();
const thumbnail = chance.url();
const categoryId = 0;
// Create post
const postCreated = await postInstance.createPost(
[title, body, thumbnail, categoryId],
{
from: accountOne,
}
);
// Get a post by array index
const post = await postInstance.getPostByIndex(0);
assert.equal(post.id, 0, "There is no data for this index");
assert.equal(post.title, title, "title is not equal");
assert.equal(post.categoryId, categoryId, "categoryId is not equal");
});
});
The problem is that you have misunderstood the concept of inheritance. The fact that Post inherits from Category does not mean that instances of Post are sharing the state with instances of Category. What it means is that Post is also a Category, so an object/instance of Post has that same state (variables) and behavior (functions/methods) of a Category contained within itself. In your case, this actually means an object of Post has its own array categories and that one is being checked when you call createPost, and it will of course be empty as you have never added a category using that object. The only way that array can be non-empty is if you call createCategory from postInstance, not from categoryInstance.
P.S.
Just to quickly clarify what I meant by "nothing should be persisted". The test suite should be created in a way that each test is independent, no test should ever depend on the execution of some other test. One should be able to run any test from the suite on its own and have it passing. I initially thought this was the problem, as you did not share the entire code.
I am trying to follow the Chainlink VRF tutorial found here: https://docs.chain.link/docs/intermediates-tutorial/ with hardhat and am running into this issue when calling the rollDice function:
Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"reason":"cannot estimate gas; transaction may fail or may require manual gas limit","code":"UNPREDICTABLE_GAS_LIMIT","method":"estimateGas","transaction":{"from":"0x014Da1D627E6ceB555975F09D26B048644382Ac6","maxPriorityFeePerGas":{"type":"BigNumber","hex":"0x9502f900"},"maxFeePerGas":{"type":"BigNumber","hex":"0x9502f90e"},"to":"0x5887946875A01D1BB79d6Fb357BceeA5A0096D2e","data":"0xdd02d9e5000000000000000000000000014da1d627e6ceb555975f09d26b048644382ac6","type":2,"accessList":null}}, tx={"data":"0xdd02d9e5000000000000000000000000014da1d627e6ceb555975f09d26b048644382ac6","to":{},"from":"0x014Da1D627E6ceB555975F09D26B048644382Ac6","type":2,"maxFeePerGas":{"type":"BigNumber","hex":"0x9502f90e"},"maxPriorityFeePerGas":{"type":"BigNumber","hex":"0x9502f900"},"nonce":{},"gasLimit":{},"chainId":{}}, code=UNPREDICTABLE_GAS_LIMIT, version=abstract-signer/5.5.0)
at Logger.makeError (/Users/matt/Desktop/hardhat/randomDay/node_modules/#ethersproject/logger/src.ts/index.ts:225:28)
at Logger.throwError (/Users/matt/Desktop/hardhat/randomDay/node_modules/#ethersproject/logger/src.ts/index.ts:237:20)
at /Users/matt/Desktop/hardhat/randomDay/node_modules/#ethersproject/abstract-signer/src.ts/index.ts:301:31
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Promise.all (index 7)
I am able to deploy to the Kovan testnet, I was able to verify the contract, and I have sent the contract LINK tokens, but am still running into the issue. The contract can be viewed here: https://kovan.etherscan.io/address/0x7b72d80670512c87605ab8ac7e6113fda9c57de4#code
I am using version 0.8 of the Chainlink Contracts.
RandomDay.sol
pragma solidity ^0.8.9;
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
contract RandomDay is VRFConsumerBase {
uint256 private constant ROLL_IN_PROGRESS = 42;
bytes32 private s_keyHash;
uint256 private s_fee;
mapping(bytes32 => address) private s_rollers;
mapping(address => uint256) private s_results;
event DiceRolled(bytes32 indexed requestId, address indexed roller);
event DiceLanded(bytes32 indexed requestId, uint256 indexed result);
constructor(address vrfCoordinator, address link, bytes32 keyHash, uint256 fee) VRFConsumerBase(vrfCoordinator, link) {
s_keyHash = keyHash;
s_fee = fee;
}
function rollDice (address roller) public returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) >= s_fee, "Not enough LINK to pay fee");
require(s_results[roller] == 0, "Already rolled");
requestId = requestRandomness(s_keyHash, s_fee);
s_rollers[requestId] = roller;
s_results[roller] = ROLL_IN_PROGRESS;
emit DiceRolled(requestId, roller);
return requestId;
}
function fulfillRandomness (bytes32 requestId, uint256 randomness) internal override {
uint256 dayOfWeek = (randomness % 7) + 1;
s_results[s_rollers[requestId]] = dayOfWeek;
emit DiceLanded(requestId, dayOfWeek);
}
function weekday (address player) public view returns (string memory) {
require(s_results[player] != 0, "Dice not rolled");
require(s_results[player] != ROLL_IN_PROGRESS, "Roll in progress");
return getWeekdayName(s_results[player]);
}
function getWeekdayName (uint256 id) private pure returns (string memory) {
string[7] memory weekdays = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
return weekdays[id - 1];
}
}
hardhat.config.js
/**
* #type import('hardhat/config').HardhatUserConfig
*/
require("#nomiclabs/hardhat-waffle")
require("#nomiclabs/hardhat-etherscan")
const ALCHEMY_API_KEY = "*************************";
const ROPSTEN_PRIVATE_KEY = "*********************";
module.exports = {
solidity: "0.8.9",
networks: {
kovan: {
url: `https://eth-kovan.alchemyapi.io/v2/${ALCHEMY_API_KEY}`,
accounts: [`0x${ROPSTEN_PRIVATE_KEY}`],
gas: 2700000000,
maxFeePerGas: 30000000000,
}
},
etherscan: {
// Your API key for Etherscan
// Obtain one at https://etherscan.io/
apiKey: "****************************"
}
};
deploy.js
const { ethers } = require("hardhat");
async function main() {
const [deployer] = await ethers.getSigners();
console.log("Deploying contracts with the account:", deployer.address);
console.log("Account balance:", (await deployer.getBalance()).toString());
const Token = await ethers.getContractFactory("RandomDay");
const token = await Token.deploy("0xa36085F69e2889c224210F603D836748e7dC0088", "0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9", "0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4", "100000000000000000");
console.log("Token address:", token.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
quickRun.js
var ethers = require('ethers');
var provider = ethers.providers.getDefaultProvider('kovan');
var address = '0x7b72d80670512c87605aB8aC7E6113Fda9c57de4';
var abi = [{"inputs":[{"internalType":"address","name":"vrfCoordinator","type":"address"},{"internalType":"address","name":"link","type":"address"},{"internalType":"bytes32","name":"keyHash","type":"bytes32"},{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"result","type":"uint256"}],"name":"DiceLanded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"roller","type":"address"}],"name":"DiceRolled","type":"event"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"rawFulfillRandomness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"roller","type":"address"}],"name":"rollDice","outputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"weekday","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}];
var privateKey = '*******************************';
var wallet = new ethers.Wallet(privateKey, provider);
var contract = new ethers.Contract(address, abi, wallet);
var sendPromise = contract.rollDice('0x014Da1D627E6ceB555975F09D26B048644382Ac6');
sendPromise.then(function(transaction){
console.log(transaction);
});
I believe the addresses are off:
Constructor Arguments of your contract:
-----Decoded View---------------
Arg [0] : vrfCoordinator (address): 0xa36085f69e2889c224210f603d836748e7dc0088
Arg [1] : link (address): 0xdd3782915140c8f3b190b5d67eac6dc5760c46e9
Arg [2] : keyHash (bytes32): 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4
Arg [3] : fee (uint256): 100000000000000000
Via Chainlinks Docs:
LINK 0xa36085F69e2889c224210F603D836748e7dC0088
VRF Coordinator 0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9
Key Hash 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4
Fee 0.1 LINK
Switched Link and VRF are probably the culprit.
9 out of 10 is because you passed something wrong in the constructor or something in the contructor is not initialized propertly. this kind of things aren't detected by compiler.
I just started playing around in Truffle and Solidity and wrote my first basic contract. I also wrote a test but it keeps failing giving me the following message:
Error: Invalid number of arguments to Solidity function
Now, the issue seems quite straight forward, I'm not pushing the right amount af arguments... Except as far as I can see I am.
This is my relevant contract code:
pragma solidity ^0.4.18;
contract FundEth {
mapping (uint => Project) _projects;
struct Project {
uint id;
uint targetWei;
uint targetBlock;
uint balanceWei;
string name;
string description;
bool payedOut;
}
function fund(uint projectId) public payable
{
_projects[projectId].balanceWei += msg.value;
}
function create(uint targetWei, uint blocks, string name, string description)
public
returns (uint)
{
Project memory p = Project({
id: ++_indexCounter,
targetWei: targetWei,
targetBlock: block.number + blocks,
balanceWei: 0,
name: name,
description: description,
payedOut: false
});
_projects[p.id] = p;
return p.id;
}
function getProjectName(uint projectId)
public
view
returns (string)
{
return "FOO";
}
function getProjectBalance(uint projectId)
public
view
returns (uint)
{
return 10000000;
}
...
}
And this is my test code:
const FundEth = artifacts.require("./FundEth.sol");
contract('FundEth', accounts => {
var _id;
var _fundEth;
it("should create a project", () => {
return FundEth.deployed()
.then(fundEth => {
_fundEth = fundEth;
return fundEth.create(1000000000000000000 /* 1 Eth */ , 5, "FOO", "We want to fund this for testing.")
}).then(id => {
_id = id;
return _fundEth.getProjectName.call(_id)
}).then(name => {
assert.equal(name, "FOO", "Has not created a valid project.");
});
});
it("should fund a project", () => {
return FundEth.deployed()
.then(fundEth => {
assert.notEqual(_id, 0);
_fundEth = fundEth;
_fundEth.fund.sendTransaction(_id, { from: accounts[0], value: 10000000 }); << SEEMS TO FAIL HERE.
}).then(() => {
return _fundEth.getProjectBalance.call(_id);;
}).then(balance => {
assert.equal(balance, 10000000, "Balance of test project was not 1 ether.");
});
});
});
I know the contract is not very useful right now, but I don't see why it fails. The full error:
1) Contract: FundEth
should fund a project:
Uncaught Error: Invalid number of arguments to Solidity function
at Object.InvalidNumberOfSolidityArgs (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/errors.js:25:1)
at SolidityFunction.validateArgs (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/function.js:74:1)
at SolidityFunction.toPayload (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/function.js:90:1)
at SolidityFunction.sendTransaction (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/function.js:163:1)
at /usr/local/lib/node_modules/truffle/build/webpack:/~/truffle-contract/contract.js:135:1
at new Promise (<anonymous>)
at /usr/local/lib/node_modules/truffle/build/webpack:/~/truffle-contract/contract.js:126:1
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:118:7)
Changing the line to
return _fundEth.fund(_id, { from: accounts[0], value: 10000000 });
seems to fix the issue. However I also needed to remove the assert before the call in order to have a working test.