truffle & solidity cant access to a function in test - javascript

after I run command truffle test
I got this error
TypeError: _character.getName is not a function
my test file
let Game = artifacts.require("./Game.sol");
let Character = artifacts.require("./Character.sol");
const PROVIDED_NAME = "TEST";
contract("Game", (accounts) => {
let creatorAccount = accounts[0];
it("should create a character with the name provided", () => {
let _game;
let _character;
return Game.deployed()
.then(instance => {
_game = instance;
return _game.createCharacter(PROVIDED_NAME, { from: creatorAccount });
})
.then(result => {
return _game.getCharacter();
})
.then(character => {
_character = Character.at(character);
return _character.getName();
})
.then(name => {
assert.equal(name, PROVIDED_NAME, "Failed to create a character with the provided name");
});
});
});
and this my Character.sol file
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
contract Character {
string private _name;
constructor(string memory name) public {
_name = name;
}
function getName() public view returns (string memory) {
return _name;
}
}
I'm using
Truffle v5.5.20 (core: 5.5.20)
Ganache v7.2.0
Solidity - 0.8.15 (solc-js)
Node v16.15.1
Web3.js v1.7.4

I think the issue is with the way how you require them. you should not pass the directory path, instead pass the name of the contracts, truffle will assign them.
let Game = artifacts.require("NameOfGamecontract");
let Character = artifacts.require("NameOfCharacterContract");

Related

Communicating with a Smart Contract on BSC over ethers gives -32603 error code

Hello I am new to Smart Contract development, for a few days I try to get this working, but no luck. I hope someone can help me. I try to communicate to a Smart Contract deployed to BSC https://testnet.bscscan.com/address/0x2ED1c3c1Fc6646F321cf546a892684E946435CE9 see the source code below.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "#chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract FundMe {
mapping(address => uint256) public addressToAmountFunded;
address[] public funders;
address public owner;
AggregatorV3Interface internal priceFeed;
uint balance;
// if you're following along with the freecodecamp video
// Please see https://github.com/PatrickAlphaC/fund_me
// to get the starting solidity contract code, it'll be slightly different than this!
constructor(address _priceFeed) {
priceFeed = AggregatorV3Interface(_priceFeed);
owner = msg.sender;
}
function fund() public payable {
uint256 mimimumUSD = 50 * 10**18;
require(
getConversionRate(msg.value) >= mimimumUSD,
"You need to spend more ETH!"
);
addressToAmountFunded[msg.sender] += msg.value;
balance += msg.value;
funders.push(msg.sender);
}
function getVersion() public view returns (uint256) {
return priceFeed.version();
}
function getPrice() public view returns (uint256) {
(, int price, , , ) = priceFeed.latestRoundData();
return uint256(price * 10000000000);
}
// 1000000000
function getConversionRate(uint256 ethAmount)
public
view
returns (uint256)
{
uint256 ethPrice = getPrice();
uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1000000000000000000;
return ethAmountInUsd;
}
function getEntranceFee() public view returns (uint256) {
// mimimumUSD
uint256 mimimumUSD = 50 * 10**18;
uint256 price = getPrice();
uint256 precision = 1 * 10**18;
return (mimimumUSD * precision) / price;
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
function withdraw() public payable onlyOwner {
payable(msg.sender).transfer(balance);
for (
uint256 funderIndex = 0;
funderIndex < funders.length;
funderIndex++
) {
address funder = funders[funderIndex];
addressToAmountFunded[funder] = 0;
}
funders = new address[](0);
}
}
I deployed the smart contract with truffle, with the following migration script
const FundMe = artifacts.require("FundMe");
const BINANCE_BNB_USD_PRICE_FEED = '0x0567F2323251f0Aab15c8dFb1967E4e8A7D42aeE';
module.exports = async (deployer, network, [defaultAccount]) => {
let priceFeedAddress = BINANCE_BNB_USD_PRICE_FEED
try {
await deployer.deploy(FundMe, BINANCE_BNB_USD_PRICE_FEED, { from: defaultAccount })
} catch (err) {
console.error(err)
}
}
I try to call getPrice() that communicates to chainlink to get the latest price of BNB/USDT.
Here is the Javascript
const getContract = () =>
new Promise(async (resolve, reject) => {
const contract = await fetch('./build/contracts/FundMe.json')
const Contract = await contract.json()
let provider = await detectEthereumProvider()
if (provider) {
await provider.request({ method: 'eth_requestAccounts' })
const networkId = await provider.request({ method: 'net_version' })
provider = new ethers.providers.Web3Provider(provider)
const signer = provider.getSigner()
showAddress(signer)
const contract = new ethers.Contract(
Contract.networks[networkId].address,
Contract.abi,
signer,
)
resolve(contract)
return
}
reject('Install Metamask')
})
const showAddress = async (signer) => {
address = await signer.getAddress()
const connectButton = document.getElementById('connect')
connectButton.innerText = address
}
const getPrice = async (contract) => {
console.log('contract', contract)
const price = await contract.getPrice()
console.log('price', price)
const priceContainer = document.getElementById('price')
priceContainer.innerText = price
}
const init = async () => {
const contract = await getContract()
getPrice(contract)
}
const fundButton = document.getElementById('fund')
fundButton.addEventListener('click', async () => {
const fundMe = await getContract()
})
init()
I get the following error in the browser console and have no idea whats the cause.
Your deploy script passing the 0x056... address as the priceFeed param of the constructor.
So the getPrice() contract function is then trying to call the latestRoundData() on the 0x056... address, expecting a response.
However, your contract is deployed on the testnet, and there's no contract on the 0x056... address on the testnet (link) to return a value, which causes the "main" call to revert.

