Events Assignment

    event transferComplete(address indexed from, address indexed to, uint amount);
    function transfer( address recipient, uint amount) public  {
        // check balance of msg.sender and validate amount exists
        require(balance[msg.sender] >= amount, "Balance not sufficient");
        require(msg.sender != recipient, "Don't transfer money to yourself");// don't send money to ourselves

        uint previousSenderBalance = balance[msg.sender];

        _transfer(msg.sender, recipient, amount);

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

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

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

Some events around here and there:

pragma solidity 0.7.5;

contract Bank {

    //state variable
    mapping(address => uint) myBalance;
    address owner;
    
    event balanceAdded(uint amount, address indexed sender);
    event balanceTransfered(uint amount, address indexed sender, address indexed recipient);

    modifier onlyOwner {
        require(msg.sender == owner, "You're not the owner!");
        _; //runs the function next
    }

    constructor(){
        owner = msg.sender;
    }

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

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

    function transfer(address _recipient, uint _amount) public {
        require(myBalance[msg.sender] > _amount, "Balance insuficient!");
        require(msg.sender != _recipient, "Don't transfer balance to yourself!");

        uint prevSenderBalance = myBalance[msg.sender];

        _transfer(msg.sender, _recipient, _amount);

        assert(myBalance[msg.sender] == prevSenderBalance - _amount);
    }

    function _transfer(address _sender, address _recipient, uint _amount) private {
        myBalance[_sender] -= _amount;
        myBalance[_recipient] += _amount;
        emit balanceTransfered(_amount, _sender, _recipient);
    }
}```
1 Like

Nice solution @JayM700 :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.

Just one observation …

Your assert() statement is one the final/further checks. It’s correct to place it before the emit statement, but have the comment refer to both of them …

  _transfer(msg.sender, recipient, amount);
  
  // event logs and further checks
  assert(balance[msg.sender] == previousSenderBalance - amount);
  emit transferComplete(msg.sender, recipient, amount);

Let me know if you have any questions.

Hi @JP-C,

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 a couple of comments …

  • It’s better to emit the event at the very end of the function which completes the transaction i.e. transfer() not _transfer().
    _transfer() is what we call a helper function.
    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 it 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 its functionality (i.e. the operations, or computation, that it performs).

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

Let me know if anything is unclear, or if you have any questions :slight_smile:

pragma solidity 0.7.5;

contract helloworld{

    //storage - means permanent storage of data (persistant data)
    //memory - temporare data storage (is stored temporarely as long as the function executes)
    //calldata - similar to memory, but READ-ONLY
    
    mapping (address => uint)balance;
    
    address owner;

    event balanceAdded(uint amount, address depositedTo);
    event balanceTransfered(uint amount, address fromAddress, address toAddress);

    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);
    assert(balance[msg.sender] == previousSenderBalance - amount);
    emit balanceTransfered(amount, recipient, msg.sender);
    
    }
    function _transfer(address from, address to, uint amount) private{
        balance[from] -= amount;
        balance[to] += amount;

    }
}

Added the event and Emit transferDone in the transfer function

pragma solidity 0.8.11;

import "./Destroyable.sol";

contract Bank is Destroyable {

    mapping(address => uint) balance;

    event depositDone(uint amount, address depositedTo);
    event transferDone(uint amount, address transferedFrom, address transferedTo);

    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 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, "Dont transfer money to yourself");
   
        uint previousSenderBalance = balance[msg.sender];
        
        _transfer(msg.sender, recipient, amount);
        
        assert(balance[msg.sender] == previousSenderBalance - amount);
        emit transferDone(amount, msg.sender, recipient);
    }

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

    function getContractBalance() public view returns(uint) {
    return address(this).balance;
    }
}
1 Like

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