Ethereum event not showing up but function completing - ethereum

I have the following contract:
Contract Store{
event Purchase(address buyer, int item_id);
struct Product {
string name;
uint price;
string desc;
uint quantity;
bool enabled;
}
mapping (address => int) balances;
function buyProduct(uint id) returns(bool){
if(products[id].quantity <= 0){ return false; }
balances[msg.sender] = balances[msg.sender] - int(products[id].price);
products[id].quantity--;
Purchase(msg.sender, id);
return true;
}
}
When I use web3 to purchase a product with Store.buyProduct, the product purchase is made, but the event doesn't fire on the front-end. Here is my event watcher code:
var eventFilter = Store.deployed().Purchase({from: "0xe02b4fc50f429624937e9425e1243292857291e2"}, {fromBlock: 0, toBlock: 'latest'});
eventFilter.watch(function(error, event){
console.log('hai');
console.log(event);
});

Argh. It just started working, I was passing a uint to the event but it was expecting an int.

Related

DeclarationError: Undeclared identifier. "..." is not visible at this point

I am practising this tutorial in Remix IDE - https://www.youtube.com/watch?v=_aXumgdpnPU
I saw in the Chainlink documentation that their Randomness VRF code has been changed since the development of the video.
I started replacing the parts and trying to deploy the class via Remix but it gives an error which I am not sure how to fix.
Would you be able to check what I have as code and I'll send a screenshot of the error?
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;
import "#chainlink/contracts/src/v0.8/ConfirmedOwner.sol";
import "#chainlink/contracts/src/v0.8/VRFV2WrapperConsumerBase.sol";
contract Lottery is
VRFV2WrapperConsumerBase,
ConfirmedOwner
{
address public owner;
address payable[] public players;
uint public lotteryId;
mapping (uint => address payable) public lotteryHistory;
event RequestSent(uint256 requestId, uint32 numWords);
event RequestFulfilled(
uint256 requestId,
uint256[] randomWords,
uint256 payment
);
struct RequestStatus {
uint256 paid; // amount paid in link
bool fulfilled; // whether the request has been successfully fulfilled
uint256[] randomWords;
}
mapping(uint256 => RequestStatus)
public s_requests; /* requestId --> requestStatus */
// past requests Id.
uint256[] public requestIds;
uint256 public lastRequestId;
// Depends on the number of requested values that you want sent to the
// fulfillRandomWords() function. Test and adjust
// this limit based on the network that you select, the size of the request,
// and the processing of the callback request in the fulfillRandomWords()
// function.
uint32 callbackGasLimit = 100000;
// The default is 3, but you can set this higher.
uint16 requestConfirmations = 3;
// For this example, retrieve 2 random values in one request.
// Cannot exceed VRFV2Wrapper.getConfig().maxNumWords.
uint32 numWords = 2;
// Address LINK - hardcoded for Goerli
address linkAddress = 0x326C977E6efc84E512bB9C30f76E30c160eD06FB;
// address WRAPPER - hardcoded for Goerli
address wrapperAddress = 0x708701a1DfF4f478de54383E49a627eD4852C816;
constructor()
ConfirmedOwner(msg.sender)
VRFV2WrapperConsumerBase(linkAddress, wrapperAddress)
{
owner = msg.sender;
lotteryId = 1;
}
function requestRandomWords()
external
onlyOwner
returns (uint256 requestId)
{
requestId = requestRandomness(
callbackGasLimit,
requestConfirmations,
numWords
);
s_requests[requestId] = RequestStatus({
paid: VRF_V2_WRAPPER.calculateRequestPrice(callbackGasLimit),
randomWords: new uint256[](0),
fulfilled: false
});
requestIds.push(requestId);
lastRequestId = requestId;
emit RequestSent(requestId, numWords);
return requestId;
}
function fulfillRandomWords(
uint256 _requestId,
uint256[] memory _randomWords
) internal override {
require(s_requests[_requestId].paid > 0, "request not found");
s_requests[_requestId].fulfilled = true;
s_requests[_requestId].randomWords = _randomWords;
emit RequestFulfilled(
_requestId,
_randomWords,
s_requests[_requestId].paid
);
payWinner();
}
function getRequestStatus(
uint256 _requestId
)
external
view
returns (uint256 paid, bool fulfilled, uint256[] memory randomWords)
{
require(s_requests[_requestId].paid > 0, "request not found");
RequestStatus memory request = s_requests[_requestId];
return (request.paid, request.fulfilled, request.randomWords);
}
/**
* Allow withdraw of Link tokens from the contract
*/
function withdrawLink() public onlyOwner {
LinkTokenInterface link = LinkTokenInterface(linkAddress);
require(
link.transfer(msg.sender, link.balanceOf(address(this))),
"Unable to transfer"
);
}
function getWinnerByLottery(uint lottery) public view returns (address payable) {
return lotteryHistory[lottery];
}
function getBalance() public view returns (uint) {
return address(this).balance;
}
function getPlayers() public view returns (address payable[] memory) {
return players;
}
function enter() public payable {
require(msg.value > .01 ether);
// address of player entering lottery
players.push(payable(msg.sender));
}
//function getRandomNumber() public view returns (uint) {
//return uint(keccak256(abi.encodePacked(owner, block.timestamp)));
//}
function pickWinner() public onlyowner {
requestRandomWords;
}
function payWinner() public {
uint index = lastRequestId % players.length;
players[index].transfer(address(this).balance);
lotteryHistory[lotteryId] = players[index];
lotteryId++;
// reset the state of the contract
players = new address payable[](0);
}
modifier onlyowner() {
require(msg.sender == owner);
_;
}
}
enter image description here

