Hi @mervxxgotti
If for whatever reason the transfer method fails, the function reverts.
A good lecture from you: https://vomtom.at/solidity-send-vs-transfer/
Cheers,
Dani
Hi @mervxxgotti
If for whatever reason the transfer method fails, the function reverts.
A good lecture from you: https://vomtom.at/solidity-send-vs-transfer/
Cheers,
Dani
clarified! thank you!
To ensure that the user cannot withdraw more than their balance, we have to require that his balance is greater than or equal to the amount withdrawn.
See code below;
function withdraw(uint amount) public returns (uint){
require(balance[msg.sender] >= amount, "Balance not up to amount);//checks user
//balance is adequate
balance[msg.sender] -= amount;//deducts amount from user balance
msg.sender.transfer(amount);//transfers the amount
return balance[msg.sender];//retrieves the user balance after transfer
}
Adding the necessary require() to insure a user cannot withdraw more than we think theyâre entitled to. Also note the âChecksâ>Effects -->Interactionsâ pattern is in play:
function withdraw(uint amount) public returns (uint){
require(balance[msg.sender] >= amount,"Insuficient Funds");
balance[msg.sender] -= amount;
msg.sender.transfer(amount);
return balance[msg.sender];
}
function withdraw(uint amount) public returns (uint) {
require(balance[msg.sender] >= amount, "Not enough funds");
balance[msg.sender] -= amount;
msg.sender.transfer(amount);
return balance[msg.sender];
}
require(balance[msg.sender] >= amount
pragma solidity 0.7.5;
contract Bank {
mapping(address => uint) balance;
address owner;
constructor() {
owner = msg.sender;
}
event depositDone(uint amount, address indexed depositedTo);
modifier onlyOwner {
require(msg.sender == owner, 'only owner can add balance');
_;
}
function deposit() public payable returns (uint) {
balance[msg.sender] += msg.value;
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint amount) public returns(uint) {
require(balance[msg.sender] >= amount, 'cannot exceed your own balance');
msg.sender.transfer(amount);
balance[msg.sender] -= amount;
return balance[msg.sender];
}
function getBalance() public view returns(uint) {
return balance[msg.sender];
}
function transfer(address recipient, uint amount) public {
require(balance[msg.sender] >= amount,'amount cannot exceed balance');
require(msg.sender != recipient);
_transfer(msg.sender, recipient, amount);
}
function _transfer(address from, address to, uint amount) private {
balance[from] -= amount;
balance[to] += amount;
}
}
msg.sender.transfer(amount);
balance[msg.sender] -= amount;
@filip I checked the solution you posted. The order of these two statements matter? Itâs the opposite in your solution.
check this answer, which play a patter that will be explained to you in the next lessons.
Carlos Z
function withdraw(uint amount) public returns (uint){
require (balance[msg.sender] >= amount, âBalance not sufficientâ); //make sure this address has sufficient balance at this contract
msg.sender.transfer(amount); //transfer function has in-built error throwing
balance[msg.sender] -= amount;
}
function withdraw(uint amount) public returns (uint){
require(balance[msg.sender] >= amount, 'Balance not sufficient');
msg.sender.transfer(amount);
balance[msg.sender] -= amount;
return balance[msg.sender];
}
function withdraw(uint amount) public returns (uint){
//msg.sender is an address (payable by default)
//address payable toSend = 0x1aE0EA34a72D944a8C7603FfB3eC30a6669E454C
require(balance[msg.sender] >= amount, "You have insufficient funds!");
msg.sender.transfer(amount);
balance[msg.sender] -= amount;
}
return balance[msg.sender];
I got this to work but I was trying to get rid of the additional function. I donât understand why the effect on memory vs storage is different by adding function.
pragma solidity 0.7.5;
contract Bank {
//storage - permanent storage of data (state variables)
//memory - temporary storage used in function execution
//calldata - save arguments/inputs to our functions
//strings, arrays, mappings, structs
mapping(address => uint) balance;
address owner;
modifier onlyOwner {
require(msg.sender == owner);
_; //run the function
}
event depositDone(uint amount, address indexed depositedTo);
event transfers(address transferFrom, address transferTo, uint amount);
constructor(){
owner = msg.sender;
}
function deposit() public payable returns (uint) {
balance[msg.sender] += msg.value;
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint amount) public payable returns (uint){
//msg.sender is an address
require(balance[msg.sender] >= amount, "Balance not sufficient");
msg.sender.transfer(amount);
uint previousSenderBalance = balance[msg.sender];
_withdraw(msg.sender, amount);
assert(balance[msg.sender] == previousSenderBalance - amount);
}
function _withdraw(address from, uint amount) private {
balance[from] -= amount;
}
function getBalance() public view returns (uint){
return balance[msg.sender];
}
function transfer(address recipient, uint amount) public {
require(balance[msg.sender] >= amount, "Balance not sufficient");
require(msg.sender != recipient, "Don't transfer money to yourself");
uint previousSenderBalance = balance[msg.sender];
_transfer(msg.sender, recipient, amount);
assert(balance[msg.sender] == previousSenderBalance - amount);
emit transfers(msg.sender, recipient, amount);
}
function _transfer(address from, address to, uint amount) private {
balance[from] -= amount;
balance[to] += amount;
}
}
pragma solidity 0.7.5;
contract Bank {
mapping(address => uint) balance;
event depositDone(uint amount, address indexed depositedTo);
function deposit() public payable returns (uint) {
balance[msg.sender] += msg.value;
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint amount) public returns (uint){
require(balance[msg.sender] >= amount);
balance[msg.sender] -= amount;
msg.sender.transfer(amount);
return balance[msg.sender];
}
function getBalance() public view returns (uint){
return balance[msg.sender];
}
function transfer(address recipient, uint amount) public {
require(balance[msg.sender] >= amount, "Balance not sufficient");
require(msg.sender != recipient, "Don't transfer money to yourself");
uint previousSenderBalance = balance[msg.sender];
_transfer(msg.sender, recipient, amount);
assert(balance[msg.sender] == previousSenderBalance - amount);
}
function _transfer(address from, address to, uint amount) private {
balance[from] -= amount;
balance[to] += amount;
}
}
Hereâs my solution:
function withdraw(uint a_amount) public returns(uint){
require(balances[msg.sender] >= a_amount, "Insufficient Balance");
balances[msg.sender] -= a_amount;
msg.sender.transfer(a_amount);
return balances[msg.sender];
}
Iâd particularly like to commend @marsrvr for referencing the Checks Effects Interactions pattern which is well demonstrated here. By executing the transfer last, reentrant code canât abuse internal state because the effect of the withdrawal (namely the mutation of the mapping) has already been applied.
Implemented require function to check if the amount input is valid. Also added an assert function to check that the balance got adjusted correctly.
Question to this: would this assert function actually add security to my contract or is it unnecessary?
function withdraw(uint amount) public returns (uint) {
require(amount <= balance[msg.sender], "Insufficient balance");
uint previousSenderBalance = balance[msg.sender];
balance[msg.sender] -= amount;
msg.sender.transfer(amount);
assert(balance[msg.sender] == previousSenderBalance - amount);
return balance[msg.sender];
}
Hey @Santiago
The assert statement is unnecessary here as the whole function would revert in case the .trasfer method fails.
Cheers,
Dani
First check if the balance is >= then the amount you want to withdraw
then subtract the amount from the balance
as last return the balance
function withdraw(uint amount) public returns (uint){
require(balance[msg.sender] >= amount, 'Balance insufficient');
msg.sender.transfer(amount);
balance[msg.sender] -= amount;
return balance[msg.sender];
}
The require amount > 0 is just to reduce gas fees if user accidentally withdraws 0âotherwise it isnât needed to solve this problem.
function withdraw(uint amount) public returns (uint) {
require(balance[msg.sender] >= amount, "Insufficient funds!");
require(amount > 0, "Must withdraw more than 0!");
uint initialBalance = balance[msg.sender];
msg.sender.transfer(amount);
balance[msg.sender] -= amount;
assert(initialBalance > balance[msg.sender]);
}