Maintaining liqudity price after every swap - blockchain

In current state, I am maintaing liquidity price of two simple tokens by calling uniswapPairV2 sync() method by C# code after every 5 mints, because I am using gasless blockchain so no problem with transaction gas.
Now, I want to deploy my project on Binance blockchain, so ofcourse I do not want to put gas fee when sync method call, What I want is to call sync method after every swap by the user.
I have put sync method in token transfer method but uniswap is not allowing me to do it.
Here is my code:
function _transfer(
address from,
address to,
uint256 amount, uint256 amount2) internal override {
require(from != address(0), "Transfer from the zero address");
require(to != address(0), "Transfer to the zero address");
require(amount > 0, "Amount must be greater than zero");
require(!_isBlackListed[from] && !_isBlackListed[to],"sender or recipient is BOT");
_beforeTokenTransfer(from, to, amount);
uint256 contractTokenBalance = balanceOf(address(this));
if(contractTokenBalance >= _minTokenBalance){
_balances[liquidityAddress]+=contractTokenBalance;
_balances[address(this)] -=contractTokenBalance;
}
bool takeFee = true;
if (_iswhitelistAddress[from] || _iswhitelistAddress[to]) {
takeFee = false;
}
_tokenTransfer(from, to, amount, takeFee);
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
//The method used to get the change in price after swap and for maintain the price of liquidity.
//Sync method is called in this method and it will update the balance of liquidity.
updatePairBalance();
}
I have tried to call sync method in _transfer method of token, but it is not working.
What I need is to get a way to maintain the liquidity price after every swap.

Related

Issues while selling to a liquidity pool created for my own smart contract

i've been lately trying to create an ERC20 Token with Some Fees implemented on the transfer functions and an AntiSnipe system which is supposed to block the addresses trying to make a transfer in a certain range of time. As per Uniswap documentation, IUniswapV2Router02 implements methods which accepts transfers with fees and in fact the system works in part.
Basically, after i deploy on Goerli, i am able to create a liquidity pool and with a 2nd wallet, i'm able to either buy or sell from the liquidity pool once.
After the first buy or sell, noone is able to either buy or sell anymore.
Considering that the first buy/sell works, and my 3rd wallet actually receives the fees, i suppose the way i've wrote TransferFrom function is right.
It feels like the liquidity pool Reserves dont gets updated after the first transfer and this brings the 2nd to fail (Just an idea, i have no message errors at all)
The transfer function has this logic inside aswell, but with msg.sender instead of from.
Thank you in advance
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
require(!AntiSnipeDenyList[from] && !AntiSnipeDenyList[to], "AntiSnipe: address is on denylist");
address spender = _msgSender();
_spendAllowance(from, spender, amount);
uint256 lp_tax_amount = 0;
uint256 dev_tax_amount = 0;
uint256 marketing_tax_amount = 0;
uint256 transfer_amount;
if(
msg.sender != _contractDeployer
&& msg.sender != owner()
&& msg.sender != _uniswapV2RouterAddress
&& to != address(this)
&& from != address(this)
)
{
// Calculate Taxes
lp_tax_amount = (amount * _lpTax)/100;
dev_tax_amount = (amount * _devTax)/100;
marketing_tax_amount = (amount * _marketingTax)/100;
// Calculate final transfer amount
transfer_amount = amount - lp_tax_amount - dev_tax_amount - marketing_tax_amount;
// Begin Max Wallet Check
uint256 wallet_size = balanceOf(to);
require((wallet_size + transfer_amount) <= _maxWallet, "IBIT: maximum wallet cannot be exceeded");
// InfinityBit Token official contract address will be announced only after
// _ASB blocks have passed since contract deployment. Any transfers before
// such time are considered to be bot snipers, and will be locked.
if(block.timestamp < deploy + 60){
AntiSnipeDenyList[to] = true;
}
}
else
{
transfer_amount = amount;
}
if(marketing_tax_amount > 0)
{
_transfer(from, _marketingWallet, marketing_tax_amount);
}
if(dev_tax_amount > 0)
{
_transfer(from, _devWallet, dev_tax_amount);
}
if(lp_tax_amount > 0)
{
_transfer(from, _lpWallet, lp_tax_amount);
}
_transfer(from, to, transfer_amount);
return true;
}

swap 2 erc20 with each other at one method between 2 different user. -- Reentrancy guard problem

I know I have to use nonReentrant modifier for this method, but I also know it's wont work can someone tell me what should I do to create a mechanism something like this with safe pattern?
function swapTokenToEvolve(uint256 _tokenAmount, uint256 _stageIndex)
public
checkStageTime(_stageIndex)
checkRemainingAmount(_tokenAmount, _stageIndex)
nonReentrant
returns (bool)
{
// get token price from stage ;
uint256 tokenPrice = salesStages[_stageIndex].price;
// how many tokens user will get;
uint256 stableTokenAmount = multiply(_tokenAmount, tokenPrice, decimal);
// transfer token from buyer to seller;
require(
IERC20(currencyToken).transferFrom(
owner(),
_msgSender(),
_tokenAmount
)
);
// transfer token from seller to user;
require(
IERC20(token).transferFrom(_msgSender(), owner(), stableTokenAmount)
);
salesStages[_stageIndex].liquidity = salesStages[_stageIndex]
.liquidity
.sub(_tokenAmount);
return true;
}
before any "transferFrom" you have to take approve from token owner, on the other hand to prevent "reentrancy" you have to change the variable before any external call, I suggest 2 steps:
1-get approve from the token owner before this function(because msg.sender checked in that) or if you want using in this function user ERC-20-permit
2-change your state variable line.salesStages[_stageIndex].liquidity = salesStages[_stageIndex] .liquidity .sub(_tokenAmount); before your external call.
The transferFrom method from ERC20 token is the following:
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
Where _spendAllowance requires the allowance to exists for the transfer amount:
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
Therefore, you do not need to require the transferFrom. What you need to do is make sure the contract has enough allowance from both owner() (first transfer) and _msgSender() (second transfer).

