I want to deploy erc721 contracts from a simple factory contract and i have this error when I try to upload NFT - "transfer to non ERC721Receiver implementer", "data"enter image description here
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "./ezeynftFactory.sol";
contract ezeNFT {
uint256 public tokenCounter;
constructor(){
tokenCounter = 201;
}
function _mintNewNFT( string memory name, string memory symbol, string memory tokenUri)public{
uint256 newTokenId = tokenCounter;
ezeynftFactory nfts = new ezeynftFactory(name,symbol,tokenUri,newTokenId);
tokenCounter += 1;
}
}
// SPDX-License-Identifier: MIT
pragma experimental ABIEncoderV2;
pragma solidity >=0.6.0 <0.8.0;
import "../ERC721/ERC721.sol";
contract ezeynftFactory is ERC721 {
constructor(string memory name, string memory symbol,string memory tokenURI,uint tokenID)
ERC721(name,symbol)
{
_safeMint(msg.sender, tokenID);
_setTokenURI(tokenID,tokenURI);
}
}
The OpenZeppelin _safeMint() function tries to invoke onERC721Received() on the receiver if the receiver is a contract (which your ezeNFT is). And reverts the transaction if it doesn't receive the expected response (which doesn't receive, so it reverts).
There are two solutions to your problem.
Either implement the onERC721Received() function on your ezeNFT contract (the token receiver), returning the expected response. See ERC721TokenReceiver interface in the ERC-721 standard definition for more info.
contract ezeNFT {
uint256 public tokenCounter;
constructor(){
tokenCounter = 201;
}
function _mintNewNFT( string memory name, string memory symbol, string memory tokenUri) public {
uint256 newTokenId = tokenCounter;
ezeynftFactory nfts = new ezeynftFactory(name,symbol,tokenUri,newTokenId);
tokenCounter += 1;
}
function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes _data) external returns(bytes4) {
// TODO validate if you want to accept tokens only from certain collections
// return the expected response
return bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));
}
}
Or use the _mint() function, instead of _safeMint(), which doesn't perform the onERC721Received() call on the token receiver. So you won't have to implement it on ezeNFT.
contract ezeynftFactory is ERC721 {
constructor(string memory name, string memory symbol,string memory tokenURI,uint tokenID)
ERC721(name,symbol)
{
_mint(msg.sender, tokenID); // `_mint()` instead of `_safeMint()`
_setTokenURI(tokenID,tokenURI);
}
}
Related
The error I face in remix is Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
execution reverted even if I have enough money to create a contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
// Get the latest ETH/USD price from chainlink price feed
import "#chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
contract FundMe {
// safe math library check uint256 for integer overflows
//mapping to store which address depositeded how much ETH
mapping(address => uint256) public addressToAmountFunded;
// array of addresses who deposited
address[] public funders;
//address of the owner (who deployed the contract)
address public owner;
constructor() public {
owner = msg.sender;
}
function fund() public payable {
// 18 digit number to be compared with donated amount
uint256 minimumUSD = 50 * 10 ** 18;
//is the donated amount less than 50USD?
require(getConversionRate(msg.value) >= minimumUSD, "You need to spend more ETH!");
//if not, add to mapping and funders array
addressToAmountFunded[msg.sender] += msg.value;
funders.push(msg.sender);
}
function getVersion() public view returns (uint256){
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);
return priceFeed.version();
}
function getPrice() public view returns(uint256){
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);
(,int256 answer,,,) = priceFeed.latestRoundData();
// ETH/USD rate in 18 digit
return uint256(answer * 10000000000);
}
function getConversionRate(uint256 ethAmount) public view returns (uint256){
uint256 ethPrice = getPrice();
uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1000000000000000000;
// the actual ETH/USD conversation rate, after adjusting the extra 0s.
return ethAmountInUsd;
}
}
1)try downgrading your compiler version to 0.5
if that does not work try this
2)In remix try to increase your gas limit to probably 8000000
You need a receve/fallback function to send ETH to a contract. Try to add these to your contract code:
receive() external payable {
// React to receiving ether
}
we are building a staking smart contract on the ethereum mainnet. All the stakes will need to have a timestamp attached to it, so our logic relies on time.
The logic is at the end of the month each stakeholders will have credits, and based on that the contract owner will attribute rewards to each stakeholders based on their creditsAmount. But in order to get the total creditsAmount we need to iterate through the list of stakeHolders, which is super expensive.
Here is a very short example of our staking contract:
pragma solidity 0.8.6;
import “#openzeppelin/contracts/utils/structs/EnumerableSet.sol”;
contract Test {
using EnumerableSet for EnumerableSet.AddressSet;
struct Stake {
uint256 lockedToken;
uint256 creditsEarned; // numberOfDays * lockedToken = 15days * 1000 = 15000
}
// Rewards = RatioOfCreditsEarnedByStakeholder * MonthlyRewards
EnumerableSet.AddressSet private stakeholders;
mapping(address => Stake) private stakeholderToStake;
function createStake(
address stakeholder,
uint256 lockedToken,
uint256 creditsEarned
) public {
stakeholders.add(stakeholder);
stakeholderToStake[stakeholder] = Stake({
lockedToken: lockedToken,
creditsEarned: creditsEarned
});
}
function distributeRewards() public {
uint256 totalCredits = 0;
for (uint256 i = 0; i < stakeholders.length(); i++) {
totalCredits += stakeholderToStake[stakeholders.at(i)].creditsEarned;
}
}
}
So as you can imagine the very last loop is extremely costly but we did not find another way to do so for now. Do you have any idea proposition on how to avoid such loop? or other staking contract which relies on time like us?
Thanks
To expand on my comments, this is how I will do it.
pragma solidity 0.8.6;
import “#openzeppelin/contracts/utils/structs/EnumerableSet.sol”;
contract Test {
using EnumerableSet for EnumerableSet.AddressSet;
struct Stake {
uint256 lockedToken;
uint256 creditsEarned;
}
// Rewards = RatioOfCreditsEarnedByStakeholder * MonthlyRewards
EnumerableSet.AddressSet private stakeholders;
mapping(address => Stake) private stakeholderToStake;
uint256 private totalCredits;
function createStake(
address stakeholder,
uint256 lockedToken,
uint256 creditsEarned
) public {
stakeholders.add(stakeholder);
stakeholderToStake[stakeholder] = Stake({
lockedToken: lockedToken,
creditsEarned: creditsEarned
});
totalCredits += creditsEarned;
}
function distributeRewards() public {
//do whatever you want with totalCredits here
}
So i want to be able to buy/sell the token, but also have the ability for users to send eth to my contract wallet and receive my tokens in exchange. I believe i have the code ready for buyers and sellers to make a transaction together, dont think i have the pieces for someone to recieve tokens for sending me ethereum. I would like to make it so at the start people send me eth for a number of coins set at a base value
pragma solidity 0.4.22;
contract ERC20Basic {
string public constant name = "Community Token";
string public constant symbol = "COMM";
uint8 public constant decimals = 1;
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
event Transfer(address indexed from, address indexed to, uint tokens);
mapping(address => uint256) balances;
mapping(address => mapping (address => uint256)) allowed;
uint256 totalSupply_;
using SafeMath for uint256;
constructor(uint256 total) public {
totalSupply_ = total;
balances[msg.sender] = totalSupply_;
}
function totalSupply() public view returns (uint256) {
return totalSupply_;
}
function balanceOf(address tokenOwner) public view returns (uint) {
return balances[tokenOwner];
}
function transfer(address receiver, uint numTokens) public returns (bool) {
require(numTokens <= balances[msg.sender]);
balances[msg.sender] = balances[msg.sender].sub(numTokens);
balances[receiver] = balances[receiver].add(numTokens);
emit Transfer(msg.sender, receiver, numTokens);
return true;
}
function approve(address delegate, uint numTokens) public returns (bool) {
allowed[msg.sender][delegate] = numTokens;
emit Approval(msg.sender, delegate, numTokens);
return true;
}
function allowance(address owner, address delegate) public view returns (uint) {
return allowed[owner][delegate];
}
function transferFrom(address owner, address buyer, uint numTokens) public returns (bool) {
require(numTokens <= balances[owner]);
require(numTokens <= allowed[owner][msg.sender]);
balances[owner] = balances[owner].sub(numTokens);
allowed[owner][msg.sender] = allowed[owner][msg.sender].sub(numTokens);
balances[buyer] = balances[buyer].add(numTokens);
emit Transfer(owner, buyer, numTokens);
return true;
}
}
library SafeMath {
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
A very basic example of buy and sell:
pragma solidity ^0.8;
contract ERC20Basic{
uint256 public constant tokenPrice = 5; // 1 token for 5 wei
function buy(uint256 _amount) external payable {
// e.g. the buyer wants 100 tokens, needs to send 500 wei
require(msg.value == _amount * tokenPrice, 'Need to send exact amount of wei');
/*
* sends the requested amount of tokens
* from this contract address
* to the buyer
*/
transfer(msg.sender, _amount);
}
function sell(uint256 _amount) external {
// decrement the token balance of the seller
balances[msg.sender] -= _amount;
increment the token balance of this contract
balances[address(this)] += _amount;
/*
* don't forget to emit the transfer event
* so that external apps can reflect the transfer
*/
emit Transfer(msg.sender, address(this), _amount);
// e.g. the user is selling 100 tokens, send them 500 wei
payable(msg.sender).transfer(amount * tokenPrice);
}
}
This will allow any user to buy or sell tokens from/to your contract. Your contract will need to own these tokens in order to sell them to the users. Also your contract will need to have enough ETH in order to buy back tokens from the users.
You can expand on this code to implement
a contract owner that is authorized to change the price
different prices for buy and sell
fees
min/max amounts (per one transaction, per user, per day, ...)
calculating the amount of tokens based on the msg.value (the user won't have to have the exact amount)
etc...
Note that my snippet is using Solidity 0.8 where integer overflow is prevented automatically. The question is using deprecated Solidity 0.4, so that you'd need to use SafeMath, check the value with require/assert or upgrade to Solidity 0.8 to reach the same result.
I have Crowdsale contract written on the basis of OpenZepelin Crowdsale.sol
my contract:
contract MoonShardToken is StandardToken, Ownable {
string public name = "MyContract";
uint8 public decimals = 18;
string public symbol = "My";
/// this constructor added as a test
constructor() public {
totalSupply_ = (36000000 * (10 ** 18));
balances[msg.sender] = totalSupply_;
}
}
my crowdsale is copy of OpenZepelin Crowdsale.sol, i deploy my contract with truffle, i can console.log in tests my rate: 200000000000000
TotalSupply of my tokens: 3.6e+25, all functions in tests from contract works correctly, but when i use function buyTokens whith massage value more then zero i become error VM Exception while processing transaction: revert;when msg.value is zero i become no errors, and event in func emited
this is function buyTokens:
function buyTokens(address _beneficiary) public payable {
uint256 weiAmount = msg.value;
// _preValidatePurchase(_beneficiary, weiAmount); this is function with required msg.value>0 was commented for test
uint256 tokens = _getTokenAmount(weiAmount);
weiRaised = weiRaised.add(weiAmount);
_processPurchase(_beneficiary, tokens);
emit TokenPurchase(
msg.sender,
_beneficiary,
weiAmount,
tokens
);
_forwardFunds();
}
in truffle tests i use this function as: await Crowdsale.buyTokens(wallet, {from: wallet, value: web3.toWei(0.0001, "ether")});
wallet is account(1) with token balance 0. i use ganache cli and all my accs have ether? simple transaction works correctly.
When attempting buyTokens, this function calls _getTokenAmount(weiAmount) which returns weiAmount.mul(_rate). Can you post your migrations file? It may be that _rate is not set properly during deployment.
Trying to test solidity using Remix IDE. I keep getting the error:
Gas estimation errored with the following message (see below). The transaction > execution will likely fail. Do you want to force sending?
Does anybody have an idea about what might be giving me this error. It I am trying to sell products using the ethereum smart contracts. I have used the Remix IDE to create this contract with value = 0.
I am successfully able to create the contract and add_product but I am unable to Buy. The last line give me the error mentionned above.
The solidity file I am testing againt is the following: As you can see I create a Sell contract which would allow a user to sell products using the blockchain and a buyer to retrieve the product paying the price in ethereum. If anyone has a better solution for me to use for this exact use-case I am opened to suggestions.
pragma solidity ^0.4.0;
contract Sell {
struct Product_Quantity{
string _product_name;
uint256 _product_quantity;
uint256 _price_unity;
bool isValue;
}
struct Seller{
address _id;
mapping(string => Product_Quantity) products;
}
Seller public seller;
mapping (address => Product_Quantity) product_owners;
function Sell(){
seller._id = msg.sender;
}
function add_product(string product_name, uint256 product_quantity, uint256 price_unity) {
if(msg.sender != seller._id) throw;
if(seller.products[product_name].isValue){
seller.products[product_name]._product_quantity += product_quantity;
}
else{
seller.products[product_name] = Product_Quantity(product_name, product_quantity, price_unity, true);
}
}
function Buy( string product_name, uint256 quantity) payable {
if(product_owners[msg.sender].isValue){
product_owners[msg.sender]._product_quantity += quantity;
}
else{
product_owners[msg.sender] = Product_Quantity(product_name, quantity, seller.products[product_name]._price_unity, true);
}
seller.products[product_name]._product_quantity -= quantity;
seller._id.transfer(seller.products[product_name]._price_unity * quantity);
}
}
That's a very generic Remix error message. Fortunately, today I'm seeing new error messages on Remix (nice update guys!), which makes it easier to debug the problem.
When someone tries to buy a product, you should check if the value passed (in wei) is the right amount to buy that product and quantity.
Since you're not checking that, a buyer can buy a product with an amout equals to 0, which means the contract will have no wei to send to the seller at the end of the buy() function. That will throw an exception and the transaction will be reverted.
I updated your code to run on solidity 0.4.23 (latest version), made some code refactoring and add a modifier to the buy() function to check if the amount passed is correct.
pragma solidity ^0.4.23;
contract Sell {
struct Product_Quantity{
string _product_name;
uint256 _product_quantity;
uint256 _price_unity;
bool isValue;
}
mapping (address => Product_Quantity) product_owners;
struct Seller{
address _id;
mapping(string => Product_Quantity) products;
}
Seller public seller;
constructor() public {
seller._id = msg.sender;
}
function add_product (string product_name, uint256 product_quantity, uint256 price_unity) public {
require(msg.sender == seller._id);
if (seller.products[product_name].isValue) {
seller.products[product_name]._product_quantity += product_quantity;
}
else{
seller.products[product_name] = Product_Quantity(product_name, product_quantity, price_unity, true);
}
}
modifier hasEnoughEther (string product_name, uint256 quantity) {
require (seller.products[product_name].isValue); // does the product exists?
uint256 neededEther = seller.products[product_name]._price_unity * quantity;
require (msg.value == neededEther); // did the buyer sent the correct value?
_;
}
function buy (string product_name, uint256 quantity) payable public hasEnoughEther (product_name, quantity) {
if (product_owners[msg.sender].isValue) {
product_owners[msg.sender]._product_quantity += quantity;
} else {
product_owners[msg.sender] = Product_Quantity(product_name, quantity, seller.products[product_name]._price_unity, true);
}
seller.products[product_name]._product_quantity -= quantity;
seller._id.transfer(seller.products[product_name]._price_unity * quantity);
}
}
In my case, I needed to fund my contract so it can perform operations.
In your case you are trying to use a MODIFIER function with arguments but have not passed any parameters to it in the Buy function.
And in my case I was trying to trigger a non-payable function with some ether in the VALUE field of the Deploy and Run Transactions tab.