Events Assignment

Events

function transfer(address recipient, uint amount) public onlyOwner {
//check balance of msg.sender
require(balance[msg.sender] >= amount, “Insufficient funds”);
require(msg.sender != recipient, “Cannot transfer tokens to yourself”);

uint previousSenderBalance = balance[msg.sender];
_transfer(msg.sender, recipient, amount);

//event logs and further checks
emit transferLog(amount, msg.sender, recipient);    // <<<<=========== event called here.
assert(balance[msg.sender] == previousSenderBalance - amount);

}

Thanks for the feedback, Jon. I’ll have it in mind!

1 Like

Hi @Cosmin_Fechet,

Your transfer event declaration is well coded. Your emit statement is in the correct position in the transfer() function body, and it will log data when the transfer() function is successfully executed. However, you are emitting the recipient address as the event’s fromAddress parameter, and the msg.sender address as the event’s toAddress parameter. Can you see that you’ve got these the wrong way round? The position of each value in the emit statement must be the same as that of its corresponding parameter in the event declaration, in terms of both data type and name. If the data types don’t correspond, then the contract won’t compile, but if the names are mixed up, then the data affected will be logged against potentially misleading identifiers (which is what will happen with your solution).

But you have referenced amount in the correct position in your emit statement :ok_hand: :sweat_smile:

Let me know if you have any questions about this, or about how to correct it.

1 Like

thanks Jon.

