I'm new to Solidity and i have this function to send value from the user account to the contract. It increments the balance of the user and that info is stored in a mapping.
function sendMoney() public payable {
payable(address(this)).transfer(msg.value);
balance_received[msg.sender] += msg.value;
}
It compiles and i can deploy but when calling the function i get this message:
"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."
I have funds in the user account and i state in the function that it's payable. What am I missing?
Thanks
Related
Setting up a bank contract to perform deposits and withdraws. I was wondering if its possible for the bank contract can execute the approve function in the erc20 contract on behalf of the msg.sender for the tokens they are wanting to deposit.
Below is my attempt for the bank contract to call the erc20 token contracts approve function. However wouldn't the msg.sender be the bank contract address instead of the original msg.sender (second line of the depositToken function.) This sounds silly but is there a way for the contract to send the request passing in the msg.senders address? If not is there an integrated way for the msg.sender to approve the bank contract address and the amount to enable the bank contract to call the transferFrom function and be provided the allowance.
//best guess on what that would look like inside the function depositTokens
msg.sender = customer;
customer.IER20(usdt).approve.address(this), uint _amount;
address public usdt;
mapping(address => uint) public bankBalance;
constructor() public {
usdt = 0x77c24f0Af71257C0ee26e0E0a108F940D1698d53;
}
usdt = 0x77c24f0Af71257C0ee26e0E0a108F940D1698d53;
function depositTokens(uint _amount) public {
IER20(usdt).approve.address(this), uint _amount;
// Trasnfer usdt tokens to contract
IERC20(usdt).transferFrom(msg.sender, address(this), _amount);
// Update the bank balance in map
bankBalance[msg.sender] = bankBalance[msg.sender] + _amount;
}
//approve function in erc20
function approve(address delegate, uint256 numTokens) public override returns (bool) {
allowed[msg.sender][delegate] = numTokens;
emit Approval(msg.sender, delegate, numTokens);
return true;
The answer is no, the approve function takes the msg.sender as the one that gives allowance. You can see the most used OpenZeppelin implementation here.
However I can see what you are trying to do and I want to add that there is a way to automatically ask an EOA (externally owned account) or a user with a wallet to approve some tokens to the contract before sending a transaction.
I don't know if a wallet does it automatically or you have to code it in the UI but I think that is what you are looking for.
And then after the user already approved your bank, you can remove your first line in the deposit function
Here are the steps I follow on Remix:
Deploy my ERC20Basic token and my DEX contract.
DEX.buy > Buy ERC20Basic tokens in exchange of ETH (works fine).
ERC20Basic.approve(contractAddress, tokenAmount) (works fine).
ERC20Basic.allowance > Works fine, function returns the amount of the allowance.
The problem comes when I try to sell tokens with this function from my DEX contract:
function sell(uint256 amount) public {
uint256 allowance = token.allowance(msg.sender, address(this));
require(allowance >= amount, "Check the token allowance");
token.transferFrom(msg.sender, address(this), amount);
payable(msg.sender).transfer(amount);
emit Sold(amount);
}
I still get "Check the token allowance".
When I log the allowance I get 0.
When I log msg.sender and address(this), I get the same addresses I used on the Remix interface to get the value of the allowance manually.
It feels like the allowance is reset to 0 when I call the sell function or that the sell function can't reach the value of the allowance. Maybe this is something about memory and storage?
My allowance function inside of ERC20Basic contract is:
function allowance(address owner, address delegate)
public
view
override
returns (uint256)
{
return allowed[owner][delegate];
}
Approval function:
function approve(address delegate, uint256 numTokens)
public
override
returns (bool)
{
allowed[msg.sender][delegate] = numTokens;
emit Approval(msg.sender, delegate, numTokens);
return true;
}
Allowance structure:
mapping(address => mapping(address => uint256)) allowed;
How are you calling the approve function?
In your code you aren't passing the require statement because your approval wasn't successful. If it was your allowance wouldn't be 0.
You are probably calling the approve function from the contract which won't work because then the msg.sender would be address of the contract not your accounts address.
You have to approve the amount manually outside of the contract for it to work.
I'm trying to create a function that destroys tokens in an address.
The remix has the error
DeclarationError: Undeclared identifier
mostly for totalSupply.
Can anyone check what the error is in the syntax and how to solve it?
Is this the best function, or is it better to remove the tokens and send them to the dead address, or to the contract itself, or even to leave it in the wallet of the holder and block their movement in the wallet forever? I would like advice (and mainly how to solve this code).
/**
#dev removes tokens from an account and decreases the token supply
can only be called by the contract owner
_from account to remove the amount from
_amount amount to decrease the supply by
*/
function removeTokens(address _from, uint256 _amount) public onlyOwner
{
balanceOf[_from] = sub(balanceOf[_from], _amount);
totalSupply = sub(totalSupply, _amount);
Transfer(_from, this, _amount);
Destruction(_amount);
}
Sub is the subtraction function of values (SafeMath)
I have such function to transfer tokens from contract and i get error where shoudl i add payable and i dont really understand if withdraw will withdraw ethers or tokens?
function withdrawBalances() public nonReentrant {
uint share = _Balances[msg.sender];
_Balances[msg.sender] = 0;
msg.sender.transfer(share);
}
.withdrawBalances 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.
This error occurs when you try to send some Ether when calling a function that isn't payable. Set Ether value to 0 to avoid this. You can also allow a function to accept Ether by using the payable keyword.
function withdrawBalances() public payable {
...
}
I get the following error every time I try to deploy a program with a wei value greater than zero:
Code:
pragma solidity ^0.5.1;
contract testContract {
uint value;
constructor (uint _p) public {
value = _p;
}
function setP(uint _n) payable public {
value = _n;
}
function setNP(uint _n) public {
value = _n;
}
function get () view public returns (uint) {
return value;
}
}
Output:
creation of testContract 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.
creation of testContract pending...
0 [vm] from: OxAb8...35cb2 to: testContract.(constructor) value: 1 wei data: 0x608...00001 logs: 0 hash: 0x344...07156
creation of testContract 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.
Perhaps you need to specify a "payable" specifier in the smart contract constructor - like for "setP" function.
This happens because you are sending Wei with the contract deployment transaction which is not required.
The transaction can get reverted because of the following reasons:
Transaction done is not for a payable function
The amount you are sending is less than you current balance