Doesnāt the information in the blockchain block give us these details anyway?
Events is the way to fetch info from the blockchain, they will indeed tell you a lot about a transaction.
A transaction without event just tells you that addressA sent x ERC20 to addressB.
A transaction with events tells you that addressA sent x ERC20 to addressB due to an exchange on uniswap.
Or tells you that addressA is a contract that minted 100 tokens to addressB.
You have correctly defined your transfer event, but the corresponding emit statement has the arguments in the wrong order: this will result in the senderās address being logged as the depositedTo address, and the receiverās address being logged as the depositedFrom address. Can you correct this?
We should emit events at the very end of the function that completes the transaction. As you only have a function call in your transfer() function, then it is appropriate to have your emit statement at the end of the _transfer() helper function. In fact, if the only code you have in your transfer() function is a call to the helper function, then all you really need is one transfer function anyway. We should always try to avoid unnecessarily repetitve code and aim for conciseness. However, you are missing the require and assert statements in transfer(). These are important to ensure the inputs and output are valid. If you add these, then having 2 separate functions for the transfer becomes relevant again, and so this will also affect where you should put the emit statement.
Another important factor to consider here is that if you emit the event in the helper function, you are actually restricting your ability to reuse it in the future. It will be more reuseable if we can call _transfer() from another function when we may not want to emit that same event ā either a different one, or no event at all. That way we can reuse it whenever we just want its functionality (i.e. the operations, or computation, that it performs).
Let us know if anything is unclear, or if you have any questions
pragma solidity 0.7.5;
contract MemoryAndStorage {
mapping(uint => User) users;
event balanceAdded(uint amount, address depositedTo);
event transferred(uint amount, address depositedFrom, address depositedTo);
struct User{
uint id;
uint balance;
}
function addUser(uint id, uint balance) public {
users[id] = User(id, balance);
}
function addBalance(uint _toAdd) public returns(uint) {
balance[msg.sender] += _toAdd;
emit balanceAdded(_toAdd, msg.sender);
return balance[msg.sender];
}
function getBalance(uint id) view public returns (uint) {
return users[id].balance;
}
function transfer(address recipient, uint amount) public {
require(balance[msg.sender] >= amount, "Insufficient Balance Available"); //require
require(address[msg.sender] != receipient, "You may not transfer to the same address.");//require
uint priorSenderBalance = balance[msg.sender];
_transfer(msg.sender, recipient, amount);
emit transferred(amount, msg.sender, recipient);
assert(balance[msg.sender] == priorSenderBalance - amount);//assert
}
function _transfer(address from, address to, uint amount) private {
balance[from] -= amount;
balance[to] += amount;
}
}
OK. I started over again because of how sloppy my initial coding was. Started with the code in github and made my changes with an eye on you critiques. Iām struggling now, because I keep getting the same Declaration Error for anything relating back to msg.sender. I suspect I set up the environment wrong or something, but Iām not sure what I missed.
You have somehow mixed up and merged the code for Bank and for MemoryAndStorage (the data location assignment code). You are getting all of the Declaration errors because you have the wrong mapping (users). The compiler is expecting a mapping called balance. Once youāve changed your mapping from the one used in the data location assignment, to the one needed for Bank, most of the errors will be resolved.
Then, you need to remove the rest of the code relating to the data location assignment:
struct User {
uint id;
uint balance;
}
function addUser(uint id, uint balance) public {
users[id] = User(id, balance);
}
function getBalance(uint id) view public returns (uint) {
return users[id].balance;
}
ā¦ and replace the wrong getBalance function with the correct one for Bank:
function getBalance() public view returns(uint) {
return balance[msg.sender];
}
You should then be left with a couple more compiler errors to resolve, which relate to your second require statement in the transfer function. See if you can work out what they are, using the error messages to help, where possible.
Your amendments in terms of the actual Event Assignment are mostly good:
The emit statement now has its arguments in the correct order.
The emit statement is in the correct function.
You have added the 2 require statements (one just needs correcting, as mentioned above).
You have added the assert statement.
The emit statement would be better placed at the very end of the transfer function, after assert(). If assert() throws, then the preceding operations in the function body will revert, but it is still safer to only log the transfer event once all of the other code has executed successfully.
Let us know if anything is unclear, or if you run into any further difficulties.