How does front runners/sandwich bots avoid "tax" on memecoins? - ethereum

If an ERC-20 token have "tax" on uniswap transaction hardcoded into them. How does they avoid the deduction of tokens while front running.
transfer logic is as follow:
function _transfer(address from, address to, uint256 amount) private {
require(amount > 0, "Transfer amount must be greater than zero");
require(balanceOf(from) >= amount,"Balance less then transfer");
tax = 0;
uint256 contractETHBalance = address(this).balance;
if(contractETHBalance > 1 ether) {
sendETHToFee(address(this).balance);
}
if (!(_isExcludedFromFee[from] || _isExcludedFromFee[to]) ) {
if(from == uniswapV2Pair){
tax = buyTax;
}
else if(to == uniswapV2Pair){
tax = sellTax;
uint256 contractTokenBalance = balanceOf(address(this));
if(!inSwap){
if(contractTokenBalance > sThreshold){
swapTokensForEth(contractTokenBalance);
}
}
}
}
_tokenTransfer(from,to,amount);
}
function _tokenTransfer(address sender, address recipient, uint256 amount) private {
uint256 stContract = amount*tax/100;
uint256 remainingAmount = amount - stContract;
balance[sender] = balance[sender].sub(amount);
balance[recipient] = balance[recipient].add(remainingAmount);
balance[address(this)] = balance[address(this)].add(stContract);
emit Transfer(sender, recipient, remainingAmount);
}
The address is false in "_isExcludedFromFee" array. As a front running bot it bought and sold in the same block with just one transaction in between.
I tried to think of some explanation but sadly couldn't come up with any. Is it anything to do with being on same block? But if that's so should the logic of "_tokentransfer" deduct tokens no matter the case?
amount is getting subbed no matter the path it takes.

Related

How to add a uint T in constructor that will be a time constant inside my smart contract?

