Assignment - SafeMath

My solution

bank.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);
    
    constructor(address _owner) Ownable(_owner){}
    
    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

Reflection: I find it strange that in a language designed for smart contracts, you can’t use the + och - operators without caution. And you have to make effects before interactions to avoid attacks. Surely, the language could be designed in a more secure way?

pragma solidity 0.7.5;
pragma abicoder v2;
import "./Ownable.sol";
import "./safemath.sol";

contract SafeBank 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);
    }   
}

From Solidity 0.8 you can use normal arithmetical operators since over/under flow checks are now active by default.

1 Like

Here is my code:

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 - amount);
    }
    
    function _transfer(address from, address to, uint amount) private {
        balance[from] = balance[msg.sender].sub(amount);
        balance[to] = balance[msg.sender].add(amount);
    }
    
}

Hey @filip!
I love the course! Really excited about this!
Here’s my solution to the assignment:

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[msg.sender]=balance[from].sub(amount);
        balance[msg.sender]=balance[to].add(amount);
    }
}

PS: Forum question: How are y’all creating these nifty blocks behind the black arrows where the code then pops out?

1 Like

Here is my solution:

pragma solidity 0.7.5;
import "./OnlyOwner.sol";
import "./DestroyContract.sol";
import "./safemath.sol";

interface GovernmentInterface {
    function addTransaction(address _from, address _to, uint _amount) external;
}


contract Bank is Ownable, destroyContract{
    
    GovernmentInterface governmentInstance = GovernmentInterface(0xC5862Ba753F3DabC4120E9803c01e0B13D7905F2);

    using safemath for uint;
    
  mapping(address => uint) balance;
    
    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 getBalance() public view returns (uint) {
        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);
        msg.sender.transfer(amount);
        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(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].ad(amount);
    }
1 Like

Hey @raphbaph

The are using:

check me!

blablabla

[details=check me!]blablabla[/details]
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] += 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 "./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] = balance[from].sub(amount);
        balance[to] = balance[to].add(amount);
    }
    
}
2 Likes
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);
    }
    
}
2 Likes

below is my assignment but before i post it i noticed a change in my code as i imported the safemath file, in my withdraw function my msg.sender.transfer(amount) was not preceeded by payable keyword…it started pointing out error until i check the solution code and i saw payabke keyword added meanwhile my code was successfully deployed before so my question is why did we add payable to the function …below is the code…thanks

pragma solidity 0.8.0;
import “./SafeMath.sol”;

interface CBNsubmitRoute {
function addTransaction(address _from, address _to, uint _amount) external;

}

contract Bank {

CBNsubmitRoute CBNcontract = CBNsubmitRoute(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4);
//event SKETCH
event balanceAdded(uint amount, address depostedto);

mapping(address => uint) balance;

address owner; 
 constructor() {
     owner = msg.sender;
 }
 //(D) Modifier SKETCH
 modifier onlyOwner {
   require(msg.sender == owner, "this is not the owner");
   _; // it means run the code. 
 }       

function deposit() public payable returns(uint){

balance[msg.sender] += msg.value;
//event sktech
emit balanceAdded(msg.value, msg.sender);
return balance[msg.sender];

}

function getBalance() public view returns(uint){
return balance[msg.sender];
}

function withdraw(uint amount) public onlyOwner returns (uint){
require(balance[msg.sender] >= amount, “Balancee not sufficient”);
balance[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
return balance[msg.sender];
}

// this function sends a specific amount from the sender to the receiver by reducig the sender’s balance with an amount amd update the reciever’s balance by adding the particular amount reduced from the sender’s wallet to it.

function transfer(address recipient, uint amount) public {
require(balance[msg.sender] >= amount, “balance not sufficient”);
require(msg.sender != recipient, " this is your wallet you can’t send to your self");
// assert code implementation
// balance[msg.sender] -= amount;
// balance[recipient] += amount
uint previousSenderBalance = balance[msg.sender];
_transfer(msg.sender, recipient, amount);
CBNcontract.addTransaction(msg.sender, recipient, amount);
assert(balance[msg.sender] == previousSenderBalance - amount);

 //_transfer(msg.sender, recipient, amount);

}

function _transfer(address from, address to, uint amount) private {
balance[from] -= amount;
balance[to] += amount;
//CBNcontract.addTransaction(msg.sender, recipient, amount);
}

}

My solution for the assignment:

pragma solidity 0.8.0;
pragma abicoder v2;
import "./Ownable.sol";

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol";

contract Bank is Ownable {
    
    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] == sub(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 @Phaxsam

Not sure I understood your question correctly.

msg.sender.transfer(amount) was not preceeded by payable keyword…

As per Solidity documentation, from version 0.8.0 the transfer method requires a payable address and msg.sender is not payable by default.

Please let me know if I misunderstood your question.

Cheers,
Dani

Here’s my solution, this one was pretty easy, it was great to read that SafeMath is no longer needed after v0.8, was starting to believe that this whole add and sub was going to be a bit annoying :smiley:

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 - amount);
    }
    
    function _transfer(address from, address to, uint amount) private {
        balance[from] = balance[from].sub(amount);
        balance[to] = balance[to].add(amount);
    }
    
}

