Hi I'm new to blockchain, truffle and Solidity and I've been stuck on this problem for quite long. I want to get all token balances given a wallet address and the token contract addresses using a contract, but I keep encountering
Error: Returned error: VM Exception while processing transaction: revert
whenever I test my contract.
Here's the code of my contract in Solidity:
pragma solidity ^0.8.17;
import {IERC20} from './IERC20.sol';
contract UtilityContract {
function getBalances(address walletAddress, address[] memory tokenAddresses) public view returns (address[] memory, uint[] memory) {
uint len = tokenAddresses.length;
uint[] memory balances = new uint256[](len);
for (uint i=0; i<len; i++) {
balances[i] = IERC20(tokenAddresses[i]).balanceOf(walletAddress);
}
return (tokenAddresses, balances);
}
}
and here's my test code:
const ADDRESS = "0xF977814e90dA44bFA03b6295A0616a897441aceC"; // some wallet address with token balance
const TOKENS = [ // token contract addresses
"0x111111111117dC0aa78b770fA6A738034120C302",
"0xC943c5320B9c18C153d1e2d12cC3074bebfb31A2",
];
const UtilityContract = artifacts.require('UtilityContract.sol');
contract('UtilityContract', ()=> {
it('getBalances', async ()=> {
const utilityContract = await UtilityContract.new();
const output = await utilityContract.getBalances(ADDRESS, TOKENS);
console.log(output);
});
});
Here's a screenshot of the error:
I imported the IERC20 interface to use the balanceOf function but for some reason it does not work.
Please try this line into your code..
address() convert your wallet string to a valid wallet address format.
IERC20(tokenAddresses[i]).balanceOf(address(walletAddress));
I'm doing transactions with Contract on Avalanche test network. I am simply minting an NFT in my Contract. I'm implementing this in Node.js as an API. Normally my codes are working. However, sometimes I get an error like this and I couldn't figure out why. Can you help me?
message: {
code: -32000,
message: 'nonce too low: address 0x190cc0978615a474092676aB740F486b7f528A5F current nonce (491) > tx nonce (490) -- Reason given: Custom error (could not decode).',
reason: 'Custom error (could not decode)'
}
Here are the parts I made with Mint:
On Contracts...
function mint(address minter, string memory uri) public returns (uint256) {
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
idToOwner[newItemId] = minter;
_safeMint(minter, newItemId);
_setTokenURI(newItemId, uri);
emit Mint(minter, uri, newItemId);
return newItemId;
}
On Nodejs API...
const mintMetaData = async (_id, mintURL, res) => {
const _instance = await hyliContract.at(process.env.CONTRACT_NFT_ADDRESS);
try {
const result = await _instance.mint(provider.getAddress(), mintURL, { from: provider.getAddress() });
...
I am trying to connect web3js in the javascript section of my html to my ganache-cli nodejs server
ganache deployment script:
const ganache = require("ganache-cli");
const Web3 = require("web3");
const web3 = new Web3(ganache.provider());
const { interface, bytecode } = require("./compile");
const deploy = async () => {
const accounts = await web3.eth.getAccounts();
const result = await new web3.eth.Contract(JSON.parse(interface))
.deploy({
data: bytecode,
arguments: ["test"],
})
.send({ from: accounts[0], gas: "1000000" });
console.log(`Contract address: ${result.options.address}`);
};
var server = ganache.server();
server.listen(8545, function (err, blockchain) {
console.log(server);
console.log(" live at port 8545");
});
deploy();
my frontend html/js file
if (typeof web3 !== 'undefined') {
web3 = new Web3(web3.currentProvider);
} else {
web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"));
web3.eth.defaultAccount = web3.eth.accounts[0];
var info = new web3.eth.Contract(
JSON.parse(interface), '0xeD9a9f326F38223a6599309F7201562DfB177997');
console.log(info.methods.GetInfo("test").call());
}
But I get the following error:
index.js:297 Uncaught (in promise) Error: Returned values aren't valid, did it run Out of Gas? You might also see this error if you are not using the correct ABI for the contract you are retrieving data from, requesting data from a block number that does not exist, or querying a node which is not fully synced.
solidty code:
pragma solidity ^0.4.17;
pragma experimental ABIEncoderV2;
contract DVA {
struct Info {
// uint Age;
// bool AgeRestriction;
string DO_Num;
string date;
string time;
string status;
string otherstatus;
string imagehash;
string imagename;
}
mapping (string => Info[]) AllInfo;
function SetInfo(string _DO, string _date, string _time, string _status, string _otherstatus, string _imagehash, string _imagename) public {
Info memory info = Info(_DO,_date,_time,_status,_otherstatus,_imagehash,_imagename);
AllInfo[_DO].push(info);
}
function GetInfo(string _DO) public view returns (string memory) {
// return (AllInfo[_DO].status,AllInfo[_DO].time);
return "hi";
}
}
The code above is the contract code.
The weird thing is, I can call SetInfo but not GetInfo. I have ensured the contract address is valid, and that the ABI is correct as well. In fact, the ABI is retrieved directly upon each compilation of the solidty code as well.
When I run truffle test on terminal I get the following error Error: Attempting to run transaction which calls a contract function, but recipient address 0x3ad2c00512808bd7fafa6dce844a583621f3df87 is not a contract address I don't understand why I get this because my build folder is normal meaning if I run truffle migrate --reset the address in the terminal is the same as the address in the build file. when I run truffle migrate it works. Also, every time I run the truffle test the recipient address always changes. I don't know what do to please help.
One other thing this only happens once I use the code selfdestruct(admin); then I get this error. the admin is = to msg.sender which is the first account in the ganache so I don't know what's wrong.
I am using this video. I have done all the other videos of this guy and everything is fine until now at minute 15:11 he does the final test and for him, it works but for me, it gives me the error above.
Anyone, please help
These is my test (javascript)
var CinoCoin = artifacts.require("./CinoCoin.sol");
var CinoCoinSale = artifacts.require("./CinoCoinSale.sol");
contract('CinoCoinSale', function(accounts) {
var tokenInstance;
var tokenSaleInstance;
var admin = accounts[0];
var buyer = accounts[1];
var tokenPrice = 1000000000000000; // in wei 0.01 ether
var tokensAvailable = 750000;
var numberOfTokens;
it('initializes the contract with the correct values', function() {
return CinoCoinSale.deployed().then(function(instance) {
tokenSaleInstance = instance;
return tokenSaleInstance.address
}).then(function(address) {
assert.notEqual(address, 0x0, 'has contract address');
return tokenSaleInstance.tokenContract();
}).then(function(address) {
assert.notEqual(address, 0x0, 'has token contract address');
return tokenSaleInstance.tokenPrice();
}).then(function(price) {
assert.equal(price, tokenPrice, 'token price is correct');
});
});
it('facilitats token buying', function() {
return CinoCoin.deployed().then(function(instance) {
//Grab token instance first
tokenInstance = instance;
return CinoCoinSale.deployed();
}).then(function(instance) {
//Then grab token sale instance
tokenSaleInstance = instance;
//Provision 75% of all tokens to the token sale contract
return tokenInstance.transfer(tokenSaleInstance.address, tokensAvailable, { from: admin})
}).then(function(receipt) {
numberOfTokens = 10;
return tokenSaleInstance.buyTokens(numberOfTokens, { from: buyer, value: numberOfTokens * tokenPrice })
}).then(function(receipt) {
assert.equal(receipt.logs.length, 1, 'triggers one event');
assert.equal(receipt.logs[0].event, 'Sell', 'should be the "Sell" event');
assert.equal(receipt.logs[0].args._buyer, buyer, 'logs the account that purchased the tokens');
assert.equal(receipt.logs[0].args._amount, numberOfTokens, 'logs the number of tokens purchased');
return tokenSaleInstance.tokensSold();
}).then(function(amount) {
assert.equal(amount.toNumber(), numberOfTokens, 'increments the number of tokens sold');
return tokenInstance.balanceOf(buyer);
}).then(function(balance) {
assert.equal(balance.toNumber(), numberOfTokens);
return tokenInstance.balanceOf(tokenSaleInstance.address);
}).then(function(balance) {
assert.equal(balance.toNumber(), tokensAvailable - numberOfTokens);
//Try to buy tokens different from the ether value
return tokenSaleInstance.buyTokens(numberOfTokens, { from: buyer, value: 1 });
}).then(assert.fail).catch(function(error) {
assert(error.message.indexOf('revert') >= 0, 'msg.value must equal number of tokens in wei');
return tokenSaleInstance.buyTokens(800000, { from: buyer, value: numberOfTokens * tokenPrice });
}).then(assert.fail).catch(function(error) {
assert(error.message.indexOf('revert') >= 0, 'connot purchase more tokens than available');
});
});
it('ends token sale', function () {
return CinoCoin.deployed().then(function(instance) {
//Grab token instance first
tokenInstance = instance;
return CinoCoinSale.deployed();
}).then(function(instance) {
//Then grab token sale instance
tokenSaleInstance = instance;
//try to end sale from account other than admin
return tokenSaleInstance.endSale({ from: buyer });
}).then(assert.fail).catch(function(error) {
assert(error.message.indexOf('revert' >= 0, 'must be admin to end sale'));
//End sale as admin
return tokenSaleInstance.endSale({ from: admin });
}).then(function(receipt) {
return tokenInstance.balanceOf(admin);
}).then(function(balance) {
assert.equal(balance.toNumber(), 999990, 'returns all unsold cino coins to admin');
//Check that the token price was reset when selfFestruct was called
return tokenSaleInstance.tokenPrice();
}).then(function(price) {
assert.equal(price.toNumber(), 0, 'token price was reset');
});
});
});
And this is my contract code (solidity)
pragma solidity ^0.4.23;
import "./CinoCoin.sol";
contract CinoCoinSale {
address admin;
CinoCoin public tokenContract;
uint256 public tokenPrice;
uint256 public tokensSold;
event Sell(address _buyer, uint256 _amount);
function CinoCoinSale(CinoCoin _tokenContract, uint256 _tokenPrice) public {
//Assign an admin / an external account connected to the blockchain that has certain priviliges
admin = msg.sender;
//Assign token contract
tokenContract = _tokenContract;
//Token Price how much the token will cost
tokenPrice = _tokenPrice;
}
//multiply function for
function multiply(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x);
}
//Buy tokens
function buyTokens(uint256 _numberOfTokens) public payable {
//Require that the value is equal to tokens
require(msg.value == multiply(_numberOfTokens, tokenPrice));
//Require that there are enough tokens in the contrat
require(tokenContract.balanceOf(this) >= _numberOfTokens);
//Require the transfer is successful
require(tokenContract.transfer(msg.sender, _numberOfTokens));
//Keep track of number of tokens sold
tokensSold += _numberOfTokens;
//Trigger a sell event
Sell(msg.sender, _numberOfTokens);
}
//ending token CinoCoinSale
function endSale()public {
//Only an admin can end the end the sale
require(msg.sender == admin);
//Transfer the amount of token in the sale back to the admin
require(tokenContract.transfer(admin, tokenContract.balanceOf(this)));
//Destroy contract
selfdestruct(admin);
}
}
It says my test are passing when I comment out the selfdestruct(admin); so it seems to be a probelm with that
thanks for the help
glad you fixed the error already. While looking at your code I noticed that the test file is quite difficult to follow because of the large promise chains. I converted the file to async/await, which might be easier to maintain and debug in the future.
I also noticed that you are trying to assert emitted events and reverts by manually checking the logs, and catching the revert exception. I actually wrote a library to make this a bit easier, so I added the code for this as well.
The library can be installed with npm:
npm install truffle-assertions
After this, the new test code should work. I hope this helps, and good luck with your Dapp development.
const CinoCoin = artifacts.require("CinoCoin");
const CinoCoinSale = artifacts.require("CinoCoinSale");
const truffleAssert = require("truffle-assertions");
contract('CinoCoinSale', function(accounts) {
let tokenInstance;
let tokenSaleInstance;
let admin = accounts[0];
let buyer = accounts[1];
let tokenPrice = 1000000000000000; // in wei 0.01 ether
let tokensAvailable = 750000;
it('initializes the contract with the correct values', async function() {
tokenInstance = await CinoCoin.deployed();
tokenSaleInstance = await CinoCoinSale.deployed();
assert.notEqual(tokenSaleInstance.address, 0x0, 'has contract address');
assert.notEqual(await tokenSaleInstance.tokenContract(), 0x0, 'has token contract address');
assert.equal(await tokenSaleInstance.tokenPrice(), tokenPrice, 'token price is correct');
assert.equal(await tokenSaleInstance.admin(), admin, 'admin is correct');
});
it('facilitates token buying', async function() {
tokenInstance = await CinoCoin.deployed();
tokenSaleInstance = await CinoCoinSale.deployed();
await tokenInstance.transfer(tokenSaleInstance.address, tokensAvailable, { from: admin });
const numberOfTokens = 10;
const receipt = await tokenSaleInstance.buyTokens(numberOfTokens, { from: buyer, value: numberOfTokens * tokenPrice });
truffleAssert.eventEmitted(receipt, 'Sell', (ev) => {
return ev._buyer === buyer && ev._amount.toNumber() === numberOfTokens;
});
const tokensSold = await tokenSaleInstance.tokensSold();
assert.equal(tokensSold.toNumber(), numberOfTokens, 'increments the number of tokens sold');
const buyerBalance = await tokenInstance.balanceOf(tokenSaleInstance.address);
assert.equal(buyerBalance.toNumber(), numberOfTokens);
const tokenSaleBalance = await tokenInstance.balanceOf(tokenSaleInstance.address);
assert.equal(tokenSaleBalance.toNumber(), tokensAvailable - numberOfTokens);
truffleAssert.reverts(
tokenSaleInstance.buyTokens(numberOfTokens, { from: buyer, value: 1 }),
null,
'msg.value must equal number of tokens in wei'
);
truffleAssert.reverts(
tokenSaleInstance.buyTokens(800000, { from: buyer, value: numberOfTokens * tokenPrice }),
null,
'connot purchase more tokens than available'
);
});
it('ends token sale', async function () {
tokenInstance = await CinoCoin.deployed();
tokenSaleInstance = await CinoCoinSale.deployed();
truffleAssert.reverts(tokenSaleInstance.endSale({ from: buyer }), null, 'must be admin to end sale');
await tokenSaleInstance.endSale({ from: admin });
const adminBalance = await tokenInstance.balanceOf(admin);
assert.equal(adminBalance.toNumber(), 999990, 'returns all unsold cino coins to admin');
const tokenPrice = await tokenSaleInstance.tokenPrice();
assert.equal(tokenPrice.toNumber(), 0, 'token price was reset');
});
});
Contract works fine in Remix, but there are issues with the web UI.
The deployed contract variable is set properly and all functions are visible in the browser console, but the functions are not working.
Web3 is installed, Ganache running ...everything looks ok...
pragma solidity ^0.4.0;
contract mycontract {
struct student {
bytes32 sid;
string name;
uint64 gender;
}
mapping (bytes32 =>student) s1;
student[] public stu;
function setstudent(bytes32 sid, string name, uint64 gender) public {
s1[sid].sid=sid;
s1[sid].name=name;
s1[sid].gender=gender;
}
function getstudent(bytes32 sid) public constant returns(bytes32, string, uint64) {
return(s1[sid].sid,s1[sid].name,s1[sid].gender);
}
}
Client:
<script>
if (typeof web3 !== 'undefined') {
web3 = new Web3(web3.currentProvider);
}
else
{
web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545"));
}
web3.eth.defaultAccount = web3.eth.accounts[0];
var myContract = web3.eth.contract('MY ABI PASTED HERE');
var student = myContract.at('MY DEPLOYED ADDRESS HERE');
console.log(student);
student.getstudent("1",function(error, result){
if(!error) {
$("#heading").html("Welcome...");
$("#studentname").html(web3.toAscii(result[1]));
console.log(result);
}
else
console.error(error);
});
$("#save").click(function() {
student.setStudent( $("#uid").val(), $("#studentname").val(),
$("#gender").val());
};
</script>