I have two contracts ERC20, and ERC721.
and everytime erc721 transferFrom function is called, I want to send some erc20 tokens to the creator (minter) of the ERC721.
After some research, I've found that I have to do two things.
call ERC20.transferfrom in ERC721 transferFrom function
Approve the spending of erc20 tokens from the frontend
it seems like the second is giving me some problems. Please see my code below:
Your help will be very much appreciated.
++ I am also not so sure if I am calling ERC20.transferFrom correctly from ERC721 contract. Is this the correct way to do it?
ERC721 contract:
import "../openzeppelin-contracts/contracts/token/ERC721/IERC721.sol";
import "../openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
import "../openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol";
import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
import "../openzeppelin-contracts/contracts/utils/Address.sol";
import "../openzeppelin-contracts/contracts/utils/Counters.sol";
import "./ERC20Token.sol";
contract NFTtoken is ERC721 {
.
.
.
ERC20Token Erc20Contract;
constructor(address tokenAddress) ERC721("NC NFT example", "NCNFT") {
owner = msg.sender;
decimals = 0;
Erc20Contract = ERC20Token(tokenAddress);
}
function mint(string calldata nftName) external payable {
uint256 newItemId = _tokenIds.current();
_mint(msg.sender, newItemId);
nftInfo[msg.sender].name = nftName;
nftInfo[msg.sender].creator = msg.sender;
allValidTokenIndex[newItemId] = allValidTokenIds.length;
allValidTokenIds.push(newItemId);
_tokenIds.increment();
}
function transferNFT(address from, address to, uint256 tokenId) public returns (bool){
transferFrom(from, to, tokenId);
Erc20Contract.transferFrom(to, nftInfo[from].creator, 10);
}
}
.
.
.
app.js
transferNFT: function() {
NFTContract.deployed().then(function(contractInstance) {
let toAddress = $("#to-address").val();
// function transferFrom(address _from, address _to, uint256 _tokenId) public payable {
let NFTid_temp = $("#nft-id").val();
let NFTid = NFTid_temp.substring(7);
console.log("to = " + toAddress);
console.log("nftid = " + NFTid);
Voting.deployed().then(function(votingcontractInstance) { votingcontractInstance.approve(contractInstance.address, votingcontractInstance.balanceOf(web3.eth.accounts[1]))});
contractInstance.transferNFT(web3.currentProvider.selectedAddress, toAddress, NFTid, {gas: 140000, from: web3.eth.accounts[0]});
})
}
error message
app.js:10169 Uncaught (in promise) BigNumber Error: new BigNumber() not a number: [object Object]
at raise (http://localhost:8080/app.js:10169:25)
at http://localhost:8080/app.js:10157:33
at new BigNumber (http://localhost:8080/app.js:9184:67)
at new BigNumber (http://localhost:8080/app.js:9194:25)
at toBigNumber (http://localhost:8080/app.js:2084:12)
at Object.toTwosComplement (http://localhost:8080/app.js:2095:21)
at SolidityTypeAddress.formatInputInt [as _inputFormatter] (http://localhost:8080/app.js:2995:38)
at SolidityTypeAddress.SolidityType.encode (http://localhost:8080/app.js:3648:17)
at http://localhost:8080/app.js:15577:29
at Array.map (<anonymous>)
I suspect this line:
votingcontractInstance.balanceOf(web3.eth.accounts[1]))
Can you check its type? I think it returns "string" but it must be number. If it is string either wrap it with Number
Number(votingcontractInstance.balanceOf(web3.eth.accounts[1])))
Or use web3.utils.toBN()
web3.utils.toBN(votingcontractInstance.balanceOf(web3.eth.accounts[1])))
Related
I'm building a DApp and i'm trying to use a function in my smart contract to get the actual ethereum value, and then use it to convert a certain amount of dollars into its Ethereum value. When trying to do so, i'm getting "Internal JSON-RPC error" and i can't understand why. The contract has been correctly compiled and migrated.
This is the js code to call the function:
App.contracts.TravelCoin.deployed().then(function(instance) {
flightsInstance = instance;
return flightsInstance.GetValueInEth(dollarPrice);
}).then(function(value) {
console.log("inside function");
cell2.innerHTML = value;
}).catch(function(err) {
console.log(err.message);
});
This is the Solidity smart contract code:
import "#chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract TravelCoin{
AggregatorV3Interface internal priceFeed;
constructor() {
priceFeed = AggregatorV3Interface(0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e);
}
function getLatestPrice() public view returns (uint) {
(, int price,,,) = priceFeed.latestRoundData();
return uint (price*1e18);
}
function GetValueInEth(uint dollarsAmount) public view returns (uint) {
uint valuePrice = uint(getLatestPrice());
uint ethAmount = (dollarsAmount*1e18)/valuePrice;
return ethAmount;
}
}
If you want to reproduce the issue, here it is the repository link: https://github.com/CicaMatt/TravelCoin.git
I really don't know what causes this issues, as i call the other function the same way but i'm not getting any problem.
I'm trying to build a frontend application using ethers.js from a smart contract that mints one of four houses of Hogwarts.
The contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
//Chainlink's VRFConsumerBase (Chainlink Verifiable Random Function)
//Link: https://docs.chain.link/docs/intermediates-tutorial/
//Github repo: https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/VRFConsumerBase.sol
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
//A ERC721 contractc alias NFT Contract will mint one of four houses of Hogwarts.
//Have you always enjoyed being part of one of the houses of Hogwarts?
//Well, you are in the right place!
//This Smart Contract will extract your Hogwarts household as the talking hat!
contract HogwartsHouses is ERC721URIStorage, VRFConsumerBase {
uint256 public tokenCounter;
bytes32 public keyhash;
uint256 public fee;
mapping(uint256 => Raffle) public tokenIdToRaffle;
mapping(bytes32 => address) public requestIdToSender;
event requestCollectible(bytes32 indexed requestId, address requester);
event raffleAssigned(uint256 indexed tokenId, Raffle raffle);
//This are the different houses that one can extract
enum Raffle {
GRYFFINDOR,
HUFFLEPUFF,
RAVENCLAW,
SLYTHERIN
}
constructor(
address _vrfCoordinator,
address _linkToken,
bytes32 _keyhash,
uint256 _fee
)
public
VRFConsumerBase(_vrfCoordinator, _linkToken)
ERC721("Houses", "HOM")
{
tokenCounter = 0;
keyhash = _keyhash;
fee = _fee;
}
function createCollectible() public returns (bytes32) {
//We want the user who called createCollectoible to be the same user
//who gets assigned the tokenId
bytes32 requestId = requestRandomness(keyhash, fee); //This is going to create our randomness request to get random Houses of Howarts.
//We can get the original caller of create collectible
requestIdToSender[requestId] = msg.sender;
emit requestCollectible(requestId, msg.sender);
}
//Function fulfillRandomness: which is the function that receives and does something
//with verified randomness.
function fulfillRandomness(bytes32 requestId, uint256 randomNumber)
internal
override
{
//Select a houses based of this randomNumber
Raffle raffle = Raffle(randomNumber % 4);
//This is the way how each tokenId is going
//to have a very specific Hogwarts Houses
uint256 newTokenId = tokenCounter;
//tokenURI based on the houses Hogwarts
tokenIdToRaffle[newTokenId] = raffle;
emit raffleAssigned(newTokenId, raffle);
address owner = requestIdToSender[requestId];
_safeMint(owner, newTokenId);
tokenCounter = tokenCounter + 1;
}
function setTokenURI(uint256 tokenId, string memory _tokenURI) public {
//Only the owner of the tokenId can be update the tokenURI
require(
_isApprovedOrOwner(_msgSender(), tokenId), //Imported from OpenZeppelin
"ERC721: caller is not owner no approved!"
);
_setTokenURI(tokenId, _tokenURI);
}
}
I'm trying to write this function in javascript:
raffle_metadata_dic = {
"GRYFFINDOR": "https://ipfs.io/ipfs/QmXJcdftXeX9ndcmsPFijRNtyMM49yvSnb8AcveMKWq61c?filename=GRYFFINDOR.json",
"HUFFLEPUFF": "https://ipfs.io/ipfs/QmPz1mxmqUGQUUuVNFWYUPU5BF6dU5MBCQ5xmG3c63pDMN?filename=HUFFLEPUFF.json",
"RAVENCLAW": "https://ipfs.io/ipfs/QmUH9J2eY2Cuu4m5raGCg2XmGqZrd6NuvTatzgwWX1Jm6z?filename=RAVENCLAW.json",
"SLYTHERIN": "https://ipfs.io/ipfs/QmPvjuj32AFV9yye7agrxSzty4Y5nCvesNkzgmYjJciA2f?filename=SLYTHERIN.json",
}
def main():
print(f"Working on {network.show_active()}")
hogwarts_houses = HogwartsHouses[-1]
number_of_collectibles = hogwarts_houses.tokenCounter()
print(f"You have {number_of_collectibles} tokenIds")
for token_id in range(number_of_collectibles):
raffle = get_raffle(hogwarts_houses.tokenIdToRaffle(token_id))
# Check to see if already have a token
if not hogwarts_houses.tokenURI(token_id).startswith("https://"):
print(f"Setting tokenURI of {token_id}")
set_token_uri(token_id, hogwarts_houses, raffle_metadata_dic[raffle])
def set_token_uri(token_id, nft_contract, tokenURI):
account = get_account()
tx = nft_contract.setTokenURI(token_id, tokenURI, {"from": account})
tx.wait(1)
print(
f"Awesome! You can view your NFT at {OPENSEA_URL.format(nft_contract.address, token_id)}"
)
print("Please wait up to 20 minutes, and hit the refresh metadata button")
For the full code: https://github.com/Pif50/Progetto-Ethereum-Web3-di-Pier-Francesco-Tripodi
So, for tokenid in range(number of collectible):
numeber_of_collectible, is hogwarts_houses.tokenCounter(). tokenCounter is a counter of the token that already have
I'm trying to write this for loop in javascript.
I know in javascript there isn't the function Range() and I know this function is to write from scratch.
I try to test this code:
contract Token {
// Some string type variables to identify the token.
string public name = "My Hardhat Token";
string public symbol = "MHT";
// The fixed amount of tokens, stored in an unsigned integer type variable.
uint256 public totalSupply = 1000;
// An address type variable is used to store ethereum accounts.
address public owner;
// A mapping is a key/value map. Here we store each account's balance.
mapping(address => uint256) balances;
// The Transfer event helps off-chain applications understand
// what happens within your contract.
event Transfer(address indexed _from, address indexed _to, uint256 _value);
/**
* Contract initialization.
*/
constructor() {
// The totalSupply is assigned to the transaction sender, which is the
// account that is deploying the contract.
balances[msg.sender] = totalSupply;
owner = msg.sender;
}
/**
* A function to transfer tokens.
*
* The `external` modifier makes a function *only* callable from *outside*
* the contract.
*/
function transfer(address to, uint256 amount) external {
// Check if the transaction sender has enough tokens.
// If `require`'s first argument evaluates to `false` then the
// transaction will revert.
require(balances[msg.sender] >= amount, "Not enough tokens");
// Transfer the amount.
balances[msg.sender] -= amount;
balances[to] += amount;
// Notify off-chain applications of the transfer.
emit Transfer(msg.sender, to, amount);
}
/**
* Read only function to retrieve the token balance of a given account.
*
* The `view` modifier indicates that it doesn't modify the contract's
* state, which allows us to call it without executing a transaction.
*/
function balanceOf(address account) external view returns (uint256) {
return balances[account];
}
}
i use this js code
const { expect } = require("chai");
describe("Token contract", function () {
it("Deployment should assign the total supply of tokens to the owner", async function () {
const [owner] = await ethers.getSigners();
const Token = await ethers.getContractFactory("Token");
const hardhatToken = await Token.deploy();
const ownerBalance = await hardhatToken.balanceOf(owner.address);
expect(await hardhatToken.totalSupply()).to.equal(ownerBalance);
});
});
The ERROR IS:
AssertionError: expected BigNumber { value: "1000" } to equal BigNumber { value: "1000" }
Seems to be working fine for me. Try running npx hardhat clean and then try again.
I have already deployed a smart contract with chainlink VRFConsumerBase named game contract as shown below to get a random number. When I am calling from front-end to get random number, it is showing "undefined" as show in the picture below.
Error Message
async BelowSeven(amount){
const gameContract=this.state.gameContract
let firstDiceNumber =(await gameContract.getRandomNumber())
window.alert("Rolling Dies")
firstDiceNumber=await gameContract.randomResult
console.log(firstDiceNumber)
window.alert("Completed")
//let secondDiceNumber =(await gameContract.getRandomNumber())
//secondDiceNumber=await gameContract.randomResult
//const result= firstDiceNumber+secondDiceNumber
//console.log(secondDiceNumber)
}
Random Number Generating Contract (game Contract):
pragma solidity >=0.4.0 <0.9.0;
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
contract game is VRFConsumerBase{
uint public randomResult;
bytes32 internal keyHash;
uint internal fee;
constructor() VRFConsumerBase(0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B,
0x01BE23585060835E02B77ef475b0Cc51aA1e0709) public
{
keyHash=0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311;
fee=0.1 *10**18;
}
function getRandomNumber() public returns(bytes32 requestId){
return requestRandomness(keyHash,fee);
}
function fulfillRandomness(bytes32 requestId,uint randomness) internal override{
randomResult=randomness%7;
}
function contractBalance() public view returns(uint){
return address(this).balance;
}
function contractFund() external payable{
}
}
This is the solidity code that I am trying. Compiling of the code works fine. However, when I call the function send() via javascript it throws exception : throw new Error('invalid address');
pragma solidity ^0.4.6;
contract Agreement {
address owner;
address seller;
uint amount;
function Agreement(address _seller,uint _amount) {
owner = msg.sender; seller=_seller; amount=_amount;
}
function send(){
if (owner.balance < amount) throw;
if (seller.balance + amount < seller.balance) throw;
if(!seller.send(amount))throw;
}
}
This is the javascript code
var compiled = web3.eth.compile.solidity(contractRaw);
var contract = web3.eth.contract(compiled.info.abiDefinition);
var nContract = contract.new('0x61e323dcf5e116597d96558a91601f94b1f80396',web3.toWei(10, "ether"),{from:this.web3.eth.coinbase, data: compiled.code, gas: 380000}, function(e, contractDetails){
if(!e) {
if(!contractDetails.address) {
console.log("Contract transaction send: TransactionHash: " + contractDetails.transactionHash + " waiting to be mined...");
} else {
console.log("Contract mined! Address: " + contractDetails.address);
console.log(contractDetails.send())
}
}
});
Whenever the code runs, it throws invalid address error and crashes.
That address in fact exists (etherscan link) > , but it's not a contract address. If was, must open like this.
When you deploy your contract to etherium, you must copy the hash resulted on contract creation (transaction hash) and search for it on etherscan. It will open all transaction details, including the created contract hash. Use that hash.
Try 61e323dcf5e116597d96558a91601f94b1f80396, without the 0x