Events Assignment

Hi @Julian,

Can you see you’re logging the sender’s address as recipientAddress, and the recipient’s address as senderAddress?

Once you’ve made this modification, your transfer event and corresponding emit statement will be correct, and the emit statement will log appropriate data when the transfer() function is successfully executed.

Just let me know if you have any questions :slight_smile:

1 Like

Ah yes, thanks for pointing out that careless mistake, I will correct it :slightly_smiling_face:

1 Like

Thanks Jon!

I appreciate you taking the time, I did get it to work. I was forgetting to switch the address. so silly of me!

1 Like

Hey Matthew,

… nah! … don’t worry, we’ve all been there and made that mistake several times before … it’s easily done, but at least next time you’ll know straight away what may well have caused the error…and not spend ages wondering what happened :sweat_smile:

1 Like

Thank You for recommendation. I already corrected it as You said.

1 Like
pragma solidity 0.7.5;

contract Bank {
    
   mapping(address => uint) balance;
   address owner;
   
   
   event balanceAdded(uint amount, address depositedTo);
    
   event transferAction(uint amount, address sender, address receiver);
   
   modifier onlyOwner {
       require(msg.sender == owner);
       _;
   }
   
   constructor(){
       owner = msg.sender;
       
   }
   
   function addBalance(uint _toAdd) public onlyOwner returns (uint){
       require(msg.sender == owner);
       balance[msg.sender] += _toAdd;
       emit balanceAdded(_toAdd, msg.sender);
       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);
        
        emit transferAction(amount, msg.sender, recipient);
    
   }
   
   function _transfer(address from, address to, uint amount) private {
       balance[from] -= amount;
       balance[to] += amount;
   }
  
}
1 Like

Nice solution @Denzel :ok_hand:

Your transfer event and corresponding emit statement are both well coded. The emit statement is in the correct position within your transfer function body, and will log appropriate data when the function is successfully executed.

Just one observation…
The onlyOwner modifier in the addBalance() function header already applies the require statement   require(msg.sender == owner);

… so you can remove it from the first line in the function body…

contract Bank {

    mapping(address => uint) balances;
    address owner;

    event balanceAdded(uint amount, address indexed recipient);
    event amountTransferred(uint amount, address indexed sender, address indexed recipient);
    
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    constructor() {
        owner = msg.sender;
    }
    
    
    function addBalance(uint _toAdd) public onlyOwner returns (uint) {
        balances[msg.sender] += _toAdd;
        emit balanceAdded(_toAdd, msg.sender);
        
        return balances[msg.sender];
    }

    function transfer(address recipient, uint amount) public {
        
        require(msg.sender != recipient, "Can't transfer to self");
        require(amount > 0, "Invalid amount");
        require(balances[msg.sender] >= amount, "Insufficient balance");
        
        _transfer(msg.sender, recipient, amount);
        
        emit amountTransferred(amount, msg.sender, recipient);
    }



    function getBalance(address id) public view returns (uint) {
       return balances[id];
    }
    
    
    function _transfer(address from, address to, uint amount) private {
        balances[from] -= amount;
        balances[to] += amount;
    }

}
1 Like

I thought to add an additional require in the transfer function to ensure amounts transferred are greater than 0 to avoid 0 transfers that make no sense and potentially waste gas.

1 Like

Nice solution @Carlo :ok_hand:

Your transfer event and corresponding emit statement are both well coded. The emit statement is in the correct position in the transfer() function body and will log appropriate data when the transfer() function is successfully executed.

This is good thinking, but while a user who tries to transfer a 0 amount will save themselves a small amount of gas, you also need to consider that all other transfers (of amounts greater than 0) will now consume slightly more gas due to the additional require statement that needs to be executed. The amounts of gas involved will be very small, but if transferring 0 does not cause any issues apart from a slight inconvenience to the sender, you need to ask yourself whether the potential frequency of 0 transfers justifies all transfers having a slightly higher gas cost.

Let me emphasise that there is no right or wrong answer here. Each case needs to considered individually. It’s good, though, that you are already thinking about the impact our choice of smart-contract code will have on gas consumption, as this is something we should always take into consideration.

Just let me know if you have any questions :slight_smile:

1 Like
pragma solidity 0.7.5;
contract Bank {

    mapping(address => uint) balance;
    
    address owner;
    
    event balanceAdded(uint amount, address depositedTo);
    event balanceTransfer(uint amount, address sender, address recipient);
    
    modifier onlyOwner {
        require(msg.sender == owner);
        _; //run the funciton
    }

    constructor(){
        owner = msg.sender;
    }

    function addBalance(uint _toAdd) public onlyOwner returns (uint) {
        balance[msg.sender] += _toAdd;
        emit balanceAdded(_toAdd, msg.sender);
        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 any money to yourself");
        
        uint previousSenderBalance = balance[msg.sender];
        
        _transfer(msg.sender, recipient, amount);
        
        assert(balance[msg.sender] == previousSenderBalance - amount);
        emit balanceTransfer(amount, msg.sender, recipient);
    }
    
    function _transfer(address from, address to, uint amount) private {
        balance[from] -= amount;
        balance[to] += amount;
    }

}
1 Like

An excellently coded Bank contract @GahuckImGoofy :muscle:

Your transfer event and corresponding emit statement are both well coded. The emit statement is in the correct position in the transfer() function body and will log appropriate data when the transfer() function is successfully executed.

pragma solidity 0.7.5;

