Events Assignment

Hi @oioii1999,

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:

1 Like
pragma solidity 0.7.5;

contract Bank {

  mapping(address => uint) balance;

  address owner;

  modifier onlyOwner {
    require (msg.sender == owner);
    _; //run the function
  }

  constructor(){
    owner = msg.sender;
  }

  event BalanceAdded(uint amount, address depositedTo);

  event TransactionLog(address indexed sender, address indexed recipient, uint transactionValue);

  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, "Don't transfer money to yourself");

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

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

    //event logs and further checks
    emit TransactionLog (msg.sender, recipient, amount);
  }

  function _transfer(address from, address to, uint amount) private {
    balance[from] -= amount;
    balance[to] += amount;
  }
    
}

I tried to test this code in Remix, but didn’t manage to see the Event logs. I got the error message “false Transaction mined but execution failed”. Pretty sure the balance was sufficient for transferring, so I’m still figuring out why Remix keeps throwing this message.

1 Like

Hi @JoriDev,

Sorry for the delay in replying!

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 logs appropriate data when the transfer() function is successfully executed :ok_hand: … at least it does when I deploy and test the contract code you’ve posted!

Have you managed to work out what the problem is yet? When exactly are you getting this error message: when you deploy the contract, when you call addBalance(), or when you call transfer()?

After deploying your contract, I performed the following steps, and it worked fine …

  1. (i) Address 0x5B3…dC4 calls addBalance() with a _toAdd argument of 5
    Address 0x5B3…dC4 is the msg.sender (showing in the Account field near the top of the Deploy & Run Transactions panel in Remix).
    (ii) You will see the logged BalanceAdded event data in the transaction receipt (with the green tick) in the Remix terminal (at the bottom of the screen, below the code editor). Click on the transaction receipt to open it and scroll down to logs and you will see the amount and the depositedTo address (the depositor, msg.sender) x2 in the "args" property.

  2. Address 0x5B3…dC4 calls getBalance() to check that their balance in the mapping is 5
    Again, address 0x5B3…dC4 is the msg.sender (showing in the Account field near the top of the Deploy & Run Transactions panel in Remix).

  3. (i) Use the Account field dropdown to copy the 2nd address from list (0xAb8…cb2), and then paste it into the transfer() function call’s recipient argument field (unhide the 2 argument fields by clicking the down-arrow).
    (ii) Don’t forget to reset the address in the Account field to 0x5B3…dC4, because this is the address that needs to call transfer() with an amount argument of less than or equal to 5
    (iii) Address 0x5B3…dC4 calls transfer() with a recipient argument of 0xAb8...cb2, and an amount argument of 3
    Address 0x5B3…dC4 is the msg.sender (showing in the Account field).
    (iv) You will see the logged TransactionLog event data in the transaction receipt (with the green tick) in the Remix terminal. Click on the transaction receipt to open it and scroll down to logs and you will see the sender and recipient addresses, and the transactionValue (the amount transferred from the sender to the recipient) x2 in the "args" property.

  4. (i) Address 0x5B3…dC4 calls getBalance() to check that their balance in the mapping is now 2
    (ii) Change the address showing in the Account field to 0xAb8…cb2
    Address 0xAb8…cb2 calls getBalance() to check that their balance in the mapping is 3


A couple of additional comments about your code …

(1) Calling both the deposit() and the transfer() functions result in transactions, so I think TransferLog and transferValue would be better/clearer names than TransactionLog and transactionValue for your transfer event and its 3rd parameter.

(2)

An assert() statement is a “further check”, so I would put this below the comment as well.
But you are right to emit the event after assert() :ok_hand:

These are just minor points though.

Let me know if you have any questions, or if you’re still having issues testing your code and seeing the logged event data.

Hi @jon_m,

Just tested it again in Remix and this time everything worked perfect. I guess I messed up with the addresses the first time. Of course your reply and taking a break helped too :smiley:

Also as I struggled a bit with the naming of the transfer event, I liked that you commented on it. Giving attention to little things like order, naming and naming conventions are a great way to make a difference on a larger scale to avoid confusion. Thank you for the fine tuning.

1 Like

You’re very welcome @JoriDev!

Glad you found the comments so helpful :slightly_smiling_face:

1 Like

pragma solidity 0.7.5;

contract Bank{

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

event balanceAdded(uint amount, address indexed depositedTo);
event transferAdded(uint amount, address indexed transferTo, address indexed transferFrom); //ANSWER

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 send to self");

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

    emit transferAdded(amount, recipient, msg.sender); //ANSWER
}


 function _transfer(address from, address to, uint amount) private {
    
    balance[from] -= amount; 
    balance[to] += amount;
    
}

}

1 Like

pragma solidity 0.7.5;