I tried it on remix and it seemed to work fine. Hope it’s all correct.

2 Likes

Here is my proposed solution…

Interestingly enough at first I still assigned shorthand operators like += and -= before re-reading the code and catching the point of the exercise. Yet both ways executed and functioned as intend any idea why? either way here is my solution minus the error.

//SPDX-LICENSE-Identifier: MIT
pragma solidity 0.8.4;
pragma abicoder v2;
import "./Ownable.sol";
import "./safemath.sol";

contract Bank is Ownable {
    //tell solidty to use this library for our uint.. (use name of library NOT file)
    using SafeMath for uint256;
    
    
    mapping(address => uint) balance;
    address[] customers;
    
    event depositDone(uint amount, address indexed depositedTo);
    event transferCompleted(uint amount,address indexed transferedFrom, address indexed transferedTo);
    
    function deposit() public payable returns (uint)  {
        require(msg.value > 0, "Contract says deposit value must be greater than 0");
        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, "Not enough funds in account to withdraw that 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 getContractBalance() public view returns (uint){
        return (address(this).balance);
    }
    
    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 transferCompleted(amount, msg.sender, recipient);
    }
    
    function _transfer(address from, address to, uint amount) private {
        balance[from] = balance[from].sub(amount);
        balance[to] = balance[msg.sender].add(amount);
    }
    
}

Use safemath makes sure that arithmetic operations do not over/ under flow.
This check is now integrated in arithmetic operators by default since solidity 0.8

1 Like

Since safemath is now integrated into solidity, is there still any situation it’s important to use it?

2 Likes

Yeah there actyally is. Sometimes you will have to change your default version of solidity when inheriting from some contracts that require an older version. In cases like this you should use safemath

1 Like

The assignment was simple enough, will be useful if I ever need to use older versions of solidity


  
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 - amount);
    }
    
    function _transfer(address from, address to, uint amount) private {
        balance[from]=balance[from].sub(amount);
        balance[to] =balance[to].sub(amount);
    }
    
}



1 Like

Hello!

Here I am enclosing the changes I did to bank.sol in order to use SafeMath as a protection for Overflow/Underflow.
In this case, I believe that the underflow cases are pretty well covered by the require statements, as they verify, beforehand, that the users have enough funds to perform the operation, thus avoiding cases where balance may go below zero (I actually tested it).
However, the overflow case will be managed by SafeMath, as we have no restrictions to the highest amount of currency that a user may hold. I haven’t tested this case by the way, is there any plausible way to do so using uint256?

Kind Regards,

pragma solidity 0.8.0;
pragma abicoder v2;
import "./Ownable.sol";
import "./SafeMath.sol"; //Here I import the library

contract Bank is Ownable {
    using SafeMath for uint256; //Here I bind the library to the uint256 data type
    
    mapping(address => uint256) balance; //Replaced uint for uint256 due to SafeMath restricted compatibility
    address[] customers;
    
    event depositDone(uint256 amount, address indexed depositedTo); //Replaced uint for uint256 due to SafeMath restricted compatibility

    //Replaced uint for uint256 due to SafeMath restricted compatibility
    function deposit() public payable returns (uint256)  {
        balance[msg.sender] = balance[msg.sender].add(msg.value); // Changed native addition for add function
        emit depositDone(msg.value, msg.sender);
        return balance[msg.sender];
    }

    //Replaced uint for uint256 due to SafeMath restricted compatibility
    function withdraw(uint256 amount) public onlyOwner returns (uint256){
        require(balance[msg.sender] >= amount);
        balance[msg.sender].sub(amount); // Changed native substraction for sub function
        payable(msg.sender).transfer(amount);
        return balance[msg.sender];
    }
    
    //Replaced uint for uint256 due to SafeMath restricted compatibility
    function getBalance() public view returns (uint256){
        return balance[msg.sender];
    }
    
    //Replaced uint for uint256 due to SafeMath restricted compatibility
    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]; //Replaced uint for uint256 due to SafeMath restricted compatibility
        
        _transfer(msg.sender, recipient, amount);
        
        assert(balance[msg.sender] == previousSenderBalance.sub(amount)); // Changed native substraction for sub function, however, in this case, native substraction might have been useful as well
    }
    
    //Replaced uint for uint256 due to SafeMath restricted compatibility
    function _transfer(address from, address to, uint256 amount) private {
           balance[from] = balance[from].sub(amount); // Changed native substraction for sub function
           balance[to] = balance[to].add(amount); // Changed native addition for add function
    } 
}