pragma solidity 0.7.5;
contract Bank_EventsExample{
mapping(address => uint) balance;
address owner;
// defining events to be triggered later in code
event balanceAdded (uint amount, address depositedTo);
event balanceTransfered (uint amount, address transferedTo);
modifier onlyOwner{
require(msg.sender == owner);
_;
}
constructor(){
owner = msg.sender;
}
//adding emit to trigger balanceAdded event defined above
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, "Insufficent Balance");
require(msg.sender != recipient, "You cannot send funds to yourself");
uint previousSenderBalance = balance[msg.sender];
_transfer(msg.sender, recipient, amount);
assert(balance[msg.sender] == previousSenderBalance - amount);
}
//new code
//adding emit to trigger balanceTransfered event defined above
function _transfer(address from, address to, uint amount) private {
balance[from] -= amount;
balance[to] += amount;
emit balanceTransfered(amount, to);
}
}
Hi @Dustin_Gearhart,
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.
A few 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.
-
Where 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.
Let me know if anything is unclear, or if you have any questions
Awesome advice. The changes have been added to my notes.
pragma solidity 0.7.5;
contract bank {
mapping(address => uint) balance;
address owner;
event balanceAdded(uint amount, address indexed depositedTo);
//Arguments that are indexed are actually indexed by the ethereum nodes...
//This means we can use these arguments to search and query for certain events that have happened in the past.
event transferAdded(uint amount, address indexed depositedTo, address depositedFrom);
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];
}
Hello all,
Here is my attempt, trying to figure out why I get an error when I attempt a transfer. add balance works fine. thanks.
pragma solidity 0.7.5;
contract Bank {
mapping(address => uint) balance;
address owner;
event balanceAdded(uint amount, address indexed depositedTo);
event transferEvent(uint amount, address toAddress, address fromAddress);
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);
//event logs and further checks
emit transferEvent(amount, recipient, msg.sender);
}
function _transfer(address from, address to, uint amount) private {
balance[from] -= amount;
balance[to] += amount;
}
}
pragma solidity 0.7.5;
contract MemoryAndStorage {
mapping(uint => User) users;
struct User{
uint id;
uint balance;
}
function addUser(uint id, uint balance) public {
users[id] = User(id, balance);
}
function updateBalance(uint id, uint balance) public {
User storage user = users[id];
user.balance = balance;
}
function getBalance(uint id) view public returns (uint) {
return users[id].balance;
}
}
pragma solidity 0.7.5;
contract Bank {
mapping(address => uint) balance;
address owner;
event balanceAdded(uint amount,address depositedTo);
event tranferred(uint amount,address 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 {
//check balance of msg.sender
require(balance[msg.sender] >= amount,"Balance not sufficient");
require(msg.sender != recipient);
uint previousSenderBalance = balance[msg.sender];
_transfer(msg.sender, recipient, amount);
assert(balance[msg.sender] == (previousSenderBalance - amount));
emit tranferred(amount,recipient);
//event logs and further checks
}
function _transfer(address from, address to, uint amount) private {
balance[from] -= amount;
balance[to] += amount;
}
}
pragma solidity 0.7.5;
contract HelloWorld {
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 transferDone(address transferFrom, address transferTo, uint amount);
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 transferDone(msg.sender, recipient, amount);
}
function _transfer(address from, address to, uint amount) private {
balance[from]-= amount;
balance[to] += amount;
}
}
Here is two new pieces of code that I added for assignement:
Declaration of the event
event transferMade(address sentFrom, address sentTo, uint amount);
Emitting event within transfer function
emit transferMade(msg.sender, recipient, amount);
How about this:
contract Bank{
// code here
event transferAdded(uint amount, address indexed _depositedTo);
// code here
function transfer(address recipient, uint amount) public{
// code here
emit transferAdded(amount, recipient);
// code here
}
}
As far as I saw it worked for me but I was wondering if it would work outside Remix
pragma solidity 0.7.5;
contract HelloWorld {
mapping(address=>uint) balance;
address owner;
//EVENT
event transferFromTo(uint amount, address depositedFrom, address depositedTo);
modifier onlyOwner {
require(msg.sender==owner);
_;
}
constructor(){
owner=msg.sender;
}
function addBalance(uint _toAdd) public onlyOwner returns (uint){
balance[msg.sender]+=_toAdd;
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);
//we emit the event here:
emit transferFromTo(amount, msg.sender, recipient);
assert(balance[msg.sender]==previousSenderBalance-amount);
}
function _transfer(address from, address to, uint amount) private{
balance[from]-=amount;
balance[to]+=amount;
}
}
Result in log:
“amount”: “200”, “depositedFrom”: “0x5B38Da6a701c568545dCfcB03FcB875f56beddC4”, “depositedTo”: “0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2”
Here is the composition of the event:
event transferTransactioned(uint amountTransferred, address transferredFrom, address transferredTo);
And this is calling a transfer function with the event:
function transfer (address recipient, uint amount) public {
require(balance[msg.sender] >= amount, "Balance not sufficient!");
require(msg.sender != recipient, "Don't transfer to yourself.");
uint previousSenderBalance = balance[msg.sender];
_transfer(msg.sender, recipient, amount);
emit transferTransactioned(amount, msg.sender, recipient);
assert(balance[msg.sender] == previousSenderBalance - amount);
}
Log printed:
[
{
"from": "0xd7Ca4e99F7C171B9ea2De80d3363c47009afaC5F",
"topic": "0x7ba92e83ac2c93264c2b58350af30d91c77eb4ea7695911ebd83300461001c09",
"event": "transferTransactioned",
"args": {
"0": "200",
"1": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
"2": "0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2",
"amountTransferred": "200",
"transferredFrom": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
"transferredTo": "0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2"
}
}
]
pragma solidity 0.7.5;
contract Bank {
mapping(address => uint) balance;
address owner;
event transferCompleted(uint amount, address transferredFrom, address transferredTo);
modifier onlyOwner {
require(msg.sender == owner);
_;
}
constructor(){
owner = msg.sender;
}
function addBalance(uint _toAdd) public onlyOwner returns (uint){
balance[msg.sender]+=_toAdd;
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, "Insufficient balance");
require(msg.sender != recipient, "Transfers cannot be made to your own account");
uint previousSenderBalance = balance[msg.sender];
_transfer(msg.sender, recipient, amount);
emit transferCompleted(amount, msg.sender, recipient);
assert(balance[msg.sender] == previousSenderBalance - amount);
}
function _transfer(address from, address to, uint amount) private{
balance[from] -= amount;
balance[to] += amount;
}
}
pragma solidity 0.7.5;
contract Bank {
mapping(address => uint) balance;
address owner;
event balanceAdded(uint amount, address indexed depositedTo);
event transferDetails(uint amount, address indexed recipientAddress, address indexed senderAddress);
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);
emit transferDetails(amount, msg.sender, recipient);
assert(balance[msg.sender] == previousSenderBalance - amount);
}
function _transfer(address from, address to, uint amount) private {
balance[from] -= amount;
balance [to] += amount;
}
}
Hi @KennethJP,
The code you’ve posted has the transferAdded event declaration, but you’re missing the actual transfer function itself, which should contain the corresponding emit statement.
But I’ve already reviewed and commented on your solution for the Transfer Assignment, which contains both the transferAdded event declaration and its corresponding emit statement
Hey @MattPerry,
Your code works fine for transfers as well, for me. Did you get it to work in the end? Maybe it’s because after copying the recipient address, you then called the transfer function with the same recipient address, when you should then change back to the contract owner address (the one that deposited ether initially) and call the transfer function with that address instead…
I recommend you always add your own error message to each require() statement, which describes what the specific error is when that require() statement fails. That way, when a function reverts, if it’s caused by one of the conditions in a require statement not being met, you’ll be able to see that in the error message displayed in the Remix console, because it will include your own specific message.
Hi @cgironda,
Apologies for the delay in giving you some feedback on your solution to this assignment.
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.
A couple of comments…
-
Generally speaking, it’s better to place an emit statement at the end of a function — after the event itself has occurred and, if there are any, after an assert statement, but before a return statement.
-
Where 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.
If it works in Remix, it should work with any external service e.g. from the frontend of a dapp
Let me know if anything is unclear, or if you have any questions
Hi @Cero,
Your transfer event and corresponding emit statement are both well coded. As you have proved, the emit statement logs 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
A very nicely presented solution @jak
Your transfer event and corresponding emit statement are both well coded. As you have proved, the emit statement logs appropriate data when the transfer() function is successfully executed.
Just one minor observation…
In general an emit statement is probably better placed after an assert statement.
Just let me know if you have any questions
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