pragma solidity 0.8.0;
pragma abicoder v2;
import "./Ownable.sol";
import "./SafeMath.sol";
contract Bank is Ownable {
mapping(address => uint) balance;
address[] customers;
using SafeMath for uint;
event depositDone(uint amount, address indexed depositedTo);
function deposit() public payable returns (uint) {
balance = balance.add(msg.value);
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint amount) public onlyOwner returns (uint){
require(balance[msg.sender] >= amount);
balance = balance.sub(amount);
payable(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.sub(amount));
}
function _transfer(address from, address to, uint amount) private {
balance[from] = balance[from].sub(amount);
balance[to] = balance[to].add(amount);
}
}
This is my solution;
pragma solidity 0.8.0;
pragma abicoder v2;
import "ownable.sol";
import "safemath.sol";
contract Bank is Ownable {
using SafeMath for uint256;
mapping(address => uint) balance;
address[] customers;
event depositDone(uint amount, address indexed depositedTo);
function deposit() public payable returns (uint) {
balance[msg.sender] = balance[msg.sender].add(msg.value);
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint amount) public onlyOwner returns (uint){
require(balance[msg.sender] >= amount);
balance[msg.sender] = balance[msg.sender].sub(amount);
payable(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] = balance[from].sub(amount);
balance[to] = balance[to].add(amount);
}
}
Here is my assignment.
bank.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.0;
pragma abicoder v2;
import "./Ownable.sol";
import { SafeMath } from "./safemath.sol";
contract Bank is Ownable {
mapping(address => uint256) balance;
address[] customers;
event depositDone(uint256 amount, address indexed depositedTo);
function deposit() public payable returns (uint256) {
balance[msg.sender] = balance[msg.value].add(msg.value);
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint256 amount) public onlyOwner returns (uint256){
require(balance[msg.sender] >= amount);
balance[msg.sender] = balance[msg.sender].sub(amount);
payable(msg.sender).transfer(amount);
return balance[msg.sender];
}
function getBalance() public view returns (uint256){
return balance[msg.sender];
}
function transfer(address recipient, uint256 amount) public {
require(balance[msg.sender] >= amount, "Balance not sufficient");
require(msg.sender != recipient, "Don't transfer money to yourself");
_transfer(msg.sender, recipient, amount);
assert(balance[msg.sender] == balance[msg.sender].sub(amount);
}
function _transfer(address from, address to, uint256 amount) private {
balance[from] = balance[from].sub(amount);
balance[to] = balance[to].add(amount);
}
}
pragma solidity ^0.8.0;
import "./own.sol";
import "./Safemath.sol";
interface GovtInterface {
function addTransaction(address from, address to, uint amount) external payable;
}
contract Bank is Ownable {
using SafeMath for uint256;
GovtInterface GovernmentInstance= GovtInterface(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4);
mapping(address => uint256) balance;
event depositDone(uint amount, address indexed depositedTo);
function deposit() public payable returns (uint256) {
balance[msg.sender] += msg.value;
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint amount) public returns (uint256){
require(balance[msg.sender] >= amount);
balance[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
return balance[msg.sender];
}
function getBalance() public view returns (uint256){
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);
GovernmentInstance.addTransaction{value:1 ether}(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;
}
}
Bank.sol
pragma solidity 0.7.5;
pragma abicoder v2;
import "./Ownable.sol";
import "./Safemath.sol";
contract Bank is Ownable {
using SafeMath for uint;
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 onlyOwner returns (uint){
require(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 payable 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] = balance[from] - amount;
balance[to] = balance[to] + amount;
}
}
But Safemath.sol is 0.8.0, Bank.sol is 0.7.5 ?
Hi @makinitnow
But Safemath.sol is 0.8.0, Bank.sol is 0.7.5 ?
Can you please elaborate?
Cheers,
Dani
Mv bad, I had a previous version of Bank.sol 0.7.5 in Remix and I changed the Ownable in 0.8.0 too now.
These imported contracts should always have the same version, right?
I had also an error in the Bank.sol I did not notice, so I could not Deploy it.
It works now.
pragma solidity 0.8.0;
pragma abicoder v2;
import "./Ownable.sol";
import "./Safemath.sol";
contract Bank is Ownable {
using SafeMath for uint;
mapping(address => uint) balance;
address[] customers;
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 onlyOwner returns (uint){
require(balance[msg.sender] >= amount);
balance[msg.sender] -= amount;
payable(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;
}
}
pragma solidity 0.8.0;
pragma abicoder v2;
import "./SafeMath.sol";
contract Bank{
using SafeMath for uint;
mapping(address => uint) balance;
address owner;
constructor(){owner = msg.sender;}
modifier onlyOwner{
require(msg.sender == owner);
_;
}
event depositDone(uint amount, address indexed depositedTo);
function deposit() public payable returns (uint) {
balance[msg.sender] = balance[msg.sender].add(msg.value);
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint amount) public onlyOwner returns (uint){
require(balance[msg.sender] >= amount);
balance[msg.sender] = balance[msg.sender].sub(amount);
payable(msg.sender).transfer(amount);
return balance[msg.sender];
}
function getBalance() public view returns (uint){
return balance[msg.sender];
}
function transfer(address payable 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] = balance[from].sub(amount);
balance[to] = balance[to].add(amount);
}
}
Hi @makinitnow
These imported contracts should always have the same version, right?
Thatās correct, your contracts should be compatible with the Solidity version that you use to compile them.
In your SafeMath exercise, you have successfully imported the library but you did not use it
balance[msg.sender] += msg.value;
should be
balance[msg.sender] = balance[msg.sender].add(msg.value);
Regards,
Dani
I am being humbled again and again by the code, as I see I am not paying enough attention to detailsā¦
I am tring again & I have few more questions:
Bank2.sol
pragma solidity 0.8.0;
pragma abicoder v2;
import "./Ownable.sol";
import "./Safemath.sol";
contract Bank is Ownable {
using SafeMath for uint;
mapping(address => uint) balance;
address[] customers;
event depositDone(uint amount, address indexed depositedTo);
function deposit() public payable returns (uint) {
balance[msg.sender] = balance[msg.sender].add(msg.value);
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint amount) public onlyOwner returns (uint){
require(balance[msg.sender] >= amount);
balance[msg.sender] = balance[msg.sender].sub(amount);
payable(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.sub(amount));
}
function _transfer(address from, address to, uint amount) private {
balance[from] = balance[from].sub(amount);
balance[to] = balance[to].add(amount);
}
}
The error I also prevoiusly got was in the withdraw function, because I did dot wrote payable here:
payable(msg.sender).transfer(amount);
Isnāt msg.sender already a payable address? Why we write payable here?
Can you also explain the difference between the withdraw function in the above Bank2.sol & the withdraw function in the lecture explaining Re-entrency:
ChecksEffectsInteraction.sol
pragma solidity 0.8.0;
contract ChecksEffectsInteraction{
mapping(address => uint) balance;
function withdraw() public{
require([msg.sender] > 0);
uint toTransfer = balance[msg.sender];
balance[msg.sender] = 0;
(bool success,) = msg.sender.call{value: toTransfer}("");
if(!success){
balance[msg.sender] = toTransfer;
}
}
}
Should we now write the withdraw function in Bank2.sol also implementing what we learned about re-entrency?
Hi @makinitnow
Isnāt msg.sender already a payable address? Why we write payable here?
From Solidity >= 8, msg.sender is not payable anymore.
Should we now write the withdraw function in Bank2.sol also implementing what we learned about re-entrency?
Can you post that function please?
thanks,
Dani
Thank you.
Bank2.sol
function withdraw(uint amount) public onlyOwner returns (uint){
require(balance[msg.sender] >= amount);
balance[msg.sender] = balance[msg.sender].sub(amount);
payable(msg.sender).transfer(amount);
return balance[msg.sender];
}
ChecksEffectsInteraction.sol
pragma solidity 0.8.0;
contract ChecksEffectsInteraction{
mapping(address => uint) balance;
function withdraw() public{
require([msg.sender] > 0);
uint toTransfer = balance[msg.sender];
balance[msg.sender] = 0;
(bool success,) = msg.sender.call{value: toTransfer}("");
if(!success){
balance[msg.sender] = toTransfer;
}
}
}
Hey @makinitnow
In both functions, the pattern check / effect / interaction is respected.
1
function withdraw(uint amount) public onlyOwner returns (uint){
require(balance[msg.sender] >= amount); ----> CHECK
balance[msg.sender] = balance[msg.sender].sub(amount); ----> EFFECT
payable(msg.sender).transfer(amount); ----> INTERACTION
return balance[msg.sender];
}
2
function withdraw() public{
require([msg.sender] > 0); ----> CHECK
uint toTransfer = balance[msg.sender];
balance[msg.sender] = 0; ----> EFFECT
(bool success,) = msg.sender.call{value: toTransfer}(""); ----> INTERACTION
if(!success){
balance[msg.sender] = toTransfer;
}
}
Cheers,
Dani
pragma solidity 0.8.1;
pragma abicoder v2;
import "./Ownable.sol";
import "./safemath.sol";
interface GovermentInterface{
function addTransaction(address _from, address _to, uint _amount) external payable;
}
contract Bank is Ownable {
using SafeMath for uint256;
GovermentInterface govermentInstance = GovermentInterface(0x3328358128832A260C76A4141e19E2A943CD4B6D);
mapping(address => uint256) balance;
event depositDone(uint amount, address indexed depositedTo);
function deposit() public payable returns (uint256) {
balance[msg.sender] = msg.value;
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint amount) public onlyOwner returns (uint256){
require(balance[msg.sender] >= amount);
balance[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
return balance[msg.sender];
}
function getBalance() public view returns (uint256){
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);
govermentInstance.addTransaction{value:1 ether}(msg.sender, recipient, amount);
assert(balance[msg.sender] == previousSenderBalance - amount);
}
function _transfer(address from, address to, uint amount) private {
balance[from] = balance[from] - amount;
balance[to] = balance[to] + amount;
}
function getTransfers() external view returns(uint[] memory) {
}
}
not really anything to it but heres my solution anyway. And from reading older posts apparently safe math is not required below solidity 0.8.0 so cheers @thecil for mentioning that and linking the 0.8.0 documentation, good to know.
pragma solidity 0.8.0;
pragma abicoder v2;
import "./SafeMath.sol";
contract Bank {
using SafeMath for uint256;
mapping(address => uint) balance;
address[] customers;
modifier onlyOwner() {
bool isOwner = false;
for (uint i = 0; i < customers.length; i++) {
if (customers[i] == msg.sender) {
isOwner = true;
}
}
require(isOwner = true);
_;
}
event depositDone(uint amount, address indexed depositedTo);
function deposit() public payable returns (uint) {
balance[msg.sender] = balance[msg.sender].add( msg.value);
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint amount) public onlyOwner returns (uint){
require(balance[msg.sender] >= amount);
balance[msg.sender] = balance[msg.sender].sub(amount);
payable(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.sub(amount));
}
function _transfer(address from, address to, uint amount) private {
balance[from] = balance[from].sub(amount);
balance[to] = balance[to].add(amount);
}
}
pragma solidity 0.8.0;
pragma abicoder v2;
import "./Ownable.sol";
import "./Safemath.sol";
contract Bank is Ownable {
using SafeMath for uint256;
mapping(address => uint) balance;
address[] customers;
event depositDone(uint amount, address indexed depositedTo);
function deposit() public payable returns (uint) {
balance[msg.sender] = balance[msg.sender].add(msg.value);
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint amount) public onlyOwner returns (uint){
require(balance[msg.sender] >= amount);
balance[msg.sender] = balance[msg.sender].sub(amount);
payable(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] = balance[from].sub(amount);
balance[to] = balance[to].add(amount);
}
}
Hey @Mickey_McClimon
You are not using SafeMath in your contract, you are using arithmetic operators instead.
You are doing:
uint result = a + b;
Should be:
uint result = a.add(b);
Cheers,
Dani
Bank.sol
pragma solidity 0.8.0;
pragma abicoder v2;
import "./Ownable.sol";
import "./SafeMath.sol";
contract Bank is Ownable {
using SafeMath for uint256;
mapping(address => uint256) balance;
address[] customers;
event depositDone(uint256 amount, address indexed depositedTo);
function deposit() public payable returns (uint256) {
balance[msg.sender] = balance[msg.sender].add(msg.value);
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint256 amount) public onlyOwner returns (uint256){
require(balance[msg.sender] >= amount);
balance[msg.sender] = balance[msg.sender].sub(amount);
payable(msg.sender).transfer(amount);
return balance[msg.sender];
}
function getBalance() public view returns (uint256){
return balance[msg.sender];
}
function transfer(address recipient, uint256 amount) public {
require(balance[msg.sender] >= amount, "Balance not sufficient");
require(msg.sender != recipient, "Don't transfer money to yourself");
uint256 previousSenderBalance = balance[msg.sender];
_transfer(msg.sender, recipient, amount);
assert(balance[msg.sender] == previousSenderBalance.sub(amount));
}
function _transfer(address from, address to, uint256 amount) private {
balance[from] -= amount;
balance[to] += amount;
}
}
pragma solidity 0.8.0;
pragma abicoder v2;
import "./Ownable.sol";
import "./SafeMath.sol";
contract Bank is Ownable {
using SafeMath for uint256;
mapping(address => uint256) balance;
address[] customers;
event depositDone(uint amount, address indexed depositedTo);
function deposit() public payable returns (uint) {
balance[msg.sender] = balance[msg.sender].add(msg.value);
emit depositDone(msg.value, msg.sender);
return balance[msg.sender];
}
function withdraw(uint amount) public onlyOwner returns (uint){
require(balance[msg.sender] >= amount);
balance[msg.sender] = balance[msg.sender].sub(amount);
payable(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.sub(amount));
}
function _transfer(address from, address to, uint amount) private {
balance[from] = balance[from].sub(amount);
balance[to] = balance[to].add(amount);
}
}