Add liquidity to Uniswap pool with Web3 - web3js

I am trying to add liquidity to Uniswap on the Ropsten network using Web3.
My JavaScript code is as follows:
(async () => {
console.log("account: ", this.state.account);
const deployedContract = await new web3.eth.Contract(
UniswapRouter02Contract.abi,
"0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"
);
console.log(web3.currentProvider);
console.log("pair address ", this.state.pairAddress);
console.log(this.state);
const liq = await deployedContract.methods
.addLiquidity(
this.state.firstAddress,
this.state.secondAddress,
1000,
1000,
0,
0,
this.state.pairAddress,
200
)
.send(
{
from: this.state.account,
gas: "2000000"
},
function(error, transactionHash) {}
)
.on("error", error => {
console.log("my error", error.message);
});
//console.log("Events", pairCreated.events);
})();
My error :
Transaction has been reverted by the EVM: { "blockHash": "0xc4bcbfe7c4e6045d20b466f7eab2a7af1693cb3e11be7a197722855876554eaa", "blockNumber": 9707061, "contractAddress": null,
"cumulativeGasUsed": 4110545, "from": "0xe3a6752cf416bd9fb766b046782a21b8722bcc3c", "gasUsed": 23341,
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "status": false, "to": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d", "transactionHash": "0xf23421d4a6cba30515e01e288893e8ecda482fccc1e3b969966187855298120c", "transactionIndex": 8, "events": {} }
I have another question : what is the address and deadline I have to put in the arguments "to" in Uniswap addLiquidity function?
function :
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline ) external returns (uint amountA, uint amountB, uint liquidity);

Your error in ropsten.etherscan.io says Expired, which probably means the transaction took longer than 20 mins to execute (assuming you were using the default deadline) so it failed.
See the following https://ethereum.stackexchange.com/questions/98678/fail-with-error-uniswapv2router-expired .
Seems to me like a timestamp issue.
Also, for v2, you have to make sure that
You call the approve method first
Supply a timestamp in UTC, 20 minutes ahead of the current one. In your case the timestamp is 200 and that is causing the issue for sure. Replace '200' with current timestamp + 20 minutes

Pass Date.now() as param for deadline instead of 200. This resolved my issue. Actually its expecting a date and you are passing an integer.

Related

ERC 20 Token transferFrom isn't working in my smart contract. Doesn't throw any Exception either

I wrote a contract in Solidity with the following task in mind:
The user approves the smart contract to transfer a certain amount of tokens from their wallet.
The smart contract uses this amount to transfer to an address given as a parameter. But it also takes 1 token from this amount to transfer to the developer of the contract.
If everything succeeds, the user receives a "Payment successful!" message.
The first step (the approval) was made using React and Web3:
const derc20contract = '0x36850b80ad73fe66216609B9796ed6ceae8BE29F';
const handleClick = async (e) => {
e.preventDefault();
const prtmp = await detectEthereumProvider();
// -------------------- Approve Part ------------------------------//
const web3 = new Web3(prtmp);
const erc20contract = new web3.eth.Contract(
erc20abi,
derc20token,
{ from: '0xFromAddress' }
);
await erc20contract.methods.approve(derc20contract, web3.utils.toHex(3e18)).send();
// ---------------------------------------------------------------//
const contract = new web3.eth.Contract(derc20abi, derc20contract);
const response = await contract.methods.send_usdt(
'0xToAddress',
web3.utils.toHex(3e18)
)
.call({ from: '0xFromAddress'});
console.log(response);
};
Once the approval succeeds the second part of the function resolves. The contract I deployed has a function called send_usdt. Through this function is my smart contract able to transfer the amount approved.
/ SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
interface IERC20 {
function transfer(address _to, uint256 _value) external returns(bool);
function transferFrom(address _from, address _to, uint _amount) external returns (bool);
function allowance(address _owner, address _contract) external returns (uint256);
function balanceOf(address _buyer) external view returns (uint256);
function approve(address _contract, uint tokens) external returns (bool);
}
contract DPortalSubscription {
address private owner;
mapping(address => uint32) subscription_fees;
constructor()
{
owner = msg.sender;
}
function check_balance() external view returns (uint256)
{
// TestToken ( Plasma Bridge ) in Mumbai Network
IERC20 usdt = IERC20(address(0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1));
uint256 balance = usdt.balanceOf(msg.sender);
return balance;
}
function check_sender_address() external view returns (address)
{
return msg.sender;
}
function check_allowance()external returns(uint256)
{
// TestToken ( Plasma Bridge ) in Mumbai Network
IERC20 usdt = IERC20(address(0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1));
uint256 allowance = usdt.allowance(msg.sender, address(this));
return allowance;
}
function send_usdt(address _to, uint256 _amount) external returns (string memory)
{
// TestToken ( Plasma Bridge ) in Mumbai Network
IERC20 usdt = IERC20(address(0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1));
require(_amount > 1, "Purchases must be higher than 1 usdt");
require(usdt.balanceOf(msg.sender) >= _amount, "The buyer doesn't have enough funds");
require(usdt.allowance(msg.sender, address(this)) >= _amount, "Permissions to transfer tokens denied");
require(usdt.transferFrom(msg.sender, _to, _amount-1) == true, "Couldn't transfer tokens to seller");
require(usdt.transferFrom(msg.sender, owner, 1) == true, "Couldn't transfer tokens to support");
return "Payment successful!";
}
}
Once the second part of the function in React resolves, I receive the confirmation "Payment successful!" But the tokens weren't transferred. I keep the same amount in my "From Wallet", "To Wallet" and "Deploy Wallet" as before.
The problem was inside the react snippet. By changing the method call to sell the money could be successfully transferred.
const response = await contract.methods.send_usdt
(
'0xToAddress',
web3.utils.toHex(3e18)
)
.call({ from: '0xFromAddress' });
was changed to:
const response = await contract.methods.send_usdt
(
'0xToAddress',
web3.utils.toHex(3e18),
{ from: '0xFromAddress' }
)
.send();
which worked but raised another question. When I use the previous call method, the function returns "Payment Successful!" and with the sell method I receive an Object.
Since "Payment Successful" isn't true, I was wondering if it could be possible to throw an Exception when someone interacts with my contract using the call method.
Is that possible?
Following #Kuly14's answer and in order to make it clearer, you may want to create the following function instead:
function send_usdt(address _to, uint256 _amount) external returns (string memory) {
// TestToken ( Plasma Bridge ) in Mumbai Network
IERC20 usdt = IERC20(address(0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1));
require(_amount > 1, "Purchases must be higher than 1 usdt");
usdt.transferFrom(msg.sender, owner, 1);
usdt.transferFrom(msg.sender, _to, _amount-1);
return "Payment successful!";
}
Notes:
By just calling the transferFrom method, it will jump its corresponding error if something goes wrong. You do not need to handle them.
I have changed the order in which you transfer the tokens. First, I send them to the owner and then to the desired recipient to avoid fees payments problems, but if you prefer the other way round, it is possible.

