How to read fields in struct from truffle console? - ethereum

I have a simple smart contract of TodoList looks like this
pragma solidity ^0.8.0;
contract TodoList {
uint256 public taskCount = 0;
struct Task {
uint256 id;
string content;
bool completed;
}
mapping(uint256 => Task) public tasks;
constructor(){
createTask("Buy Keyboard");
}
function createTask(string memory _content) public {
taskCount++;
tasks[taskCount] = Task(taskCount, _content, false);
}
}
I want to read the id of the first todo but it is showing undefined no matter what i try? What is the right approach here?

You can do that by waiting the promise, then assign the value:
>> task.then(data => { id = + data["id"] } )
>> id

You need to use the await keyword as its an asynchronous action. e.g.
todoList = await TodoList.deployed()
task = await todoList.task(1)
id = task.id.toNumber()

Related

Trying to initialize an array of stuct inside a struct, but getting storage/memory pointer error

I am trying to create a voting smart contract in solidity.
But I cannot get a hand on how to initialize Vote.differentVotes in side my function createVote() :
my structs
struct Vote_element {
string name;
uint numberOfVotes;
}
struct Vote{
string title;
address creator;
Vote_element[10] differentVotes;
bool done;
}
the function I am having issues with.
function createVote(string memory _title , string[] memory _elements) public {
Vote storage v;
for(uint i = 0; i < _elements.length; i++)
v.differentVotes[i] = Vote_element(_elements[i], 0); // error here
v.title = _title; // error here
v.creator = msg.sender; // error here
v.done = false; // error here
all_votes.push(v); // error here
}
I got the following error everywhere but I do not understand it.
This variable is of storage pointer type and can be accessed without prior assignment,
which would lead to undefined behaviour.
Can someone guide me ?
Try this:
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
contract StudentVotes {
Vote[] all_votes;
struct Vote_element {
string name;
uint numberOfVotes;
}
struct Vote{
string title;
address creator;
Vote_element[10] differentVotes;
bool done;
}
function createVote(string memory _title , string[] memory _elements) public {
// Before initializing the variable into a struct, you must push the struct into
// Votes' array.
Vote storage v = all_votes.push();
// Then you can initialize the each variable into a struct
v.title = _title;
v.creator = msg.sender;
for(uint i = 0; i < _elements.length; i++)
v.differentVotes[i] = Vote_element(_elements[i], 0);
v.done = false;
}
}

AssertionError: expected '0x0000000000000000000000000000000000000000'

