Uncaught (in promise) BigNumber Error for address - solidity

I have a function in ERC721 contract which returns an address.
I am passing the returned address to ERC20 transferFrom function, and getting the following error.
My javascript code
Voting.deployed().then(function(ERC20Instance) {
let buyerAddress = $("#to-address").val();
ERC20Instance.approve(buyerAddress, 100, {gas: 1000000, from: web3.eth.accounts[0]});
ERC20Instance.transferFrom(buyerAddress, contractInstance.getCreator(), 10, {gas: 1000000, from: web3.eth.accounts[0]});
^^^^This line is causing an error.
})
and ERC721 contract:
function getCreator() public view returns (address) {
return nftInfo[owner].creator;
}
function mint(string calldata nftName) external payable {
uint256 newItemId = _tokenIds.current();
_mint(msg.sender, newItemId);
owner = msg.sender;
nftInfo[msg.sender].nftId = newItemId;
nftInfo[msg.sender].name = nftName;
nftInfo[msg.sender].creator = msg.sender;
allValidTokenIndex[newItemId] = allValidTokenIds.length;
allValidTokenIds.push(newItemId);
_tokenIds.increment();
}

contractInstance.getCreator()
This JS function returns a Promise - not the actual address. You need to resolve the Promise first to get the address.
Same goes with the approve() function. You should wait until the function has been processed (i.e. after the JS Promise has been resolved) to prevent unexpected behavior resulting from the transferFrom() being executed asynchronously before the approve() finishes running.
Voting.deployed().then(async function(ERC20Instance) { // add `async`
let buyerAddress = $("#to-address").val();
await ERC20Instance.approve( // recommended: add `await`
buyerAddress,
100,
{gas: 1000000, from: web3.eth.accounts[0]}
);
await ERC20Instance.transferFrom( // recommended: add `await`
buyerAddress,
await contractInstance.getCreator(), // add `await`
10,
{gas: 1000000, from: web3.eth.accounts[0]}
);

Related

In hardhat unit testing how do you assert multiple return values from a contract

I have this solidity contract function that returns multiple values of multiple types. How do I assert them in my unit tests?
I tried something like
var [x, y] = await contractA.getAll()
etc. but that doesn’t work.
Assuming the Solidity return variables are not named, you can access them using their position indexes.
function getAll() external pure returns (uint8, bool) {
return (1, true);
}
const returnedValues = await contract.getAll(); // [ 1, true ]
const number = returnedValues[0];
const status = returnedValues[1];
And if they are named, you can also access them with object keys.
function getAll() external pure returns (uint8 number, bool status) {
return (1, true);
}
const returnedValues = await contract.getAll(); // [ 1, true, number: 1, status: true ]
const number = returnedValues.number;
const status = returnedValues.status;

Getting a Runtime error when passing an Integer into a Solidity function that take uint256 as parameter

My Solidity smart contract has this function:
function getPlayerAddress(uint256 index) public view returns(address) {
return s_players[index];
}
And I am trying to pass an Integer as parameter via my frontend React application.
This is what the State looks like:
const [playerIndex, setPlayerIndex] = useState(0)
This is the function where I am trying to pass the value:
const updatePlayer = async () => {
const provider = new ethers.providers.Web3Provider(window.ethereum)
const contract = new ethers.Contract(stallionRunAddress, abi, provider)
**const newPlayer = await contract.getPlayerAddress(playerIndex)**
const newPlayerLevelBI = await contract.ownedHorseLevel(newPlayer)
const newPlayerLevel = parseInt(newPlayerLevelBI)
const newPlayerHorseArr = await contract.ownedHorseName(newPlayer)
const newPlayerHorse = newPlayerHorseArr[0].toString()
setPlayers(...players, {address: newPlayer, level: newPlayerLevel, horse: newPlayerHorse})
}
I get this error:
Unhandled Runtime Error
Error: call revert exception; VM Exception while processing transaction: reverted with panic code 50 [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (method="getPlayerAddress(uint256)", data="0x4e487b710000000000000000000000000000000000000000000000000000000000000032", errorArgs=[{"type":"BigNumber","hex":"0x32"}], errorName="Panic", errorSignature="Panic(uint256)", reason=null, code=CALL_EXCEPTION, version=abi/5.7.0)
I have tried passing it as a value with 18 decimals (wei format):
playerIndex * 1e18
But it still doesn't fix the error. How do i fix this?
Solidity uint256 integers can be passed by web3js should be BigNumber instead of js integers. Also you can use string as well.

Error during minting with code from Opensea guide

I'm trying to deploy my first SmartContract following the Opensea guide. Everything was working fine until I set a price for my tokens and added the payable keyword. Now when I try to mint, I get the error Transaction value did not equal the mint price. Looking at the code I'm thinking I need to send ETH in the mint request in msg.value somehow but I'm not sure what the syntax would be for that?
Here's how I'm minting in shell:
npx hardhat mint --address {wallet_address}
Here's the mint function in JS:
task("mint", "Mints from the NFT contract")
.addParam("address", "The address to receive a token")
.setAction(async function (taskArguments, hre) {
const contract = await getContract("NFT", hre);
const transactionResponse = await contract.mintTo(taskArguments.address, {
gasLimit: 500_000,
});
console.log(`Transaction Hash: ${transactionResponse.hash}`);
});
And the mintTo function in the .sol contract:
// Main minting function
function mintTo(address recipient) public payable returns (uint256) {
uint256 tokenId = currentTokenId.current();
require(tokenId < TOTAL_SUPPLY, "Max supply reached");
require(msg.value == MINT_PRICE, "Transaction value did not equal the mint price");
currentTokenId.increment();
uint256 newItemId = currentTokenId.current();
_safeMint(recipient, newItemId);
return newItemId;
}
I figured out a solution for this issue. You need to set the price inside the mint task in mint.js like so:
task("mint", "Mints from the NFT contract")
.addParam("address", "The address to receive a token")
.setAction(async function (taskArguments, hre) {
const contract = await getContract("NFT", hre);
const transactionResponse = await contract.mintTo(taskArguments.address, {
gasLimit: 500_000,
value: ethers.utils.parseEther("0.01")
});
console.log(`Transaction Hash: ${transactionResponse.hash}`);
});
I have not figured out a way to have this import the MINT_PRICE variable from the contract. Note: You may need to add const { ethers } = require("ethers"); at the top of the file.

Error: invalid address (argument="address", value=undefined, code=INVALID_ARGUMENT, version=address/5.1.0)

I'm Getting this error when trying to deploy a smart contract with a function:
Error: invalid address (argument="address", value=undefined, code=INVALID_ARGUMENT, version=address/5.1.0) (argument="tokenAddress", value=undefined, code=INVALID_ARGUMENT, version=abi/5.0.7)
Here is my code:
const handlePresale = async (e) => {
e.preventDefault();
const web3 = await getWeb3();
const abiData = SafeHubPresaleAbi;
const contractAddress = "0x4498F943E0a13D70B28e7565CF4E33bF443e6Bf9";
const duration = {
seconds: function (val) {
return val;
},
minutes: function (val) {
return val * this.seconds(60);
},
hours: function (val) {
return val * this.minutes(60);
},
days: function (val) {
return val * this.hours(24);
},
weeks: function (val) {
return val * this.days(7);
},
years: function (val) {
return val * this.days(365);
},
};
const latestTime = new Date().getTime();
const openingTime = latestTime + duration.minutes(1);
const closingTime = openingTime + duration.minutes(10);
const liqAddingTime = closingTime + duration.minutes(5);
let _info = {
address : "0x4498F943E0a13D70B28e7565CF4E33bF443e6Bf9",
tokenPrice : web3.utils.toWei("10", "ether"),
hardCap: web3.utils.toWei("100", "ether"),
softCap: web3.utils.toWei("30", "ether"),
minInv: web3.utils.toWei("0.1", "ether"),
maxInv: web3.utils.toWei("5", "ether"),
openingTime: openingTime,
closingTime: closingTime,
};
let _uniInfo = {
listingPrice: web3.utils.toWei("20", "ether"),
liqTime: liqAddingTime,
lockTime: 365,
precentLock: 25,
};
let _stringInfo = {
listingName: "WER sale",
};
const preslaeContract = await new web3.eth.Contract(
abiData,
contractAddress
);
// console.log(preslaeContract.methods)
preslaeContract.methods
.createPresale(_info,_uniInfo,_stringInfo)
.call((err, result) => {
console.log(result), console.log(err);
});
}
Solidity constructor:
constructor(address _safuFactoryAddress, address _safuDevAddress) public {
require(_safuFactoryAddress != address(0));
require(_safuDevAddress != address(0));
safuFactoryAddress = payable(_safuFactoryAddress);
safuDevAddress = payable(_safuDevAddress);
}
since there are still no answers yet, but over 1k views though, I'll leave here a solution if anyone else is facing the same error.
The solidity constructor in your example expects 2 arguments of type address. This means if you deploy your contract you also need to provide those 2.
As for the deployment:
No matter how you deploy your contract, providing all constructor arguments should solve your problem and your contract should be able to get deployed now.
If you work with truffle, you need to adjust your deployer .../migrations/2_deploy_contracts.js and pass 2 addresses to satisfy the constructor parameters.
var SafeHubPresale = artifacts.require("./SafeHubPresale.sol");
module.exports = function(deployer) {
deployer.deploy(SafeHubPresale, [address1], [address2]);
};
The same applies for test:
let's say:
var myContract = await SafeHubPresale.new(accounts[1], accounts[2], {from: accounts[0], gas: 0});
For those in Remix, select the drop down next to "deploy" and you will need to provide a "to" & "from" address for this to work
In your smart contract, more than one argument may present and cannot fulfill its value when you deploy. When you deploy you take these values and call deploy() it's working correctly.
In your constructor
constructor(address _safuFactoryAddress, address _safuDevAddress)
more than one address value present there you may not provide this value when you deploy.

Web3 | TransferFrom() transactions always Failed

I'm trying to send Custom ERC20 Token to Owner Wallet Address using transferFrom() function using Web3.js
However all the Transactions are failed. Which is the same problem occur on Remix IDE.
Some answers on stackOverflow here says that the approve() is needed to call first before the transferFrom() function. so, I tried on Remix frist but I got the same problem. And then tried with using Web3.js like below.
const myContract = new web3.eth.Contract(abi);
const amount = sendAmount;
let address = myAddress;
myContract.options.address = contractAddress;
myContract.options.from = TokenOwner;
let options = myContract.options;
let data1 = myContract.methods.approve(address, amount).encodeABI();
let data2 = myContract.methods.transferFrom(address, TokenOwner, amount).encodeABI();
const ethAccount = fromPrivateKey(toBuffer("0x..."));
const fromPrivateKeyBuffer = ethAccount.getPrivateKey();
web3.eth.getTransactionCount(TokenOwner, (err, count) => {
if (err) return;
const txData = {
chainId: 0x03,
gasPrice: web3.utils.toHex(42000000000),
gasLimit: web3.utils.toHex(90000),
to: contractAddress,
from: TokenOwner,
value: 0x0,
nonce: web3.utils.toHex(count),
data: data1
};
const tx = new ethTx(txData);
tx.sign(fromPrivateKeyBuffer);
const serializedTx = tx.serialize().toString("hex");
if (!serializedTx) {
return;
} else {
web3.eth.sendSignedTransaction(`0x${serializedTx}`, (err, MuiTXHash) => {
console.log("err : ", err, "Data1-MuiTXHash : ", MuiTXHash);
// START DATA2
web3.eth.getTransactionCount(TokenOwner, (err, count) => {
if (err) return;
const txData2 = {
chainId: 0x03,
gasPrice: web3.utils.toHex(42000000000),
gasLimit: web3.utils.toHex(90000),
to: contarctAddress,
from: TokenOwner,
value: 0x0,
nonce: web3.utils.toHex(count + 1),
data: data2
};
const tx2 = new ethTx(txData2);
tx2.sign(fromPrivateKeyBuffer);
const serializedTx2 = tx2.serialize().toString("hex");
if (!serializedTx2) {
return;
} else {
web3.eth.sendSignedTransaction(`0x${serializedTx2}`, (err, MuiTXHash2) => {
console.log("err : ", err, "Data2-MuiTXHash : ", MuiTXHash2);
});
}
});
// END DATA2
});
}
});
};
I got the two Transaction Hash return data and the TransferFrom() transaction is failed again.
What is the problem?
How can I make it success? I have to withdraw the custom ERC20 token from specific address to owner. so I have to use transferFrom() transaction.
Please let me know how to do. Thanks.
I guess the compiling on Remix had some errors so I created new solidity file with same code on it and deployed it. The new smart contract worked well and no errors occurred. The errors was not about my code. If someone's suffering like this problems, then create a new contract address and I don't recommend using 'At Address' on Remix. This is not work properly at all.
I was tried appove() + transferFrom () , allowance() on Solidity working well but on web3 not working error same as you
I guess the transferFrom function should be called by the spender (i.e the address to which the TokenOwner has approved to spend). So,
const txData2 = {
chainId: 0x03,
gasPrice: web3.utils.toHex(42000000000),
gasLimit: web3.utils.toHex(90000),
to: contarctAddress,
from: address, // spender's address
value: 0x0,
nonce: web3.utils.toHex(count + 1),
data: data2
};
And don't forget to use spender's privateKey to sign the txn and spender's address in getTransactionCount
Read Here : Ethereum Wiki
Hope it helps. :)