I'm trying to listen a specific event in USDT smartcontract on Tron blockchain. I want to update a database when a payment has been made to my address.
In order to do that, I use TronWeb. Here is my code :
const fullNode = 'https://api.shasta.trongrid.io';
const solidityNode = 'https://api.shasta.trongrid.io';
const eventServer = 'https://api.shasta.trongrid.io';
const tronweb = new Tronweb(fullNode,solidityNode,eventServer);
let contract = await tronweb.contract().at('TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs')
let watchTest = await contract.Transfer().watch({filters{"to":"TGdMonBPqH9THEhgNxMtHEcnxgbXxUuXeX"}},(err, res) => {
if(res) {
console.log(res)
}
})
However, this code is printing every event emmited by the smart contract (not only the transfer to my address).
I'm looking for an equivalent of the following code with ethereum blokchain and ethers.js librairy :
let contract = new ethers.Contract(contractAddress, abi, provider);
let filter=contract.filters.Transfer(null, payment.PublicAddress);
provider.on(filter,async (log) => {})
What's the correct way to do that ?
I was trying to deploy my smart contract through unit testing using hardhat. The owner upon deployment is being returned as 0x0000.. although when writing my js script i assign a certain address from the hardhat network as the owner.
const hre = require('hardhat')
const { expect, assert } = require('chai')
describe('ProperSubsetFund', async function () {
// Initialize Contract Var
let deployERC20, deployer, user1, user2, trader1, trader2
let signers
beforeEach(async function () {
// Getting all the signers
signers = await hre.ethers.getSigners()
// console.log(signers.map(item => item.address));
// Assign addresses to roles for later use
deployer = signers[0].address
user1 = signers[1].address
user2 = signers[2].address
trader1 = signers[3].address
trader2 = signers[4].address
// Read Contract ERC20
const contractERC20 = await hre.ethers.getContractFactory('ProperSubsetERC20')
// Read Contract Launchpad
const contractLaunchpad = await hre.ethers.getContractFactory('ProperSubsetFactory')
// Read Contract Funds
const contractFunds = await hre.ethers.getContractFactory('ProperSubsetFund')
// Deploy the three contracts
deployERC20 = await contractERC20.connect(signers[0]).deploy(true)
});
describe('Deployment and Ownership', function () {
it('Check if the owner is the deployer', async function () {
expect(await deployERC20.owner()).to.equal(deployer)
});
});
})
These are the results
ProperSubsetFund
Deployment and Ownership
Deployment
Should set the right owner:
AssertionError: expected '0x00000000000000000000000000000000000…' to equal '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb…'
+ expected - actual
-0x0000000000000000000000000000000000000000
+0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
at Context.<anonymous> (test/ProperSubsetFund.test.js:71:49)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
Hardhat is not returning address(0), your contract owner() is returning address(0). If you read the terminal it says
AssertionError: expected '0x00000000000000000000000000000000000…' to equal '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb…'
since you set this:
expect(await deployERC20.owner()).to.equal(deployer)
your deployer address by hardhat is '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb…'. But deployERC20.owner() is '0x00000000000000000000000000000000000…'
So the plan is to make a basic nft marketplace in which you can buy with eth and with a custom token, the eth part works but I haven´t been able to make the custom token part work.
The token is already deployed to the mainnet, the nft marketplace will make use of it, so I forked the ethereum mainnet with hardhat so I could interact with it.
This is the buy with eth function:
function purchaseItemWithEth(uint _itemId) external payable nonReentrant {
uint _totalPrice = getTotalPrice(_itemId);
Item storage item = items[_itemId];
require(_itemId > 0 && _itemId <= itemCount, "item doesn't exist");
require(msg.value >= _totalPrice, "not enough ether to cover item price and market fee");
require(!item.sold, "item already sold");
// pay seller and feeAccount
item.seller.transfer(item.price);
feeAccount.transfer(_totalPrice - item.price);
// update item to sold
item.sold = true;
// transfer nft to buyer
item.nft.transferFrom(address(this), msg.sender, item.tokenId);
// emit Bought event
emit Bought(
_itemId,
address(item.nft),
item.tokenId,
item.price,
item.priceOsaku,
item.seller,
msg.sender
);
}
In theory, with the purchase with custom token function I would only need to change the token that is being sent, use the token instead of eth, so I made this:
function purchaseItemWithToken(uint _itemId) external payable nonReentrant {
uint _totalPrice = getTotalPriceWithToken(_itemId;
Item storage item = items[_itemId];
require(_itemId > 0 && _itemId <= itemCount, "item doesn't exist");
//require(msg.value >= _totalPrice, "not enough ether to cover item price and market fee");
require(!item.sold, "item already sold");
//pay seller and fee account
depositTokens(10);
sendTokens(item.seller, item.pricewithToken);
sendTokens(feeAccount, (_totalPrice - item.pricewithToken));
// update item to sold
item.sold = true;
// transfer nft to buyer
item.nft.transferFrom(address(this), msg.sender, item.tokenId);
// emit Bought event
emit Bought(
_itemId,
address(item.nft),
item.tokenId,
item.price,
item.priceToken,
item.seller,
msg.sender
);
}
function getTotalPrice(uint _itemId) view public returns(uint){
return((items[_itemId].price*(100 + feePercent))/100);
}
function getTotalPriceToken(uint _itemId) view public returns(uint) {
return((items[_itemId].priceToken*(100 + feePercent))/100);
}
function depositTokens(uint _amount) public {
ERC20(_token).transferFrom(msg.sender, address(this), _amount);
}
function sendTokens(address _to, uint _amount) public {
ERC20(_token).transfer(_to, _amount);
}
function getTokenSmartContractBalance() external view returns(uint) {
return ERC20(_token).balanceOf(address(this));
}
Buy it doesn't work.
I tried approving the token before the transferFrom function is called like this:
const name = await tokenContract.name()
const approve = await tokenContract.connect(Buyer1Wallet).approve(publicKeyBuyer1, 1000000000)
const approveMarketplace = await osakuContract.connect(Buyer1Wallet).approve('0xe8f7d98be6722d42f29b50500b0e318ef2be4fc8', 1000000000)
console.log(approve)
console.log(`${name} approved`)
But I get the error "not enough ether to cover item price and market fee" which is defined as one of the requires of the purchaseItem function.
It mentions it even though before approving I bought 1 eth worth of tokens via uniswap with this:
const apeBuyer1 = await uniswapContract.connect(Buyer1Wallet).swapExactETHForTokensSupportingFeeOnTransferTokens(
99,
PAIR_ADDRESS,
publicKeyBuyer1,
Date.now() + 1000 * 60 * 5,
{
value: ethers.utils.parseUnits(String(1), "ether"),
gasLimit: 1000000,
gasPrice: ethers.utils.parseUnits(String(50), "gwei"),
}
)
let receipt3 = await apeBuyer1.wait()
console.log(`Buyer1 Bought: ${receipt3.transactionHash}`);
I don't know why it says it doesn't have enough balance when I a lot more than necessary for the function to run.
All help is appreciated, thank you beforehand.
I am trying to follow the Chainlink VRF tutorial found here: https://docs.chain.link/docs/intermediates-tutorial/ with hardhat and am running into this issue when calling the rollDice function:
Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"reason":"cannot estimate gas; transaction may fail or may require manual gas limit","code":"UNPREDICTABLE_GAS_LIMIT","method":"estimateGas","transaction":{"from":"0x014Da1D627E6ceB555975F09D26B048644382Ac6","maxPriorityFeePerGas":{"type":"BigNumber","hex":"0x9502f900"},"maxFeePerGas":{"type":"BigNumber","hex":"0x9502f90e"},"to":"0x5887946875A01D1BB79d6Fb357BceeA5A0096D2e","data":"0xdd02d9e5000000000000000000000000014da1d627e6ceb555975f09d26b048644382ac6","type":2,"accessList":null}}, tx={"data":"0xdd02d9e5000000000000000000000000014da1d627e6ceb555975f09d26b048644382ac6","to":{},"from":"0x014Da1D627E6ceB555975F09D26B048644382Ac6","type":2,"maxFeePerGas":{"type":"BigNumber","hex":"0x9502f90e"},"maxPriorityFeePerGas":{"type":"BigNumber","hex":"0x9502f900"},"nonce":{},"gasLimit":{},"chainId":{}}, code=UNPREDICTABLE_GAS_LIMIT, version=abstract-signer/5.5.0)
at Logger.makeError (/Users/matt/Desktop/hardhat/randomDay/node_modules/#ethersproject/logger/src.ts/index.ts:225:28)
at Logger.throwError (/Users/matt/Desktop/hardhat/randomDay/node_modules/#ethersproject/logger/src.ts/index.ts:237:20)
at /Users/matt/Desktop/hardhat/randomDay/node_modules/#ethersproject/abstract-signer/src.ts/index.ts:301:31
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Promise.all (index 7)
I am able to deploy to the Kovan testnet, I was able to verify the contract, and I have sent the contract LINK tokens, but am still running into the issue. The contract can be viewed here: https://kovan.etherscan.io/address/0x7b72d80670512c87605ab8ac7e6113fda9c57de4#code
I am using version 0.8 of the Chainlink Contracts.
RandomDay.sol
pragma solidity ^0.8.9;
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
contract RandomDay is VRFConsumerBase {
uint256 private constant ROLL_IN_PROGRESS = 42;
bytes32 private s_keyHash;
uint256 private s_fee;
mapping(bytes32 => address) private s_rollers;
mapping(address => uint256) private s_results;
event DiceRolled(bytes32 indexed requestId, address indexed roller);
event DiceLanded(bytes32 indexed requestId, uint256 indexed result);
constructor(address vrfCoordinator, address link, bytes32 keyHash, uint256 fee) VRFConsumerBase(vrfCoordinator, link) {
s_keyHash = keyHash;
s_fee = fee;
}
function rollDice (address roller) public returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) >= s_fee, "Not enough LINK to pay fee");
require(s_results[roller] == 0, "Already rolled");
requestId = requestRandomness(s_keyHash, s_fee);
s_rollers[requestId] = roller;
s_results[roller] = ROLL_IN_PROGRESS;
emit DiceRolled(requestId, roller);
return requestId;
}
function fulfillRandomness (bytes32 requestId, uint256 randomness) internal override {
uint256 dayOfWeek = (randomness % 7) + 1;
s_results[s_rollers[requestId]] = dayOfWeek;
emit DiceLanded(requestId, dayOfWeek);
}
function weekday (address player) public view returns (string memory) {
require(s_results[player] != 0, "Dice not rolled");
require(s_results[player] != ROLL_IN_PROGRESS, "Roll in progress");
return getWeekdayName(s_results[player]);
}
function getWeekdayName (uint256 id) private pure returns (string memory) {
string[7] memory weekdays = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
return weekdays[id - 1];
}
}
hardhat.config.js
/**
* #type import('hardhat/config').HardhatUserConfig
*/
require("#nomiclabs/hardhat-waffle")
require("#nomiclabs/hardhat-etherscan")
const ALCHEMY_API_KEY = "*************************";
const ROPSTEN_PRIVATE_KEY = "*********************";
module.exports = {
solidity: "0.8.9",
networks: {
kovan: {
url: `https://eth-kovan.alchemyapi.io/v2/${ALCHEMY_API_KEY}`,
accounts: [`0x${ROPSTEN_PRIVATE_KEY}`],
gas: 2700000000,
maxFeePerGas: 30000000000,
}
},
etherscan: {
// Your API key for Etherscan
// Obtain one at https://etherscan.io/
apiKey: "****************************"
}
};
deploy.js
const { ethers } = require("hardhat");
async function main() {
const [deployer] = await ethers.getSigners();
console.log("Deploying contracts with the account:", deployer.address);
console.log("Account balance:", (await deployer.getBalance()).toString());
const Token = await ethers.getContractFactory("RandomDay");
const token = await Token.deploy("0xa36085F69e2889c224210F603D836748e7dC0088", "0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9", "0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4", "100000000000000000");
console.log("Token address:", token.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
quickRun.js
var ethers = require('ethers');
var provider = ethers.providers.getDefaultProvider('kovan');
var address = '0x7b72d80670512c87605aB8aC7E6113Fda9c57de4';
var abi = [{"inputs":[{"internalType":"address","name":"vrfCoordinator","type":"address"},{"internalType":"address","name":"link","type":"address"},{"internalType":"bytes32","name":"keyHash","type":"bytes32"},{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"result","type":"uint256"}],"name":"DiceLanded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"roller","type":"address"}],"name":"DiceRolled","type":"event"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"rawFulfillRandomness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"roller","type":"address"}],"name":"rollDice","outputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"weekday","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}];
var privateKey = '*******************************';
var wallet = new ethers.Wallet(privateKey, provider);
var contract = new ethers.Contract(address, abi, wallet);
var sendPromise = contract.rollDice('0x014Da1D627E6ceB555975F09D26B048644382Ac6');
sendPromise.then(function(transaction){
console.log(transaction);
});
I believe the addresses are off:
Constructor Arguments of your contract:
-----Decoded View---------------
Arg [0] : vrfCoordinator (address): 0xa36085f69e2889c224210f603d836748e7dc0088
Arg [1] : link (address): 0xdd3782915140c8f3b190b5d67eac6dc5760c46e9
Arg [2] : keyHash (bytes32): 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4
Arg [3] : fee (uint256): 100000000000000000
Via Chainlinks Docs:
LINK 0xa36085F69e2889c224210F603D836748e7dC0088
VRF Coordinator 0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9
Key Hash 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4
Fee 0.1 LINK
Switched Link and VRF are probably the culprit.
9 out of 10 is because you passed something wrong in the constructor or something in the contructor is not initialized propertly. this kind of things aren't detected by compiler.
I have created a test contract which has been compiled successfully and want to broadcast on ropsten test network using web3js. I have a metmask account which i am using. I would like to know how can i call constructor of my contract and then broadcast on ropsten.
I did broadcast one of my contract without constructor and do have my transaction hash key which is 0xf7e5a8e93db9989b033b85323cdff713ba88b547ef64a544550e145961999aac but i am getting a following error Error encountered during contract execution [Reverted] and Transaction has been reverted by the EVM on console. I would like to know also why i am getting this error after broadcast has been done
const fs = require('fs')
var Tx = require('ethereumjs-tx').Transaction
const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/v3/KEY')
deploy()
function deploy () {
const privateKey = 'PRIVATE_KEY'
const account1 = 'ACCOUNT_NUMBER'
const privateKey1 = Buffer.from(privateKey, 'hex')
const contractData = fs.readFileSync('../../build/contracts/Testcontract.json')
const contract = JSON.parse(contractData)
const byteCode = contract['bytecode']
web3.eth.getTransactionCount(account1, (err, txCount) => {
const txObject = {
nonce: web3.utils.toHex(txCount),
gasLimit: web3.utils.toHex(100000),
gasPrice: web3.utils.toHex(web3.utils.toWei('0.004', 'gwei')),
data: byteCode
}
let tx = new Tx(txObject, {'chain':'ropsten'})
tx.sign(privateKey1)
const serializedTx = tx.serialize()
const raw = '0x' + serializedTx.toString('hex')
web3.eth.sendSignedTransaction(raw, (err, txHash) => {
console.log('err: ', err, 'txHash: ', txHash)
})
})
}
My contract with constructor looks like this
pragma solidity ^0.5.11;
contract Testcontract {
string public senderName;
string public receiverName;
uint public transferAmount;
constructor (string memory _sender, string memory _receiver, uint _amount) public {
senderName = _sender;
receiverName = _receiver;
transferAmount = _amount;
}
}
UPDATE
A simple way to deploy a contract through an Infura node is using Truffle. In your project's root directory
$ npm install truffle
$ truffle init
Here is a tutorial on how to configure Truffle to use your Infura project. In short, install Truffle's hd-wallet-provider
$ npm install #truffle/hdwallet-provider
Replace truffle-config.js with
const HDWalletProvider = require("#truffle/hdwallet-provider");
const mnemonic = "orange apple banana...";
module.exports = {
networks: {
ropsten: {
provider: () => new HDWalletProvider(mnemonic, 'https://ropsten.infura.io/v3/<YOUR INFURA PROJECT ID>'),
network_id: 3, // Ropsten's id
},
},
compilers: {
solc: {
version: "0.5.11", // Fetch exact version from solc-bin (default: truffle's version)
}
}
}
The previous code configures Truffle to connect to Infura an use your account. In ./migrations directory (created by truffle init) create a new file 2_deploy_testContrac.js where you can define how to deploy your contract and provide the arguments needed by TestContract.
var TestContract = artifacts.require("./TestContract");
module.exports = function(deployer) {
deployer.deploy(TestContract, "AliceSender", "BobSender", 120);
}
Finally, deploy your contract by executing
$ truffle migrate --network ropsten
The reason why your transaction has been reverted is because the constructor of TestContract expected three arguments but you have given zero. Since the constructor couldn't be executed, your deploying transaction was reverted as well.
Instead of manually creating your deploying transaction, you can use web3.eth.Contract.deploy. With this method you can conveniently provide all parameters required by the contract's constructor.
UPDATE: The solution below won't work with Infura because the Infura API does not expose web3.eth.personal functions and it only allows sending rawTranscations.
You should be able to deploy your contract with the following code. Note that it was mainly copy-pasted from the official web3 documentation.
var contractData = fs.readFileSync('../../build/contracts/Testcontract.json');
var contract = JSON.parse(contractData);
var abi = contract['abi'];
var bytecode = contract['bytecode'];
var testContract = eth3.eth.Contract(abi);
var account = ...;
var password = ...;
web3.eth.personal.unlockAccount(account, password);
testContract.deploy({
data: bytecode,
arguments: ['SenderAlice', 'ReceiverBob', 120]
})
.send({
from: account,
gas: 1500000,
gasPrice: '30000000000000'
}, function(error, transactionHash){
console.log(error, transactionHash);
})
.on('error', function(error){
console.log(error);
})
.on('transactionHash', function(transactionHash){
console.log(transactionHash);
})
.on('receipt', function(receipt){
console.log(receipt.contractAddress) // contains the new contract address
})
.on('confirmation', function(confirmationNumber, receipt){
console.log(confirmationNumber, transactionHash);
})
.then(function(newContractInstance){
console.log(newContractInstance.options.address) // instance with the new contract address
});