In the below code eth will be transferred in the form of Wei by default, but I want the amount will transfer in the form of Ether, how can I do that?
function (uint amount) public payable {
someaddress.transfer(amount);
}
Wei is the smallest unit of Ether, specifically 1 ETH == 1,000,000,000,000,000,000 (or 1e18) wei.
The transfer() function always accepts the amount in wei. So if you want to pass just 1 as the input param, meaning that you want to send 1 full ETH, you can multiply the value by 1e18 effectively converting ETH to wei.
function (uint ethAmount) public payable {
uint weiAmount = ethAmount * 1e18;
someaddress.transfer(weiAmount);
}
Note: There's also the ether global unit, but in the current Solidity version (0.8), this can be used only in combination with number literals - not with variables.
uint weiAmount = 1 ether; // ok
uint weiAmount = ethAmount ether; // syntax error
Related
Good day Everyone, I am trying to implement a tax feature in an ERC20 token.
I successfully implemented something similar to a project that involved the creation of a TRC20 token using the code below as a reference:
pragma solidity ^0.6.0;
contract TransfertTokenAndPercentageToTargetAddress{
// pay 1% of all transactions to target address
address payable target = TUEtmARJ2m147RDJ5hy37mhZhEqx2Fnv8r; // I converted the tron address, I didn't use it as shown
// state variables for your token to track balances and to test
mapping (address => uint) public balanceOf;
uint public totalSupply;
// create a token and assign all the tokens to the creator to test
constructor(uint _totalSupply) public {
totalSupply = _totalSupply;
balanceOf[msg.sender] = totalSupply;
}
// the token transfer function with the addition of a 1% share that
// goes to the target address specified above
function transfer(address _to, uint amount) public {
// calculate the share of tokens for your target address
uint shareForX = amount/100;
// save the previous balance of the sender for later assertion
// verify that all works as intended
uint senderBalance = balanceOf[msg.sender];
// check the sender actually has enough tokens to transfer with function
// modifier
require(senderBalance >= amount, 'Not enough balance');
// reduce senders balance first to prevent the sender from sending more
// than he owns by submitting multiple transactions
balanceOf[msg.sender] -= amount;
// store the previous balance of the receiver for later assertion
// verify that all works as intended
uint receiverBalance = balanceOf[_to];
// add the amount of tokens to the receiver but deduct the share for the
// target address
balanceOf[_to] += amount-shareForX;
// add the share to the target address
balanceOf[target] += shareForX;
// check that everything works as intended, specifically checking that
// the sum of tokens in all accounts is the same before and after
// the transaction.
assert(balanceOf[msg.sender] + balanceOf[_to] + shareForX ==
senderBalance + receiverBalance);
}
}
Then I tried to follow the same approach for an ERC20 token using the template from openzeppelin: https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20
The following code shows the result of the modification:
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);
uint tax = amount/10;
uint256 fromBalance = _balances[from];
require(fromBalance >= amount + tax, "ERC20: transfer amount and Tax exceeds balance");
unchecked {
_balances[from] = fromBalance - amount - tax;
}
uint receiverBalance = _balances[to];
_balances[to] += amount;
_balances[target] += tax;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
// assert(_balances[from] + _balances[to] + tax == fromBalance + receiverBalance);
}
The token was successfully minted but the transfer function won't work. Any suggestions are highly appreciated.
I'm trying to learn developing my first smart contract in order to use flash loans on aave. I have a problem regarding the amount input for the transaction.
I've a function asking for the amount of token I need and the type is uint256. When I type 10 I only receive 0.0000000000000001 by the flash loan. Why? Maybe it's a stupid question but I'm not understanding what's wrong.
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
import { FlashLoanReceiverBase } from "./FlashLoanReceiverBase.sol";
import { ILendingPool, ILendingPoolAddressesProvider, IERC20 } from "./Interfaces.sol";
import { SafeMath } from "./Libraries.sol";
import "./Ownable.sol";
/*
* A contract that executes the following logic in a single atomic transaction:
*
*
*/
contract BatchFlashDemo is FlashLoanReceiverBase, Ownable {
ILendingPoolAddressesProvider provider;
using SafeMath for uint256;
uint256 flashDaiAmt0;
address lendingPoolAddr;
// mumbai reserve asset addresses
address mumbaiDai = 0x001B3B4d0F3714Ca98ba10F6042DaEbF0B1B7b6F;
// intantiate lending pool addresses provider and get lending pool address
constructor(ILendingPoolAddressesProvider _addressProvider) FlashLoanReceiverBase(_addressProvider) public {
provider = _addressProvider;
lendingPoolAddr = provider.getLendingPool();
}
/**
This function is called after your contract has received the flash loaned amount
*/
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
)
external
override
returns (bool)
{
/*
*
*
*/
// Approve the LendingPool contract allowance to *pull* the owed amount
// i.e. AAVE V2's way of repaying the flash loan
for (uint i = 0; i < assets.length; i++) {
uint amountOwing = amounts[i].add(premiums[i]);
IERC20(assets[i]).approve(address(_lendingPool), amountOwing);
}
return true;
}
/*
* This function is manually called to commence the flash loans sequence
*/
function executeFlashLoans(uint256 _flashDaiAmt0) public onlyOwner {
address receiverAddress = address(this);
// the various assets to be flashed
address[] memory assets = new address[](1);
assets[0] = mumbaiDai;
// the amount to be flashed for each asset
uint256[] memory amounts = new uint256[](1);
amounts[0] = _flashDaiAmt0;
flashDaiAmt0 = _flashDaiAmt0;
// 0 = no debt, 1 = stable, 2 = variable
uint256[] memory modes = new uint256[](1);
modes[0] = 0;
address onBehalfOf = address(this);
bytes memory params = "";
uint16 referralCode = 0;
_lendingPool.flashLoan(
receiverAddress,
assets,
amounts,
modes,
onBehalfOf,
params,
referralCode
);
}
/*
* Rugpull all ERC20 tokens from the contract
*/
function rugPull() public payable onlyOwner {
// withdraw all ETH
msg.sender.call{ value: address(this).balance }("");
// withdraw all x ERC20 tokens
IERC20(mumbaiDai).transfer(msg.sender, IERC20(mumbaiDai).balanceOf(address(this)));
}
}
I'm deploying passing this address as parameter:
0x178113104fEcbcD7fF8669a0150721e231F0FD4B
it is the Lending Pool Addresses Provider contract taken from here: https://docs.aave.com/developers/v/2.0/deployed-contracts/matic-polygon-market.
When I try asking for more than 1000tokens I get the error. Hope this helps to reproduce.
EVM doesn't support decimal numbers. So a common approach is to declare a number of decimals in the contract, and then include them with the stored values.
Example:
When a contract uses 2 decimals, value of 1 is stored as 100.
Aave protocol works with ERC20 tokens, where the standard defines a function named decimals() to return a number of decimal places.
Quick question let say I have product number 1 which its price is declared as 8 eth, is there a way to format it to avoid insering it in Wei on solidity?
A literal number can take a suffix of wei, gwei or ether to specify a subdenomination of Ether, where Ether numbers without a postfix are assumed to be Wei.
contract EtherUnits {
uint public oneWei = 1 wei;
// 1 wei is equal to 1
bool public isOneWei = 1 wei == 1;
uint public oneEther = 1 ether;
// 1 ether is equal to 10^18 wei
bool public isOneEther = 1 ether == 1e18;
}
When there are fees, normally contracts send tokens or BNB to wallets (i.e. marketing wallet) and auto add liquidity (swapandliquify) in BNB. I am attempting to replace BNB for both with BUSD. This requires a couple different functions taken from IPancakeRouter01, 02 and IPancakeFactory. Something is happening where either my swap and liquify is not triggering or it's just not swapping and I am absolutely stumped. Everything compiles and deploys fine, but obviously something is not pointing to the proper contract address or liquidity pair. My _transfer function is all good, I am sure of it. I am going to post the relevant parts of my code related to this issue.
//BUSD Contract Address
address constant public BUSD = 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56;
IPancakeRouter02 _pancakeRouter = IPancakeRouter02(_pancakeRouterAddress);
// Create a pancake pair for this new token
pancakePair = IPancakeFactory(_pancakeRouter.factory()).createPair(address(this), BUSD);
// set the rest of the contract variables
pancakeRouter = _pancakeRouter;
function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap {
uint256 totalFees = _buyLiquidityFee + _sellLiquidityFee + _buyMarketingFee + _sellMarketingFee + _buyWhaleBuybackFee + _sellWhaleBuybackFee;
uint256 _totalMarketingFee = _buyMarketingFee + _sellMarketingFee;
uint256 marketingPercent = _totalMarketingFee.div(totalFees);
uint256 marketingQuota = marketingPercent.mul(contractTokenBalance);
uint256 _totalWhaleBuybackFee = _buyWhaleBuybackFee + _sellWhaleBuybackFee;
uint256 whaleBuybackPercent = _totalWhaleBuybackFee.div(totalFees);
uint256 whaleBuybackQuota = whaleBuybackPercent.mul(contractTokenBalance);
// capture the contract's current ETH balance.
// this is so that we can capture exactly the amount of ETH that the
// swap creates, and not make the liquidity event include any ETH that
// has been manually sent to the contract
uint256 initialBalance = address(this).balance;
swapTokensForBNB(marketingQuota);
swapBNBForBUSD(address(this).balance);
transferOutBUSD(marketingWallet, address(this).balance.sub(initialBalance));
//transferOutBNB(marketingWallet, address(this).balance.sub(initialBalance));
uint256 initialBalance2 = address(this).balance;
swapTokensForBNB(whaleBuybackQuota);
transferOutBUSD(whaleBuybackWallet, address(this).balance.sub(initialBalance2));
//transferOutBNB(whaleBuybackWallet, address(this).balance.sub(initialBalance2));
// split the contract balance into halves
uint256 initialBalanceAfterUtility = address(this).balance;
uint256 half = initialBalanceAfterUtility.div(2);
uint256 otherHalf = initialBalanceAfterUtility.sub(half);
swapTokensForBNB(half);
swapBNBForBUSD(address(this).balance);
uint256 newBalance = address(this).balance.sub(initialBalanceAfterUtility);
addLiquidity(otherHalf, newBalance);
emit SwapAndLiquify(half, newBalance, otherHalf);
}
function swapTokensForBNB(uint256 tokenAmount) private {
// generate the pancake pair path of token -> wbnb
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = pancakeRouter.WETH();
_approve(address(this), address(pancakeRouter), tokenAmount);
// make the swap
pancakeRouter.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
0, // accept any amount of BNB
path,
address(this),
block.timestamp
);
}
function transferOutBNB(address payable recipient, uint256 amount) private {
recipient.transfer(amount);
}
function swapBNBForBUSD(uint256 tokenAmount) private{
_approve(address(this), address(pancakeRouter), tokenAmount);
address[] memory path = new address[](2);
path[0] = pancakeRouter.WETH();
path[1] = BUSD; //pancakeRouter.BUSD();
pancakeRouter.swapExactETHForTokensSupportingFeeOnTransferTokens(
tokenAmount,
path,
address(this),
block.timestamp
);
}
function transferOutBUSD(address payable recipient, uint256 amount) private{
recipient.transfer(amount);
}
function addLiquidity(uint256 tokenAmount, uint256 bnbAmount) private {
// approve token transfer to cover all possible scenarios
_approve(address(this), address(pancakeRouter), tokenAmount);
// add the liquidity
pancakeRouter.addLiquidity( // the return values of function not will are handled
address(this),
BUSD,
tokenAmount,
bnbAmount,
0,
0,
owner(),
block.timestamp
);
}
Instead of this,
//BUSD Contract Address
address constant public BUSD = 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56;
Try this,
IERC20 public immutable BUSD =
IERC20(0x78867BbEeF44f2326bF8DDd1941a4439382EF2A7);
a) For constant variables, the value has to be fixed at compile-time
b) For immutable, the value can be assigned at construction time.
I need put a minimum value of user can pay, and this value must be e.g 0.5 BNB.
But I don't know how I can do this.
uint comissionFee = 5; // 5 will represent 0,5
uint256 minimunPay = comissionFee*100/1000;
But return 0
pragma solidity ^0.8.4;
function payFees() public payable {
require(msg.value >= 0.5); // <-- not compatible with uint256
(bool success,) = owner.call{value: msg.value}("");
require(success, "Failed to send money");
}
Firstly, there are no double numbers in solidity lang.
All calculations are done with whole numbers. To solve this issue, all tokens on Ethereum/Binance Chain consider some big decimal number as a threshold of double and ceil parts.
In ERC20 tokens this number is calculated based on the decimal field of the contract: 10^decimal.
For the native token ETH/BNB, there is a fixed decimal equal to 18.
Your code could be fixed this way:
pragma solidity ^0.8.4;
function payFees() public payable {
require(msg.value >= 0.5 ether);
(bool success,) = owner.call{value: msg.value}("");
require(success, "Failed to send money");
}
OR
pragma solidity ^0.8.4;
function payFees() public payable {
require(msg.value >= 5 * 10**17);
(bool success,) = owner.call{value: msg.value}("");
require(success, "Failed to send money");
}
In solidity msg.value is not represented as Ether but as Wei a smaller denomination of ether you can think of it as ether with 18 decimals. Example:
1 ether is 1000000000000000000 Wei. Note that this applies for most chains to my knowledge BSC is also based on an 18 decimal system so 0.5BNB would be 500000000000000000 Wei this way you can check decimal values like this:
pragma solidity ^0.8.4;
function payFees() public payable {
require(msg.value >= 500000000000000000);
(bool success,) = owner.call{value: msg.value}("");
require(success, "Failed to send money");
}
Or:
pragma solidity ^0.8.4;
function payFees() public payable {
require(msg.value >= 0.5 ether);
(bool success,) = owner.call{value: msg.value}("");
require(success, "Failed to send money");
}
You can also take a look at this for a better demonstration of how this works.
Solidity works with integers. Why are there no decimal numbers in Solidity?
Uniswap created FixedPoint. you can use this function:
function fraction(uint256 numerator, uint256 denominator) internal pure returns (uq112x112 memory) {
require(denominator > 0, 'FixedPoint::fraction: division by zero');
if (numerator == 0) return FixedPoint.uq112x112(0);
if (numerator <= uint144(-1)) {
uint256 result = (numerator << RESOLUTION) / denominator;
require(result <= uint224(-1), 'FixedPoint::fraction: overflow');
return uq112x112(uint224(result));
} else {
uint256 result = FullMath.mulDiv(numerator, Q112, denominator);
require(result <= uint224(-1), 'FixedPoint::fraction: overflow');
return uq112x112(uint224(result));
}
}
in your solidity code:
using FixedPoint for *;
FixedPoint.fraction(numeratorValue,denominatorValue)