My "Buy" function in smart contract file keep making error

This is my solidity file for NFT marketplace.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
contract NFT is ERC721URIStorage,Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
address payable public _owner;
mapping(address => uint[]) public addressToTokenArray;
mapping(uint256 => bool) public forSale;
mapping(uint256 => uint256) public tokenIdToPrice;
event Minting(address _owner, uint256 _tokenId, uint256 _price);
event Purchase(address _seller, address _buyer, uint256 _price);
event Remove(uint256 _tokenId, uint[] beforeBuy, uint[] afterBuy);
constructor() ERC721("TeddyBear", "TEDDY") {
}
function mint(string memory _tokenURI, uint256 _price) public onlyOwner returns (bool)
{
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
tokenIdToPrice[newItemId] = _price;
if(addressToTokenArray[msg.sender].length !=1){
addressToTokenArray[msg.sender].push(newItemId);
}else{
addressToTokenArray[msg.sender] = [newItemId];
}
_mint(msg.sender, newItemId);
_setTokenURI(newItemId, _tokenURI);
emit Minting(msg.sender, newItemId, _price);
return true;
}
// 토큰의 주인이 판매 하는 함수
function sell(uint256 _tokenId, uint256 _price) external {
require(msg.sender == ownerOf(_tokenId), 'Not owner of this token');
require(_price > 0, 'Price zero');
tokenIdToPrice[_tokenId] = _price;
forSale[_tokenId] = true;
}
// 토큰의 주인이 판매를 취하하는 함수
function stopSell(uint256 _tokenId) external {
require(msg.sender == ownerOf(_tokenId), 'Not owner of this token');
forSale[_tokenId] = false;
}
// function remove(uint[] memory array, uint index) public pure returns(uint[] memory) {
// if (index >= array.length) return array;
// for (uint i = index; i<array.length-1; i++){
// array[i] = array[i+1];
// }
// delete array[array.length-1];
// return array;
// }
function buy(uint256 _tokenId, uint256 sendAmount) external payable {
uint256 price = tokenIdToPrice[_tokenId];
bool isOnSale = forSale[_tokenId];
require(isOnSale, 'This token is not for sale');
require(sendAmount == price, 'Incorrect value');
address seller = ownerOf(_tokenId);
require(seller == ownerOf(_tokenId), 'Seller and Owner is not same');
// uint[] memory beforeBuy = addressToTokenArray[seller];
// // for(uint i=0;i<addressToTokenArray[seller].length;i++){
// // if(_tokenId == addressToTokenArray[seller][i]){
// // remove(addressToTokenArray[seller],i);
// // }
// // }
// uint[] memory afterBuy = addressToTokenArray[seller];
// emit Remove(_tokenId, beforeBuy, afterBuy);
addressToTokenArray[msg.sender] = [_tokenId];
safeTransferFrom(seller, msg.sender, _tokenId);
forSale[_tokenId] = true;
payable(seller).transfer(sendAmount); // send the ETH to the seller
emit Purchase(seller, msg.sender, sendAmount);
}
function getPrice(uint256 _tokenId) public view returns (uint256){
uint256 price = tokenIdToPrice[_tokenId];
return price;
}
function isSale(uint256 _tokenId) public view returns (bool){
bool isOnSale = forSale[_tokenId];
return isOnSale;
}
function getMyTokenId() public view returns (uint[] memory){
uint[] memory myTokens = addressToTokenArray[msg.sender];
return myTokens;
}
}
Among functions up there, the buy function does not emit an error when I compile the .sol file, but after I deploy this contract and send transaction for "buy" function it keeps making this error.
I just want to know where I should fix it and if there is any better idea for other functions, feel free to let me know... many thanks
Most likely it is failing here:
safeTransferFrom(seller, msg.sender, _tokenId);
If you check the ERC721 contract, safeTransferFrom eventually calls this:
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// ****** HERE IS THE ISSUE *****
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
If your contract is going to transfer a token on behalf of owner, owner has to approve first.
so from the seller's contract, this should be called:
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
tokenApprovals is a mapping that keeps track of which tokens can be transferred.
Debugging
in order to test which function call is causing error, place this requirement statement require(sendAmount == price, 'Incorrect value'); right before the function. and pass an incorrect value and you will get an error : 'Incorrect value'
Then put that require statement after the function, and pass a wrong value, if this require does send you error, you can be sure that function is causing the error

MyContractInstance.methods.MyMethod is not a function (Contract Instance cannot get contract methods) web3

