"Execution reverted" error when I call createCollectible function on goerli testnet - ethereum

I'm new to smart contract and Solidity programming and I've been trying to deploy an NFT contract on goerli testnet. The contract deploys without any problem but when I try to call the "createCollectible" function, I get the following error:
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
execution reverted
{
"originalError": {
"code": 3,
"data": "0xf0019fe60000000000000000000000000000000000000000000000000000000000000c6a000000000000000000000000b54644506388a04187d943dbbbd3edbb3ee53094",
"message": "execution reverted"
}
}
Here is my contract:
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.9.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "#chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol";
import "#chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
/**
* #title The AdvandedCollectible contract
* #notice A contract that mints an NFT
*/
contract AdvancedCollectible is ERC721, VRFConsumerBaseV2 {
VRFCoordinatorV2Interface immutable COORDINATOR;
LinkTokenInterface immutable LINKTOKEN;
uint256 public tokenCounter;
uint64 immutable s_subscriptionId;
// The gas lane to use, which specifies the maximum gas price to bump to.
// For a list of available gas lanes on each network,
// see https://docs.chain.link/docs/vrf-contracts/#configurations
bytes32 immutable s_keyhash;
uint32 immutable s_numWords = 1;
uint16 immutable s_requestConfirmations = 3;
// Depends on the number of requested values that you want sent to the
// fulfillRandomWords() function. Storing each word costs about 20,000 gas,
// so 100,000 is a safe default for this example contract. 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 immutable s_callbackGasLimit = 100000;
uint256 public s_requestId;
uint256 public s_randomWords;
address s_owner;
enum Breed {
PUG,
SHIBA_INU,
ST_BERNARD
}
mapping(uint256 => Breed) public tokenIdToBreed;
mapping(uint256 => address) public requestIdToSender;
event requestCollectible(uint256 indexed requestId, address requester);
event breedAssigned(uint256 tokenId, Breed breed);
constructor(
address vrfCoordinator,
address link,
bytes32 keyhash,
uint64 subscriptionId
) VRFConsumerBaseV2(vrfCoordinator) ERC721("Dogie", "DOG") {
tokenCounter = 0;
COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
LINKTOKEN = LinkTokenInterface(link);
s_keyhash = keyhash;
s_owner = msg.sender;
s_subscriptionId = subscriptionId;
}
modifier onlyOwner() {
require(msg.sender == s_owner, "You are not the owner");
_;
}
function createCollectible() public returns (uint256) {
s_requestId = COORDINATOR.requestRandomWords(
s_keyhash,
s_subscriptionId,
s_requestConfirmations,
s_callbackGasLimit,
s_numWords
);
requestIdToSender[s_requestId] = msg.sender;
emit requestCollectible(s_requestId, msg.sender);
}
function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords)
internal
override
{
s_randomWords = randomWords[0];
Breed breed = Breed(s_randomWords % 3);
uint256 newTokenId = tokenCounter;
tokenIdToBreed[newTokenId] = breed;
emit breedAssigned(newTokenId, breed);
address owner = requestIdToSender[requestId];
_safeMint(owner, newTokenId);
tokenCounter++;
}
function setTokenURI(uint256 tokenId, string memory _tokenURI) public {
require(
_isApprovedOrOwner(_msgSender(), tokenId),
"ERC721: Caller is not owner nor approved."
);
setTokenURI(tokenId, _tokenURI);
}
}
Does anybody have an idea what I'm doing wrong here?

So I realized that I'm missing one small yet important step, and that is adding a consumer to my subscription.
Using the Chainlink VRF V2, you need to create a subscription, add funds to that subscription and add the address where your contract is deployed at as a consumer to the subscription. I wasn't doing that last step and that's why my transaction's execution kept reverting.

Related

Getting AAVE smartcontract error - caller is not ownable

