This is my Test file
const { assert } = require('chai');
const chaiAsPromised = require('chai-as-promised')
const MyToken = artifacts.require("Saubaan");
const MySwap = artifacts.require("MySwap");
require('chai')
.use(chaiAsPromised)
.should()
function tokens(n){
return web3.utils.toWei(n, 'ether')
}
contract('MySwap', (deployer, investor) => {
let token, myswap
before(async() =>{
token = await MyToken.new()
myswap = await MySwap.new()
await token.transfer(myswap.address,tokens('190000000'))
})
describe('MyToken deployment', async() => {
it('contract has a name', async() => {
const name = await token.name()
assert.equal(name , 'MyToken')
})
})
describe('MySwap deployment', async() => {
it('contract has a name', async() => {
const name = await myswap.name()
assert.equal(name , 'MySwap Ultimate Exchange')
})
it('contract has tokens', async() => {
let balance = await token.balanceOf(myswap.address)
assert.equal(balance.toString(), tokens('190000000'))
})
})
describe ('buyTokens()', async() => {
before( async() => {
result = await myswap.buyTokens({from: investor, value: web3.utils.toWei('1','ether')})
})
it('Allows user to instantly buy tokens from myswap for a fixed price ',async() => {
//check investor balance after purchase
let investorBalance = await token.balancrOf(investor)
assert.equal(investorBalance.toString(), tokens('100'))
//check myswap alance after purchase
let myswapBalance
myswapBalance = await token.balanceOf(myswap.address)
assert.equal(myswapBalance.toString(), tokens('99900'))
myswapbalance = await web3.eth.getBalance(myswap.address)
assert.equal(myswapBalance.toString(), web3.utils.toWei('1', 'ether'))
const event = result.logs[0].args
assert.equal(event.account,investor)
assert.equal(event.token, token.address)
assert.equal(event.amount.toString(), token('100').toString())
assert.equal(event.rate.toString(), '100')
})
})
describe ('sellTokens()', async() => {
let result
before( async() => {
// investor must approve the purchase
await token.approve(myswap.address, tokens('100'), {from: investor})
result = await myswap.sellTokens(tokens('100'), {from: investor})
})
it('Allows user to instantly sell tokens from myswap for a fixed price ',async() => {
// Check investro balance after purchase
let investorBalance = await token.balanceOf(investor)
assert.equal(investorBalance.toString(), tokens('100'))
})
})
})
This is my Exchange contract
pragma solidity 0.8.6;
import "./MyToken.sol";
contract MySwap {
string public name = "MySwap Ultimate Exchange";
Saubaan public token;
uint public rate = 100;
event TokenPurchased(
address account,
address token,
uint amount,
uint rate
);
constructor (Saubaan _token) public {
token = _token;
}
function buyTokens() public payable {
uint tokenAmount = msg.value*rate;
// Require that myswap has enough tokens
require(token.balanceOf(address(this)) >= tokenAmount);
// Transfer tokens to the user
token.transfer(msg.sender, tokenAmount );
// Emit an event
emit TokenPurchased(msg.sender, address(token), tokenAmount, rate);
}
function sellTokens(uint _amount) public payable {
//Calculate the amount of Ether to redeem
uint etherAmount = _amount / rate;
//perform sale
token.transferFrom(msg.sender, address(this), _amount);
payable(msg.sender).transfer(etherAmount);
}
}
This is my token contract
pragma solidity 0.8.6;
interface ERC20Interface{
function totalSupply() external view returns (uint256);
function balanceOf(address tokenOwner) external view returns (uint);
function allowance(address tokenOwner, address spender)
external view returns (uint);
function transfer(address to, uint tokens) external returns (bool);
function approve(address spender, uint tokens) external returns (bool);
function transferFrom(address from, address to, uint tokens) external
returns
(bool);
event Approval(address indexed tokenOwner, address indexed spender,
uint tokens);
event Transfer(address indexed from, address indexed to,
uint tokens);
}
contract Saubaan is ERC20Interface{
string public symbol;
string public name;
uint8 public decimals;
uint public _totalSupply;
mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowed;
constructor() public {
symbol = "SAU";
name = "Saubaan";
decimals = 2;
_totalSupply = 19000000000;
balances[msg.sender] = _totalSupply;
emit Transfer(address(0), 0x9fC33138878450a7475ff8b83028277a6BBc60DB,
_totalSupply);
}
function totalSupply() public view override returns (uint) {
return _totalSupply - balances[address(0)];
}
function balanceOf(address tokenOwner) public view override returns (uint
balance) {
return balances[tokenOwner];
}
function transfer(address to, uint tokens) public override returns (bool )
{
require(tokens <= balances[msg.sender]);
balances[msg.sender] = balances[msg.sender].sub(tokens);
balances[to] = balances[to].add(tokens);
emit Transfer(msg.sender, to, tokens);
return true;
}
function approve(address spender, uint tokens) public override returns
(bool ) {
allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
return true;
}
function transferFrom(address from, address to, uint tokens) public
override returns (bool ) {
require(tokens <= balances[from]);
require(tokens <= allowed[from][msg.sender]);
balances[from] = balances[from].sub(tokens);
allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens);
balances[to] = balances[to] + tokens;
emit Transfer(from, to, tokens);
return true;
}
function allowance(address tokenOwner, address spender) public override
view returns (uint ) {
return allowed[tokenOwner][spender];
}
using SafeMath for uint;
}
library SafeMath{
function sub(uint a, uint b) internal pure returns(uint){
assert(b <= a);
return a - b;
}
function add(uint a, uint b) internal pure returns(uint){
uint c = a + b;
assert(c >= a);
return c;
}
}
Now the problem is whenever i try to run truffle test it show me this error in console
Contract: MySwap
1) "before all" hook in "Contract: MySwap"
0 passing (1s)
1 failing
1) Contract: MySwap
"before all" hook in "Contract: MySwap":
Error: Invalid number of parameters for "undefined". Got 0 expected 1
I dont how to solve this error i have searched all over internet but i cannot find any solution . Somebody please help me as I am new to coding and stuff
Thanks in advance
Related
I will explain my app a bit.
1)user makes call
2)validating user request
3)save user info with call status "CREATED",
4)send it to the target user
5)once target user accepts Modify user info with call status "ACCEPTED",
6)Then send event to the sender that user accept the call and rest of logic to connect the user.
All this logic are working fine without any issue,but facing an issue which is very hard to reproduce.
ISSUE
If user A calls User B and user B calls User A at the same time
Both user get calls. I use a locking mechanism to avoid this race condition. Now issue is reduced drastically but let say if user A and user B calls at same time (precisely) The issue still appear.
import * as Redis from 'redis';
export class LockHandler {
private static instance: LockHandler;
private senderUserId: string;
private receiverUserId: string;
private redisClient: any;
private lockSuccessSender: any;
private lockSuccessReciever: any;
private lockKeySender: string;
private lockKeyReciever: string;
private constructor() {
const host = process.env.DISTRIBUTED_REDIS_LOCK_HANDLER_HOST;
let port = Number(process.env.DISTRIBUTED_REDIS_LOCK_HANDLER_PORT);
let password=process.env.DISTRIBUTED_REDIS_LOCK_HANDLER_PASSWORD
port = isNaN(port) ? 6379 : port;
// setTimeout(()=>{
// console.log(">>>>>>>REDIS createClient >>>>>")
// },0.035)
console.table({
port,
host
})
this.redisClient = Redis.createClient({
host,
port,
password
});
}
public static getInstance(): LockHandler {
if (!LockHandler.instance) {
LockHandler.instance = new LockHandler();
}
return LockHandler.instance;
}
public setSenderId(senderId: string): LockHandler {
this.senderUserId = senderId;
return this;
}
public setReceiverId(receiverId: string): LockHandler {
this.receiverUserId = receiverId;
return this;
}
public async acquireLock(): Promise<LockHandler | null> {
this.lockKeySender = `call-lock-${this.senderUserId}-${this.receiverUserId}`;
this.lockKeyReciever = `call-lock-${this.receiverUserId}-${this.senderUserId}`;
const lockValue = `${Date.now()}`;
this.lockSuccessSender = await new Promise((resolve, reject) => {
this.redisClient.set(this.lockKeySender, lockValue, 'NX', 'PX', 5000, (err, result) => {
if (err) {
reject(err);
}
resolve(result === 'OK');
});
});
this.lockSuccessReciever = await new Promise((resolve, reject) => {
this.redisClient.set(this.lockKeyReciever, lockValue, 'NX', 'PX', 5000, (err, result) => {
if (err) {
reject(err);
}
resolve(result === 'OK');
});
});
if (!this.lockSuccessSender || !this.lockSuccessReciever) {
//one of either User is busy
return null;
}
return this;
}
public releaseLock(): null {
if (!this.lockKeyReciever || !this.lockKeySender) return null;
this.redisClient.del(this.lockKeySender, (err) => {
if (err) {
console.error(`Error releasing lock for key ${this.lockKeySender}`);
}
});
this.redisClient.del(this.lockKeyReciever, (err) => {
if (err) {
console.error(`Error releasing lock for key ${this.lockKeyReciever}`);
}
});
return null;
}
}
This is my implementation for locking mechanism with redis.
public async save(entity: CallEntity): Promise<CallEntity> {
if (!entity) return null ;
const lockHandler = LockHandler.getInstance().setSenderId(entity.senderUserId).setReceiverId(entity.receiverUserId);
let lockedCallBuilder = await lockHandler.acquireLock();
if (!lockedCallBuilder) {
//means user is busy
return null;
}
try {
// just create user info with call status "CREATED"
return await this.repository.save(entity)
} catch (error) {
return null ;
} finally {
lockHandler.releaseLock();
}
}
This is how i save the user info.
Can anyone help me to achieve this ?
my question is about truffle, i would like to know if someone can help me.
I want to set a vote for one of that presidents, with the second account on ganache(Who deploy
the contract(address 0 in ganache) cannot vote).
During Test the error is: Error: Returned error: VM Exception while processing transaction:
revert
This are the contracts and test
1 - VotingToken.sol
```
//SPDX-License-Identifier: UNLICENSED
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "./Voting.sol";
import "./VotingInfo.sol";
pragma solidity ^0.8.4;
contract VotingToken is Ownable, ERC20{
Voting private voting;
VotingInfo private votingInfo;
string private _name;
string private _symbol;
uint private _totalSupply;
mapping(address=>uint)private _balances;
modifier onlyVoting(){
msg.sender == address(voting);
_;
}
constructor(string memory name, string memory symbol, uint totalSupply)ERC20(name, symbol){
_totalSupply = totalSupply;
_mint(msg.sender, _totalSupply);
_balances[msg.sender] = _totalSupply;
_name = name;
_symbol = symbol;
}
function initVotingContract(address _votingAddress)public onlyOwner{
voting = Voting(_votingAddress);
}
function initVotingInfoContract(address _votingInfoContract)public onlyOwner{
votingInfo = VotingInfo(_votingInfoContract);
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual override{
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function withdraw()external{
require(msg.sender != owner(), "Contract Owner cannot withdraw!");
require(votingInfo.getWhitdrawStatus(msg.sender) == false, "Already withdrawed!");
uint settedAmount = 1;
votingInfo.setWithdrawedHappen(msg.sender);
_transfer(owner(), msg.sender, settedAmount);
emit Transfer(owner(), msg.sender, settedAmount);
}
function tokenAmountAfterVotation(address voter)external onlyVoting{
_balances[voter] -= 1;
}
function balanceOf(address account) public view virtual override returns (uint256){
return _balances[account];
}
function name()public view virtual override returns(string memory){
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function totalSupply()public view virtual override returns(uint){
return _totalSupply;
}
function getVotingContractAddress()public view returns(address){
return address(voting);
}
function getVotingInfoContractAddress()public view returns(address){
return address(votingInfo);
}
} ```
2 - Voting.sol
```
//SPDX-License-Identifier: UNLICENSED
import "#openzeppelin/contracts/access/Ownable.sol";
import "./VotingToken.sol";
pragma solidity ^0.8.4;
contract Voting is Ownable{
VotingToken private votingToken;
VotingInfo private votingInfo;
enum Presidents{Obama, Trump, Biden}
event FinalResult(
string firstCandidate,
uint finalVoteFirst,
string secondCandidate,
uint finalVoteSecond,
string thirdCandidate,
uint finalVoteThird
);
mapping(Presidents=>uint) private Counter;
constructor(){
}
function initVotingTokenContract(address _votingTokenAddress)public onlyOwner{
votingToken = VotingToken(_votingTokenAddress);
}
function initVotingInfoContract(address _votingInfoContract)public onlyOwner{
votingInfo = VotingInfo(_votingInfoContract);
}
function votingObama()external{
require(votingToken.balanceOf(msg.sender) > 0, "Don't have tokens to vote!");
require(votingInfo.getUserVotationStatus(msg.sender) != true, "Already made your preference!");
require(msg.sender != owner(), "Admin cannot vote!");
votingInfo.setVoteHappen(msg.sender);
votingToken.tokenAmountAfterVotation(msg.sender);
Counter[Presidents.Obama] += 1;
}
function votingTrump()external{
require(votingToken.balanceOf(msg.sender) > 0, "Don't have tokens to vote!");
require(votingInfo.getUserVotationStatus(msg.sender) != true, "Already made your preference!");
require(msg.sender != owner(), "Admin cannot vote!");
votingInfo.setVoteHappen(msg.sender);
votingToken.tokenAmountAfterVotation(msg.sender);
Counter[Presidents.Trump] += 1;
}
function votingBiden()external{
require(votingToken.balanceOf(msg.sender) > 0, "Don't have tokens to vote!");
require(votingInfo.getUserVotationStatus(msg.sender) != true, "Already made your preference!");
require(msg.sender != owner(), "Admin cannot vote!");
votingInfo.setVoteHappen(msg.sender);
votingToken.tokenAmountAfterVotation(msg.sender);
Counter[Presidents.Biden] += 1;
}
function getVotingResult()public onlyOwner{
emit FinalResult(
"Obama's Final Count ",
Counter[Presidents.Obama],
"Trump's Final Count ",
Counter[Presidents.Trump],
"Biden's Final Count ",
Counter[Presidents.Biden]
);
}
function getVotingTokenContract()public view returns(address){
return address(votingToken);
}
function getVotingInfoContract()public view returns(address){
return address(votingInfo);
}
}
```
3 - VotingInfo.sol
```
//SPDX-License-Identifier: UNLICENSED
import "#openzeppelin/contracts/access/Ownable.sol";
import "./Voting.sol";
import "./VotingToken.sol";
pragma solidity ^0.8.4;
contract VotingInfo is Ownable{
Voting voting;
VotingToken votingToken;
mapping(address=>bool)private votedAlready;
mapping(address=>bool)private withdrawHappen;
modifier onlyVoting{
msg.sender == address(voting);
_;
}
modifier onlyVotingToken{
msg.sender == address(votingToken);
_;
}
constructor(){
}
function initVotingContract(address _votingAddress)public onlyOwner{
voting = Voting(_votingAddress);
}
function setVoteHappen(address voter)public onlyVoting{
votedAlready[voter] = true;
}
function getUserVotationStatus(address voter)public view returns(bool){
return votedAlready[voter];
}
function setWithdrawedHappen(address voter)public onlyVotingToken{
withdrawHappen[voter] = true;
}
function getWhitdrawStatus(address voter)public view returns(bool){
return withdrawHappen[voter];
}
}
```
Test Starting here...
4 - VotingTokenTest.js
```
const Voting = artifacts.require("Voting");
const VotingInfo = artifacts.require("VotingInfo");
const VotingToken = artifacts.require("VotingToken");
contract("Voting Token", function(accounts){
it("Should initialize Voting Contract", async () => {
let deployerAccount = accounts[0];
let instance = await VotingToken.deployed();
await instance.initVotingContract(Voting.address);
let deployer = await instance.owner();
let addresssVoting = await instance.getVotingContractAddress();
assert.equal(addresssVoting, Voting.address);
assert.equal(deployerAccount, deployer);
console.log("Result is :")
console.log("Voting Address Setted ", addresssVoting);
console.log("Voting Address Deployed ", Voting.address);
})
it("Should initialize VotingInfo Contract", async () => {
let deployerAccount = accounts[0];
let instance = await VotingToken.deployed();
await instance.initVotingInfoContract(VotingInfo.address);
let deployer = await instance.owner();
let addressVotingInfo = await instance.getVotingInfoContractAddress();
assert.equal(addressVotingInfo, VotingInfo.address);
assert.equal(deployerAccount, deployer);
console.log("Result is :");
console.log("VotingInfo Address Setted ", addressVotingInfo);
console.log("VotingInfo Address Deployed ", VotingInfo.address);
})
it("Check some rest ", async () => {
let instance = await VotingToken.deployed();
let name = await instance.name();
let symbol = await instance.symbol();
let totalSupply = await instance.totalSupply();
assert.equal(name, "BABA");
assert.equal(symbol, "ABBA");
assert.equal(totalSupply, 10000);
console.log("Name => ", name)
console.log("Symbol => ", symbol)
console.log("Supply => ", parseFloat(totalSupply));
})
it("Withdraw token to partecipate at the votation", async () => {
let instance = await VotingToken.deployed();
let instanceVotingInfo = await VotingInfo.deployed();
await instance.withdraw({from: accounts[1]});
await instanceVotingInfo.setWithdrawedHappen(accounts[1]);
let getWithdrawStatus = await instanceVotingInfo.getWhitdrawStatus(accounts[1]);
let owner = await instance.owner();
let balanceSender = await instance.balanceOf(accounts[1]);
let ownerBalance = await instance.balanceOf(owner);
assert.equal(balanceSender, 1);
assert.equal(ownerBalance, 9999);
assert.equal(getWithdrawStatus, true);
console.log("Withdraw Status", getWithdrawStatus);
console.log("Sender Balance ", parseFloat(balanceSender));
console.log("Owner Balance ", parseFloat(ownerBalance));
})
})
```
```const Voting = artifacts.require("Voting");
const VotingInfo = artifacts.require("VotingInfo");
const VotingToken = artifacts.require("VotingToken");
contract("Voting Contract", function(accounts){
it("Should initialize correctly Voting token Contract", async()=>{
let deployerAccount = accounts[0];
let instance = await Voting.deployed();
await instance.initVotingTokenContract(VotingToken.address);
let deployer = await instance.owner();
let addressVotingToken = await instance.getVotingTokenContract();
assert.equal(addressVotingToken, VotingToken.address);
assert.equal(deployerAccount, deployer);
console.log("VotingToken Address Correct!");
})
it("Should initialize correctly VotingInfo Contract", async()=>{
let deployerAccount = accounts[0];
let instance = await Voting.deployed();
let deployer = await instance.owner();
await instance.initVotingInfoContract(VotingInfo.address);
let addressVotingInfoContract = await instance.getVotingInfoContract();
assert.equal(addressVotingInfoContract, VotingInfo.address);
assert.equal(deployerAccount, deployer);
console.log("VotingInfo Address Correct!");
})
it("Should set a vote for Obama", async()=>{
let instance = await Voting.deployed();
let votingInfoInstance = await VotingInfo.deployed();
let votingTokenInstance = await VotingToken.deployed();
await instance.initVotingTokenContract(VotingToken.address);
await instance.initVotingInfoContract(VotingInfo.address);
await votingTokenInstance.withdraw({from:accounts[1]});
await instance.votingObama({from: accounts[1]});
await votingInfoInstance.setVoteHappen(accounts[1]);
await votingTokenInstance.tokenAmountAfterVotation(accounts[1]);
===========>>>>> ERROR IS HERE <<<<<===========
})
})```
Initially i was thinking about a problem refer to the _transfer function in the
VotingToken.sol, maybe something like the accounts who call the withdraw function, doesn't
"receive" an allowance to spend that token, but the point now is the Error looks so generic
and i'm bit stuck on that.
Can someone help me to fix it? thanks in advice and have a good day
The total code is here in my gist
https://gist.github.com/supersuperrookie/0cd4584c691c88af9aaa43d67fb730cd
I created a smart contract which has the below function,
function execute() public checkExternalStatus checkDeadline(false) {
uint256 balanceAmount = address(this).balance;
require(balanceAmount > threshold, "threshold is not reached");
(bool sent, ) = address(exampleExternalContract).call{
value: balanceAmount
}(abi.encodeWithSignature("complete()"));
require(sent, "exampleExternalContract.complete failed");
}
and when I test this method like this, i do not know why stakerContractbalance is 0 (★)
it('external contract sucessfully completed', async() => {
const amount = ethers.utils.parseEther('1.1');
await stakerContract.connect(addr1).stake({
value :amount,
});
await stakerContract.connect(addr1).execute();
const competed = await exampleExternalContract.completed();
expect(competed).to.equal(true);
const externalBalance = await ethers.provider.getBalance(exampleExternalContract.address);
expect(externalBalance).to.equal(amount);
const stakerContractbalance = await ethers.provider.getBalance(stakerContract.address);
--(★)confuing witch this line(why stakerContractbalance is 0?)
expect(stakerContractbalance).to.equal(0);
});
I have simple smartcontract:
pragma solidity ^0.7.0;
contract Token {
string public name = "My Hardhat Token";
string public symbol = "MHT";
uint256 public totalSupply = 1000000;
address public owner;
mapping(address => uint256) balances;
constructor() {
balances[msg.sender] = totalSupply;
owner = msg.sender;
}
function transfer(address to, uint256 amount) external {
require(balances[msg.sender] >= amount, "Not enough tokens");
balances[msg.sender] -= amount;
balances[to] += amount;
}
function balanceOf(address account) external view returns (uint256) {
return balances[account];
}
}
I take this contract from
And I have successfully compiled and uploaded this smart contract to the ropsten testnet. I use hardhat frameworc for this actions.
https://hardhat.org/tutorial/deploying-to-a-live-network.html
After that, I wrote a script that should receive the balance, perform the transfer and create transactions.
var provider = "https://eth-ropsten.alchemyapi.io/v2/iwxxx";
var Web3 = require('web3');
var web3 = new Web3(new Web3.providers.HttpProvider(provider));
const abi = [{...}];
const address = "0xC1xxx"; // after deploy smart contract
const senderAddress = "0x2bxxx";
const receiverAddress = "0x39xxx";
const privKey = "0xf5xxx";
const token = new web3.eth.Contract(abi, address);
token.setProvider(web3.currentProvider)
token.methods.balanceOf(address).call( (err, res) => { console.log("Address Balance: ", res); }); // 0
token.methods.balanceOf(senderAddress).call((err, res) => { console.log("SenderAddress Balance: ", res); }); // 0
token.methods.transfer(receiverAddress, "1").send({ "from": address }, (err, res) => {
if (err) {console.log("Error occured ! ", err);return}
console.log("Hash transaction: " + res);
});
send_tr();
async function send_tr(){
let transactionNonce = await web3.eth.getTransactionCount(senderAddress);
let raw = {"to":receiverAddress, "value":"1", "gas":2000000, "nonce":web3.utils.toHex(transactionNonce)};
const signedTx = await web3.eth.accounts.signTransaction(raw, privKey);
await web3.eth.sendSignedTransaction(signedTx.rawTransaction, (err, ret) => {
if (err) {console.log("An error occurred", err);return;}
console.log("Success, txHash is: ", ret);
});
}
The question is why my balance is zero even though the contract is underdeployed?
the transaction at the end is successful (as far as I understand, the transaction is needed so that the tokens transferred from address to address are successfully transferred)
In the solidity constructor, you're setting the balance of the deployer address - not of the contract address.
constructor() {
balances[msg.sender] = totalSupply;
owner = msg.sender;
}
But then in the JS script, you're asking about balance of the contract address.
const token = new web3.eth.Contract(abi, address);
token.methods.balanceOf(address)
A basic contract to check the balance of your smart contract
//contract Balance {
// address owner;
// mapping(address => uint) balance;
//
// constructor () {
// owner = msg.sender;
// }
// function retBal() public view returns (uint) {
// return (balance[owner]);
// }
// }
I'm having a problem executing my smart contract. From the error code, I figured it is must be a gas limit problem, although I don't know where I would place the code in order for it to execute properly. Any suggestions?
Solidity code:
pragma solidity ^0.8.0;
import 'hardhat/console.sol';
contract WavePort {
//TrackWaves
uint totalWaves; //State Variable, Permanetly Stored In Contract Storage
constructor() {
console.log("Yo, I am I contract");
}
//Function Increments Waves On The Blockchain/ Immutable Never Decreasing
function wave() public {
totalWaves += 1;
console.log("%s has waved!", msg.sender);
}
//Function Returns Us the The Total Waves To Be Viewed
function getTotalWaves()public view returns(uint256) {
console.log("We have %d total waves", totalWaves);
return totalWaves;
}
}
JavaScript code:
const App = () => {
const [currentAccount, setCurrentAccount] = useState("")
const contractAddress = "contractAddress"
const contractABI = abi.abi
const checkIfWalletConnected = async () => {
let web3
try {
const {ethereum} = window;
if(!ethereum) {
window.alert("Make sure you have metamask !");
return;
}else {
web3 = new Web3(window.ethereum)
console.log("We have the ethereum object", ethereum)}
const accounts = await ethereum.request({method: 'eth_accounts'})
if(accounts.length !== 0) {
const account = accounts[0]
console.log("Found an Authorized account:", account, );
setCurrentAccount(account)
} else {
window.alert("NO authorized account found")
}
const EthBalance = await web3.eth.getBalance(accounts[0])
console.log(EthBalance)
}catch(err) {console.log(err)}
}
const connectWallet = async () => {
try {
const {ethereum} = window;
if(!ethereum) {alert("Get Metamask extenstion")
return
} else {
const accounts = await ethereum.request({method: 'eth_accounts'})
console.log("Connected", accounts[0])
window.alert("Wallet is Connected")
setCurrentAccount(accounts[0])
const ethBlance = await Web3.eth.getBalance(currentAccount)
console.log(ethBlance)
}
}catch(err) {
console.log(err)
}
}
const wave = async () => {
try {
const {ethereum} = window;
if(ethereum) {
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const wavePortalContract = new ethers.Contract(contractAddress, contractABI, signer);
let count = await wavePortalContract.getTotalWaves( );
const waveTxn = await wavePortalContract.wave({gas:10000000 }, {gasPrice:80000000000});
console.log("Mining....", waveTxn.hash)
await waveTxn.wait( );
console.log("Mined-- ", waveTxn.hash)
count = await await wavePortalContract.getTotalWaves( );
console.log("Retrieved total wave count.. ", count.toNumber())
}else {
console.log("Eth Object doesn't exist!")
}
} catch(err) {console.log(`${err} hello world`) }
}
useEffect(() => {
checkIfWalletConnected();
}, [])
The error code I get:
Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"code":-32000,"message":"execution reverted"}, method="call", transaction={"from":"0xD49a9a33F180D1e35A30F0ae2Dbfe5716a740Ebc","to":"0x5FbDB2315678afecb367f032d93F642f64180aa3","data":"0x9a2cdc08","accessList":null}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.5.1)
While calling a contract Abi method, you can pass an object of additional gas-related params in the second argument (or first if you don't have any arguments in your method).
So calling of wave function should looks like following:
const waveTxn = await wavePortalContract.wave({gasLimit:30000});
Check all additional params in the below documentation.
https://docs.ethers.io/v5/api/contract/contract/#contract-functionsSend