I am writing a unit test for my smart contract using truffle and when I run the test using "truffle test" the test failed with this error "Error: Returned error: VM Exception while processing transaction: invalid opcode".
smart contract code:
pragma solidity ^0.4.3;
contract owned {
address public owner;
/* Initialise contract creator as owner */
function owned() public {
owner = msg.sender;
}
/* Function to dictate that only the designated owner can call a function */
modifier onlyOwner {
require(owner == msg.sender);
_;
}
/* Transfer ownership of this contract to someone else */
function transferOwnership(address newOwner) public onlyOwner() {
owner = newOwner;
}
}
/*
* #title AsnScRegistry
* Open Vote Network
* A self-talling protocol that supports voter privacy.
*
* Author: Shahrul Sharudin
*/
contract AsnScRegistry is owned{
struct IPAddress {
uint128 ip;
uint8 mask;
}
struct MemberAddresses {
address contractAddress;
address walletAddress;
uint index;
}
mapping (uint => IPAddress[]) managedIps;
mapping (uint => MemberAddresses) ethAddresses;
uint[] private registeredAsn;
function getManagedIpByAsn(uint _asn) view public returns (uint128[] _ip, uint8[] _mask){
IPAddress[] memory addresses = managedIps[_asn];
uint128[] memory ips = new uint128[](addresses.length);
uint8[] memory mask = new uint8[](addresses.length);
for (uint i = 0; i < addresses.length; i++) {
ips[i] = addresses[i].ip;
mask[i] = addresses[i].mask;
}
return (ips, mask);
}
function getMemberAddressesByAsn(uint _asn) view public returns (address _contractAddress, address _walletAddress){
MemberAddresses memory memberAddresses = ethAddresses[_asn];
return (memberAddresses.contractAddress, memberAddresses.walletAddress);
}
function addMember(uint _asn, uint128[] _ip, uint8[] _mask, address _contractAddress, address _walletAddress) public {
MemberAddresses memory member = ethAddresses[_asn];
//throw error if member already exist
assert(member.contractAddress != 0);
for(uint i=0; i<_ip.length; i++){
managedIps[_asn].push(IPAddress({ip:_ip[i], mask:_mask[i]}));
}
uint idx = registeredAsn.push(_asn)-1;
ethAddresses[_asn] = MemberAddresses({contractAddress:_contractAddress, walletAddress:_walletAddress, index:idx});
}
function removeMember(uint _asn) public returns (uint[] _registeredAsn){
//uint memory index = ethAddresses[_asn].index;
if (ethAddresses[_asn].index >= registeredAsn.length) return;
for (uint i = ethAddresses[_asn].index; i<registeredAsn.length - 1; i++){
registeredAsn[i] = registeredAsn[i+1];
}
registeredAsn.length--;
delete managedIps[_asn];
delete ethAddresses[_asn];
return registeredAsn;
}
function getTotalMembers() view public returns (uint _totalMembers) {
return (registeredAsn.length);
}
function getRegisteredAsn() view public returns (uint[] _asn){
return (registeredAsn);
}
}
javascript unit test:
const AsnScRegistry = artifacts.require('./AsnScRegistry.sol')
const assert = require('assert')
const ip = [3524503734,3232235776];
const mask = [255,255];
const contractAddress = '0x1234567890123456789012345678901234567891';
const walletAddress = '0x1234567890123456789012345678901234567891';
const asn = 123;
let registryInstance;
contract("AsnScRegistry", accounts => {
it("Should add a new member", () =>
AsnScRegistry.deployed()
.then(instance => {
registryInstance = instance;
return instance.addMember(asn, ip, mask, contractAddress, walletAddress);
})
.then(() => registryInstance.getTotalMembers())
.then(total => assert.equal(total.toNumber(), 1, "xxxxx"))
);
});
the full source is available here: https://github.com/shaza4061/electioncommissioner
I expect the addMember() function to store the information in the smart contract and getTotalMembers() to return the number of record in registeredAsn[] array and the assertion in the unit test to pass.
The following error message:
"Error: Returned error: VM Exception while processing transaction: invalid opcode"
indicates a failed assert statement in solidity.
In your code, you have an assert which causes this error.
//throw error if member already exist
assert(member.contractAddress != 0);
Here is a manual for Solidity Smart contract debugging using Truffle.
Related
My smart contract has a struct and a function that populates it:
struct voter {
uint ID;
string firstName;
string lastName;
uint phone;
string addy;
//add picture
}
contract Poll {
uint public numVoters;
event VoterAdded(
voter newVoter
);
function AddVoter(string memory _firstName, string memory _lastName, uint _phone, string
memory _addy) public returns (voter memory){
numVoters++;
voter memory _voter = voter(numVoters, _firstName, _lastName, _phone, _addy);
_voter.ID = numVoters;
_voter.firstName = _firstName;
_voter.lastName = _lastName;
_voter.phone = _phone;
_voter.addy = _addy;
emit VoterAdded(_voter);
return _voter;
}
}
I am using truffle to test this struct, and Im trying to populate a struct and then storing a struct variable in a javascript variable.
const Poll = artifacts.require('Poll.sol');
it('Poll 1 : create voter and candidate objects2', async () =>
const tx = await poll.AddVoter('Jack', 'Jackson', 0, '');
const results = await poll.getPastEvents(
'VoterAdded',
{
fromBlock: 0, toBlock: 'latest'
});
console.log("Results", results, '${results.length} results');
const JJ = results[0];
assert.equal(JJ.firstName, 'Jack');
});
I think there is a problem with the lines after getPastEvents().
Heres the error I get:
Poll 1 : create voter and candidate objects2:
AssertionError: expected undefined to equal 'Jack'
I don't know if it's going to be of use or not, but I always used queryFilter to get the past events, using etherjs.
const eventFilter = poll.filters.VoterAdded();
const events = await poll.queryFilter(eventFilter);
console.log(events);
Hi am new to blockchain technology i have made a smart contract that will show contract balance and user data like his address, balance, and user can deposit inserted amount in smartcontract my code is down am not able to show neither contract balance nor user data. its working perfectly in remix.
smartcontract
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.9.0;
contract UserData {
address owner;
uint bal;
constructor() {
owner = msg.sender;
}
receive() external payable {}
function getBalance() view public returns(uint) {
return bal;
}
function deposit(uint amt) external payable {
bal = bal + amt;
bal += msg.value;
}
// function to get the useraddress
function getOwner() public view returns (address) {
return owner;
}
// Function to return current balance of user
function getUserBalance() public view returns(uint256){
return owner.balance;
}
function withdraw(uint withdrawAmount) external payable {
require(msg.sender == owner, "Only owner can withdraw!");
payable(msg.sender).transfer(withdrawAmount);
}
}
and here is my javascript code:
<script>
var contract;
$(document).ready(function(){
web3 = new Web3(web3.currentProvider);
//ethereum.request({ method: 'eth_requestAccounts' });
var address = "0xd3553504e02681C4d4f1969017dAca11003bB496";
var abi = [];
contract = new web3.eth.Contract(abi, address);
contract.methods.getBalance().call().then(function(bal){
$('#balance').html(bal/10000000000000000);
})
contract.methods.getOwner().call().then(function(address){
$('#userAddress').html(address);
})
})
$('#deposit').click(function(){
var amt = 0;
amt = parseInt($('#amount').val());
web3.eth.getAccounts().then(function(accounts){
var acc = accounts[0];
return contract.methods.deposit(amt).send({from: acc});
}).then(function(tx){
console.log(tx);
}).catch(function(tx){
console.log(tx);
})
})
</script>
Your question is not specific. You can check this repository that contains videos of related topics. I'm sure you'll find your answer here.
https://github.com/smartcontractkit/full-blockchain-solidity-course-js
I am new to solidity and smart contracts and I am bit confused with sending money from metamask to my smart contract. Everything seems to work fine in remix but when I use metamask I get a revert error message. I am using ganache as my local blockchain
My smart contract looks like this: -
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.10;
import "#openzeppelin/contracts/access/Ownable.sol";
contract Bet is Ownable{
uint public Money; // set variable to display balance on contract
bool Odd; // variable to set true or false
uint TotalDiceNumber = 12; // dice numbers from 1 - 12
uint result; // variable to hold the dice roll
mapping(address => uint) allowance; //allowance for non owners of the contract
uint BetValue; //variable for original bet value
uint _amount; //variable to hold value of allowance
bool Active; // is the game active
constructor() {
}
function isOwner() internal view returns(bool) {
return owner() == msg.sender; //returns the address who deployed it
}
event BetMade(address player, uint Bet); //placeholder to send data to front end
function receiveMoney() public payable { // get money(bet) from metamask and put on smart
emit BetMade(msg.sender, BetValue); // send player and value of bet
//Money += BetValue; //added after react
Money += msg.value;
BetValue = msg.value;
if (owner() == msg.sender) {
Active = false; // owner doesnt active contract to protect funds
} else {
Active = true; // player activates contract when bet is placed
require(BetValue <= 20 ether, "Bets must be below 21 Ether"); //player can only
bet under 20 ether/ owner can put as much money as they want on
}
}
event BalanceofContract(uint Balcontract);
function getBalance()public returns(uint) {
uint Bal;
Bal = address(this).balance;
emit BalanceofContract(Bal);
return Bal;
}
event PlayerSelectOddEven(address player, bool OddEven);
function selectOddorEven(bool OddEven) public {
emit PlayerSelectOddEven(msg.sender, OddEven);
require(msg.sender != owner(), "You are the house and cannot bet"); // house cannot bet
require(Active = true, "Game not in play. Please place a bet"); // game must be active
Odd = OddEven; // create field to enter true for odd or false for Even
//default is false
}
function Random() internal view returns(uint) {
return uint(keccak256(abi.encodePacked
(block.difficulty,
block.timestamp,
TotalDiceNumber))); // create a random number from blockchain.
//in production would look at chainlink VR but looks like there is a cost so
//went with a less secure option
}
event RollDiceOutput(address player, uint DiceNumber);
function Rolldice() public returns(uint){
emit RollDiceOutput(msg.sender, result);
uint Outcome;
require(Active = true, "Game not in play. Please place a bet"); //game must be actvie
Outcome = Random() % TotalDiceNumber;
result = Outcome + 1; // use + 1 to remove 0 out of random sequence
return result; // function to create number
}
function OutcomeDice() public view returns (uint) {
uint Outcome1;
Outcome1 = result;
return Outcome1;
// function to view number from above function
}
function numberOddorEven() public view returns (bool) {
bool OddorEven; // true for odd false for even
uint _result;
_result = result;
if (_result == 1 || _result == 3 || _result == 5 || _result == 7 || _result == 9 ||
_result == 11) {
OddorEven = true;
} else {
OddorEven = false;
}
return OddorEven;
}
event Winning(address Player, uint WinningsValue);
function addAllowance() public {
emit Winning(msg.sender, _amount);
require(msg.sender != owner(), "You are the house and cannot bet");
require(Active = true, "Game not in play. Please place a bet");
address _who = msg.sender; // assign player to variable
_amount = BetValue * 2; //assign allowance twice as much original bet
allowance[_who] == _amount; // set allowance in mapping against player
}
event Won(address Player, uint Winnings);
function WinMoney() public {
emit Won(msg.sender, _amount);
bool UserInputOdd = numberOddorEven();
bool decisionOdd = Odd;
address _who = msg.sender; // assign player to variable
require(Active = true, "Game not in play. Please place a bet");
require(_amount > 0, "Add the house's money by adding a allowance to collect winning");
if (UserInputOdd == decisionOdd) {
address payable to = payable(msg.sender); //pay the player's address
to.transfer(_amount); // transfer the winning
_amount = 0; //zeroed the variable for multiplying the bet
allowance[_who] = 0; // zeroed the allowance
BetValue = 0; // zeroed the bet
Odd = false; // resets the odd/even input
Active = false; //disable the game
} else {
_amount = 0; //zeroed the variable for multiplying the bet
allowance[_who] = 0; // zeroed the allowance
BetValue = 0; // zeroed the bet
Odd = false; // resets the odd/even input
Active = false; //disable the game
}
}
receive() external payable {
receiveMoney();
}
}
On the front end I am trying to add funds to the smart contract: -
import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'
import { useState } from "react" //import library for line 9
import { ethers } from "ethers" // import library for ethers
import { abi_file } from "../constants/abi"; // import abi from different file
export default function Home() {
const [isConnected, setIsConnected] = useState(false); //to show a button is not connected
const [signer, setSigner] = useState();
async function connect() { //create function to connect metameask
if (typeof window.ethereum !== "undefined") { // check to see if metamask is installed
try {
await ethereum.request({ method: "eth_requestAccounts"});
setIsConnected(true); // set variable as true
const connectedProvider = new ethers.providers.Web3Provider(window.ethereum);
setSigner(connectedProvider.getSigner());
} catch (e) {
console.log(e); // catch and log and errors in console(F12 in chrome)
}
} else {
setIsConnected(false);
}
}
async function Rolldice() { //execute function
if (typeof window.ethereum !== "undefined") { // check to see if metamask is installed
const contractAddress = "0x89f6D41f87054127066d4639e3Ada3DeEefE5EB7"; // address of the contract
const abi = abi_file;
const contract = new ethers.Contract(contractAddress, abi, signer); // calls the contract from the 3 variables
try {
// await contract.Rolldice(); //function will are calling on the sol contract
const transactionResponse = await contract.Rolldice();
const transactionReceipt = await transactionResponse.wait();
var player = (transactionReceipt.events[0].args.player);
var result = (transactionReceipt.events[0].args.DiceNumber.toString());
//alert("Dice Number pressed");
//var x = document.createElement("H3");
//var t = document.createTextNode("Dice rolled from " + player);
// x.appendChild(t);
// document.body.appendChild(x);
var z = document.createElement("H3");
var w = document.createTextNode("Dice number is " + result);
z.appendChild(w);
document.body.appendChild(z);
} catch (error) {
console.log(error);
}
} else {
document.getElementById("executeButton").innerHTML =
"Please install MetaMask";
}
}
async function receiveMoney() { //execute function
if (typeof window.ethereum !== "undefined") { // check to see if metamask is installed
const contractAddress = "0x89f6D41f87054127066d4639e3Ada3DeEefE5EB7"; // address of the contract
const abi = abi_file;
const contract = new ethers.Contract(contractAddress, abi, signer); // calls the contract from the 3 variables
try {
// await contract.Rolldice(); //function will are calling on the sol contract
const transactionResponse = await contract.receiveMoney();
const transactionReceipt = await transactionResponse.wait();
var Balance = (transactionReceipt.events[0].args.Bet.toString());
//alert("Dice Number pressed");
//var x = document.createElement("H3");
//var t = document.createTextNode("Dice rolled from " + player);
// x.appendChild(t);
// document.body.appendChild(x);
var z = document.createElement("H2");
var w = document.createTextNode("The Balance of the contract is " + Balance);
z.appendChild(w);
document.body.appendChild(z);
} catch (error) {
console.log(error);
}
} else {
document.getElementById("executeButton").innerHTML =
"Please install MetaMask";
}
}
return <div className={styles.container}>
{isConnected ?
<>
<h2>"Connected!" </h2>
<p> Please send money to 0x89f6D41f87054127066d4639e3Ada3DeEefE5EB7 but no higher than 20 ethers</p>
<button onClick= {() => receiveMoney()}>Bet Money</button>
<br></br>
<br></br>
<button onClick= {() => Rolldice()}>Roll dice</button>
<br></br>
<br></br>
</>
: (<button onClick={() =>connect()}>Connect</button>) }
</div>;
}
Can anybody suggest where I am going wrong? Many thanks
First in your solidity can you emit the event after assigned the value for the variable betvalue
Second you need to specify for wich account the signer is like this
let provider = new ethers.providers.Web3Provider(window.ethereum);
const accounts = await provider.listAccounts();
let account = null;
if (accounts.length > 0)
{ account = accounts[0] }
let signer = provider.getSigner(account);
Third you need to pass the value the user send into the smart contract through argument options
const options = { value: ethers.utils.parseEther(value) }
var transactionResponse = await contract.receiveMoney(options);
Value need to ve string like this value="1"
This mean you will send 1 ethers
The version I'm using is 0.5.2
I'm executing the below code in Remix IDE
pragma solidity ^0.5.2;
contract Lottery {
address public manager;
address payable[] public players;
constructor () public {
manager = msg.sender;
}
function enter() public payable {
require(msg.value > 0.01 ether);
players.push(msg.sender);
}
// function getPlayers() public view returns(address[] memory) {
// return players;
// }
function random() public view returns(uint) {
return uint(keccak256(abi.encodePacked(block.difficulty, now, players)));
}
function pickWinner() public {
uint index = random() % players.length;
players[index].transfer(address(this).balance);
players = new address[](0); // This line of code giving an error
}
}
The error I'm getting is:
Type address[] memory is not implicitly convertible to expected type address payable[] storage ref.
in the function pickWinner():
function pickWinner() public {
uint index = random() % players.length;
players[index].transfer(address(this).balance);
players = new address[](0); // This line of code giving an error
}
I'm trying to reset my players' array all to 0 so as to reset my Lottery contract
Probably the best/easiest thing to do is players.length = 0.
Note that this will use gas proportional to the number of elements in the array (because it deletes all of them). If this is a problem, you might want to consider using a mapping instead with a separately stored length. E.g.
mapping(uint256 => address payable) players;
uint256 playersLength;
Then just do playersLength = 0 to "reset."
EDIT
Per the comments, it sounds like you're not seeing the gas usage based on the size of the array. Here's a simple way to test in Remix:
pragma solidity 0.5.2;
contract Test {
uint256[] foo;
uint256[] bar;
constructor() public {
for (uint256 i = 0; i < 5; i++) {
foo.push(i);
}
for (uint256 i = 0; i < 100; i++) {
bar.push(i);
}
}
function deleteFoo() external {
foo.length = 0;
}
function deleteBar() external {
bar.length = 0;
}
}
In my testing, using the JavaScript VM, deleteFoo consumes 26,070 gas, and deleteBar consumes 266,267 gas.
function pickWinner() public {
uint index = random() % players.length;
players[index].transfer(address(this).balance);
players = new address payable [](0); //add payable to this line
}
I'm trying to compile and migrate a solidity code built in an older version of solidity, using a newer solidity. This is the solidity code:
//solium-disable linebreak-style
pragma solidity ^ 0.4 .23;
// Simple Solidity intro/demo contract for BlockGeeks Article
contract Geekt {
address GeektAdmin;
mapping(bytes32 => notarizedImage) notarizedImages; // this allows to look up notarizedImages by their SHA256notaryHash
bytes32[] imagesByNotaryHash; // this is like a whitepages of all images, by SHA256notaryHash
mapping(address => User) Users; // this allows to look up Users by their ethereum address
address[] usersByAddress; // this is like a whitepages of all users, by ethereum address
struct notarizedImage {
string imageURL;
uint timeStamp;
}
struct User {
string handle;
bytes32 city;
bytes32 state;
bytes32 country;
bytes32[] myImages;
}
constructor() public payable {
// this is the CONSTRUCTOR (same name as contract) it gets called ONCE only when contract is first deployed
GeektAdmin = msg.sender; // just set the admin, so they can remove bad users or images if needed, but nobody else can
}
modifier onlyAdmin() {
if (msg.sender != GeektAdmin)
revert("invalid message sender: sender not admin");
// Do not forget the "_;"! It will be replaced by the actual function body when the modifier is used.
_;
}
function removeUser(address badUser) public onlyAdmin returns(bool success) {
delete Users[badUser];
return true;
}
function removeImage(bytes32 badImage) public onlyAdmin returns(bool success) {
delete notarizedImages[badImage];
return true;
}
function registerNewUser(string handle, bytes32 city, bytes32 state, bytes32 country) public returns(bool success) {
address thisNewAddress = msg.sender;
// don't overwrite existing entries, and make sure handle isn't null
if (bytes(Users[msg.sender].handle).length == 0 && bytes(handle).length != 0) {
Users[thisNewAddress].handle = handle;
Users[thisNewAddress].city = city;
Users[thisNewAddress].state = state;
Users[thisNewAddress].country = country;
usersByAddress.push(thisNewAddress); // adds an entry for this user to the user 'whitepages'
return true;
} else {
return false; // either handle was null, or a user with this handle already existed
}
}
function addImageToUser(string imageURL, bytes32 SHA256notaryHash) public returns(bool success) {
address thisNewAddress = msg.sender;
if (bytes(Users[thisNewAddress].handle).length != 0) { // make sure this user has created an account first
if (bytes(imageURL).length != 0) { // ) { // couldn't get bytes32 null check to work, oh well!
// prevent users from fighting over sha->image listings in the whitepages, but still allow them to add a personal ref to any sha
if (bytes(notarizedImages[SHA256notaryHash].imageURL).length == 0) {
imagesByNotaryHash.push(SHA256notaryHash); // adds entry for this image to our image whitepages
}
notarizedImages[SHA256notaryHash].imageURL = imageURL;
notarizedImages[SHA256notaryHash].timeStamp = block.number;
// note that updating an image also updates the timestamp
Users[thisNewAddress].myImages.push(SHA256notaryHash); // add the image hash to this users .myImages array
return true;
} else {
return false; // either imageURL or SHA256notaryHash was null, couldn't store image
}
return true;
} else {
return false; // user didn't have an account yet, couldn't store image
}
}
function getUsers() public view returns(address[]) {
return usersByAddress;
}
function getUser(address userAddress) public view returns(string, bytes32, bytes32, bytes32, bytes32[]) {
return (Users[userAddress].handle, Users[userAddress].city, Users[userAddress].state, Users[userAddress].country, Users[userAddress].myImages);
}
function getAllImages() public view returns(bytes32[]) {
return imagesByNotaryHash;
}
function getUserImages(address userAddress) public view returns(bytes32[]) {
return Users[userAddress].myImages;
}
function getImage(bytes32 SHA256notaryHash) public view returns(string, uint) {
return (notarizedImages[SHA256notaryHash].imageURL, notarizedImages[SHA256notaryHash].timeStamp);
}
}
This is the complete error log showing:
> Using network 'development'.
>
> Running migration: 1_initial_migration.js
>
> C:\Users\Kombos\AppData\Roaming\npm\node_modules\truffle\build\cli.bundled.js:101723
> var artifact = JSON.parse(
> ^ undefined:1 [.ShellClassInfo] ^
>
> SyntaxError: Unexpected token . in JSON at position 1
> at JSON.parse (<anonymous>)
> at FS.getContractName (C:\Users\Kombos\AppData\Roaming\npm\node_modules\truffle\build\cli.bundled.js:101723:25)
> at FS.require (C:\Users\Kombos\AppData\Roaming\npm\node_modules\truffle\build\cli.bundled.js:101698:28)
> at Resolver.require (C:\Users\Kombos\AppData\Roaming\npm\node_modules\truffle\build\cli.bundled.js:59966:25)
> at Object.require (C:\Users\Kombos\AppData\Roaming\npm\node_modules\truffle\build\cli.bundled.js:69602:36)
> at ResolverIntercept.require (C:\Users\Kombos\AppData\Roaming\npm\node_modules\truffle\build\cli.bundled.js:197047:32)
> at D:\Cloud\Google Drive\Knowledge Base\Blockchain\Bitcoin\Blockchain Specialization\Smart
> Contracts\Project 1 - Image based Social
> app\Geek\migrations\1_initial_migration.js:1:28
> at ContextifyScript.Script.runInContext (vm.js:59:29)
> at ContextifyScript.Script.runInNewContext (vm.js:65:15)
> at C:\Users\Kombos\AppData\Roaming\npm\node_modules\truffle\build\cli.bundled.js:101639:14
> at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:511:3)
could you please let me know what the error could be? Thanks in advance.
SyntaxError: Unexpected token . in JSON at position 1 exception happen probably for invalid chars in JSON
already answered here
Try deleting your build folder and start over, you might have leftover files from previous builds.