I understand my mistake. The correct way should be ` emit balanceTransfered(amount, msg.sender, recipient);

1 Like

An excellently-coded Bank contract, @Tomaage :muscle:

Your transfer event and corresponding emit statement are both correct and 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.

Hi @Waiguru,

Your emit statement for your transferLog event looks well coded, but we need to see your transferLog event declaration as well, in order to know if it will work and log the data when the transfer() function is successfully executed.

Can you post the event declaration as well?

One other observation…
In general, an emit statement is probably better placed after an assert statement.

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 transferCompleted(uint amount, address transferredTo, address transferredFrom);

    modifier onlyOwner {

        require(msg.sender == owner);

        _; // run the function

    }

    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);

        require(msg.sender != recipient);

        uint previousSenderBalance = balance[msg.sender];

       _transfer(msg.sender, recipient, amount);

        assert(balance[msg.sender] == previousSenderBalance - amount);

        emit transferCompleted(amount, recipient, msg.sender);

    }

    function _transfer(address from, address to, uint amount) private {

        balance[from] -= amount;

        balance[to] += amount;

    }

}
2 Likes

Nice solution @h0h :ok_hand:

Your transfer event and corresponding emit statement are both correct and 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 transferMade(uint amount, address indexed sentFrom, address indexed depositedTo);

    modifier onlyOwner {

        require(msg.sender == owner);

        _; //run the function

    }

    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 money to yourself");

       

        uint previousSenderBalance = balance[msg.sender];

        _transfer(msg.sender, recipient, amount);

        assert(balance[msg.sender] == previousSenderBalance - amount);

        emit transferMade(amount, msg.sender, recipient);

    }

    function _transfer(address from, address to, uint amount) private {

        balance[from] -= amount;

        balance[to] += amount;

    }

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

    event balanceAdded(uint amount, address indexed depositedTo);
    
    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, "Balance not Sufficient");
        require(msg.sender != recipient, "Can't transfer money to yourself");
        
        uint previousSenderBalance = balance[msg.sender];
        
        _transfer(msg.sender, recipient, amount);
        
        assert(balance[msg.sender] == previousSenderBalance - amount);
        
        emit balanceAdded(amount, recipient);
    }
    
    function _transfer(address from, address to, uint amount) private {
        balance[from] -= amount; 
        balance[to] += amount;
    }
    
}
2 Likes

Hello I have not been able to test my code for this assignment in remix because the application crashes when I try to execute the transfer function.

pragma solidity 0.7.5;

contract Bank {

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

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }

    event fundsAdded(uint amount, address depoAddy);

    event fundsTransferred(address indexed fromAccount, address indexed toAccount, uint _amount); // Event Solution

    constructor(){
        owner = msg.sender;
}

    function addBalance(uint _toAdd) public onlyOwner returns(uint){
        balance[msg.sender] += _toAdd;
        emit fundsAdded(_toAdd, msg.sender);
        return balance[msg.sender];
    }

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

    function transfer(address recipient, uint amount) public onlyOwner {
        require(balance[msg.sender] >= amount, "Insufficient funds.");
        require(msg.sender != recipient, "(recipient != msg.sender)");

        uint balanceBeforeTransfer = balance[msg.sender];
            transfer(recipient, amount);

        assert(balance[msg.sender] == balanceBeforeTransfer - amount);
            
            emit fundsTransferred(msg.sender, recipient, amount); // Event Solution
    
    }
    
    function _transfer(address from, address to, uint amount) private {
        balance[from] -= amount;
        balance[to] += amount;
    }


}


1 Like

Nice solution, and a very well coded contract @Techman120 :muscle:

Your transfer event and corresponding emit statement are both correct and 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.

1 Like

Hi @hellopath,

… and welcome to the forum! I hope you’re enjoying the course :slight_smile:

The additional balanceAdded() emit statement you’ve added to the transfer() function is coded correctly. You’ve placed it in the correct position in the function body and it will log data relating to a transfer whenever the transfer() function is successfully executed.

It is certainly always a good idea to consider whether we can re-use the same event declaration to emit event data from more than one function. However, do you think it’s appropriate to do this here?
While the addBalance() function executes a transaction that only involves 1 user address (the depositer), the transfer() function executes a transaction that involves 2 user addresses (the sender and the recipient). So, it would be useful to include the sender’s address, as well as the recipient’s address, within the data emitted for the transfer event. This obviously involves including a separate event declaration with 3 instead of 2 parameters.

It is also important to consider whether the names given to the event and to each of its parameters are suitable and helpful in terms of the transaction data they describe.

By the way, don’t forget to post your solution to the Data Location Assignment. This assignment comes just before the Events Assignment, near the beginning of the same Additional Solidity Concepts section of the course.

Just let me know if you have any questions.

Hi @MichaelAudire,

Your transfer event and corresponding emit statement are both correct and well coded. You’ve also placed the emit statement in the correct position in the transfer() function body. When you’ve corrected the error in your transfer() function which is causing Remix to crash whenever this function is executed (see below), the emit statement will log appropriate data when the transfer() function is successfully executed.

This because the execution is entering an infinite loop as a result of the following line of code …

The transfer function is calling itself recursively. Instead, it needs to call the private _transfer() helper function (don’t forget the all important underscore in the function name!) with three arguments instead of only two. Can you correct this yourself?

Once you’ve corrected this, your transfer function will work, but for the whole contract to work effectively, you should also remove the onlyOwner modifier from both the transfer() function and the getBalance() function headers. Can you see why?

Let me know if anything is still unclear, if you have any questions, or if you need any further help in correcting your code :slight_smile:

1 Like

Thank you so much! I see my errors clearly now. Here is my corrected code.

pragma solidity 0.7.5;

contract Bank {

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

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }

    event fundsAdded(uint amount, address depoAddy);

    event fundsTransferred(address indexed fromAccount, address indexed toAccount, uint _amount);

    constructor(){
        owner = msg.sender;
}

    function addBalance(uint _toAdd) public onlyOwner returns(uint){
        balance[msg.sender] += _toAdd;
        emit fundsAdded(_toAdd, msg.sender);
        return balance[msg.sender];
    }

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

    function transfer(address recipient, uint amount) public onlyOwner {
        require(balance[msg.sender] >= amount, "Insufficient funds.");
        require(msg.sender != recipient, "(recipient != msg.sender)");

        uint balanceBeforeTransfer = balance[msg.sender];
            _transfer(msg.sender, recipient, amount);

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


}
1 Like

Hi @MichaelAudire,

That’s corrected the problem with the infinite loop, and your transfer() function will now work :ok_hand:

If you can’t, then just let me know, and I’ll explain exactly what the issue is.

1 Like
pragma solidity 0.7.5;
contract Bank{

  mapping(address => uint)Balance;
  address owner;
  modifier OnlyOwner{
        require(owner == msg.sender);
        _; //run the function
  }
  
  event BalanceAdded(uint Amount, address DepositedTo);
  event TransactionDetails(address sender, address receiver, uint amount);

  constructor(){
     owner = msg.sender;
     
  }

    function addBalance(uint _toAdd) public OnlyOwner{
        emit BalanceAdded(_toAdd, msg.sender);
        Balance[msg.sender] = Balance[msg.sender] + _toAdd;
    }

    function transfer(address recipient, uint amount) public{

        require(Balance[msg.sender] >= amount, "Balance not enough");
        require(msg.sender != recipient, "You can't send funds to yourself!");

        uint BalanceBefore = Balance[msg.sender];

        _transfer(msg.sender, recipient, amount);

        assert( Balance[msg.sender] == BalanceBefore - amount);

         emit TransactionDetails(msg.sender , recipient, amount);
    }

    function _transfer(address from, address to, uint _amount) private{

        Balance[from] -= _amount;
        Balance[to] += _amount;


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

Hi @Adrian1,

Your transfer event and corresponding emit statement are both correct and 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 :ok_hand:

A couple of additional comments …

(1) An emit statement should be placed at the end of a function, after the event itself has occurred, but before a return statement if there is one. Generally speaking, it’s probably also better to place an emit statement after an assert statement if there is one.
You’ve positioned your emit statement perfectly in the transfer() function, but can you now see that you should change the position of your emit statement in the deposit() function, so that it comes after all of the operations associated with the deposit have been successfully executed?

(2) A generally-accepted convention is to start the names of …

  • Contracts, Interfaces, Events and Structs with a capital letter
  • functions, variables, mappings, arrays, arguments, parameters and modifiers with a lower-case letter

Doing the opposite will not prevent your code from compiling, but following this generally accepted convention applies a certain degree of consistency to our code, which also makes it more readable. See if you can improve the consistency of the names in your contract e.g.

Mapping and variable names

Parameter names

Let me know if you have any questions.

1 Like
pragma solidity 0.7.5;

contract Bank {
    mapping(address => uint) balance;
    address owner;

    event balanceAdded(uint amount, address indexed depositedTo);
    event transferedTo(address indexed from, address indexed to, uint amount);

    modifier OnlyOwner() {
        require(msg.sender == owner);
        _;
    }

    constructor() {
        owner = msg.sender;
    }

    function addBalance(uint _add) public OnlyOwner returns (uint) {
        balance[msg.sender] += _add;
        emit balanceAdded(_add, 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);

        emit transferedTo(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

Hi @CryptoUsic,

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

Just one observation…
In general, an emit statement is probably better placed after an assert() statement.

Just let me know if you have any questions.

1 Like