Hardhat ERC20 transfer failed - ethereum

I don't know why the transfer function does not work. I tried npx hardhat test but it seems to fail when transferring.
function deposit(address token, uint256 amount) external onlyOwner {
uint256 balance = ERC20(token).balanceOf(msg.sender);
console.log(token, balance);
require(balance > amount, "not enough money to deposit");
ERC20(token).approve(address(this), amount);
ERC20(token).transferFrom(msg.sender, address(this), amount);
}
This is the hardhat JavaScript code which executes the contract
await WETH.transfer(arb.address, ethers.utils.parseUnits("2", "ether"));
await IWETH.deposit({
value: ethers.utils.parseUnits("100.0", "ether"),
});
await arb
.connect(owner)
.deposit(
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
ethers.utils.parseUnits("2", "ether")
);
I seems like it failed at ERC20(token).transferFrom(msg.sender, address(this), amount);

Related

Swapping using Uniswap

Here is my code:
// SPDX-License-Identifier: UNLICENCED
pragma solidity <0.9.0;
interface UniswapInterface{
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
}
interface IERC20{
function balanceOf(address account) external view returns (uint256);
function decimals() external view returns (uint8);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}
contract swapContract{
address public UniSwapRouterAddress = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
address public USDCAddress = 0x2fB298BDbeF468638AD6653FF8376575ea41e768;
address public BTCAddress = 0x577D296678535e4903D59A4C929B718e1D575e0A;
IERC20 USDC = IERC20(0x2fB298BDbeF468638AD6653FF8376575ea41e768);
IERC20 BTC = IERC20(0x577D296678535e4903D59A4C929B718e1D575e0A);
UniswapInterface UniSwapRouter = UniswapInterface(UniSwapRouterAddress);
function approveUSDC() public{
USDC.approve(UniSwapRouterAddress, 999**9);
}
function approveBTC() public{
BTC.approve(UniSwapRouterAddress, 999**9);
}
function deposit(uint256 amount) public{
require(amount > 0, "0 is not accepted!");
uint256 allowance = USDC.allowance(msg.sender, address(this));
require(allowance >= amount, "Check USDC allowance");
USDC.transferFrom(msg.sender, address(this), amount);
}
function withdraw() public {
USDC.transfer(msg.sender, USDC.balanceOf(address(this)));
}
function swapUSDC() public {
address[] memory Path = new address[](2);
Path[0] = USDCAddress;
Path[1] = BTCAddress;
UniSwapRouter.swapExactTokensForTokens(
100000000,
0,
Path,
address(this),
block.timestamp + 240
);
}
}
I simply want to swap 1 USDC (its decimal is 8) to BTC on Rinkeby testnetwork.
I tried so many changes like increasing deadline, change in amountIn and amountOutMin but no gain. Also the pool on Uniswap has liquidity.
The error just says:
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
execution reverted
I have checked the stackoverflow for answer but could not find a solution
I tried to figure out what the problem might be and realized that most likely there is no such pool.
If you go to the Uniswap UI, you will see that the pool was created only for V3, and you are trying to use the V2 address of router.
There are two ways to solve the problem, the first is to create a liquidity pool in V2 or to make an exchange through V3.

Sending ether to a payable function in Solidity doesn't decrease the sender's Ether in Ganache

I have the following smart contract:
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./MyCoinSupply.sol";
contract MyCoinDEX
{
IERC20 public token;
event Bought(uint256 amount);
event Sold(uint256 amount);
constructor() public
{
token = new MyCoinSupply();
}
function getSenderAddress() public view returns (address) // for debugging purposes
{
return (msg.sender);
}
function getAddress() public view returns (address)
{
return address(this);
}
function getTokenAddress() public view returns (address)
{
return address(token);
}
function buy() payable public // send ether and get tokens in exchange; 1 token == 1 ether
{
uint256 amountTobuy = msg.value;
uint256 dexBalance = token.balanceOf(address(this));
require(amountTobuy > 0, "You need to send some ether");
require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");
token.transfer(msg.sender, amountTobuy);
emit Bought(amountTobuy);
}
function sell(uint256 amount) public // send tokens to get ether back
{
require(amount > 0, "You need to sell at least some tokens");
uint256 allowance = token.allowance(msg.sender, address(this));
require(allowance >= amount, "Check the token allowance");
token.transferFrom(msg.sender, address(this), amount);
// https://stackoverflow.com/questions/67341914/error-send-and-transfer-are-only-available-for-objects-of-type-address-payable
payable(msg.sender).transfer(amount);
emit Sold(amount);
}
}
if I call the buy() method from truffle console, it executes without any exceptions:
truffle(development)> MyCoinDEX.buy({value: 1})
I verified that the account calling the buy() method receives the token. However, the balance of Ether in Ganache for the account calling the buy() method doesn't decrease. So essentially, the account is getting tokens for free.
What's going on here? How do I fix it?
I am not sure but it would be necessary to investigate about the balance of the contract account. The gas for token.transfer might be paid by the contract account balance, since the contract account is the transaction sender for token contract.
Or the balance decrement would be unnoticeable because it is too small.
I would be happy to know about the answer if you have found out.

