I'm trying to write a smart contract to transfer eth from one metamask wallet to another metamask wallet in solidity in remix with Injected Web 3 environment. I deployed the contract but the transaction send_ETH failed. Could anyone help me figure out why? Thank you so much
pragma solidity >=0.8.0;
// Get the latest ETH/USD price from chainlink price feed
import "#chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract myContract {
address payable[] recipients;
mapping(address => uint256) public balanceAccount;
address public owner;
constructor() {
owner = msg.sender;
}
function send_ETH(address payable recipient, uint256 amount) public {
//set the minimum amount of dollar to transfer
uint256 minimumUSD = 0.01 * 10 ** 18;
amount = minimumUSD;
require(getConversionRate(amount) >= minimumUSD, "You need to spend more ETH!");
this.invest(amount);
this.fund(recipient);
}
function invest(uint256 amount) payable external{
//transfer amount ETH from metadata wallet to smart contract
recordTransaction(address(this), amount, false);
recordTransaction(owner, amount, true);
address payable contractAddress = payable(address(this));
contractAddress.send(amount);
}
function fund(address payable recipient) external {
//transfer amount ETH from this smart contract to the recipient
recordTransaction(address(this), address(this).balance, true);
recordTransaction(recipient, address(this).balance, false);
recipient.send(address(this).balance);
}
function recordTransaction(address recipient, uint256 deposit, bool out) private {
if (out) {
balanceAccount[recipient] -= deposit;
} else {
balanceAccount[recipient] += deposit;
}
}
function getVersion() public view returns (uint256){
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x8A753747A1Fa494EC906cE90E9f37563A8AF630e);
return priceFeed.version();
}
function getPrice() public view returns(uint256){
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x8A753747A1Fa494EC906cE90E9f37563A8AF630e);
(,int256 answer,,,) = priceFeed.latestRoundData();
// ETH/USD rate in 18 digit
return uint256(answer * 10000000000);
}
function getConversionRate(uint256 ethAmount) public view returns (uint256){
uint256 ethPrice = getPrice();
uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1000000000000000000;
// the actual ETH/USD conversation rate, after adjusting the extra 0s.
return ethAmountInUsd;
}
}
your function invest() is wrong
function invest(uint256 amount) payable external{
//transfer amount ETH from metadata wallet to smart contract
recordTransaction(address(this), amount, false);
recordTransaction(owner, amount, true);
//these 2 lines below are wrong
address payable contractAddress = payable(address(this));
contractAddress.send(amount);
}
You marked that function as payable, that's correct if you interact directly with that, but you interact with send_eth, so it needs to be payable to receive eth
Then you saved the contract address as payable and did contractAddress.send(amount) that's mean: "contract send 'amount' to contract"
the send() function send money from contract to an address
also the amount var is wrong
all eth sent are sent directly through tx information, and not through data
the function correct:
function send_ETH(address payable recipient) payable public {
//set the minimum amount of dollar to transfer
uint256 minimumUSD = 0.01 * 1e18;
require(getConversionRate(msg.value) >= minimumUSD, "You need to spend more ETH!");
this.invest(msg.value);
this.fund(recipient);
}
function invest() internal{
//transfer amount ETH from metadata wallet to smart contract
recordTransaction(address(this), amount, false);
recordTransaction(owner, amount, true);
}
then when calling send_eth you have to write manually the amount of eth to send, if you will make an interface for that, you can write the eth amount to send inside the tx details like:
const transaction = {
'to': '0x31B98D14007bDEe637298086988A0bBd31184523', //contract address
'value': 1, //1 eth
'gas': 30000,
'maxFeePerGas': 1000000108,
'nonce': nonce,
};
Related
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.
What's wrong with my smart contract, because I get "Error: cannot estimate gas; transaction may fail or may require manual gas limit". On frontend I am calling approveTokens() first and acceptPayment() later
pragma solidity ^0.8.11;
import '#openzeppelin/contracts/token/ERC20/IERC20.sol';
contract PaymentProcessor {
address public owner;
IERC20 public token;
constructor(address _owner, address _token) {
owner = _owner;
token = IERC20(_token);
}
event PaymentCompleted(
address payer,
uint256 amount,
uint paymentId,
uint timestamp
);
function approveTokens(uint256 amount) public returns(bool){
token.approve(owner, amount);
return true;
}
function getAllowance() public view returns(uint256){
return token.allowance(msg.sender, owner);
}
function acceptPayment(uint256 amount, uint paymentId) payable public {
require(amount > getAllowance(), "Please approve tokens before transferring");
token.transfer(owner, amount);
emit PaymentCompleted(msg.sender, amount, paymentId, block.timestamp);
}
}
Users need to call approve() directly on the token address - not through your contract.
Your current implementation approves owner to spend PaymentProcessor's tokens because PaymentProcessor is the msg.sender in the context of the token contract.
I want to write a contract using router from uniswap. But when swapping 1 token to another, I get an error
The transaction has been reverted to the initial state. Note: The called function should be payable if you send value and the value you send should be less than your current balance. Debug the transaction to get more information.
I attach the code from below. How can I fix the error ?
// SPDX-License-Identifier: MIT
pragma solidity =0.8.7;
pragma abicoder v2;
import "https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/interfaces/ISwapRouter.sol";
import "https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/interfaces/IQuoter.sol";
interface IUniswapRouter is ISwapRouter {
function refundETH() external payable;
}
contract SwapV1 {
IUniswapRouter public constant uniswapRouter = IUniswapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
IQuoter public constant quoter = IQuoter(0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6);
address public token1;
uint24 public ownerFee;
function setToken1(address _token1) payable external {
token1 = _token1;
}
function setFee(uint24 _fee) payable external {
ownerFee = _fee;
}
function convertToken1ToToken2(address token2) external payable {
require(msg.value > 0, "Must pass non 0 ETH amount");
uint256 deadline = block.timestamp + 20; // using 'now' for convenience, for mainnet pass deadline from frontend!
address tokenIn = token1;
address tokenOut = token2;
uint24 fee = ownerFee;
address recipient = msg.sender;
uint256 amountIn = msg.value;
uint256 amountOutMinimum = 1;
uint160 sqrtPriceLimitX96 = 0;
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams(
tokenIn,
tokenOut,
fee,
recipient,
deadline,
amountIn,
amountOutMinimum,
sqrtPriceLimitX96
);
uniswapRouter.exactInputSingle{ value: msg.value }(params);
uniswapRouter.refundETH();
// refund leftover ETH to user
(bool success,) = msg.sender.call{ value: address(this).balance }("");
require(success, "refund failed");
}
function convertToken1ToExactToken2(uint256 token2Amount, address token2) external payable {
require(token2Amount > 0, "Must pass non 0 DAI amount");
require(msg.value > 0, "Must pass non 0 ETH amount");
uint256 deadline = block.timestamp + 20; // using 'now' for convenience, for mainnet pass deadline from frontend!
address tokenIn = token1;
address tokenOut = token2;
uint24 fee = ownerFee;
address recipient = msg.sender;
uint256 amountOut = token2Amount;
uint256 amountInMaximum = msg.value;
uint160 sqrtPriceLimitX96 = 0;
ISwapRouter.ExactOutputSingleParams memory params = ISwapRouter.ExactOutputSingleParams(
tokenIn,
tokenOut,
fee,
recipient,
deadline,
amountOut,
amountInMaximum,
sqrtPriceLimitX96
);
uniswapRouter.exactOutputSingle{ value: msg.value }(params);
uniswapRouter.refundETH();
// refund leftover ETH to user
(bool success,) = msg.sender.call{ value: address(this).balance }("");
require(success, "refund failed");
}
// do not used on-chain, gas inefficient!
function getEstimatedToken1forToken2(uint token2Amount, address token2) external payable returns (uint256) {
address tokenIn = token1;
address tokenOut = token2;
uint24 fee = ownerFee;
uint160 sqrtPriceLimitX96 = 0;
return quoter.quoteExactOutputSingle(
tokenIn,
tokenOut,
fee,
token2Amount,
sqrtPriceLimitX96
);
}
// important to receive ETH
receive() payable external {}
}
pragma solidity >=0.5.1 <0.6.0;
contract HelloWorld {
mapping(address => uint) public balance;
uint public countOfInvestors = 0;
mapping(address => uint) public time;
event Invest(address investor, uint256 amount);
function deposit() private {
if (msg.value > 0) {
if (balance[msg.sender] == 0) {
countOfInvestors += 1;
}
balance[msg.sender] = msg.value;
time[msg.sender] = now;
emit Invest(msg.sender, msg.value);
}
}
function() external payable {
deposit();
}
}
When i SEND SOME TRX ON CONTRACT i have no new data on tronscan, contract balance increased but not display any transaction
How to make contract should what i need?
No one events and transactions but i sent few times
Only a maximum of 2300 gas can be used on a fallback function, and your deposit function 100% uses more than that.
Since you used too much gas, the fallback function won’t get called.
https://ethereum.stackexchange.com/questions/5992/how-much-computation-can-be-done-in-a-fallback-function
I am building a sample smart contract . I am trying to deposit ether from 1 account to another but the issue is amount is deducted from the sender's account but not able to deposit to receiver's account.
Here is my contract code :
pragma solidity ^0.5.0;
contract ApprovalContract{
address public sender;
address public receiver;
function deposit(address _receiver) external payable {
require(msg.value > 0);
sender = msg.sender;
receiver = _receiver;
address payable _rec = receiver.make_payable();
_rec.transfer(address(this).balance);
}
using address_make_payable for address;
}
library address_make_payable {
function make_payable(address x) internal pure returns (address payable) {
return address(uint160(x));
}
}
Here is my web3 code :
let ApprovalContract = new web3.eth.Contract(
abi,
"0xABd4495e3afc9E61Bbbf54620587aB4B48CEd7d3" //contract address
);
ApprovalContract.methods
.deposit("0xF33ca58CbD25bC0fFe5546Dc494E5c61C8D7fFc3")
.send(
{
from: "0x7186ffcf5ea764257fdbaefccb9472f054495d11",
gas: 100000,
value: web3.utils.toWei("1", "ether")
},
(err, res) =>
err
? console.log(`error: ${err}`)
: console.log(`Success: ${res}`)
);
Just add some mapping in your smart contract, like this mapping( address => uint256 ) balance and this is fixed smart contract for you :
pragma solidity ^0.5.0;
contract ApprovalContract{
address payable owner = msg.sender;
mapping(address => uint256) balance;
function deposit() external payable {
require(msg.value > 0);
sender = msg.sender;
deposited = msg.value;
receiver = owner;
balance[sender] = deposited;
receiver.transfer(deposited);
}
}