VM Exception while processing transaction: revert - blockchain

I have 2 Contracts. One is an ERC721 Token (NFTCollectables). The other one is a market including an auction system (NFTMarket).
An auction can be claimed after it ended and only by the highest bidder.
When claiming an auction the transfer method of the NFTCollectables contract is called to transfer the NFT from the markets address to the address of the highest bidder.
I do not exactly understand why the exception comes, but it occurs at/inside the transfer method of the NFTCollectables contract. The strange thing is that even the last line of code inside the transfer method is getting executed (tested by putting a require(false, 'test') after _transfer(msg.sender, to, nftId)). But nothing after ctr.transfer(auction.highestBid.bidder, auction.nftId) is getting executed (tested by putting a require(false, 'test') after it).
Could it have to do with the gas limit?
Any idea is appreciated, thanks!
NFTMarket
function claimAuction(uint auctionIndex) external {
require(auctionIndex < auctions.length, "no auction");
Auction memory auction = auctions[auctionIndex];
require(block.timestamp <= auction.end, "auction still active");
NFTCollectables ctr = NFTCollectables(nftCollectablesAddress);
ctr.transfer(auction.highestBid.bidder, auction.nftId);
// deleting auction from active auctions list
for (uint i; i < activeAuctionIndexes.length; i++) {
if (activeAuctionIndexes[i] == auctionIndex) {
delete activeAuctionIndexes[i];
break;
}
}
emit AuctionEnd(auction.highestBid.bidder, auction.highestBid.price, auction.nftId);
}
NFTCollectables
function transfer(address payable to, uint nftId) external payable {
require(_exists(nftId), "transfer of non existing token");
require(_isApprovedOrOwner(msg.sender, nftId), "Sender not approved nor owner");
_transfer(msg.sender, to, nftId);
}

If you have deployed the contracts on the public network, like mainnet or testnet, use https://tenderly.co or EtherScan to debug the revert reason.
If you are running the contracts using unit tests then keep modifying the contracts e.g. by removing lines to see when it starts failing. Or alternatively use a better smart contract development framework like Brownie which will give you the cause of revert right away.

We had implemented a function on our codebase that i can share with you. This function is used to transfer ownership of nft to who wins the auction.
function transferNFTtoNewOwner(NFTItem memory t,address oldOwner, address newOwner) internal {
require(newOwner != address(0), "New owner can't be address zero.");
XXXX storage r = creatureList[t.tokenAddress][t.tokenId];
IERC721 nft = IERC721(t.tokenAddress);
nft.safeTransferFrom(oldOwner, newOwner, t.tokenId);
address currOwner = nft.ownerOf(t.tokenId);
require(newOwner == currOwner, "Problem on nft transfer");
r.owner = newOwner;
}
The major differences are we used safetransferfrom here. If your contract owns the NFT then you can call safeTransfer. and after that we checked the nft owner with require statement. If you put this statement and change your transfer function to safetransfer and the transaction still revert without giving any error on etherscan then you can investigate about your nft contract.

Related

I want to create a nft as a hotel room ticket. Is it possible?