Setting a mint price for a contract extending a open zeplin ERC721URIStorage contract

I have the following contract in Solidity that was working up until I added the line
require(msg.value == mintPrice, "Not Enough Ether");
// contracts/NFT.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
contract NFT is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
uint256 mintPrice = 0.025 ether;
constructor() ERC721("NFT", "ITM"){}
function mint(address user, string memory tokenURI)
public
payable
returns (uint256)
{
require(msg.value == mintPrice, "Not Enough Ether");
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(user, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
}
I have the following chai test that fails saying not enough ether, but the address I am using is a hardhat address with tons of ether in it
describe("NFT", function () {
it("Should return a transaction hash, async function", async function () {
const NFT = await ethers.getContractFactory("NFT");
const nft = await NFT.deploy();
await nft.deployed();
expect(await nft.mint('0xf3...fFb92266', "/Users/.../web3/nft-next-minter/public/test.json")).to.have.any.keys('hash');
expect(await nft.tokenURI(1)).to.equal('/Users/.../web3/nft-next-minter/public/test.json');
});
})
I am running npx hardhat test --network localhost
Not quite sure why I am getting this error, any help would be greatly appreciated.
Thanks ahead of time.
await nft.mint(
'0xf3...fFb92266',
"/Users/.../web3/nft-next-minter/public/test.json"
)
This JS snippet doesn't specify any value of the transaction, so it's sent with 0 value by default.
And since the contract is expecting the value to equal mintPrice (0.025 ether), it fails the require() condition, effectively reverting the transaction.
You can specify the value in the overrides param (docs).
await nft.mint(
'0xf3...fFb92266',
"/Users/.../web3/nft-next-minter/public/test.json",
{value: ethers.utils.parseEther('0.025')}
)

Smart contract transfer eth to address failed

I'm trying to send eth from smart contract to contract owner's address but in vain. Here's my contract function:
function ownerDebit(uint amount) public payable onlyOwner returns(bool status){
status = owner.send(amount);
return status;
}
I'm using NodeJS and Web3JS to interact with this contract:
contract.methods.ownerDebit(10000000000000000).call().then(function(response){
console.log(response);
});
And the response in console.log was "true".
But the eth in my account remain the same.
address(this) is used to get the address of the contract.
status = address(this).transfer(owner, amount)

solidity error with addr.transfer(1 ether)

Error message:
transact to Payment.deposit errored: VM error: revert.
revert 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.
contract Payment{
address Account2;
address Owner;
constructor() public{
Account2 = 0x583031D1113aD414F02576BD6afaBfb302140225;
Owner = msg.sender;
}
function deposit() payable public{
address(uint160(Account2)).transfer(1 ether);
}
If you don't want to use msg.value then it is compulsory that your contract should have enough balance.
So you can create a fallback function in order to deposit enough ether to your contract first and then you can call your deposit() function.
Your contract after adding fallback function
pragma solidity ^0.5.1;
contract Payment{
address Account2;
address Owner;
constructor() public{
Account2 = 0x583031D1113aD414F02576BD6afaBfb302140225;
Owner = msg.sender;
}
function () payable external{}
function deposit() payable public{
address(uint160(Account2)).transfer(1 ether);
}
function getContractBalance() public view returns(uint) {
return address(this).balance;
}
}
It works without error on my remix VM.
So make sure:
The contract has a balance greater than 1 ether
If Account2 is a contract's address, then it need to have a fallback function to receive ether