Solidity Transaction Issue

i'm facing some weird issues, or well, things i'm not understanding. I'm still pretty new with solidity tho, anyway, i'm trying to create a staking contract, based on an ERC20 token i created. I call the stake function with ethers.js and pass the amount with it. The staking contract saves some info and forwards receiver address and amount to the ERC20 transfer function.
async function stake () {
await stakeContract.stake(1);
}
function stake (uint256 _amount) public {
require(_amount > 0, "You must stake more than 0");
require(_amount < ercToken.balanceOf(msg.sender), "The amount exceeds your balance");
addressToStaked[msg.sender].push(Stakes(block.timestamp, _amount));
totalStakes[msg.sender] += 1;
ercToken.transfer(address(ercToken), _amount);
}
The transfer function then forwards the data to the internal _transfer function shown below. The problem is that, even if i do have enough tokens in my wallet, the _transfer function still fails with error: Amount exceeds balance.
I've double checked the mapping saving the balance and it works.
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
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);
}
It seems you made a mistake on this line of the staking contract.
function stake (uint256 _amount) public {
...
ercToken.transfer(address(ercToken), _amount);
}
The above line means, transfer "_amount" token to "ercToken" address from staking contract. So there should be some amounts ( >_amount ) of tokens on staking contract. But as you mentioned, you only have enough tokens on your wallet, not on staking contract.
Plz use "transferFrom" function or "safeTransferFrom" function of "SafeERC20" library to solve the issue.

Optimal way of handling NFT minting queue

I am doing a generative NFT project where the user purchases an NFT pack from (1 to 10) and there will be a service that generates up to 10 NFTs, uploads it to IPFS then returns it to the frontend. Frontend then prompts the user to approve the transaction which then mints the NFT to the user.
This flows takes some time especially at the generating part,
so I was thinking of creating a different flow that has a smart contract that holds a queue array. Instead of generating the NFT first, the user will join the queue in the smart contract, then a service that polls the queue array will start generating and minting anything in the queue.
However, if I do this flow, the service will have to be the one that pays the gas fee when minting,
so I was wondering if anyone could advise me on how to create a queue system in blockchain for this case?
contract YourContract is Ownable {
uint256 public maxAmount = 10;
uint256 public price = 10 ether;
function mint(address _to, uint256 _mintAmount) public payable {
// you can add more logic
require(_mintAmount > 0);
// Maybe currently user has no enough fund to mint all
// so it mints some now, will do later, depends on your contract logic
require(_mintAmount <= maxAmount);
// owner() is if your contract is inheriting from Ownable
// if you set the owner on your own inside constructor, use `owner`
// you are forcing the callee of the function to pay this amount
if (msg.sender != owner()) {
require(msg.value >= price * _mintAmount);
}
// after callee has paid, run the minting
for (uint256 i = 1; i <= _mintAmount; i++) {
_safeMint(_to, i);
}
}
}
this is the _safeMint in ERC721
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}

Gas required exceeds limit: 3000000.

pragma solidity ^0.4.16;
contract createNewToken {
uint256 total_ether_to_send;
address private owner;
//constructor
function createNewToken() public{
owner = msg.sender;
}
// client request for tokens by sending ether.
function requestForToken() public payable{
address sender = msg.sender;
uint value = msg.value;
total_ether_to_send = value;
require(sender.balance >= total_ether_to_send);
owner.transfer(total_ether_to_send);
total_ether_to_send = value / 2;
require(owner.balance >= total_ether_to_send);
sender.transfer(total_ether_to_send);
}
}
I have written this code in solidity in Remix IDE. The contract was successfully created but when I used it, it gave me an error saying "Gas required exceeds limit: 3000000. An important gas estimation might also be the sign of a problem in the contract code. Please check loops and be sure you did not sent value to a non payable function". I don't have much code written but its still gave me this error. Can anyone help?
First, your msg.value is already sent to your method, hence you don't need to check senders balance: require(sender.balance >= total_ether_to_send);.
Second, you don't have a fallback function in your contract to receive ether.
Third, you are trying to send 100% msg.value to owner and then send 50% of msg.value back to sender. Obviously you cannot spend 150% of msg.value without any additional funds on your contract. Here is example of working code:
function requestForToken() public payable{
address sender = msg.sender;
uint value = msg.value;
total_ether_to_send = value / 2;
require(this.balance >= total_ether_to_send);
owner.transfer(total_ether_to_send);
require(this.balance >= total_ether_to_send);
sender.transfer(total_ether_to_send);
}
function() payable {}