I am getting the following error when try to execute the flashloan in Goerli testnet with USDC
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
execution reverted: Ownable: caller is not the owner
{
"originalError": {
"code": 3,
"data": "0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000204f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572",
"message": "execution reverted: Ownable: caller is not the owner"
}
}
I have used the following addresses for deployment and flashloan
//Goerli testnet 0xC911B590248d127aD18546B186cC6B324e99F02c
//faucet address 0x1ca525Cd5Cb77DB5Fa9cBbA02A0824e283469DBe
//USDC address 0x65aFADD39029741B3b8f0756952C74678c9cEC93
Could you please advice how can i solve this problem?
I am using the following code
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.8.10;
pragma experimental ABIEncoderV2;
//Deploy address
//Goerli testnet 0xC911B590248d127aD18546B186cC6B324e99F02c
//faucet address 0x1ca525Cd5Cb77DB5Fa9cBbA02A0824e283469DBe
//USDC address 0x65aFADD39029741B3b8f0756952C74678c9cEC93
import {
IPoolAddressesProvider
} from "https://github.com/aave/aave-v3-core/contracts/interfaces/IPoolAddressesProvider.sol";
import { IPool } from "https://github.com/aave/aave-v3-core/contracts/interfaces/IPool.sol";
import { IFlashLoanSimpleReceiver } from "https://github.com/aave/aave-v3-core/contracts/flashloan/interfaces/IFlashLoanSimpleReceiver.sol";
import { IERC20 } from "https://github.com/aave/aave-v3-core/contracts/dependencies/openzeppelin/contracts/IERC20.sol";
import { SafeMath } from "https://github.com/aave/aave-v3-core/contracts/dependencies/openzeppelin/contracts/SafeMath.sol";
interface IFaucet {
function mint(
address _token,
uint256 _amount
) external;
}
abstract contract FlashLoanSimpleReceiverBase is IFlashLoanSimpleReceiver {
using SafeMath for uint256;
IPoolAddressesProvider public immutable override ADDRESSES_PROVIDER;
IPool public immutable override POOL;
IFaucet public immutable FAUCET;
constructor(IPoolAddressesProvider provider, IFaucet faucet) {
ADDRESSES_PROVIDER = provider;
POOL = IPool(provider.getPool());
FAUCET = faucet;
}
}
/**
!!!
Never keep funds permanently on your FlashLoanSimpleReceiverBase contract as they could be
exposed to a 'griefing' attack, where the stored funds are used by an attacker.
!!!
*/
contract MySimpleFlashLoanV3 is FlashLoanSimpleReceiverBase {
using SafeMath for uint256;
constructor(IPoolAddressesProvider _addressProvider, IFaucet _faucet) FlashLoanSimpleReceiverBase(_addressProvider, _faucet) {}
/**
This function is called after your contract has received the flash loaned amount
*/
function executeOperation(
address asset,
uint256 amount,
uint256 premium,
address initiator,
bytes calldata params
)
external
override
returns (bool)
{
//
// This contract now has the funds requested.
// Your logic goes here.
//
// At the end of your logic above, this contract owes
// the flashloaned amounts + premiums.
// Therefore ensure your contract has enough to repay
// these amounts.
// Approve the LendingPool contract allowance to *pull* the owed amount
uint amountOwed = amount.add(premium);
FAUCET.mint(asset,premium);
IERC20(asset).approve(address(POOL), amountOwed);
return true;
}
function executeFlashLoan(
address asset,
uint256 amount
) public {
address receiverAddress = address(this);
bytes memory params = "";
uint16 referralCode = 0;
POOL.flashLoanSimple(
receiverAddress,
asset,
amount,
params,
referralCode
);
}
}

Ethernaut level 24 - Puzzle Wallet: to which contract the wallet object on the browser console refers to?

