Assignment - SafeMath

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);
    }
    
}
1 Like

Hey @MyName

Only functions declared as view show the returned value.

Cheers,
Dani

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);
    }
    
}
1 Like

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);
    }
    
}
2 Likes
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;
    }
    
}
1 Like

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;
    }
    
}
1 Like
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);
    }
    
}
1 Like

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 :slight_smile:

balance[msg.sender] += msg.value;

should be

balance[msg.sender] = balance[msg.sender].add(msg.value);

Regards,
Dani

1 Like

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?

1 Like

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

1 Like

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

1 Like
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) {

    }
    
}
1 Like

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);
    }
    
}
1 Like
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

1 Like
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;
    }
    
}
1 Like
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);
    }
    
}
1 Like