How to transfer ERC1155 token using web3js? - blockchain

I am trying to transfer ERC1155 tokens to another account. I have deployed the contract and have put down my contract code below.
The problem I am facing is I get the below error when I call getMyToken function from my frontend web3js code.
{code: -32603, message: 'execution reverted: ERC1155: caller is not owner nor approved', data: {…}}
Not sure what is happening. I am calling the function as below from frontend. The isApproved function is returning true.
const selectedAccountIsApproved = await monkeysContract.methods.isApproved(selectedAccount).call();
console.log('IS APPROVED RESULT: ', selectedAccountIsApproved);
if(selectedAccountIsApproved) {
const result = await monkeysContract.methods.mintMyMonkey(selectedAccount, 0).call();
console.log('Transfer Result: ', result);
} else {
console.log('Account not approved by owner for transfers');
}
NOTE:
I have called the setApprovalForAll method and approved the receiver account.
I am able to call isApprovedForAll and verify that the account is approved.
I am able to transfer tokens to the receiver through Etherscan contract interface.
Contract Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "#openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract Monkeys is ERC1155, Ownable {
uint256 public constant CC1 = 0;
uint256 public constant CC2 = 1;
mapping (uint256 => string) private _uris;
constructor() public ERC1155("https://game.example/api/item/{id}.json") {
_mint(msg.sender, CC1, 1000, "");
_mint(msg.sender, CC2, 1000, "");
}
function uri(uint256 tokenId) override public view returns (string memory) {
return(_uris[tokenId]);
}
function setTokenUri(uint256 id, string memory url) public onlyOwner {
require(bytes(_uris[id]).length == 0, "Cannot set uri twice");
_uris[id] = url;
}
function transfer(address from, address to, uint256 id, uint256 amount, bytes memory data) public {
safeTransferFrom(from, to, id, amount, data);
}
function isApproved(address user) public view virtual returns (bool) {
return isApprovedForAll(owner(), user);
}
function getMyToken(address to, uint256 id) public {
transfer(owner(), to, id, 1, 'test');
}
}

Related

ERC20 Payment processing

What's wrong with my smart contract, because I get "Error: cannot estimate gas; transaction may fail or may require manual gas limit". On frontend I am calling approveTokens() first and acceptPayment() later
pragma solidity ^0.8.11;
import '#openzeppelin/contracts/token/ERC20/IERC20.sol';
contract PaymentProcessor {
address public owner;
IERC20 public token;
constructor(address _owner, address _token) {
owner = _owner;
token = IERC20(_token);
}
event PaymentCompleted(
address payer,
uint256 amount,
uint paymentId,
uint timestamp
);
function approveTokens(uint256 amount) public returns(bool){
token.approve(owner, amount);
return true;
}
function getAllowance() public view returns(uint256){
return token.allowance(msg.sender, owner);
}
function acceptPayment(uint256 amount, uint paymentId) payable public {
require(amount > getAllowance(), "Please approve tokens before transferring");
token.transfer(owner, amount);
emit PaymentCompleted(msg.sender, amount, paymentId, block.timestamp);
}
}
Users need to call approve() directly on the token address - not through your contract.
Your current implementation approves owner to spend PaymentProcessor's tokens because PaymentProcessor is the msg.sender in the context of the token contract.

Transaction fails with CALL_EXCEPTION whenever I try to mint an NFT using ethers.js