contract Bank {

mapping (address => uint) balance;

address owner;

event balanceAdded(uint amount, address depositedTo);

event transferAdded(uint amount, address depositedTo, address depositedFrom); //THIS IS MY ANSWER FOR EVENTS ASSIGNMENT

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, "Don't transfer money");

 uint previousSenderBalance = balance[msg.sender];

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

 balance[msg.sender] -= amount;

 balance[recipient] += amount;

  }

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

 **emit transferAdded(amount, to, msg.sender);** // THIS IS MY ANSWER FOR EVENTS ASSIGNMENT

 balance[from] -= amount;

 balance[to] += amount;

}

}Preformatted text

1 Like

Hi @martina,

Your transfer event declaration and corresponding emit statement are both well coded and, once you correct a couple of issues in your transfer() function, your emit statement will log appropriate data when the transfer() function is successfully executed.

You need to add a call to the _transfer() helper function in the body of your main transfer() function, otherwise your emit statement won’t be executed! You also need to remove the last two lines of code from your transfer() function …

… otherwise you will be adjusting the sender and recipient balances for the transfer amount twice!

The assert() statement needs to check the sender’s individual balance after it has been adjusted for the transfer amount, and so the _transfer() helper function needs to be called before the assert() statement.

If you don’t use a separate helper function, and put all of the code associated with the transfer transaction in the main transfer() function (which is also a possible solution), then you’ll need to place your assert() statement after the individual balance adjustments, otherwise it will fail when it shouldn’t and prevent valid transfers from completing.


Your error message is wrong here. Users can transfer tokens — that’s the whole point of the function — but just not to themselves!

"Don't transfer tokens to yourself"

One final observation …

Whenever possible, an emit statement should be placed at the end of a function after all of the operations associated with the event have been performed, but before a return statement if there is one. And generally speaking, it’s probably also better to place an emit statement after an assert statement if there is one.

In addition, it’s better to emit the event at the end of the function which completes the transaction i.e. transfer() not _transfer().
Another important factor here is that if you emit an event in a helper function, you are restricting your ability to reuse that helper function. It will be more reuseable if we can call this same helper function from another function when we may not want to emit the same event — either a different one, or no event at all. That way we can reuse the helper function whenever we just want to implement its functionality (i.e. the operations, or computation, that it performs).

See if you can correct your code for these points. Just let me know if anything is unclear, or if you have any questions :slight_smile:

Hi @jon_m. Thank you for your notes, I have tried to correct my code but I’m not sure to be honest:
I have just copied from the part: function transfer as I understood event transferAdded was correct. If you can have a look, thank you.

function transfer(address recipient, uint amount) public {

 require(balance[msg.sender] >= amount, "Balance not sufficient");

 require(msg.sender != recipient, "Don't transfer tokens to yourself");

 uint previousSenderBalance = balance[msg.sender];

 _transfer(msg.sender, recipient, amount);

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

 emit transferAdded(amount, recipient, msg.sender);
1 Like

Hi @martina,

Yes … your event declaration was correct.

Your transfer() function is looking good now, and the emit statement is in the correct place, at the very end of the function body :muscle:

The only thing to also confirm is that your _transfer() helper function should now look like this…

function _transfer(address from, address to, uint amount) private {
    balance[from] -= amount;
    balance[to] += amount;
}

i.e. the same as you had before, but without the emit statement, which you’ve correctly moved to the main transfer() function.

1 Like

Hi @jon_m, is this a good solution or what am i missing.

pragma solidity 0.7.5;

contract Bank {

mapping (address => uint) balance;

address owner;



event balanceAdded(uint amount, address depositedTo);

event transferMade(address from, address to, uint amount); //answer

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

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

    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;

   

}

}Preformatted text

1 Like

Hi @Rebe

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:

However, whenever possible, an emit statement should be placed at the end of a function after all of the operations associated with the event have been performed, but before a return statement if there is one. And generally speaking, it’s probably also better to place an emit statement after an assert statement if there is one.

Just let me know if you have any questions.


event emits: sender, recipient and transferred amount

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

    event balanceAdded(uint amount, address indexed depositedTo); 
    event transferExecuted(address sender, address indexed recipient, uint amountTransferred);

    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);
        require(msg.sender != recipient);

        uint previousSenderBalance = balance[msg.sender];

        _transfer(msg.sender, recipient, amount);
        emit transferExecuted(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 @sph73,

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

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

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

Thank you for clarifying this because I was unsure and I chose before because I thought the assert statement was the final check however in retrospect I see it makes more sense to check first. :pray:

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

    event transferMade(address recipient, uint amount);

    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");
        emit transferMade(recipient, amount);

        uint previousSenderBalance = balance[msg.sender];

        _transfer(msg.sender, recipient, amount);

        assert(balance[msg.sender] == previousSenderBalance - amount);
        //event logs and further checks
    }

    function _transfer(address from, address to, uint amount) private {
        balance[from] -= amount;
        balance[to] += amount;
    }

}