Problem stubbing a class method with Sinon

I have a NodeJS + Typescript application with the following class:
export default class OrderStreamWriter {
private readonly redis: IORedis;
private readonly orderStream: string;
private readonly logger: LoggerFactory;
constructor(redisHost: string, redisPort: number, redisPass: string, orderStream: string) {
this.orderStream = orderStream;
this.redis = createRedisClient(redisHost, redisPort, redisPass);
this.logger = new LoggerFactory('streams/OrderStreamWriter');
}
public async write(msg: string): Promise<void> {
await this.redis.xadd(this.orderStream, '*', 'trade', msg).catch((err: Error) => {
this.logger.log(
`Error Writing message to stream (${this.orderStream}): ${err.message}. Quitting...`,
);
process.exit(1);
});
}
}
In another class I use the write method to write the result in a Redis stream.
I want to test that flow without calling the actual write function but just to check that that function will be called with certain parameters, here's my test(run using mocha + sinon):
it('process the input and return an order', () => {
const rule = directOrder[0].rule;
const user = directOrder[0].user;
//const writeStub = sinon.stub(OrderStreamWriter.prototype, "write");
const Writer: any = sinon.stub();
sinon.stub(Writer.prototype, "write");
const writer = new Writer();
const order = {}
// console.log(writeStub)
const directTriggerStrategy: TriggerContext = new TriggerContext(user, rule, writer);
directTriggerStrategy.execute()
sinon.assert.calledWithExactly(writer, order);
})
With both the current code and the commented line const writeStub = sinon.stub(OrderStreamWriter.prototype, "write"); I receive the same error when running the test:
TypeError: Cannot stub non-existent property write
How can I fix this?
// someclass.js
class SomeClass {
prop1;
prop2;
contructor(param1, param2) {
this.prop1 = param1;
this.prop2 = param2;
}
async someFunction(givenParam) {
// do something here
return "somedata";
}
}
// create a factory . This is what you will use to create an instance rather than using the new word ever time to create a new instance.
const someClassInstanceFactory = (param1, param2) => {
return new SomeClass(param1, param2);
};
export default { someClassInstanceFactory, SomeClass };
// ********************************************************
// somemodule.js
// this file uses the class we created above as below
import classAndFactory from "./someclass.js";
const moduleFunction = () => {
const instance = classAndFactory.someClassInstanceFactory(param1, param2);
// this line returns an instance of SomeClass . it's like calling new SomeClass(pram1, param2);
const result = instance.someFunction("givenParam");
console.log(result);
return result;
// result should be 'somedata'
// so how do we unit test moduleFunction and stub instance.someFunction when testing? ?
};
export default moduleFunction;
// *******************************************************************
// somemodule.test.js
import classAndFactory from "./../someclass.js";
import moduleFunction from "./somemodule.js";
const { someClassInstanceFactory, SomeClass } = classAndFactory;
// now if you want to stub any thing what you do is
describe("moduleFunction", () => {
const fakeSomeClassInstance = new SomeClass(1, 2);
// arrange
// stub the factory first to return your fake instance created above.
const expectedResut = "stubbed yoo";
sinon
.stub(classAndFactory, "someClassInstanceFactory")
.returns(fakeSomeClassInstance);
someFunctionStub = sinon
.stub(fakeSomeClassInstance, "someFunction")
.returns(expectedResut);
it("must call someFunction function with required argument", () => {
// act
const result = moduleFunction();
// assert
sinon.assert.calledOnce(someFunctionStub);
assert.equals(result, expectedResut);
});
});

