I have a contract deployed on goerli testnet but I don't understand why the contract balance doesn't increase after minting an nft.
Contract on goerli:
https://goerli.etherscan.io/address/0x41c13FF48Edc715612763394Ac8D36C4d11b5856
Succesful mint transaction:
https://goerli.etherscan.io/tx/0x4a0248639a427b2a824433dce5712d1d86bf85d8a7658d0215aff8cdc9448ea9
uint256 public constant TOTAL_SUPPLY = 100;
uint256 public constant MINT_PRICE = 0.02 ether;
uint256 public constant MAX_PUBLIC_MINT = 10;
function mintTo(address recipient, uint256 count) public payable {
uint256 tokenId = currentTokenId.current();
require(tokenId < TOTAL_SUPPLY, "Max supply reached");
require(
count > 0 && count <= MAX_PUBLIC_MINT,
"Max mint supply reached"
);
require(
msg.value == MINT_PRICE * count,
"Transaction value did not equal the mint price"
);
for (uint256 i = 0; i < count; i++) {
currentTokenId.increment();
uint256 newItemId = currentTokenId.current();
_safeMint(recipient, newItemId);
}
bool success = false;
(success, ) = owner().call{value: msg.value}("");
require(success, "Failed to send to owner");
}
I tried minting using hardhat:
task("mint", "Mints from the NFT contract")
.addParam("address", "The address to receive a token")
.setAction(async function (taskArguments, hre) {
const contract = await getContract("NftGame", hre);
const transactionResponse = await contract.mintTo(taskArguments.address, 1, {
gasLimit: 500_000,
value: ethers.utils.parseEther(String(0.02 * 1))
});
console.log(`Transaction Hash: ${transactionResponse.hash}`);
});
What balance should be incremented? Show us the entire contract.
If you mean the balance of the NFTs minted to some address, check the balanceOf(address) method.
But I think by "contract balance doesn't increase after minting an nft" you mean the ether balance of the contract does not increase after calling mintTo. The reason behind this can be found in line (success, ) = owner().call{value: msg.value}("");. The ether send with a tx when calling mintTo is sent to the owner of the contract. For this reason, the ether balance of the contract does not increase, but the ether balance of the contract owner should increase by msg.value. Look at the tx you provided, it says "TRANSFER 0.02 Ether From 0x41c13ff48edc715612763394ac8d36c4d11b5856 To 0x6c3455607f5592612e9e3754ba37c63123d68722" where 0x41c13ff48edc715612763394ac8d36c4d11b5856 is the address of the contract and 0x6c3455607f5592612e9e3754ba37c63123d68722 is the address of the owner of the contract.
Related
I new to solidity so could you guys please help me thanks? I tried to deploy the contract will ETH Value but always got the error "The transaction has been reverted to the initial state.
The called function should be payable if you send value and the value you send should be less than your current balance.".
Is there any way to fix this?
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract CustomToken is ERC20 {
constructor(string memory name, string memory symbol) ERC20(name, symbol){
_mint(msg.sender, 1000000 * 10 ** 18);
}
}
contract Uniswap {
// Custom tokens to be initialiazed
string[] public tokens = ["CoinA", "CoinB", "CoinC"];
// map to maintain the tokens and its instances
mapping(string => ERC20) public tokenInstanceMap;
// 1 CoinA/CoinB/COinC = 0.0001 eth
uint256 ethValue = 100000000000000;
// 0.0001 eth = 1 CoinA/CoinB/CoinC
// 1 CoinA/CoinB/CoinC = 1 CoinA/CoinB/CoinC
constructor() {
for (uint i=0; i<tokens.length; i++) {
CustomToken token = new CustomToken(tokens[i], tokens[i]);
tokenInstanceMap[tokens[i]] = token;
}
}
function getBalance(string memory tokenName, address _address) public view returns (uint256) {
return tokenInstanceMap[tokenName].balanceOf(_address);
}
function getTotalSupply(string memory tokenName) public view returns (uint256) {
return tokenInstanceMap[tokenName].totalSupply();
}
function getName(string memory tokenName) public view returns (string memory) {
return tokenInstanceMap[tokenName].name();
}
function getTokenAddress(string memory tokenName) public view returns (address) {
return address(tokenInstanceMap[tokenName]);
}
function getEthBalance() public view returns (uint256) {
return address(this).balance;
}
function swapEthToToken(string memory tokenName) public payable returns (uint256) {
uint256 inputValue = msg.value;
uint256 outputValue = (inputValue / ethValue) * 10 ** 18; // Convert to 18 decimal places
require(tokenInstanceMap[tokenName].transfer(msg.sender, outputValue));
return outputValue;
}
}
I try with 0 ETH and it worked fine!
(https://i.stack.imgur.com/UtLNt.png)
However, with 1 ETH and it got error message
(https://i.stack.imgur.com/MsjE0.png)
A function needs to use the payable modifier in order to accept ETH.
When you're deploying a contract, it executes the constructor.
constructor(string memory name, string memory symbol) ERC20(name, symbol) payable {
_mint(msg.sender, 1000000 * 10 ** 18);
}
i got stucked in it and i don't understand where the error is...
Is a Lottery Project and the problem comes in placeABid function in lottery.sol contract.
Below i attached my code:
LotteryToken.sol
//SPDX-License-Identifier: MIT
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
pragma solidity ^0.8.4;
contract LotteryToken is Ownable, ERC20{
mapping(address=>uint)private _balances;
constructor(string memory name, string memory symbol, uint totalSupply)ERC20(name, symbol){
_mint(msg.sender, totalSupply);
_balances[msg.sender] = totalSupply;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual override returns (bool) {
address owner = owner();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
function _transfer(
address _from,
address _to,
uint _amount
)internal virtual override{
_balances[_from] -= _amount;
_balances[_to] += _amount;
super._transfer(_from, _to, _amount);
}
function balanceOf(address account)public view virtual override returns(uint){
return _balances[account];
}
}
Lottery.sol
//SPDX-License-Identifier: MIT
import "#openzeppelin/contracts/access/Ownable.sol";
import "./LotteryToken.sol";
import "./LotteryInfo.sol";
pragma solidity ^0.8.4;
contract Lottery is Ownable{
LotteryInfo private lotteryInfo;
LotteryToken private lotteryToken;
event BidCorrect(address bidder, uint tokenId, uint defaultBid);
constructor(){
}
function initLotteryTokenContract(address _lotteryTokenContract)public onlyOwner{
lotteryToken = LotteryToken(_lotteryTokenContract);
lotteryToken.increaseAllowance(address(this), lotteryToken.balanceOf(lotteryToken.owner()));
}
function initLotteryInfoContract(address _lotteryInfoContract)public onlyOwner{
lotteryInfo = LotteryInfo(_lotteryInfoContract);
}
function setItemToWin(
string memory _name,
uint _defaultBid,
uint _endingTimeLottery
)public onlyOwner{
require(_endingTimeLottery > block.timestamp, "Cannot set a date in the Past!");
lotteryInfo.setItemToWin(_name, _defaultBid, _endingTimeLottery);
}
function buyTokens(uint _quantity)external payable{
uint singleTokenPrice = 0.02 ether;
uint finalPrice = singleTokenPrice * _quantity;
require(msg.sender != owner() && msg.sender != lotteryToken.owner(), "Admin Cannot Buy Tokens!");
require(msg.value == finalPrice, "Please set the right price!");
payable(owner()).transfer(msg.value);
address lotterytokenOwner = lotteryToken.owner();
lotteryToken.transferFrom(lotterytokenOwner, msg.sender, _quantity);
}
function placeABid(uint _tokenIds)external{
require(block.timestamp < lotteryInfo.getEndingTimeLottery(_tokenIds), "Lottery is closed!");
require(msg.sender != owner() && msg.sender != lotteryToken.owner(), "Admin Cannot Place A Bid!");
uint requiredTokenAmounts = lotteryInfo.getDefaultItemBid(_tokenIds);
require(lotteryToken.balanceOf(msg.sender) >= requiredTokenAmounts, "No Necessary Funds To Partecipate!");
address lotteryTokenOwner = lotteryToken.owner();
lotteryToken.transferFrom(msg.sender, lotteryTokenOwner, requiredTokenAmounts);
lotteryInfo.updateBid(_tokenIds, requiredTokenAmounts);
lotteryInfo.updateAddress(_tokenIds, msg.sender);
emit BidCorrect(msg.sender, _tokenIds, requiredTokenAmounts);
}
There is another contract LotteryInfo but doesn't need to understand the problem.
What i want to do is to place a bid and send back the amount of bid to the lotteryToken.owner() but i receive error revert "ERC20 insufficient allowance".
Can someone explain me why?
Thanks a lot
You have to call "approve" method from the caller of "placeABid" function. He/She has to approve your Lottery contract to spend (calling transferFrom) he/shes ERC20 tokens. Without increasing the allowance (approval) of ERC20, you wont be able to withdraw ERC20 tokens from msg.sender.
You can detaily check ERC20 standart contract from OpenZeppelin library aswell.
First you have to call approve method from the caller of placeABid function. Then person has to approve your Lottery contract to spend (calling transferFrom) the ERC20 tokens. Without increasing the allowance (approval) of ERC20, you wont be able to withdraw ERC20 tokens from msg.sender.
If amount is the maximum uint256, the allowance is not updated on
* transferFrom. This is semantically equivalent to an infinite approval.
* Requirements:
- spender cannot be the zero address.
Here's a reference link
This is the simple contract in which I am allowing user to open an account i.e smart contract acts as a account. I have kept an initial balance limit of 1 ether i.e user is bond to pay 1 ether at the time of opening of the account. Moreover, user has to set the secret key which will used for withdrawing the balance. In withdraw function I am unable to transfer ether back to the user. I am checking the balance of the user and after verifying balance condition. I am sending back the ether to the depositor. Can anyone help me I have commented the line on which I am facing the issue.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract ActualBank{
uint minAccountBalance=1 ether;
address payable owner;
mapping(address => uint256) balance ;
mapping(address => uint256) secretKey;
constructor(){
owner=payable(msg.sender);
}
function openAccount(uint256 _secretKey) payable public returns(uint256) {
require(msg.value >= minAccountBalance,"There must a minimum balance of 1 ether");
balance[msg.sender]+=msg.value;
secretKey[msg.sender]=_secretKey;
return balance[msg.sender];
}
function withDraw(uint256 _secretKey) payable public returns(uint256) {
require(msg.value <= balance[msg.sender],"With drawal value not correct");
require(secretKey[msg.sender] == _secretKey, "Secret key didn't matched");
balance[msg.sender]-=msg.value;
address payable receiver= payable(msg.sender);
receiver.transfer(msg.value); // issue seems to be on this line
return balance[msg.sender];
}
function getAccountBalance() public view returns(uint256){
return balance[msg.sender];
}
}
I think it's a bit strange because Msg.value is the ETH sent to the contract when the user calls the contract, you should want to send the balance on the contract to the user, right? Then you should change this code
receiver.transfer(msg.value); // issue seems to be on this line
to this
receiver.transfer(address(this).balance); // issue seems to be on this line
UPDATE:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract ActualBank{
uint minAccountBalance=1 ether;
address payable owner;
mapping(address => uint256) balance ;
mapping(address => uint256) secretKey;
constructor(){
owner=payable(msg.sender);
}
function openAccount(uint256 _secretKey) payable public returns(uint256) {
require(msg.value >= minAccountBalance,"There must a minimum balance of 1 ether");
balance[msg.sender]+=msg.value;
secretKey[msg.sender]=_secretKey;
return balance[msg.sender];
}
function withDraw(uint256 _secretKey) payable public returns(uint256) {
require(address(this).balance >= balance[msg.sender],"With drawal value not correct");
require(secretKey[msg.sender] == _secretKey, "Secret key didn't matched");
balance[msg.sender] = 0;
address payable receiver= payable(msg.sender);
receiver.transfer(address(this).balance); // issue seems to be on this line
return balance[msg.sender];
}
function getAccountBalance() public view returns(uint256){
return balance[msg.sender];
}
}
I just modified all the code and it should run fine :)
I am trying to build an arbitrage bot (learning) using AAVE flashloans, 0x and 1 Inch exchange swaps. While my flashloan call is successful but swap call to 0x exchange fails and revert 'SWAP_CALL_FAILED'. To examine I have tested both of my swap functions individually (by making them external payable and calling) and they work perfectly fine. But when I use them in my contract 0x swap fail.
Question - Could it be because the _zrxSwap (0x swap function) is an internal function? I can't seem to understand the reason.
My contract code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.6;
pragma experimental ABIEncoderV2;
import "./aave/FlashLoanReceiverBase.sol";
import "./aave/ILendingPoolAddressesProvider.sol";
import "./aave/ILendingPool.sol";
import "hardhat/console.sol";
import "./interfaces/IOneInchExchange.sol";
// A partial WETH interface.
interface IWETH is IERC20 {
function deposit() external payable;
function withdraw(uint256) external;
}
// Flashloan contract
contract Flashloan is FlashLoanReceiverBase {
uint public walletBalance = 0;
address payable beneficiary;
// The WETH contract.
IWETH public immutable WETH;
// One Inch Exchange Config
address ONE_INCH_EXCHANGE = 0x111111125434b319222CdBf8C261674aDB56F3ae;
// ZRX Config -- Mainet
address ZRX_EXCHANGE_PROXY_ADDRESS = 0xDef1C0ded9bec7F1a1670819833240f027b25EfF;
// Struct to pass calldata
struct MyCustomData {
address loanToken;
uint256 loanAmount;
uint256 repayAmount;
address arbToken;
bytes zrxData;
bytes oneData;
}
constructor(
address _addressProvider,
address payable _beneficiary,
IWETH weth
) FlashLoanReceiverBase(_addressProvider) public {
beneficiary = _beneficiary;
WETH = weth;
}
/**
This function is called after your contract has received the flash loaned amount
*/
function executeOperation(
address _reserve,
uint256 _amount,
uint256 _fee,
bytes calldata _params
)
external
override
{
MyCustomData memory mcd = abi.decode(_params, (MyCustomData));
require(_amount <= getBalanceInternal(address(this), _reserve), "Invalid balance, was the flashLoan successful?");
walletBalance = _amount;
// Arbitrage
_arb(mcd.loanToken, mcd.arbToken, mcd.loanAmount, mcd.zrxData, mcd.oneData);
uint totalDebt = _amount.add(_fee);
transferFundsBackToPoolInternal(_reserve, totalDebt);
}
function _arb(address _fromToken, address _toToken, uint256 _fromAmount, bytes memory _0xData, bytes memory _calldata) internal {
// Track original balance
uint256 _startBalance = IERC20(_fromToken).balanceOf(address(this));
// Perform the arb trade
_trade(_fromToken, _toToken, _fromAmount, _0xData, _calldata);
// Track result balance
uint256 _endBalance = IERC20(_fromToken).balanceOf(address(this));
// Require that arbitrage is profitable
require(_endBalance > _startBalance, "End balance must exceed start balance.");
}
function _trade(address _fromToken, address _toToken, uint256 _fromAmount, bytes memory _0xData, bytes memory _calldata) internal {
// Track the balance of the token RECEIVED from the trade
uint256 _beforeBalance = IERC20(_toToken).balanceOf(address(this));
// Swap on 0x: give _fromToken, receive _toToken
_zrxSwap(_fromToken, _fromAmount, _0xData);
// Calculate the how much of the token we received
uint256 _afterBalance = IERC20(_toToken).balanceOf(address(this));
// Read _toToken balance after swap
uint256 _toAmount = _afterBalance - _beforeBalance;
// Swap on 1Split: give _toToken, receive _fromToken
_oneSplitSwap(_toToken, _fromToken, _toAmount, _calldata);
}
// Swap back tokens on 0x exchange
function _zrxSwap(address _from, uint256 _amount, bytes memory _calldata) internal {
// Approve tokens
IERC20 _fromIERC20 = IERC20(_from);
// Approve zrx contract
require(_fromIERC20.approve(ZRX_EXCHANGE_PROXY_ADDRESS, uint256(-1)));
// Swap tokens
(bool success, ) = ZRX_EXCHANGE_PROXY_ADDRESS.call{value: _amount}(_calldata);
require(success, 'SWAP_CALL_FAILED');
// Reset approval
_fromIERC20.approve(ZRX_EXCHANGE_PROXY_ADDRESS, 0);
}
// Swap back tokens on 1 Inch exchange
function _oneSplitSwap(address _from, address _to, uint256 _amount, bytes memory _calldata) internal {
// Setup contracts
IERC20 _fromIERC20 = IERC20(_from);
IERC20 _toIERC20 = IERC20(_to);
IOneInchExchange _oneExchangeContract = IOneInchExchange(ONE_INCH_EXCHANGE);
// Approve tokens
_fromIERC20.approve(address(_oneExchangeContract), uint256(-1));
// Unpack the params
(IOneInchCaller caller, IOneInchExchange.SwapDescription memory desc, IOneInchCaller.CallDescription[] memory calls) = abi
.decode(_calldata, (IOneInchCaller, IOneInchExchange.SwapDescription, IOneInchCaller.CallDescription[]));
// Swap tokens: give _from, get _to
uint256 returnAmount = _oneExchangeContract.swap{ value: msg.value }(caller, desc, calls);
require(returnAmount > 0, '1INCH_SWAP_CALL_FAILED');
// Reset approval
_fromIERC20.approve(address(_oneExchangeContract), 0);
}
// Transfer ETH into this contract and wrap it into WETH.
function depositWETH()
external
payable
{
WETH.deposit{value: msg.value}();
}
/**
Flash loan 1000000000000000000 wei (1 ether) worth of `_asset`
*/
function flashloan(
address _loanToken,
uint256 _loanAmount,
address _arbToken,
bytes memory _zrxData,
bytes memory _calldata,
uint256 _gas
) public onlyOwner {
uint256 _repayAmount = _loanAmount.add(_gas);
bytes memory _params = abi.encode(MyCustomData({
loanToken: _loanToken,
loanAmount: _loanAmount,
repayAmount: _repayAmount,
arbToken: _arbToken,
zrxData: _zrxData,
oneData: _calldata
}));
uint amount = _loanAmount * 1e18;
ILendingPool lendingPool = ILendingPool(addressesProvider.getLendingPool());
lendingPool.flashLoan(address(this), _loanToken, amount, _params);
}
}
My Tx call:
const tx = {
from: owner,
to: flashloanAddress,
gas: 30000000,
data: flashloanContract.methods.flashloan(
fromAssetAddress,
1,
toAssetAddress,
zrx_data,
one_exchange_data,
total_gas
).encodeABI(),
}
// Web3 code
let amount = 55;
let messageToSign = `Please sign the message for claiming the reward amount of
${amount} tokens!`;
let signature = await web3_obj.eth.personal.sign(messageToSign, account.toString());
// Smart contract code to verify the signed message to get the signer's address
function getSigner(uint _amount, bytes memory _signature)
public
pure
returns(address) {
bytes32 _prefixHash =
ECDSA.toEthSignedMessageHash(keccak256(abi.encodePacked("Please sign the
message for claiming the reward amount of ", _amount, " tokens!")));
return ECDSA.recover(_prefixHash, _signature);
}