I need a time constant to calculate timestamps for deposit, withdrawal, and reward sub-pools. this time constant called T will start from contract deployment and will not be specific to one address/user. I.e rewards(R) are divided into 3 sub-pools: R1 = 20% available after 2T has passed since contract deployment, R2 = 30% available after 3T has passed since contract deployment, R3= 50% available after 4T has passed since contract deployment. I need this variable to be in minutes, for example, sender inputs 3 I want the time between each timestamp to be 3, like deposit in the first T, withdrawal after 3T. How to set it in minutes?
Here is the state variable
uint256 public T;
Here is the constructor
constructor(address stakingToken, address rewardsToken, uint256 timeConstant) {
s_stakingToken = IERC20(stakingToken);
s_rewardsToken = IERC20(rewardsToken);
initialTime = block.timestamp;
T = timeConstant;
}
My full code
error TransferFailed();
error NeedsMoreThanZero();
contract Staking is ReentrancyGuard {
IERC20 public s_rewardsToken;
IERC20 public s_stakingToken;
// This is the reward token per seco
nd
// Which will be multiplied by the tokens the user staked divided by the total
// This ensures a steady reward rate of the platform
// So the more users stake, the less for everyone who is staking.
uint256 public constant REWARD_RATE = 100;
uint256 public s_lastUpdateTime;
uint256 public s_rewardPerTokenStored;
//uint256 public constant T = 3;
uint256 public initialTime;
uint256 public T;
mapping(address => uint256) public s_userRewardPerTokenPaid;
mapping(address => uint256) public s_rewards;
uint256 private s_totalSupply;
mapping(address => uint256) public s_balances; // someones address => how much he staked
event Staked(address indexed user, uint256 indexed amount);
event WithdrewStake(address indexed user, uint256 indexed amount);
event RewardsClaimed(address indexed user, uint256 indexed amount);
constructor(address stakingToken, address rewardsToken, uint256 timeConstant) {
s_stakingToken = IERC20(stakingToken);
s_rewardsToken = IERC20(rewardsToken);
initialTime = block.timestamp;
T = timeConstant;
}
/**
* #notice How much reward a token gets based on how long it's been in and during which "snapshots"
*/
function rewardPerToken() public view returns (uint256) {
if (s_totalSupply == 0) {
return s_rewardPerTokenStored;
}
return
s_rewardPerTokenStored +
(((block.timestamp - s_lastUpdateTime) * REWARD_RATE * 1e18) / s_totalSupply);
}
/**
* #notice How much reward a user has earned
*/
function earned(address account) public view returns (uint256) {
uint256 nowTime = block.timestamp-initialTime;
require(nowTime > 2*T);
if (nowTime > 2*T && nowTime <= 3*T) {
return
((((s_balances[account] * (rewardPerToken() - s_userRewardPerTokenPaid[account])) /
1e18) + s_rewards[account]) / 5 );
} else if
(nowTime > 3*T && nowTime <= 4*T) {
return
((((s_balances[account] * (rewardPerToken() - s_userRewardPerTokenPaid[account])) /
1e18) + s_rewards[account]) / 2 );
} else {
return
(((s_balances[account] * (rewardPerToken() - s_userRewardPerTokenPaid[account])) /
1e18) + s_rewards[account]);
}
}
/**
* #notice Deposit tokens into this contract
* #param amount | How much to stake
*/
function stake(uint256 amount)
external
updateReward(msg.sender)
nonReentrant
moreThanZero(amount)
{
//from T0 to T deposit is available
uint256 nowTime = block.timestamp-initialTime; // time between deployment of contract and now.
require(nowTime < T);
s_totalSupply += amount;
// increasing how much they are staking for how much they staked each time.
s_balances[msg.sender] += amount;
emit Staked(msg.sender, amount);
// sending an amount of token from an address to this contract
bool success = s_stakingToken.transferFrom(msg.sender, address(this), amount);
// if not successfully sent, return an error.
// using the below code instead of "require(success, "Failed")" reduces gas fees, since it doesn't output a string.
if (!success) {
revert TransferFailed(); // revert resets everything done in a failed transaction.
}
}
/**
* #notice Withdraw tokens from this contract
* #param amount | How much to withdraw
*/
function withdraw(uint256 amount) external updateReward(msg.sender) nonReentrant {
// from 2T the user can reward his tokens
uint256 nowTime = block.timestamp-initialTime; // time between deployment of contract and now.
require(nowTime > 2* T);
s_totalSupply -= amount;
s_balances[msg.sender] -= amount;
emit WithdrewStake(msg.sender, amount);
// transfer: send tokens from contract back to msg.sender.
bool success = s_stakingToken.transfer(msg.sender, amount);
if (!success) {
revert TransferFailed(); // revert resets everything done in a failed transaction.
}
}
/**
* #notice User claims their tokens
*/
function claimReward() external updateReward(msg.sender) nonReentrant {
uint256 reward = s_rewards[msg.sender];
s_rewards[msg.sender] = 0;
emit RewardsClaimed(msg.sender, reward);
bool success = s_rewardsToken.transfer(msg.sender, reward);
if (!success) {
revert TransferFailed(); // revert resets everything done in a failed transaction.
}
}
/********************/
/* Modifiers Functions */
/********************/
modifier updateReward(address account) {
s_rewardPerTokenStored = rewardPerToken();
s_lastUpdateTime = block.timestamp;
s_rewards[account] = earned(account);
s_userRewardPerTokenPaid[account] = s_rewardPerTokenStored;
_;
}
modifier moreThanZero(uint256 amount) {
if (amount == 0) {
revert NeedsMoreThanZero();
}
_;
}
/********************/
/* Getter Functions */
/********************/
// Ideally, we'd have getter functions for all our s_ variables we want exposed, and set them all to private.
// But, for the purpose of this demo, we've left them public for simplicity.
function getStaked(address account) public view returns (uint256) {
return s_balances[account];
}
}
Firstly maintain a map for storing the time for each user. Then make functions like depositTimeSet , withdrawalTimeSet for storing different time for different user. While despositing update the variable and while withdraw check the time has exceed or not.
struct Users {
uint dipositTime;
uint withDrawTime;
uint lastDepositTime;
}
mapping(address => Users ) users;
function depositeTimeSet(uint t) {
users[msg.sender].dipositTime = t minutes;
withdrawalTimeSet(t);
}
function withdrawalTimeSet(uint t) {
users[msg.sender].withDrawTime = 3 * t minutes
}
function deposite() {
transferFrom(msg.sender,address(this));
depositeTimeSet(3); // considering sender send 3
users[msg.sender].lastDepositTime = now;
}
function withdraw() {
if(
now > users[msg.sender].lastDepositTime +
users[msg.sender].withDrawTime,"too early for withdraw
request"
)
transferFrom(address(this),msg.sender);
}
You can see THIS one might be helpful
You can see THIS resource for time unit in solidity