I got a little confused when trying to solve this level and I got even more confused when I read this solution.
I thought that the contract object loaded in the browser console was the PuzzleWallet contract, because when I look at its ABI, there are all the functions from that contract and none from the PuzzleProxy. And the PuzzleWallet does not inherit from any other contract. I don't understand how it is possible to call proposeNewAdmin() function from the PuzzleProxy contract, if it does not inherit from PuzzleProxy...
On the other hand, if the contract object in the browser console is the PuzzleProxy, why there are all the functions from the PuzzleWallet in the ABI and none from the PuzzleProxy?
Here is the Ethernaut level.
The contracts are:
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import "#openzeppelin/contracts/math/SafeMath.sol";
import "#openzeppelin/contracts/proxy/UpgradeableProxy.sol";
contract PuzzleProxy is UpgradeableProxy {
address public pendingAdmin;
address public admin;
constructor(address _admin, address _implementation, bytes memory _initData) UpgradeableProxy(_implementation, _initData) public {
admin = _admin;
}
modifier onlyAdmin {
require(msg.sender == admin, "Caller is not the admin");
_;
}
function proposeNewAdmin(address _newAdmin) external {
pendingAdmin = _newAdmin;
}
function approveNewAdmin(address _expectedAdmin) external onlyAdmin {
require(pendingAdmin == _expectedAdmin, "Expected new admin by the current admin is not the pending admin");
admin = pendingAdmin;
}
function upgradeTo(address _newImplementation) external onlyAdmin {
_upgradeTo(_newImplementation);
}
}
contract PuzzleWallet {
using SafeMath for uint256;
address public owner;
uint256 public maxBalance;
mapping(address => bool) public whitelisted;
mapping(address => uint256) public balances;
function init(uint256 _maxBalance) public {
require(maxBalance == 0, "Already initialized");
maxBalance = _maxBalance;
owner = msg.sender;
}
modifier onlyWhitelisted {
require(whitelisted[msg.sender], "Not whitelisted");
_;
}
function setMaxBalance(uint256 _maxBalance) external onlyWhitelisted {
require(address(this).balance == 0, "Contract balance is not 0");
maxBalance = _maxBalance;
}
function addToWhitelist(address addr) external {
require(msg.sender == owner, "Not the owner");
whitelisted[addr] = true;
}
function deposit() external payable onlyWhitelisted {
require(address(this).balance <= maxBalance, "Max balance reached");
balances[msg.sender] = balances[msg.sender].add(msg.value);
}
function execute(address to, uint256 value, bytes calldata data) external payable onlyWhitelisted {
require(balances[msg.sender] >= value, "Insufficient balance");
balances[msg.sender] = balances[msg.sender].sub(value);
(bool success, ) = to.call{ value: value }(data);
require(success, "Execution failed");
}
function multicall(bytes[] calldata data) external payable onlyWhitelisted {
bool depositCalled = false;
for (uint256 i = 0; i < data.length; i++) {
bytes memory _data = data[i];
bytes4 selector;
assembly {
selector := mload(add(_data, 32))
}
if (selector == this.deposit.selector) {
require(!depositCalled, "Deposit can only be called once");
// Protect against reusing msg.value
depositCalled = true;
}
(bool success, ) = address(this).delegatecall(data[i]);
require(success, "Error while delegating call");
}
}
}
The contract.abi object on the browser console is:
I understand the concept of proxy patterns. But I thought that it would be done via delegatecall() functions. For example, the addToWhiteList() function on the PuzzleWallet contract would be called by a function as follows on the PuzzleProxy contract:
function addToWhitelist(address _add) external {
puzzleWalletAddress.delegatecall(abi.encodeWithSignature("addToWhitelist(address)", _add);)
}
Hopefully my question here is not as confusing as I got while trying to solve this level :)
Appreciate very much if anyone coould help me! Thanks!
I also got confused by the same thing :)
The answer is that they created the Web3 contract object with the ABI of the logic contract but with the address of the proxy contract so you can interact with the logic as if there wasn't a proxy pattern under the hood.
In reality it is calling the proxy contract with the data of a function of the logic contract. As the function doesn't exist in the proxy, its fallback function runs and redirects the call to the logic contract via delegatecall.
So if you want to call proposeNewAdmin() in the proxy, call the contract mounted in the console (aka the proxy contract) but instead of using any function from the ABI defined there (which is the logic abi), make a generic transaction calling proposeNewAdmin(). As the function does exist in the proxy, it won't trigger the fallback.
web3.eth.abi.encodeFunctionSignature("proposeNewAdmin(address)");
> '0xa6376746'
web3.eth.abi.encodeParameter("address", player);
> '0x000000000000000000000000c3a005e15cb35689380d9c1318e981bca9339942'
contract.sendTransaction({ data: '0xa6376746000000000000000000000000c3a005e15cb35689380d9c1318e981bca9339942' });

ERC721 contract deployed with create2 stops working after a particular function is called