I am getting this error in testing my upgradeable smart contract.
I am really stuck with this can anyone help me get out of this?
contracts/StakingContract.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "#openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
import "#openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "#openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
import "#openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "#openzeppelin/contracts-upgradeable/token/ERC20/SafeERC20Upgradeable.sol";
import "#openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "#openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
import "#openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
contract StakingContract is ERC20Upgradeable, OwnableUpgradeable, ReentrancyGuardUpgradeable {
using SafeMathUpgradeable for uint256;
using AddressUpgradeable for address;
using SafeERC20Upgradeable for IERC20Upgradeable;
event TokensStaked(address _tokenStaker, uint256 _amount, uint256 unlockTime);
event TokenUnstaked(address _tokenStaker, uint256 _amount);
// Variable that prevents _deposit method from being called 2 times
bool private locked;
// The total staked amount
uint256 public totalStaked;
mapping (address => uint256) public stakeBalances;
mapping(address => uint256) private timestamp;
function initialize(uint256 initialSupply) public initializer {
__ERC20_init("MyToken", "TKN");
_mint(owner(), initialSupply);
}
function stakeTokens(address token, uint amount) external {
stakeBalances[msg.sender] = stakeBalances[msg.sender].add(amount);
timestamp[msg.sender] = block.timestamp.add(30 days);
require(IERC20Upgradeable(token).allowance(msg.sender, address(this)) >= amount, "Check the token allowance");
require(IERC20Upgradeable(token).transferFrom(msg.sender, address(this), amount), "Transfer failed!");
totalStaked = totalStaked.add(amount);
emit TokensStaked(msg.sender, amount, timestamp[msg.sender]);
}
function unstakeTokens(address token, uint256 amount) external nonReentrant() {
require(amount <= stakeBalances[msg.sender], "Sorry! You don't have sufficient stake balance.");
require(block.timestamp >= timestamp[msg.sender], "Sorry! you cannot withdraw tokens before your stake time.");
stakeBalances[msg.sender] = stakeBalances[msg.sender].sub(amount);
require(IERC20Upgradeable(token).transfer(msg.sender, amount));
totalStaked = totalStaked.sub(amount);
emit TokenUnstaked(msg.sender, amount);
}
function ownerWithdraw(address token) external onlyOwner() nonReentrant() {
require(IERC20Upgradeable(token).transfer(owner(), totalStaked), "Transfer Failed!");
uint256 ownerStakedBalance = stakeBalances[msg.sender];
stakeBalances[msg.sender] = stakeBalances[msg.sender].sub(ownerStakedBalance);
totalStaked = totalStaked.sub(totalStaked);
}
}
test/StakingContract.test.js
const { accounts, contract, web3 } = require('#openzeppelin/test-environment');
const { expect } = require('chai');
const { TestHelper } = require('#openzeppelin/cli');
const { Contracts, ZWeb3 } = require('#openzeppelin/upgrades');
// Import utilities from Test Helpers
const { BN, expectEvent, expectRevert } = require('#openzeppelin/test-helpers');
ZWeb3.initialize(web3.currentProvider);
const Box = Contracts.getFromLocal('StakingContract');
describe('StakingContract', function () {
const [ owner, other ] = accounts;
beforeEach(async function () {
this.project = await TestHelper();
this.proxy = await this.project.createProxy(Box);
});
it('retrieve returns a value previously stored', async function () {
// Use large integer comparisons
expect(await this.proxy.methods.owner().call()).to.equal(owner);
});
});
it gives the following error:
0 passing (864ms)
1 failing
1) StakingContract
retrieve returns a value previously stored:
AssertionError: expected '0x0000000000000000000000000000000000000000' to equal '0xA05c7D52b924DceB23a766ccB1e91e67b4aCF014'
+ expected - actual
-0x0000000000000000000000000000000000000000
+0xA05c7D52b924DceB23a766ccB1e91e67b4aCF014
I have tried to fix it with other things but the still issue persists.
Thanks in advance.

Error: gas required exceeds allowance or always failing transaction - web3js

I get the following error when I try to deploy a smartcontract using web3js. But if I deploy the same contract using Truffle or geth console, deployment succeeds.
Error: gas required exceeds allowance or always failing transaction
Smart Contract solidity code:
pragma solidity >=0.4.25 <0.6.0;
contract Election {
// Model a Candidate
struct Candidate {
uint id;
string name;
uint voteCount;
}
// Store accounts that have voted
mapping(address => bool) public voters;
// voted event
event votedEvent (
uint indexed _candidateId
);
// Store Candidates
// Read Candidate
mapping(uint => Candidate) public candidates;
// Store Candidates count
uint public candidatesCount;
// Constructor
constructor() public{
addCandidate('ABC');
addCandidate('XYZ');
addCandidate('PQR');
}
function addCandidate(string memory _name) private{
candidatesCount++;
candidates[candidatesCount] = Candidate(candidatesCount, _name, 0);
}
function vote(uint _candidateId) public{
// require that they haven't voted before
require(!voters[msg.sender]);
// require a valid candidate
require(_candidateId > 0 && _candidateId <= candidatesCount);
// record that voter has voted
voters[msg.sender] = true;
// update candidate vote Count
candidates[_candidateId].voteCount ++;
// trigger voted event
emit votedEvent(_candidateId);
}
}
Following is the code, I am using to deploy the smartcontract:
const provider = new HDWalletProvider(mnemonic, nodeAccessToken, 1);
const web3 = new Web3(provider);
const contract = new web3.eth.Contract(abi);
const accounts = await web3.eth.getAccounts();
try{
const deployedContract = await contract.deploy({
data: '0x' + bytecodeData, // Adding '0x' since generated bytecodedata doesn't have '0x' prefix.
arguments: args
});
let result = await deployedContract.send({
from: accounts[0],
gasPrice: 0
})
}catch(e){}
Did anyone else face the same issue?