I am trying to implement ERC20 Token Contract using web3.js.
I created an instance of the contract, but when I am logging it in the browser console, I am not getting some of the later newly created methods.
The deployAddress and the abi are perfectly alright.
Here, is the code snippet, if anyone can help.
Token contract
pragma solidity ^0.6.0;
import "/contracts/ERC20.sol";
contract YatharthaMudra is IERC20{
string public symbol;
string public name;
uint public decimals;
uint public __totalSupply;
mapping(address => uint) private __balanceOf;
mapping(address => mapping(address => uint)) __allowances;
constructor () public{
symbol = "YMT";
name = "Yathaartha Mudra";
decimals = 18;
__totalSupply = 1000*10**decimals;
__balanceOf[msg.sender] = __totalSupply;
}
function getName() public view returns (string memory){
return name;
}
function getSymbol() public view returns (string memory){
return symbol;
}
function getDecimal() public view returns (uint){
return decimals;
}
function totalSupply()external view override returns (uint _totalSupply){
_totalSupply = __totalSupply;
}
function balanceOf(address _addr) public view override returns(uint _balanceOf){
return __balanceOf[_addr];
}
function transfer(address _to, uint256 _value) external override returns (bool _success){
//require instead of if
if(_value <= __balanceOf[msg.sender]&&
_value > 0){
__balanceOf[msg.sender] -= _value;
__balanceOf[_to] += _value;
return true;
}
return false;
}
function transferFrom(address _from, address _to, uint256 _value) external override returns (bool _success){
if(__allowances[_from][msg.sender] > 0 &&
_value > 0 &&
__allowances[_from][msg.sender] >= _value &&
__balanceOf[_from] >= _value){
__balanceOf[_from] -= _value;
__balanceOf[_to] += _value;
__allowances[_from][msg.sender] -= _value;
return true;
}
return false;
}
function approve(address _spender, uint256 _value) external override returns (bool _success){
__allowances[msg.sender][_spender] = _value;
return true;
}
function allowance(address _owner, address _spender) external view override returns (uint256 _remaining){
return __allowances[_owner][_spender];
}
}
index.js(web3.js)
$(document).ready(function(){
if(!window.ethereum){
alert("Please install Metamask!");
}
else{
window.web3 = new Web3(window.ethereum);
console.log("Metamask connected");
console.log(window.ethereum);
web3.eth.net.getId().then(console.log);
web3.eth.getAccounts().then(function(accounts){
let account = accounts[0];
web3.eth.getBalance(account).then(function(balance){
let balance1 = web3.utils.fromWei(balance);
console.log(balance1+" ETH");
});
});
var abi = /* abi here */
var contractAddress = /* contract deploy address here */
var YTMTokenContract = new web3.eth.Contract(abi, contractAddress);
console.log(YTMTokenContract);
YTMTokenContract.methods.getName().call(function(token_name){
console.log(token_name);
tokenSupply.innerHTML = token_name[enter image description here][1];
}).catch(function(err) {
console.log(err);
});
YTMTokenContract.methods.totalSupply().call(function(total_supply){
console.log(total_supply);
tokenSupply.innerHTML = total_supply;
}).catch(function(err) {
console.log(err);
});
}
});
Output in the console:
[1]: https://i.stack.imgur.com/KXJNJ.jpg
Actually, some of my contract methods are not visible, so I cannot access them although I created the contract Instance.
Any answers to why this happens?>>>
I got my answer.
I was using the ABI of erc20.sol and not of the token.sol.
Thankyou!

Check that object is null in solidity mapping

I have this solidity mapping
mapping (string => Ticket) public myMapping;
I want to check if myMapping[key] exists or not. How can I check?
The entire storage space is virtually initialized to 0 (there is no undefined).
So you have to compare the value to the 0 value for your type.
For example, mapping[key] == address(0x0) or mapping[key] = bytes4(0x0).
There is no direct method to check whether the mapping has particular key. But you can check if mapping property has value or not. The following example considered that the Ticket is the struct with some property.
pragma solidity >=0.4.21 <0.6.0;
contract Test {
struct Ticket {
uint seatNumber;
}
mapping (string => Ticket) myMapping;
function isExists(string memory key) public view returns (bool) {
if(myMapping[key].seatNumber != 0){
return true;
}
return false;
}
function add(string memory key, uint seatNumber) public returns (bool){
myMapping[key].seatNumber = seatNumber;
return true;
}
}
pragma solidity ^0.8.0;
contract BookLibNew{
address public owner;
constructor() public{
owner = msg.sender;
}
modifier onlyOwner(){
require(msg.sender == owner);
_;
}
struct bookDet{
uint bookId;
string bookTitle;
string bookAuthor;
}
mapping (uint8 => bookDet) public bookLib;
function addBookLib(uint8 _bookId, string memory _bookTitle, string memory _bookAuthor)
public onlyOwner {
require(bookLib(_bookId) == false, "Error: Book already exists");
bookLib[_bookId].bookTitle = _bookTitle;
bookLib[_bookId].bookAuthor = _bookAuthor;
}
function readBookDetails(uint8 _bookId) public view returns(string memory, string memory){
return(bookLib[_bookId].bookTitle, bookLib[_bookId].bookAuthor);
}
}

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++;
}