contract Bank {
  
    mapping(address => uint) balance;
    
    address owner;
    
    event balanceAdded(uint amount, address indexed depositedTo);
    
    event balanceTransfer(uint amount, address depostiedFrom, address depositedTo); //event added
    
    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }
    
    constructor(){
        owner = msg.sender;}
    
    function addBalance(uint _toAdd) public onlyOwner returns (uint){
        balance[msg.sender] += _toAdd;
        emit balanceAdded(_toAdd, msg.sender);
        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, "Insuficient balance");
            require(msg.sender != recipient, "Don't send money to yourself");
            
            uint previousSenderBalance = balance[msg.sender];
            
            _transfer(msg.sender, recipient, amount);
            
            emit balanceTransfer(amount, msg.sender, recipient); //emitted event
            
            assert(balance[msg.sender] == previousSenderBalance - amount);
            }
            
    function _transfer(address from, address to, uint amount) private {
            balance[from] -= amount;
            balance[to] += amount;
                
    }
    
}
1 Like

Hi @DHash,

Your transfer event and corresponding emit statement are both correctly coded, and the emit statement will log appropriate data when the transfer() function is successfully executed :ok_hand:

Just a couple of observations …

  • In general, an emit statement is probably better placed after an assert statement.

  • Strictly speaking, transfers are not deposits — at least not in the sense of a deposit into the contract. They are transfers between 2 account holders within the contract. The amount is transferred internally and does not enter or leave the contract. As a result of this, and also to clearly distinguish data logged by different transactions, I would probably name the address arguments in your balanceTransfer event something like transferredFrom/To instead of depositedFrom/To

Just let me know if you have any questions :slight_smile:

1 Like

2021-07-16_23-54-45

Logs Output:

2021-07-16_23-57-13

Actual Code:

// SPDX-License-Identifier: MIT
pragma solidity 0.7.5;  // Tells compiler which version of Solidity being used

contract Bank {
    mapping(address => uint) balances;
    address owner;
    
    // events
    event balanceAdded(uint _amount, address indexed _depositedTo);
    event transferredDetails(uint _amount, address indexed _to, address indexed _from);
    
    modifier onlyOwner {
        require(msg.sender == owner, "Not authorized");
        _; // allows remaining code to run if the above is true
    }
    
    constructor() {
        owner = msg.sender;
    }
    
    function addBalance(uint _add) public onlyOwner returns(uint) {
        balances[msg.sender] += _add;
        emit balanceAdded(_add, msg.sender);
        return balances[msg.sender];
    }
    
    function getBalance() public view returns(uint) {
        return balances[msg.sender];
    }
    
    function transfer(address _recipient, uint _amount) public {
        require(balances[msg.sender] >= _amount, "Balance insufficient");
        require(msg.sender != _recipient, "Cannot transfer to self");
        
        uint previousBalance = balances[msg.sender];
        _transfer(msg.sender, _recipient, _amount);
        
        // assert should always be true unless the code it is testing against is defective
        assert(balances[msg.sender] == previousBalance - _amount);
        
        //event logs and additional validation
        emit transferredDetails(_amount, _recipient, msg.sender);
    }
    
    function _transfer(address _from, address _to, uint _amount) private {
        balances[_from] -= _amount;
        balances[_to] += _amount;
    }
}
1 Like

An excellently coded Bank contract @jCA :muscle:

Your transfer event and corresponding emit statement are both well coded. The emit statement is in the correct position in the transfer() function body and, as you have demonstrated, logs appropriate data when the transfer() function is successfully executed.

Just one observation…

In the event logs, as well as _amount ,  _to  and  _from  are also the names/identifiers you’ve given to each of the values defined within your transfer event. This has nothing to do with the fact that these two values are indexed. These names will appear in the logs whether the values are indexed or not.

Let me know if you have any questions… and don’t forget to post your code as explained in the FAQ I linked to in my previous reply. You’ll also be doing my eyesight a favour! :pray: :wink:

1 Like

Regarding indexing, would these be queried on the front-end/ui side?

Thanks,

Joe

1 Like

Hey Joe,

Essentially, yes… it allows logged event data to be filtered in the frontend/UI, using a library such as web3.js. Specific events can be searched for using the names of the indexed values as search parameters.

Here’s a link to a helpful discussion about this, which I think explains quite well how this works in practice:

https://ethereum.stackexchange.com/questions/8658/what-does-the-indexed-keyword-do/8659

1 Like

Thank you for the helpful explanation!

1 Like
pragma solidity 0.7.5;

contract Bank {
   
    mapping(address => uint) balance;
    address owner;
   
    event balanceAdded(uint amount, address depositedTo);
    event transferFunds(uint amount, address sentFrom, address sentTo);

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }
    
    constructor(){
        owner = msg.sender;
    }
   
    function addBalance(uint _toAdd) public onlyOwner returns (uint){
        balance[msg.sender] += _toAdd;
        emit balanceAdded(_toAdd, msg.sender);
        return balance[msg.sender];
    }
   
    function getBalance() public view returns (uint){
        return balance[msg.sender];
    }
   
    function transfer(address recipient, uint amount) public {
        // check balance of msg.sender
        require(balance[msg.sender] >= amount, "Balance not sufficient");
        require(msg.sender != recipient, "Do not send to yourself");

        // Save the senders balance
        uint previousSenderBalance = balance[msg.sender];

        _transfer(msg.sender, recipient, amount);
        
        // event logs and further checks
        // Confirm senders balance reduced by amount sent.
        assert(balance[msg.sender] == previousSenderBalance - amount);

        emit transferFunds(amount, msg.sender, recipient); 
 
    }
   
    function _transfer(address from, address to, uint amount) private {
        balance[from] -= amount;
        balance[to] += amount;
    }
}
1 Like