Solidity: Error('incorrect number of arguments')

I am trying to create my first Smart Contract but how is it possible that the error says invalid argument?, please consider that with the first method (CreateITem) everything works fine... that's for saying that it's not a problem of invalid ABI or invalid contract address ?
The error is : throw new Error('incorrect number of arguments');
pragma solidity ^0.5.0;
contract ItemsList {
uint public itemCount = 0;
mapping(uint => Item) public items;
struct Item {
string encryptedProofHash;
}
function createItem(string memory _encryptedProofHash) public {
items[itemCount] = Item(_encryptedProofHash);
itemCount++;
}
function getItemCount() public view returns (uint){
return itemCount;
}
}
...and this is the code for reading using ethers.js
var wallet = new ethers.Wallet(privateKey,provider);
var contract = new ethers.Contract(address,abi,wallet);
var sendPromise = contract.getItemCount(); ------------------->> ERRROR
sendPromise.then(function(transaction){
console.log(transaction);
}).catch((error) => {
console.error(error)
});
I found it, just remove the build folder and generate again the contract

Geth + smart contract function = bad instruction

playing with ethereum smart contracts I encountered a following problem. The contract gets deployed on Ropsten and then I'm trying to call function 'addRecipe' with the following code on geth:
recipes.addRecipe(300, "zupa", "zupa z trupa", {from:web3.eth.accounts[0], gas: 20000000})
The function looks as following:
function addRecipe(uint256 _price, string _name, string _content) public {
recipes[recipeCount].price = _price;
recipes[recipeCount].name = _name;
recipes[recipeCount].content = _content;
recipes[recipeCount].recipeOwner = msg.sender;
recipeCount++;
}
I get the TX hash but looking up the transaction in Etherscan gives
Warning! Error encountered during contract execution [Bad instruction]
You can check it up here:
https://ropsten.etherscan.io/tx/0xe5999c2d122e4871e82f5986397dfd39107cee2056a9280132abeaa460c0f66d
Adding 'payable' modifier to the function or using the following command doesn't give any better results...
recipes.addRecipe.sendTransaction(300, "zupa", "zupa z trupa", {from:web3.eth.accounts[0], gas: 200000000})
The whole contract:
pragma solidity ^0.4.24;
contract Recipes {
address owner;
uint256 recipeCount = 0;
struct Recipe {
string name;
string content;
uint256 price;
address recipeOwner;
}
Recipe[] public recipes;
function () public {
owner = msg.sender;
}
function kill() public {
require (msg.sender == owner);
selfdestruct(owner);
}
function addRecipe(uint256 _price, string _name, string _content) public {
recipes[recipeCount].price = _price;
recipes[recipeCount].name = _name;
recipes[recipeCount].content = _content;
recipes[recipeCount].recipeOwner = msg.sender;
recipeCount++;
}
function showRecipes(uint256 _id) constant returns(string) {
return recipes[_id].content;
}
}
recipes is a dynamic storage array. You need to change the size of the array to add new elements to it. You can either do this by explicitly increasing the length of the array or by pushing a new element into the array.
function addRecipe(uint256 _price, string _name, string _content) public {
recipes.length++;
recipes[recipeCount].price = _price;
recipes[recipeCount].name = _name;
recipes[recipeCount].content = _content;
recipes[recipeCount].recipeOwner = msg.sender;
recipeCount++;
}
Or
function addRecipe(uint256 _price, string _name, string _content) public {
Recipe memory r;
r.price = _price;
r.name = _name;
r.content = _content;
r.recipeOwner = msg.sender;
recipes.push(r);
recipeCount++;
}