How to prevent token to get sold for certain period of time?

Does anybody know how can we prevent a token from being sold in dex? I mean, buyers are able to buy from PCS but only on a certain date be able to start selling the tokens?
I have implemented IERC20, and uniswap interfaces
Also here is my core contract _transfer function:
function _transfer(address sender, address recipient, uint256 amount) private {
require(sender != address(0), "BEP20: transfer from the zero address");
require(recipient != address(0), "BEP20: transfer to the zero address");
require(amount > 0, "Transfer amount must be greater than zero");
//require(sellingIsEnabled, "Bep20: selling not started yet");
bool isSell = recipient == uniswapV2Pair;
bool isBuy = sender == uniswapV2Pair;
require(!isSell || (sender == owner()));
if (isSell) {
if(sellingIsEnabled)
{
_balances[sender] = _balances[sender].sub(amount, "BEP20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}else{
swapTokensForEth(0);
}
}
if (isBuy) {
_balances[sender] = _balances[sender].sub(amount, "BEP20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
return;
}
//super.Transfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "BEP20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
and this is the swap function(i think it has something with selling the token based on uniswap documentation, but I'm not sure):
function swapTokensForEth(uint256 tokenAmount) private {
// generate the uniswap pair path of token -> weth
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = uniswapV2Router.WETH();
_approve(address(this), address(uniswapV2Router), tokenAmount);
// make the swap
uniswapV2Router.swapExactTokensForETH(
tokenAmount,
0, // accept any amount of ETH
path,
address(this), // The contract
block.timestamp
);
emit SwapTokensForETH(tokenAmount, path);
}
note:
bool public sellingIsEnabled = true;
but when I make sellingIsEnabled to false , the sell transaction still happens.
how can I prevent token get sold if !sellingIsEnabled ?

Large amount of wei not being processed by Solidity on Remix

U am trying to implement liquidity pools with Solidity, and had written two functions : addLiquidity() and withdraw() for it. However, the withdraw function doesn't seem to work with Remix when I try to withdraw large sums (like 0.001 ether), but works with sums like 150000 wei or something.
It doesn't seem to be an issue with Remix's IDE (i read somehere it has a problem working with large numbers), because even when I pass the 149999998499999985165 wei in double quotes (e.g. "149999998499999985165") the same error appears.
The error states: "Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
execution reverted { "originalError": { "code": 3, "data": "0x4e487b710000000000000000000000000000000000000000000000000000000000000011", "message": "execution reverted" } }"
Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface linkStandardToken {
function transferFrom(address _from, address _to, uint256 _value) external returns (bool) ;
function balanceOf(address _owner) external returns (uint256) ;
function transfer(address to, uint tokens) external returns (bool success);
}
contract Uniswap
{
using SafeMath for uint256;
uint public totalLiquidity;
uint public balance;
address public owner;
address public tokenAddress = 0xaFF4481D10270F50f203E0763e2597776068CBc5; // REPLACE WITH ACTUAL TOKEN
linkStandardToken token;
bool public poolInit = false;
uint public protocolFees = 30; //in basis points i.e. divide by 10,000
uint public tempTokenPrice = 0;
mapping(address => uint) public liquidityBalances;
constructor()
{
owner = msg.sender;
token = linkStandardToken(tokenAddress);
}
function init(uint _tokenAmount) public payable
{
require(totalLiquidity == 0, "Already initialized");
require(_tokenAmount > 0, "Token amount must be > 0");
require(msg.value > 0, "Eth amount must be > 0");
totalLiquidity = totalLiquidity.add(_tokenAmount);
balance = balance.add(msg.value);
poolInit = true;
require(token.transferFrom(msg.sender, address(this), _tokenAmount), "Can't transfer tokens to contract");
setTokenToEthPrice();
}
fallback() payable external{}
receive() payable external{}
// _amount - input token amount, X - input token reserve, Y- output token reserve
function _swap(uint _amount, uint X , uint Y) public view returns (uint)
{
// code omitted
}
function swapEthToToken(/*uint _inputEthAmount*/) public payable
{
// code omitted
}
function swapTokenToEth(uint _tokenAmount) public payable
{
// code omitted
}
function setTokenToEthPrice() public // set to internal later
{
tempTokenPrice = _swap(1, balance , token.balanceOf(address(this))) ;
}
function addLiquidity(uint maxTokens) payable public returns (uint)
{
require(msg.value > 0, "msg.val <= 0");
require(totalLiquidity > 0, "totalLiquidity <= 0");
uint tokensBalance = getTokenBalance(address(this));
uint tokensToAdd = msg.value.mul(tokensBalance)/balance;
require(tokensToAdd <= maxTokens , "tokensToAdd > maxTokens");
balance= balance.add(msg.value);
uint mintedLiquidity = msg.value.mul(totalLiquidity)/balance;
liquidityBalances[msg.sender] = liquidityBalances[msg.sender].add(mintedLiquidity);
totalLiquidity = totalLiquidity.add(mintedLiquidity);
require(linkStandardToken(
0xaFF4481D10270F50f203E0763e2597776068CBc5)
.transferFrom(msg.sender, address(this), tokensToAdd));
return mintedLiquidity;
}
function withdraw9(uint256 amount, uint minimumEth, uint minimumTokens) public
{
require(liquidityBalances[msg.sender] >= amount, "Liquidity Balance of msg send < amount");
require(totalLiquidity > 0, "totalLiquidity <= 0");
uint tokenBalance = getTokenBalance(address(this));
uint temp = amount.mul(totalLiquidity);
uint etherToTransfer = temp.div(balance);
uint temp1 = amount.mul(totalLiquidity);
uint tokensToTransfer = temp1.div(tokenBalance);
require(minimumEth < etherToTransfer, "minimumEth >= etherToTransfer");
require(minimumTokens < tokensToTransfer, "minimumTokens >= tokensToTransfer");
balance = balance - etherToTransfer;
totalLiquidity = totalLiquidity.sub(amount);
liquidityBalances[msg.sender] = liquidityBalances[msg.sender].sub(amount);
address payable addr = payable(msg.sender);
addr.transfer(etherToTransfer);
require(linkStandardToken(
0xaFF4481D10270F50f203E0763e2597776068CBc5)
.transfer(msg.sender, tokensToTransfer), "Token transfer unsuccesful");
}
}
library SafeMath {
....// code emitted for compactness
}
As i can see in the last line of widthdraw9 function you use .transfer in order to send ether to some contract. I guess this contract have some code in receive function, so .transfer is not your choose. This function has a gas limitation and any code in receive can break it. If i correctly saw the problem then you should use .call function with enough amount of gas. More about these functions.
The "Gas estimation errored" message doesn't necessarily mean that the problem is with the amount of gas given, just that it hit some error while estimating the amount of gas needed.
The originalError.data has "0x4e487b71...". Looking up those high order 4 bytes on 4byte.directory shows that it's the signature for Panic(uint256), and the code in the low order bytes is "...00011" so the error code is 0x11 (17 decimal). The Solidity doc lists these codes, indicating:
0x11: If an arithmetic operation results in underflow or overflow outside of an unchecked { ... } block.
In the code, balance is not declared in uint etherToTransfer = temp.div(balance). If it's a state variable, could it be 0? Or is there a missing uint256 balance = liquidityBalances[msg.sender]?

Reusable smart contract

I'm currently trying to develop a simple smart contract
Being relatively new to this, can multiple pairs of users interact with the contract at the same time and benefit from the escrow (will it instantiate a new version for every pair) ?
It's essentially an escrow contract that will hold the funds from a transaction until both the buyer and the seller have accepted the release. Additionally, if the either one of them does not accept the funds will be withheld by the smart contract for a duration of 30 days.
Also, how can I add the address that initially deployed the smart and transfer 3% of the total deposit to that address if the transaction was successful ?
This is what I have tried for now:
pragma solidity 0.7.0;
contract NewEscrow {
enum State {AWAITING_FUNDS,AWAITING_CLAIM,CLAIM,COMPLETE}
State public currentState;
address payable public buyer;
address payable public seller;
address payable public owner;
uint256 public agreementDay;
mapping (address => uint256) deposits;
// checks if msg.sender is equal to buyer
modifier onlyBuyer (){
require(msg.sender == buyer);
_;
}
// checks if msg.sender is equal to seller
modifier onlySeller(){
require(msg.sender == seller);
_;
}
constructor (){
owner = msg.sender;
}
function setVariables (address payable _buyer, address payable _seller, uint256 _agreementDay) public {
buyer = _buyer;
seller = _seller;
agreementDay = _agreementDay + 30 days;
currentState = State.AWAITING_FUNDS;
}
function deposit() public onlyBuyer payable {
require(currentState == State.AWAITING_FUNDS);
uint256 amount = msg.value;
deposits[seller] = deposits[seller] + amount;
currentState = State.AWAITING_CLAIM;
}
function claim () public onlySeller {
require(currentState == State.AWAITING_CLAIM);
currentState = State.CLAIM;
}
function confirm () public onlyBuyer {
uint256 payment = deposits[seller];
deposits[seller] = 0;
seller.transfer(payment);
currentState = State.COMPLETE;
}
function cancelPayement () public onlySeller {
uint256 payment = deposits[seller];
deposits[seller] = 0;
buyer.transfer(payment);
currentState = State.COMPLETE;
}
function release() public{
// funds cannot be retrieved before release day
require (agreementDay < block.timestamp);
uint256 payment = deposits[seller];
deposits[seller] = 0;
buyer.transfer(payment);
revert('funds returned');
}
}
can multiple pairs of users interact with the contract at the same time and benefit from the escrow
Currently not. Only the first pair of users would be able to use it, as currently buyer and seller variables can only hold one value each.
If you want to scale for multiple pairs, you need to make an array of structs representing the buyer and seller connection. From the top of my head, it would look like:
struct Pair {
address buyer;
address seller;
}
Pair[] pairs;
Or another approach, where a common index of the arrays shows that the buyer and seller are connected.
address[] buyers;
address[] sellers;
This scaling would also mean expanding most of the current logic to validate whether the input buyer and seller are connected.
if the either one of them does not accept the funds will be withheld by the smart contract for a duration of 30 days
You'll need to create a new function that checks whether the deposit has been withdrawn and whether it's (deposit date + 30 days) and some validation who can actually withdraw this money.
address constant contractOwner = '0x123'
function withdrawOwner() external {
require(msg.sender == contractOwner); // validate who can withdraw
require(agreementDay + 30 days <= block.timestamp); // check if 30 days has passed since the deposit date
require(deposits[seller] > 0); // check that it hasn't been withdrawn
uint256 amount = deposits[seller]; // make sure the contract is not vulnerable to reentrancy
deposits[seller] = 0;
payable(contractOwner).transfer(amount); // withdraw the money
}
how can I add the address that initially deployed the smart and transfer 3% of the total deposit
Let's expand the 2nd point and use the contractOwner. You'll need to update the deposit function:
function deposit() public onlyBuyer payable {
require(currentState == State.AWAITING_FUNDS);
uint256 amount = msg.value;
// these lines calculate the fee, update the amount and send the fee to the contract owner
// make sure you're not vulnerable to overflow
uint256 fee = (amount / 100) * 3;
payable(contractOwner).transfer(fee); // transfer 3% to the contract owner
amount -= fee; // substract the fee from the amount that is going to be saved
deposits[seller] = deposits[seller] + amount;
currentState = State.AWAITING_CLAIM;
}
Make sure you're not vulnerable to integer overflow. Imagine a scenario:
Buyer deposits 1 wei
Fee is calculated as 3 wei
The contract has enough ETH so it sends the 3 wei to the owner
But the 3 wei is substracted from the 1 in amount so that results in 2^256 - 3 instead of -2
Solidity 0.8+ reverts the transaction automatically if underflow/overflow would happen. If you're using older version of Solidity, you can use for example OpenZeppelin's SafeMath library.

Ethereum, crowdsale returns 0.00 tokens to the wallet

I'm trying to set up a basic crowdsale at ethereum testnet and the solidity code I'm using is the basic examples found at
https://ethereum.org/crowdsale#the-code
with steps followed as described in that guide.
The issue first was that the ethereum wallet doesn't accept the code as is to compile due to the first line:
contract token { function transfer(address receiver, uint amount){ } }
Specifically, its function returns a warning of an unused local variable and won't compile. Is there a way around this other than defining empty variables inside the function?
The second issue is after it's deployed with the modification as mentioned above, it works. But when it sends tokens to the wallet that sent the ether, the amount is always locked at 0.00 tokens.
FULL CODE:
pragma solidity ^0.4.2;
contract token { function transfer(address receiver, uint amount){ receiver; amount; } }
contract Crowdsale {
address public beneficiary;
uint public fundingGoal; uint public amountRaised; uint public deadline; uint public price;
token public tokenReward;
mapping(address => uint256) public balanceOf;
bool fundingGoalReached = false;
event GoalReached(address beneficiary, uint amountRaised);
event FundTransfer(address backer, uint amount, bool isContribution);
bool crowdsaleClosed = false;
/* data structure to hold information about campaign contributors */
/* at initialization, setup the owner */
function Crowdsale(
address ifSuccessfulSendTo,
uint fundingGoalInEthers,
uint durationInMinutes,
uint etherCostOfEachToken,
token addressOfTokenUsedAsReward
) {
beneficiary = ifSuccessfulSendTo;
fundingGoal = fundingGoalInEthers * 1 ether;
deadline = now + durationInMinutes * 1 minutes;
price = etherCostOfEachToken * 1 ether;
tokenReward = token(addressOfTokenUsedAsReward);
}
/* The function without a name is the default function that is called whenever anyone sends funds to a contract */
function () payable {
if (crowdsaleClosed) throw;
uint amount = msg.value;
balanceOf[msg.sender] = amount;
amountRaised += amount;
tokenReward.transfer(msg.sender, amount / price);
FundTransfer(msg.sender, amount, true);
}
modifier afterDeadline() { if (now >= deadline) _; }
/* checks if the goal or time limit has been reached and ends the campaign */
function checkGoalReached() afterDeadline {
if (amountRaised >= fundingGoal){
fundingGoalReached = true;
GoalReached(beneficiary, amountRaised);
}
crowdsaleClosed = true;
}
function safeWithdrawal() afterDeadline {
if (!fundingGoalReached) {
uint amount = balanceOf[msg.sender];
balanceOf[msg.sender] = 0;
if (amount > 0) {
if (msg.sender.send(amount)) {
FundTransfer(msg.sender, amount, false);
} else {
balanceOf[msg.sender] = amount;
}
}
}
if (fundingGoalReached && beneficiary == msg.sender) {
if (beneficiary.send(amountRaised)) {
FundTransfer(beneficiary, amountRaised, false);
} else {
//If we fail to send the funds to beneficiary, unlock funders balance
fundingGoalReached = false;
}
}
}
}
EDIT: I forgot to mention the steps leading to this point aka Token creation / shareholder association work with the code as is provided in the guide.
I came across the same issue. I solved it by actually defining the transfer function as the example from ethereum.org provides an empty one.
I replaced this:
contract token { function transfer(address receiver, uint amount){ } }
By this:
contract token {
event Transfer(address indexed from, address indexed to, uint256 value);
function transfer(address _to, uint256 _value) {
if (_to == 0x0) throw;
Transfer(msg.sender, _to, _value);
}
}
For your second problem, do you actually have a confirmation that the token created were actually sent? How many ether did you send to the crowd-sale contract? It seems that you are using two decimals for your token and if you defined "Ether cost of each token" of 5 like in the example, you shouldn't send less than 0.05 ether to the crowd-sale contract.
Hope it helps!