I am using ethers.js to call the mint function in my smart contract but it fails with this error:
Error: transaction failed [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ].
I am able to call the view functions this error only occurs when I call functions which make transactions. So, I know that I have connected to the same network as the contract.
My smart contract:
pragma solidity ^0.8.12;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract FutNFT is ERC721, ERC721Enumerable, Ownable {
struct Player {
string name;
string preferredPosition;
uint256 id;
uint8 age;
uint8 level;
uint64 lastUpgrade;
string[] suitablePositions;
string imageURI;
}
struct History {
uint256 winCount;
uint256 lossCount;
}
mapping(address => History) ownerHistory;
mapping(uint256 => Player) players;
mapping(uint256 => address) public playerToOwner;
mapping(uint256 => uint256) listedPlayerIndex;
uint256[] public listedPlayers;
event PlayerAdded(uint256 playerId);
modifier owned(uint256 id) {
require(getPlayerExists(id), "Player does not exist");
require(msg.sender == ownerOf(id), "Not the owner!");
_;
}
constructor() ERC721("FutNFT", "FNFT") {}
function getListedPlayers() public view returns (uint256[] memory) {
return listedPlayers;
}
function getPlayer(uint256 _id) public view returns (Player memory) {
return players[_id];
}
function ownerOf(uint256 tokenId)
public
view
override(ERC721, IERC721)
returns (address)
{
return super.ownerOf(tokenId);
}
function getPlayerExists(uint256 _id) public view returns (bool) {
return playerToOwner[_id] != address(0);
}
function mint(Player memory _player) public onlyOwner {
require(playerToOwner[_player.id] == address(0), "Player Exists!");
players[_player.id] = _player;
playerToOwner[_player.id] = msg.sender;
_mint(msg.sender, _player.id);
emit PlayerAdded(_player.id);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal override(ERC721, ERC721Enumerable) {
super._beforeTokenTransfer(from, to, tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
my frontend code:
const player: PlayerInterface = {
name: "Lionel Messi",
preferredPosition: "RWF",
id: 1,
age: 34,
level: 20,
lastUpgrade: new Date().getTime(),
suitablePositions: ["ST", "CF", "RMF", "CAM"],
imageURI:
"https://bafybeicfhmevzs4aso7rqvx7l5ndb2ly7gudjyj5xjkztvohpwxw2za7iy.ipfs.dweb.link/nft.png",
};
const provider = new ethers.providers.Web3Provider(
(window as any).ethereum
);
const signer = provider.getSigner();
const tx = await futNFT.connect(signer).mint(player, {
gasPrice: 30000000000,
gasLimit: 2000000,
});
await tx.wait();
console.log("minted");
const player1 = await futNFT.getPlayer(1);
console.log(player1);

ERC721 Minted NFT not showing on Opensea.io testnet

I run my code on rinkeby etherscan network and it works perfectly. But the image and descriptions are not showing on opensea testnet. I run the /validate/ url it shows Valid: "false".
Here is what I found when I force update on opensea, https://testnets-api.opensea.io/api/v1/asset/0x668D179B933af761e4732B084290D32B3235C22b/0/?force_update=true
Here is my code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
import "./ERC2981ContractWideRoyalties.sol";
import "hardhat/console.sol";
contract SmoothApe is ERC721URIStorage, Ownable, ERC2981ContractWideRoyalties {
using Counters for Counters.Counter;
using Strings for uint256;
Counters.Counter private _tokenIdCounter;
event EmitNFT(address sender, uint256 tokenId);
uint256 public preSaleTokenPrice = 0.01 ether;
uint256 public costPrice = 0.02 ether;
uint256 public maxSupply = 10000;
uint256 public maxMintNft = 10;
string public baseURI;
string public baseExtension = ".json";
string public notRevealedUri;
bool public paused = false;
bool public revealed = true;
bool public presale = false;
// set 0x7350243981aB92E2A3646e377EBbFC28e9DE96C1 as payable admn wallet
address payable public adminWallet = payable(0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2);
address payable public communityWallet = payable(0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db);
address payable public t1Wallet = payable(0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB);
address payable public t2Wallet = payable(0x617F2E2fD72FD9D5503197092aC168c91465E7f2);
address payable public t3Wallet = payable(0x17F6AD8Ef982297579C203069C1DbfFE4348c372);
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
constructor(string memory _name, string memory _symbol,string memory _initBaseURI, string memory _initNotRevealedUri) ERC721(_name, _symbol) {
setBaseURI(_initBaseURI);
setNotRevealedUri(_initNotRevealedUri);
}
// inherit and override erc165
function supportsInterface(bytes4 interfaceId) public view virtual override (ERC721, ERC2981Base) returns (bool) {
return super.supportsInterface(interfaceId);
}
// set Royalty value (between 0 and 10000)
function setRoyalties(address recipient, uint256 value) public onlyOwner {
_setRoyalties(recipient, value);
}
function _baseURI() internal view override returns (string memory) {
return baseURI;
}
function mintApe() public payable {
uint256 tokenId = _tokenIdCounter.current();
require(!paused, "Minting is paused");
require(msg.sender != owner(), "You can't mint ape to admin");
// require(_mintAmount > 0, "Mint amount must be greater than 0");
// require(_mintAmount <= maxSupply, "Mint amount must be less than or equal to max supply");
if(presale == true) {
preSaleTokenPrice = costPrice;
}
require(msg.value >= costPrice, string(abi.encodePacked("Must send at least ", costPrice.toString(), " ether to purchase")));
require(balanceOf(msg.sender) < maxMintNft, "You can only own 11 ape at a time");
// require(_mintAmount + balanceOf(msg.sender) <= maxMintNft, "You can only own 10 ape at a time");
// adminWallet.transfer(msg.value);
payable(owner()).transfer(msg.value);
emit EmitNFT(msg.sender, tokenId);
// for(uint256 i = 1; i <= _mintAmount; i++){
_safeMint(msg.sender, tokenId);
// _setTokenURI(tokenId, _baseURI());
_tokenIdCounter.increment();
// }
}
// admin mint ape to wallet
function mintApeTo(address _to, uint256 _mintAmount) public onlyOwner {
require(!paused, "Minting is paused");
require(_mintAmount > 0, "Mint amount must be greater than 0");
require(_mintAmount <= maxSupply, "Mint amount must be less than or equal to max supply");
for(uint256 i = 1; i <= _mintAmount; i++){
uint256 tokenId = _tokenIdCounter.current();
_safeMint(_to, tokenId);
// _setTokenURI(tokenId, _baseURI());
_tokenIdCounter.increment();
}
}
function getCostPrice() public view virtual returns (uint256) {
return costPrice;
}
// function to set cost of ape
function setCost(uint256 _preSaleTokenPrice, uint256 _publicTokenPrice) public onlyOwner {
preSaleTokenPrice = _preSaleTokenPrice;
costPrice = _publicTokenPrice;
}
// set presale to true
function setPresale(bool _presale) public onlyOwner {
presale = _presale;
}
function reveal(bool _reveal) public onlyOwner {
revealed = _reveal;
}
// pause function
function pause() public onlyOwner {
paused = true;
}
// set function for setBaseURI and setNotRevealed function
function setBaseURI(string memory _newBaseURI) public onlyOwner {
baseURI = _newBaseURI;
}
function setTokenURI(uint256 _tokenId, string memory _tokenURI) public onlyOwner {
_setTokenURI(_tokenId, _tokenURI);
}
// override tokenURI function
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
require(tokenId < _tokenIdCounter.current(), "Token ID must be less than the total supply");
if(!revealed) {
return notRevealedUri;
}
string memory currentBaseURI = _baseURI();
return bytes(currentBaseURI).length > 0
? string(
abi.encodePacked(
currentBaseURI,
tokenId.toString(),
baseExtension))
: "";
}
}
Here is a sample of NFT i mint:
https://testnets.opensea.io/assets/0x668D179B933af761e4732B084290D32B3235C22b/0
my ipfs CID:
ipfs://QmaoMZ19zhpC6T4id6jdBP1Qz5dQSmRZMkQZU7Zt8hyFNQ/
as you can see in the right up corner there is a "reload" button, you need to click it to reload the ipfs on opensea
I had the same problem. Turned out that I wasn't uploading the images to ipfs correctly because it was visible only to me on my machine. So try to see if the ipfs metadata are correctly formated and are accesible from different devices.
Also you shouldn't just paste your entire contract in. Tt is really hard to answer your question then. Just write out the important sections of the code.

"VM Exception while processing transaction: revert", when running a chainlink node and try to deploy TestnetConsumer contract?

The scenario is when deploying a ATestnetConsumer.sol on mathchain via Remix, following the official tutorial to run a node on mathchain, which is a EVM-compatitable public chain. And I finish deploying the Oracle contract and LINKToken contract, and running the node on mathchain successfully, but when trying to deploy a TestnetConsumer contract, it shows that:
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
Internal JSON-RPC error. { "code": -32603, "message": "VM Exception while processing transaction: revert", "data": "" }
Anybody know why?
The TestnetConsumer contract is list as below:
pragma solidity 0.4.24;
import "https://github.com/smartcontractkit/chainlink/evm-contracts/src/v0.4/ChainlinkClient.sol";
import "https://github.com/smartcontractkit/chainlink/evm-contracts/src/v0.4/vendor/Ownable.sol";
contract ATestnetConsumer is ChainlinkClient, Ownable {
uint256 constant private ORACLE_PAYMENT = 1 * LINK;
uint256 public currentPrice;
int256 public changeDay;
bytes32 public lastMarket;
event RequestEthereumPriceFulfilled(
bytes32 indexed requestId,
uint256 indexed price
);
event RequestEthereumChangeFulfilled(
bytes32 indexed requestId,
int256 indexed change
);
event RequestEthereumLastMarket(
bytes32 indexed requestId,
bytes32 indexed market
);
constructor() public Ownable() {
setPublicChainlinkToken();
}
function requestEthereumPrice(address _oracle, string _jobId)
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(stringToBytes32(_jobId), this, this.fulfillEthereumPrice.selector);
req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD");
req.add("path", "USD");
req.addInt("times", 100);
sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT);
}
function requestEthereumChange(address _oracle, string _jobId)
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(stringToBytes32(_jobId), this, this.fulfillEthereumChange.selector);
req.add("get", "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD");
req.add("path", "RAW.ETH.USD.CHANGEPCTDAY");
req.addInt("times", 1000000000);
sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT);
}
function requestEthereumLastMarket(address _oracle, string _jobId)
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(stringToBytes32(_jobId), this, this.fulfillEthereumLastMarket.selector);
req.add("get", "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD");
string[] memory path = new string[](4);
path[0] = "RAW";
path[1] = "ETH";
path[2] = "USD";
path[3] = "LASTMARKET";
req.addStringArray("path", path);
sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT);
}
function fulfillEthereumPrice(bytes32 _requestId, uint256 _price)
public
recordChainlinkFulfillment(_requestId)
{
emit RequestEthereumPriceFulfilled(_requestId, _price);
currentPrice = _price;
}
function fulfillEthereumChange(bytes32 _requestId, int256 _change)
public
recordChainlinkFulfillment(_requestId)
{
emit RequestEthereumChangeFulfilled(_requestId, _change);
changeDay = _change;
}
function fulfillEthereumLastMarket(bytes32 _requestId, bytes32 _market)
public
recordChainlinkFulfillment(_requestId)
{
emit RequestEthereumLastMarket(_requestId, _market);
lastMarket = _market;
}
function getChainlinkToken() public view returns (address) {
return chainlinkTokenAddress();
}
function withdrawLink() public onlyOwner {
LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress());
require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer");
}
function cancelRequest(
bytes32 _requestId,
uint256 _payment,
bytes4 _callbackFunctionId,
uint256 _expiration
)
public
onlyOwner
{
cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration);
}
function stringToBytes32(string memory source) private pure returns (bytes32 result) {
bytes memory tempEmptyStringTest = bytes(source);
if (tempEmptyStringTest.length == 0) {
return 0x0;
}
assembly { // solhint-disable-line no-inline-assembly
result := mload(add(source, 32))
}
}
}
The problem is located at the constructor:
constructor() public Ownable() {
setPublicChainlinkToken();
}
When you run a node on a public-chain, and deploy a totally new LINKToken contract as the way to transferAndCall the service provided by your own node, do remember to replace the line: setPublicChainlinkToken() to:
// set the Oracle contract address
setChainlinkOracle(YOUR_ORACLE_CONTRACT_ADDRESS);
// set LINKToken contract address
setChainlinkToken(YOUR_LINKTOKEN_CONTRACT_ADDRESS);
Then you should be good to go. And remember that you should deposit some LINK token before invoking the function to get service from your Chainlink node!