I am a PHP user but a complete novice in blockchain.
I want to create a nft as a hotel room ticket.
I would like to sell them on platforms such as opensensea.
Is it realistically possible to implement the following?
1: Can only be used once.
2: It has an expiration date.
3: After use, the design of the nft will change for used.
4: If holder don't use it and the expiration date has passed, the design will change to used.
From my research, it seems that the "expiration date" can be implemented.
What I find problematic is
3: "After use, the nft design will change to used".
I'm not sure how to do this automatically, so I'd prefer to do it manually.
For example, is it possible to manually rewrite the data of nft "A" to "used" when the holder of nft "A" makes a hotel reservation?
I would appreciate any advice you can give me.
Thank you.
Of course, it's possible.
OpenSea extracts the NFT's metadata from the url returns by the tokenURI function of the NFT smart contract. So you can achieve the goal by overriding this function.
function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) {
require(_exists(_tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
//Implement the features you want to add
//Imagine there is already structure called TicketInfo that stores information of NFTs and "used" NFT has zero index in the collection
uint256 tokenId = _tokenId;
TicketInfo storage ticket = ticketInfo[tokenId];
if(ticket.expirationDate < now || ticket.isUsed) tokenId = 0;
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}

What Does this code mean in BEP20 token writting with Solidity

I'm trying to understand what this lines of BEP20 code mean, it is written in solidity
constructor () {
_rOwned[owner()] = _rTotal;
IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x10ED43C718714eb63d5aA57B78B54704E256024E);
uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
.createPair(address(this), _uniswapV2Router.WETH());
uniswapV2Router = _uniswapV2Router;
_isExcludedFromFee[owner()] = true;
_isExcludedFromFee[address(this)] = true;
emit Transfer(address(0), owner(), _tTotal);
In the first lines, he instanciate UniswapV2Router pointing the address router to PancakeSwap. This because, he want to create a liquidity pool with his TOKEN and BNB, indeed after this instanciating operation he call createPair() that allows him to create this pair between his smart contract and the address WETH().
IMPORTANT: WETH() is a function that provider the chain native wrapped coin address where smart contract was deployed. For example: If I create a pair instanciating Uniswap router on Ethereum blockchain then WETH() will return address about WETH (Wrapping Ether) address present into Etheruem. On the contrary if I instanciate Uniswap Router with its address present into binance smart chain (and so I refers to Pancakeswap in this case), the value of WETH() will be WBNB address.
After this lines of code, I assume that he excluded from paying a fee for only transactions the owner() address (who deployed the smart contract for the first time) and smart contract itself.
Finally he emitted a Transfer event passing : address(0) (0x0000000000000000000000000000000000000000), owner() and total supply.
More information about pair on documentation.

address.call.value(amount)( ) method is not working with me

I've written a very simple method in solidity to send Ethereum to account but unfortunately it is not working
(ALREADY TRIED SEND AND TRANSFER METHOD)
function sendByCallValue(address payable _receiver, uint _amount) public payable {
(bool success, ) = _receiver.call{value:_amount}("");
require(success, "Transfer failed.");
}
I'm calling this function from REMIX IDE by passing an address and amount but it is throwing error.
In pic you will find this:
to : NftStaker.sendByCallValue(address,uint256) 0xEf9f1ACE83dfbB8f559Da621f4aEA72C6EB10eBf
which I think should be like this
to : 0xEf9f1ACE83dfbB8f559Da621f4aEA72C6EB10eBf
I'm not sure which thing is throwing error.
The transaction output shows that you're passing 0 wei along with the transaction, and trying to send 10 wei from the contract address.
It doesn't show how much the contract owns, but assuming it's less than 10 wei, the transaction fails because the .call() is trying to send from the contract more than it owns.
You can specify the value to send along with the transaction in the "Deploy & run transactions" of the Remix IDE.

Getting mined blocks instead of the supposed returned values

I've just deployed a Smart Contract using the ethereum wallet.
I got the Smart Contract address , I copied its ABI from remix and verified it on ethereum wallet,it was active and I could see all its methods.
Then I tried to call it from my nodejs server.I did it,I didn't get any error...
But instead of a classic response like the returned values of the methods below I got mined blocks....and this is very weird I think...
How am I supposed to get the methods output(the returns) ?
After that I tried to deploy another contract,this time a very simple one with the same methods name,smart contract name,parameters but without code inside the methods only a basic hard-coded return.When I deployed this contract as well I got the same mined smart contract address...which is weird,in my opinion...
I've been using 1.0.0-beta.46 , nodejs , expressjs
When I said eth wallet I meant...that website generated with puppeth , on /#wallet page
Here is the basic smart contract I tried to deploy second time.The result was the same as the first smart contract.
pragma solidity >= 0.4.22 < 0.6.0;
contract BasicContract {
function function1(uint16 a,uint16 b,uint16 c,uint16 d) external payable returns(uint256){
//a,b,c,d doesn't matter
return 68;
}
//buy a ticket
function function2(uint128 a,uint16 b) external payable returns(uint128){
//a,b doesn't matter
return 94;
}
function function3(uint128 a) external payable returns(bool){
//a doesn't matter
return false;
}
}
There are two ways to invoke a function in a smart contract: through a transaction sent to the network or via a local call.
Transactions don't have return values. What you get back from the library you use to make the transaction is typically the transaction hash. Any return value from the function you invoked is discarded.
A local call doesn't involve a transaction to the network and thus can't change any state. But it does give you a return value.
Which method is chosen by default for most libraries is based on whether the function is state-changing or not. If you mark your functions as view or pure, it tells the library that those functions don't change state and can then safely be just called locally to get a return value. So a simple "fix" for the above code is to make those functions pure. For functions that do change state, you'll want to switch from using return values to emitting events instead, which can be read after the transaction is mined.

Solidity basics: what "msg.sender" stands for

I just started to learn Solidity as a personal challenge. I'm not a developer so I've a loooooong way to go.
I'm following the Ethereum.org tutorial, here is what I've got doubt about: What does [msg.sender] stand for? I guess it is the wallet address of who triggered the contract, but I'm not sure.
msg.sender (address): sender of the message (current call)
msg.sender will be the person who's currently connecting with the contract.
Later on, you'll probably deal with contracts connecting with contracts. In that case, the contract that is creating the call would be the msg.sender.
Check out the documentation here: https://docs.soliditylang.org/en/develop/units-and-global-variables.html#block-and-transaction-properties
Let's make it very simple.
There are two types of accounts in the Ethereum Chain
1). Externally Owned Accounts(EOA) [Person]
2). Contracts Accounts [Contracts on Chain]
Both accounts have their addresses.
Now, look at an example.
Wallet address of personA (EOA) is
0x0cE446987406E92DF41614C46F1d6df9Cc925847.
Contract Address of Math.sol is
0x0cE446987406E92DF41614C46F1d6df9Cc753869 and
Math.sol contains ContractA
Contract Address of Addition.sol is
0x0cE446987406E92DF41614C46F1d6df9Cc357241 and
Addition.sol contains ContractB
Here, one of the functions of ContractB is called from ContractA.
So, whenever personA calls any functions of ContractA.
In this scenario, if you print or get `msg.sender` and `tx.origin` inside function of `ContractB` then the result would be like this
msg.sender = `0x0cE446987406E92DF41614C46F1d6df9Cc753869` // You will get address of `ContractA`
tx.origin = `0x0cE446987406E92DF41614C46F1d6df9Cc925847` // personA's (EOA) Wallet Address
Here,
msg.sender (address): means sender of the message (current call)
on the other hand
address owner = msg.sender;
The msg.sender is the address that has called or initiated a function or created a transaction. Now, this address could be of a contract or even a person like you and me.
That's why you may use msg.sender instead of msg.sender()