Cannot figure out why I am getting VM Exception while processing transaction: revert error

I am a beginner in blockchain programming and I am not able to understand why I am getting an error while trying to solidity function using Web3 and Ganache.
const PetList = require('./build/contracts/PetList.json')
const fs = require('fs')
const Web3 = require('web3')
const abi = fs.readFileSync("build/contracts/PetList.json").toString().trim();
// Ganache Blockchain
const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545"));
web3.eth.net.isListening()
.then(() => console.log('Web3 is connected'))
.catch(e => console.log('Wow. Something went wrong'));
var setUpContract = async function( ){
await web3.eth.net.getId().then((networkId) => {
const networkData = PetList.networks[networkId]
console.log("Setting up contract...")
if(networkData){
return petList = new web3.eth.Contract(PetList.abi, networkData.address)
}
})
acc = await web3.eth.getAccounts()
currentAccount = acc[0]
console.log("Account: ", acc[0])
}
async function start(){
await setUpContract()
await addPet()
}
var addPet = async function(){
console.log(await getPetCount())
return results = await petList.methods.addPet('Zippo', 'Dog').send({from: currectAccount})
}
start()
pragma solidity ^0.5.0;
contract PetList{
uint public petCount = 0;
mapping (uint => Pet) public pets;
struct Pet{
uint id;
string name;
string tag;
}
event PetAdded(
uint id,
string name,
string tag
);
function addPet(string memory _name, string memory _tag) public {
require(bytes(_name).length > 0, "INVALID TAG");
require(bytes(_tag).length > 0, "INVALID NAME");
petCount++;
pets[petCount] = Pet(petCount, _name, _tag);
emit PetAdded(petCount, _name, _tag);
}
}
I also used .send() without any parameters and it gave me an error saying No "from" address specified in neither the given options, nor the default options.
To make a function receive ether you must have a fallback function or add payable modifier
So you can change your code to the following
function addPet(string memory _name, string memory _tag) public payable

Truffle - Expected parameter 'solc' not passed to function