How to handle REST API response in Solidity on Ethereum platform?

I call REST API on the Ethereum platform with Solidity language. I need to handle the response. API returns true or false. Could you please help to handle the response?
Thanks in advance!
I am using the following code:
import "github.com/oraclize/ethereum-api/provableAPI.sol";
contract UrlRequests is usingProvable {
event LogNewProvableQuery(string description);
event LogResult(string result);
constructor()
public
{
provable_setProof(proofType_Android | proofStorage_IPFS);
}
function __callback(
bytes32 _myid,
string memory _result,
bytes memory _proof
)
public
{
require(msg.sender == provable_cbAddress());
emit LogResult(_result);
}
function request(
string memory _query,
string memory _method,
string memory _url,
string memory _kwargs
)
public
payable
{
if (provable_getPrice("computation") > address(this).balance) {
emit LogNewProvableQuery("Provabl e query was NOT sent, please add some ETH to cover for the query fee");
} else {
emit LogNewProvableQuery("Provable query was sent, standing by for the answer...");
provable_query("computation",
[_query,
_method,
_url,
_kwargs]
);
}
}
/**
* #dev Sends a custom content-type in the header and returns the header used
* as result. Wrap the first argument of computation ds with helper needed,
* such as JSON in this case
*/
function requestPost()
public
payable
{
request("testaccaount",
"POST",
"https://xxxxtest",
'{"json": { "username": "usertest", "password": "passwordtest"}}');
}
}
The response of provable_query is sent in to the __callback function. In your case it's logged and included to transaction information. This event can be a signal for backend (that is subscribed to the contract events / specific topic), so it can parse the result or from event information. I'd recommend to go with this approach.
If you want to have an access to the result in other way you can create mapping queryIds to result, and another one your customerRequestID to queryIds. And then you can use requestID to obtain the result. You can convert "true" / "false" on backend.
mapping(bytes32 => string) public queryIdsResults;
mapping(string => bytes32) public requestsQueryIds;
function __callback(
bytes32 _queryId,
string memory _result,
bytes memory _proof
)
public
{
require(msg.sender == provable_cbAddress());
queryIdsResults[_queryId]=_result;
emit LogResult(_result);
}
function request(
string memory _requestID,
string memory _query,
string memory _method,
string memory _url,
string memory _kwargs
)
public
payable
{
if (provable_getPrice("computation") > address(this).balance) {
emit LogNewProvableQuery("Provabl e query was NOT sent, please add some ETH to cover for the query fee");
} else {
emit LogNewProvableQuery("Provable query was sent, standing by for the answer...");
bytes32 queryId = provable_query("computation",
[_query,
_method,
_url,
_kwargs]
);
requestsQueryIds[_requestID]= queryId;
}
}
function requestPost()
public
payable
{
request("custom_request_id","testaccaount",
"POST",
"https://xxxxtest",
'{"json": { "username": "usertest", "password": "passwordtest"}}');
provable_query("URL", "json(https://api.pro.coinbase.com/products/ETH-USD/ticker).price");
}
function getResultByRequestID(string memory _requestID) public view returns ( string memory){
bytes32 queryId = requestsQueryIds[_requestID];
return queryIdsResults[queryId];
}