2 Likes

pragma solidity 0.8.13;

contract Bank_Events{

mapping (address => uint) balance;

address owner; //state variable

//event logs, further cheks, and error handling

event balanceAdded (uint indexed amount, address indexed depositedTo);

event transferedAmount(address indexed from, address indexed to, uint indexed amount);

modifier onlyOwner {

    require(msg.sender == owner);  //A modifier is for restricting permissions like "only employees", "admins", or "owner" etc...

    _;

}

constructor(){

    owner = msg.sender;

}

function addBalance (uint _toAdd) public onlyOwner returns (uint){

    balance[msg.sender] += _toAdd;

    emit balanceAdded (_toAdd, msg.sender);      //log event

    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,"ERROR 1_Insufficient balance to transfer funds.");  //Check balance of msg.sender

    require(msg.sender != recipient,"ERROR 2_The sender cannot be the recipient.");

    uint previousSenderBalance = balance[msg.sender];

    _transfer (msg.sender, recipient, amount);  

    emit transferedAmount(msg.sender, recipient, amount);  //log event

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

       

}

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

    balance[from] -= amount;

    balance[to] += amount;

}

}

2 Likes

pragma solidity 0.8.7;

contract helloBank {

mapping(address => uint) balances;

address owner;

event balanceUpdated(uint prevBalance,uint newBalance, address indexed updatedAccount);

modifier onlyOwner {

    require(msg.sender == owner,"Only SC Owner can Call this");

    //run the real functions, Practically EVM will replace all of function statement here

    _;

}

modifier sufficientBalance(uint _amount){

    require(balances[msg.sender] >= _amount,"Balance Not Sufficient");

    _;

}



constructor(){

    //here owner becomes the creator of SC

    //mostly useful for restricting function access to admins

    owner = msg.sender;

}

// admin function can only be perfromed by owner of SC

function addBalance(address _toAddress, uint _balance2Add) public onlyOwner returns(uint){

    //example admin function can be restricted to owner only

    //commented as using modifier

    //require(msg.sender == owner,"Only SC Owner can Call this");

    uint prevBalance = balances[_toAddress];

    balances[_toAddress] += _balance2Add;

    //emit log

    emit balanceUpdated(prevBalance, balances[_toAddress], _toAddress);

    return balances[_toAddress];

}

function getBalance() public view returns(uint){

    return balances[msg.sender];

}

function transfer(address recipient, uint amount) public sufficientBalance(amount) {

    //checks balance of msg-sender

    //if any of the require condition fails, all operation will be reverted

    //check if balance is sufficient

    //we can also have error statement

    //using modifier so commented here

    //require(balances[msg.sender] >= amount,"Balance Not Sufficient");

   

    //check if recipient is not as sender, unnecessary operation will cost GAS

    require(msg.sender != recipient,"Transfer to Self not Allowed");

    //variable to store previous balance, to be used for assert to check internal error

    uint prevFromBalance = balances[msg.sender];

    uint prevToBalance = balances[recipient];

    _transfer(msg.sender,recipient,amount);

    //check with assert for any internal error

    assert(balances[msg.sender] == prevFromBalance - amount);

    //event logs and further checks

    //from balance event

    emit balanceUpdated(prevFromBalance, balances[msg.sender], msg.sender);

    //to balance event

    emit balanceUpdated(prevToBalance, balances[recipient], recipient);

}

//private function, can be resused by others fn

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

    balances[from] -= amount;

    balances[to] += amount;

}

}

2 Likes
pragma solidity 0.8.13;

contract Bank{

    //storage - permanent storage of data (state variables)
    //memory - temporary storage used in funtion execution
    //calldate - save arguments/inputs to our functions
    //strings, arrays, mapping, scructs

    mapping(address => uint) balance;
    
    address owner;
    
    event balanceAdded(uint amount, address indexed depositedTo);

    event transfered(uint amount, address recipient);

    modifier onlyOwner{
        require(msg.sender == owner);
        _; //run the funtion
    }
    
    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, "Dont transfer money to yyourself");

        uint previousSenderBalance = balance[msg.sender];

        _transfer(msg.sender, recipient, amount);

         emit transfered(amount, recipient);
        assert(balance[msg.sender] == previousSenderBalance - amount);
       
    }

    function  _transfer(address from, address to, uint amount) private {
        balance[from] -= amount;
        balance[to] += amount;
    }
}
2 Likes
Event Assignment
pragma solidity 0.7.5;

contract Bank {

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

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

    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, "Don't transfer money to yourself");
        uint previousSenderBalance = balance[msg.sender];
        _transfer(msg.sender, recipient, amount);
        emit trasferComplited(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;
    }
}
2 Likes