Solidity Error Handling

Thank you mate! Yeah I thought it’d be clear with screenshot but next time I’ll just copy paste it here.
@thecil already helped me out telling me the assert() call shoul be AFTER the _transfer function. That solved the problem. Cheers!

2 Likes

A modifier is a function, so why is an underscore needed to run the function? image

Hi @Kkrypto,

Modifiers are not standard functions — they modify functions. As you probably already know (from the video) if a modifier is referenced in a function header, the modifier’s code will be executed first. The underscore _; is the syntax required for control flow to pass from the modifier to the code in the function body (of the function referencing the modifier).

So, the underscore doesn’t mean “run the code in the modifier”. It means “now run the code in the body of the modified function”.

Let me know if anything is still unclear, or if you have any further questions.

Nothing else on this, thanks.

1 Like

In the addBalance function, the usage and meanings of ‘msg.sender’ and owner are not clear. If owner is being set equal to msg.sender in the constructor function, what is the purpose checking if msg.sender is equal to owner?

Why can’t it be written as: require(msg.sender == msg.sender)?!

Screen Shot 2021-06-08 at 4.59.39 PM|395x139

1 Like

Hey @ZacSed

The owner is set when the contract is deployed. The msg.sender can then change to a different address whereas the ‘owner’ will remain constant.

1 Like

@filip pls help me check this my code it’s not deploying why…my transfer function not working below is my code :

pragma solidity 0.7.5;

contract Bank {

mapping(address => uint) balance;
address owner = msg.sender;

/* constructor(){
owner = msg.sender;
} */

function addBalance(uint _toAdd) public returns(uint){
    require(msg.sender == owner);
    balance[msg.sender] += _toAdd; // _toAdd is to keep updating the balance as more value is added to the balance
     return balance[msg.sender];

}

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

// this function sends a specific amount from the sender to the receiver by reducig the sender’s balance with an amount amd update the reciever’s balance by adding the particular amount reduced from the sender’s wallet to it.

function transfer(address recipient, uint amount) public {
require(balance[msg.sender] >= amount);
require(msg.sender != recipient);
balance[msg.sender] -= amount;
balance[recipient] += amount;
}

Hi @ZacSed,

Apologies for the late response to your question.

As @Random has explained in his reply, msg.sender is not constant. It always references the address that is calling the function (also know as the sender) which it is used in.

So, when the contract is first deployed, msg.sender in the constructor is whichever address deploys the contract. This address is then assigned to the state variable owner. Therefore, owner in the require statement in the addBalance function is always the address that initially deployed the contract (the contract owner). But, unless the contract owner themself calls the addBalance function, msg.sender in the same require statement will refer to a different address to the contract owner, meaning the require statement will evaluate to false and trigger revert.

Hopefully you can now see that…

… would always evaluate to true, and would not restrict access to this function to the contract owner only.

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

Hi @Phaxsam,

The code you’ve posted is missing a final closing curly brace for the whole contract, but that could just be because you’ve missed it off when copying and pasting.

If I add that missing closing curly brace, your code compiles and deploys successfully, and your transfer function works.

If the closing curly brace isn’t the problem, what exactly is the error message you are getting? It could be that you are not inputting the 2 arguments in the correct format before calling the transfer function from Remix. Unless you are inputting them into the separate recipient and amount fields (available in the dropdown), you need to separate them with a comma.

thanks @jon_m…I’ve been able to get this…but old help.me still check the second one

pls help me check k this code…I’m trying to interact with the government contract but it’s not complying as it’s showing me that the function to get details from the bank contract is not declared…below is the code…

pragma solidity 0.7.5;

interface CBNsubmitRoute {
function addTransaction(address _from, address _to, uint _amount) external;
}

contract Bank {

CBNsubmitRoute CBNcontract = CBNsubmitRoute(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4);
//event SKETCH
event balanceAdded(uint amount, address depostedto);

mapping(address => uint) balance;

address owner = msg.sender;

 //(D) Modifier SKETCH
 modifier OnlyOwner {
   require(msg.sender == owner, "this is not the owner");
   _; // it means run the code. 
 }       

function deposit() public payable  returns(uint){
CBNcontract.(msg.sender, recipient, amount);
//event sktech
emit balanceAdded(msg.value, msg.sender);
    balance[msg.sender] += msg.value; 
     return balance[msg.sender];

}

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

}

Hi @Phaxsam,

it’s because you haven’t included the function name in your external function call…

You have the contract instance you are calling (CBNcontract) and the arguments, but you also need to define what function on that instance you are calling and passing parameters to

CBNcontract.addTransaction(msg.sender, recipient, amount);

This is also something I wanted to mention about the code in your previous post. You should be assigning msg.sender to the owner state variable via a constructor:

address owner;

constructor() {
    owner = msg.sender;
}

address owner = msg.sender;   does still work, but I don’t think it’s good practice. Although, I would need to find out the reason why…

This constructor, together with your owner variable and onlyOwner modifier, could be placed back into the Ownable contract and inherited by Bank.

okay sir…I’ll make corrections now.

1 Like

16234449823174022532244021987329

I’m still getting this error message what does it mean and how can I get it solved

In your deposit() function, you should also update the contract state…

balance[msg.sender] += msg.value;

… before interacting with the external contract. This is to reduce security risk.

Also, you shouldn’t emit the event until after all of the associated operations have been performed (i.e. just before the return statement).

I didn’t understand what you mean here… is the “second one” the Government contract, which I’ve just checked?

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

I cannot see from that photo, please only post your code, otherwise I can’t check it.

Filip,
In looking at the assert() example to see if the transfer actually took place by comparing the new balance, is there ever a time that some other contract could have changed a balance at the same time this contract did? Does every node execute each contract in the same order? Can I assume any state changes in one contract will never affect the state of another contract happening simultaneously?

I hope I am making sense here.
I am thinking of the DAI re-entrant bug that happened some time back.

Thanks for the great classes!

@filip why am i always getting below error

CompilerError: Stack too deep, try removing local variables. address refered8 = NetTree[_ref].refered8; ^–^

while trying to access variable on solidity

1 Like

I just want to check if I understand correctly : if I create a public function, that function can then be called from another smart contract- correct?

1 Like