What do the keys in the '_performanceLogger' object of an XMLHttpRequest response mean?

I am trying to measure download (and later upload) speed using Axios in React Native. My question's relate to the most appropriate way to do so, and understanding if the _performanceLogger in the response from XMLHttpRequest is accurate for this purpose. There surprisingly doesn't seem to be much out there about _performanceLogger ... Appreciate the help!
A MWE is:
import React from "react";
import axios from 'axios';
// Dummy API endpoint
let requestURL = 'https://jsonplaceholder.typicode.com/users/2'
// Getting timestamp immediately before request is started
var startTimestamp = (new Date()).getTime()
// Make request through Axios
// Make a request for a user with a given ID
axios.get(requestURL)
.then(function (response) {
// Handle success
console.log("And I am burdened with glorious purpose.")
// Getting timestamp immediately after request is completed
let endTimestamp = (new Date()).getTime()
console.log("Request start time stamp: " + startTimestamp)
console.log("Request completed time stamp: " + endTimestamp)
// Logging the whole _performanceLogger object
let responsePerformanceLogger = response.request._performanceLogger
console.log('Perf Logger:')
console.log(responsePerformanceLogger)
// Logging the key/value specific to the actual request within the _performanceLogger object
let requestPerfString = 'network_XMLHttpRequest_' + requestURL
let responseTimespans = responsePerformanceLogger._timespans[requestPerfString]
console.log('Specific Request Timings:')
console.log(responseTimespans)
})
.catch(function (error) {
// Handle error
console.log("This is a mistake! I shouldn't be here!")
console.log(error);
})
.then(function () {
// always executed
console.log('For all time! Always!')
});
I use Expo to run this code on my device, and I get the following output to the console:
And I am burdened with glorious purpose.
Request start time stamp: 1640229022039
Request completed time stamp: 1640229022156
Perf Logger:
PerformanceLogger {
"_closed": false,
"_extras": Object {},
"_pointExtras": Object {},
"_points": Object {
"initializeCore_end": 194691080.25150004,
"initializeCore_start": 194691027.19495836,
},
"_timespans": Object {
"network_XMLHttpRequest_http://192.168.1.40:19000/logs": Object {
"endExtras": undefined,
"endTime": 194692352.89145836,
"startExtras": undefined,
"startTime": 194691383.22187504,
"totalTime": 969.6695833206177,
},
"network_XMLHttpRequest_http://192.168.1.40:19001/symbolicate": Object {
"endExtras": undefined,
"endTime": 194694267.96945837,
"startExtras": undefined,
"startTime": 194694100.6875417,
"totalTime": 167.2819166779518,
},
"network_XMLHttpRequest_https://jsonplaceholder.typicode.com/users/2": Object {
"endExtras": undefined,
"endTime": 194699846.2774167,
"startExtras": undefined,
"startTime": 194699738.0606667,
"totalTime": 108.21674999594688,
},
},
}
Specific Request Timings:
Object {
"endExtras": undefined,
"endTime": 194699846.2774167,
"startExtras": undefined,
"startTime": 194699738.0606667,
"totalTime": 108.21674999594688,
}
For all time! Always!
My specific questions are:
What are the different objects under the _timespans key? There are two (log, symbolicate) to the local IP for Expo ... what's happening here? Presumably these won't there when I deploy outside of Expo.
Is the third, the one that contains the actual URL made in the request, the actual timing of the download? (I've extracted this one as Specific Request Timings.) This is total download time (latency + file download), correct?
Is relying on the XMLHttpRequest timing less/more accurate than just using the simple getTime() timestamps that I have called before the request and after successful completion? I would expect that they should be close, but the getTime()'s require some finite execution time that could be variable by device/load.

Calling withdraw method with web3 ethereum

I'm calling a withdrawal method from a contract written in solidity from a react.js app using metamask. The transaction is failing and I don't know why. I think is something related to the gas fee because when I change it I get different errors. This is the react code:
contract.methods
.withdrawDividends()
.send({
from: userAddress,
value: availableToWithdraw,
})
.on("transactionHash", function (hash: string) {
console.log(hash);
})
.on(
"confirmation",
function (confirmationNumber: number, receipt: unknown) {
console.log(confirmationNumber);
console.log(receipt);
}
)
.on("receipt", function (receipt: unknown) {
// receipt example
console.log(receipt);
})
.on("error", function (error: unknown, receipt: unknown) {
// If the transaction was rejected by the network with a receipt, the second parameter will be the receipt.
console.log(error);
console.log(receipt);
});
This is my solidity method:
function withdrawDividends() public {
User storage user = users[_msgSender()];
uint256 totalAmount = getUserDividends(_msgSender());
require(totalAmount > 0, "User has no dividends");
user.checkpoint = block.timestamp;
(bool success, ) = _msgSender().call.value(totalAmount)("");
require(success, "Transfer failed.");
emit Withdrawn(_msgSender(), totalAmount);
}
The method is not crashing but I see the following error in metamask:
What I'm doing wrong? Is something related to the gas?
If you want your function to accept ETH value, it needs to have the payable modifier.
In your case:
function withdrawDividends() public payable {
You can read more about the payable modifier in the docs. It links to the receive function, which is a slightly different topic. But it also covers the payable modifier.

ReactJS : update state regularly in a specific time interval

I am creating a sensor app, where I have to update the state regular in a time interval of 15 seconds with the data receiving from the backend. Eventhough I can get the data successfully from the backend in the time interval, I cannot update the state in ReactJS. The code is as follows:
async regularCallAPI(){
let result;
const url = "http://..../...";
await fetch(url).then( res => res.json()).then( res => { result = res});
console.log("Regular Data from Backend : ", result);
let updatedSensors = result.map( sensor => {
return {
floorNum: sensor.floor_no,
roomNum: sensor.room_no,
sensorStatus: sensor.sensor_status,
alertStatus: sensor.alert_status,
ownerName: sensor.owner_name,
email: sensor.email,
phoneNumber: sensor.phone_number,
recordedDateAndTime: new Date(sensor.created_date).toLocaleString()
}
});
await this.setState({ sensors: updatedSensors });
console.log("sensor state updated ...");
}
and I have executed the above function in a interval of 15 seconds ;
timerId = setInterval(this.regularCallAPI, 15000);
The problem I have is, it runs the first time successfully and then when it run the second time, I get this error:
Unhandled Rejection (TypeError): this.setState is not a function
and yes, the function is already binded to the component in the constructor. What is the reason for this behavior and what is the possible solution for this ?
The callback is made in a different context. You need to bind to this in order to have access inside the callback:
setInterval( () => this.regularCallAPI(), 15000);

Making the bot stop sending messages if a user hasn't sent a message within x minutes

I have a !trivia command which has 4 functions and inside the functions I have a .then() function and .setTimeout(). The problem is that once someone triggers the command, it will only stop once someone say '!stop'. How can I make it so it stops if no one typed in that channel within 5 minutes?
Use .awaitMessages()
let userUsingTheCommand = "<USER_ID>";
let filter = msg => msg.author.id = userUsingTheCommand;
// Errors: ['time'] treats ending because of the time limit as an error
function wait() {
channel.awaitMessages(filter, {
max: 1,
time: 60000 * 5,
errors: ['time']
})
.then(wait)
.catch(() => {
console.log("Time to stop!");
});
}

Resources