So I'm working on an NFT marketplace smart contract and one of the features in this marketplace allows users to deploy their own collection (this is basically a smart contract that extends the ERC721 specification). For this, I'm leveraging the create2 opcode. It deploys well while testing on the testnet (except for the insanely huge gas requirement) but the problem is, I can only call a function once in this contract. This is the contract that extends ERC721:
pragma solidity ^0.8.0;
import '#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol';
import '#openzeppelin/contracts/token/ERC721/IERC721.sol';
import '#openzeppelin/contracts/security/ReentrancyGuard.sol';
import '#openzeppelin/contracts/utils/Counters.sol';
import './interfaces/IDeployableCollection.sol';
contract DeployableCollection is IDeployableCollection, ERC721URIStorage, ReentrancyGuard {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
address public _collectionOwner;
bytes32 public _category;
address payable public _paymentReceiver;
string public _collectionURI;
mapping(address => uint256) public lastMintedForIDs;
constructor(
string memory name_,
string memory symbol_,
address collectionOwner_,
string memory category_,
address paymentReceiver_,
string memory collectionURI_
) ERC721(name_, symbol_) {
_collectionOwner = collectionOwner_;
_category = keccak256(abi.encode(category_));
_paymentReceiver = payable(paymentReceiver_);
_collectionURI = collectionURI_;
}
function mintFor(string memory _tokenURI, address to) external nonReentrant returns (uint256 _tokenId) {
_tokenIds.increment();
_tokenId = _tokenIds.current();
_mint(to, _tokenId);
_setTokenURI(_tokenId, _tokenURI);
lastMintedForIDs[to] = _tokenId;
}
}
This is the line that deploys the contract:
function deployCollection(
string memory name_,
string memory symbol_,
string memory category_,
address paymentReceiver_,
string memory _collectionURI
) external payable nonReentrant {
uint256 _fee = _utilityToken != address(0) && IERC20(_utilityToken).balanceOf(_msgSender()) >= _requiredHold
? _collectionDeployFeeInEther.sub((uint256(_percentageDiscount).mul(_collectionDeployFeeInEther)).div(100))
: _collectionDeployFeeInEther;
require(msg.value >= _fee, 'FEE_TOO_LOW');
bytes memory _byteCode = abi.encodePacked(
type(DeployableCollection).creationCode,
abi.encode(name_, symbol_, _msgSender(), category_, paymentReceiver_, _collectionURI)
);
bytes32 _salt = keccak256(abi.encode(name_, _msgSender()));
address _collection;
assembly {
_collection := create2(0, add(_byteCode, 32), mload(_byteCode), _salt)
}
emit CollectionDeployed(_collection, _msgSender(), block.timestamp, name_, category_, symbol_);
}
Now this works fine, except once I call mintFor and an NFT gets minted, the contract stops working. It shows a total supply of zero (0) on the block explorer even though an NFT has been created (I'm only able to create an NFT with an ID of 1). I also am not able to call any function again as it raises an exception (the cause of which is unknown). This is the line in the factory contract that does the actual minting:
function mintNFT(
address collection,
string memory tokenURI_,
address _for
) external payable nonReentrant returns (bool) {
uint256 _fee = _utilityToken != address(0) && IERC20(_utilityToken).balanceOf(_msgSender()) >= _requiredHold
? _mintFeeInEther.sub((uint256(_percentageDiscount).mul(_mintFeeInEther)).div(100))
: _mintFeeInEther;
require(msg.value >= _fee, 'FEE_TOO_LOW');
address _paymentReceiver = IDeployableCollection(collection)._paymentReceiver();
uint256 _feeForOwner = (uint256(_percentageForCollectionOwners).mul(_fee)).div(100);
_safeMintFor(collection, tokenURI_, _for);
_safeTransferETH(_paymentReceiver, _feeForOwner);
uint256 _tokenId = IDeployableCollection(collection).lastMintedForIDs(_msgSender());
emit Mint(collection, _tokenId, block.timestamp, tokenURI_, _msgSender());
return true;
}
I'm guessing an optimization with a runs of 1 is applied upon deployment using create2 (forgive me if this is stupid) but I also think it isn't likely as I'm also watching for events on the smart contract with a Nodejs back-end and I'm able to call '_collectionURI()' when the event data is propagated to my back-end app and this is before calling mintFor. I'm confused! Please help!
This is a link to the contract info on the explorer: https://testnet.bscscan.com/token/0x6dd5bd0072cdc5e8c24f262a9631c175bc2356a0

Constructor error, setter not working(Solidity)

I was working on my smart contract project and when I put some values at the depolyment of the contract as inputs and I got an error of saying.
"revert
The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the
value you send should be less than your current balance.
Debug the transaction to get more information."
And my code is
uint[] private Info;
function SetInfo(uint[] memory data) private onlyOwner{
Info = new uint[](data.length);
for(uint i = 0; i < data.length;i++){
Info[i] = data[i];
}
constructor(uint[] memory _Info,uint[] memory _SecondInfo)
ERC721(_name, _symbol) {
SetInfo(_Info);
SetSecondInfo(_SecondInfo)
}
I tried to adjust your smart contract. I put some comments that will help you to understand what I did and your errors in original smart contract.
Smart contract code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
// Your class must inheritance ERC721 smart contract, if you want to use its functions
contract Test is ERC721 {
uint[] private Info;
// Specify variable that will contain owner address when contract will create.
address owner;
modifier onlyOwner() {
require(msg.sender == owner, "You aren't the owner!");
_;
}
// You must to give a name and symbol about your ERC721 token
constructor(uint[] memory _Info, uint[] memory _SecondInfo) ERC721("TESTToken", "TST") {
// Set owner variable with msg.sender value
owner = msg.sender;
SetInfo(_Info);
SetSecondInfo(_SecondInfo);
}
function SetInfo(uint[] memory data) private onlyOwner {
Info = new uint[](data.length);
for(uint i = 0; i < data.length;i++){
Info[i] = data[i];
}
}
function SetSecondInfo(uint[] memory data) private onlyOwner {
// your logic
}
}

How to call a method from a contract that was instantiated from another contract via truffle console?

I'm trying to call a method from a contract that was instantiated from another contract. I use truffle console.
Here are the details: (I think you can gloss over the code, since this question is aimed at using truffle console, not fixing any bugs)
I have a contract called MyCoinSupply.sol:
pragma solidity ^0.8.0;
import "./MyCoin.sol";
contract MyCoinSupply is MyCoin("MyCoin", "MYC") // MyCoin is ERC20
{
constructor() public // gives 1000 tokens to the owner
{
_mint(msg.sender, 1000);
}
function getCoinbase() public returns (address) // for debugging purposes
{
return block.coinbase;
}
function _mintMinerReward() internal // gives 20 tokens to the miner
{
// _mint(block.coinbase, 20); // for some reason, block.coinbase is address 0
}
function _transfer(address from, address to, uint256 value) override internal
{
_mintMinerReward();
super._transfer(from, to, value);
}
}
I instantiate MyCoinSupply.sol within MyCoinDEX.sol:
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./MyCoinSupply.sol";
contract MyCoinDEX
{
IERC20 public token;
event Bought(uint256 amount);
event Sold(uint256 amount);
constructor() public
{
token = new MyCoinSupply();
}
function showSender() public view returns (address) // for debugging purposes
{
return (msg.sender);
}
function buy(uint256 amountTobuy) payable public // send ether and get tokens in exchange; 1 token == 1 ether
{
uint256 dexBalance = token.balanceOf(address(this));
require(amountTobuy > 0, "You need to send some ether");
require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");
token.transfer(msg.sender, amountTobuy);
emit Bought(amountTobuy);
}
function sell(uint256 amount) public // send tokens to get ether back
{
require(amount > 0, "You need to sell at least some tokens");
uint256 allowance = token.allowance(msg.sender, address(this));
require(allowance >= amount, "Check the token allowance");
token.transferFrom(msg.sender, address(this), amount);
payable(msg.sender).transfer(amount);
emit Sold(amount);
}
}
Here's my migration for deploying contracts:
const MyCoinSupply = artifacts.require("MyCoinSupply");
const MyCoinDEX = artifacts.require("MyCoinDEX");
module.exports = function(deployer) {
deployer.deploy(MyCoinSupply);
deployer.deploy(MyCoinDEX);
};
Here's my problem:
When I try to call functions that belong to MyCoinDEX, all works well:
truffle(development)> let instance = await MyCoinDEX.deployed()
undefined
truffle(development)> instance.buy(1)
All is good here.
However, when I try the following I get an error:
truffle(development)> instance.token.balanceOf("0xE1994C1054f9c4171B8ae9a7E7a68F404c2bF829")
evalmachine.<anonymous>:0
instance.token.balanceOf("0xE1994C1054f9c4171B8ae9a7E7a68F404c2bF829")
^
Uncaught TypeError: instance.token.balanceOf is not a function
I Googled this error (I read this solution and this solution), but I didn't really stumble upon a solution. Can someone tell me how can I call token's methods from MyCoinDEX?
Thank you in advance!