I have this error:
.../node_modules/truffle-expect/index.js:3
expected_keys.forEach(function(key) {
^
Error: Expected parameter 'solc' not passed to function.
when I try to use truffle-solidity-loader using webpack. Any idea how to fix it? Thank you.
UPDATE:
The smart contract:
pragma solidity ^0.5.0;
contract ToDo {
struct Task {
uint id;
uint date;
string content;
string author;
bool done;
}
uint lastTaskId;
mapping(uint => Task) tasks;
uint[] taskIds;
constructor () public{
lastTaskId = 0;
}
event TaskCreated(uint id, uint date, string content, string author, bool done);
function createTask(string memory _content, string memory _author) public {
lastTaskId++;
tasks[lastTaskId] = Task(lastTaskId, now, _content, _author, false);
taskIds.push(lastTaskId);
emit TaskCreated(lastTaskId, now, _content, _author, false);
}
function getTask(uint id) taskExists(id) public view returns (uint, uint, string memory, string memory, bool) {
return(
id,
tasks[id].date,
tasks[id].content,
tasks[id].author,
tasks[id].done
);
}
function getTaskIds() view public returns (uint[] memory) {
return taskIds;
}
// function getTaskFixtures(uint _id) public view returns(uint,uint,string,string,bool) {
// return (0, now, "Create more tutorials for ETB", "Julien", false);
// }
modifier taskExists(uint id){
if(tasks[id].id == 0){
revert();
}
_;
}
}
The index.js:
import artifact from '../../contracts/ToDo.sol';
import Web3 from 'web3';
import TruffleContract from 'truffle-contract';
// import config from './config.js';
console.log('loaded');
const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545'));
const abstraction = new TruffleContract(artifact);
abstraction.setProvider(web3.currentProvider);
const network = Object.keys(artifact.networks)[0];
const address = artifact.networks[network].address;
abstraction.at(address)
.then((todo) => {
todo.getTaskIds()
.then((taskIds) => {
console.log(taskIds);
});
});
web3.eth.getAccounts(console.log);
The server:
const express = require('express');
const app = express();
const PORT = 3000;
//Serve static assets (js, css, ...)
app.use(express.static('app'));
//Serve contract artifact files (ex: ToDo.json)
app.use(express.static('build/contracts'));
//Serve index.html
app.get('/', (req, res) => {
res.sendFile(`${__dirname}/app/index.html`);
});
//If anything else is requested that's an error
app.get('*', (req, res) => {
res.status(404);
res.send('Oops... this URL does not exist');
});
//Start the server
app.listen(PORT, () => {
console.log(`ETB Ethereum ToDo List App running on port ${PORT}...`);
});
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Truffle JS test not working

I have a solidity contract in the Truffle framework and I cannot figure out why my JS test doesn't work.
I'm trying to test the 'setPlayers' function, the contract works and the tests are running but I can't understand how to call the function in the test:
pragma solidity ^0.4.23;
contract Swindle {
string public eventName;
uint public entryFee;
string[] public players;
string public winner;
uint public winnings;
function comp(string _eventName, uint _entryFee) public {
eventName = _eventName;
entryFee = _entryFee;
}
function addPlayers(string _player) public {
players.push(_player);
}
function winner(string _player) public returns (string, uint) {
winner = _player;
winnings = (players.length * entryFee);
return (winner, winnings);
}
}
Test file:
var Swindle = artifacts.require("Swindle");
contract('Swindle', function(accounts) {
it('sets player to stuart', function(){
return Swindle.deployed().then(function(instance) {
swindle = instance;
return swindle.addPlayers.call("stuart");
}).then(function(swindle) {
assert.equal(swindle.players[0], "stuart", "sets the total supply");
})
})
})
Error:
0 passing (302ms)
1 failing
1) Contract: Swindle
sets player to stuart:
TypeError: Cannot read property '0' of undefined
at test/test-swindle.js:10:32
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:118:7)
There is no setPlayers method in the contract as you had mentioned in the test.
You can not directly access the array of a contract in your javascript. First you need to call the players as method.
it('sets player to stuart', function(){
return Swindle.deployed().then(function(instance) {
swindle = instance;
return swindle.addPlayers.call("stuart");
}).then(function(swindle) {
return swindle.players();
}).then(function(players) {
assert.equal(players[0], "stuart", "sets the total supply");
})
})
You could async/await for better readability of your tests.
it('sets player to stuart', async () => {
let swindle = await Swindle.deployed();
await swindle.addPlayers.call("stuart");
let players = await swindle.players.call();
assert.equal(players[0], "stuart", "sets the total supply");
});

Categories