Solidity Error Handling

Hello,
i am currently working on MultiSigWallet and i decided to add onlyOwner modifier to function addOwner. Function addOwner is working but when i put onlyOwner to heading it stops working and starts to revert. Anyone knows whats wrong?

Edit: the owner address is in a format address: 0x0000000000000000000000000000000000000000
I saw in the video about inheritance, that Filip has normal address not just zero´s.
Thanks


pragma solidity 0.7.5;

contract MultiSigWallet{
    address public owner;
    
    constructor(){
    owner == msg.sender;
    }
    
    modifier onlyOwner{
        require(msg.sender == owner);
        _;
    }
    
    address[] Owners;
    
    function addOwner(address _owners) public onlyOwner{
        Owners.push(_owners);
    }
}
1 Like

So after more than a week of reviewing the code i found the mistake…
It was in constructur double == should be just single =
I dont how this took me so long to fing :smiley:

How would we introduce a modifier that checks for msg.sender != recipient?

EDIT: I found out… by passing recipient address as an argument to the modifier. In that way we can check for msg.sender != recipient address

So the modifer would look like this:

modifier notSenderAddress(address recipient){
require(msg.sender != recipient, “Do not send money to yourself!”); //prevents sender to send money to him/herself --> same address
_;
}

And would be set in the function header like this:

function transfer(address recipient, uint amount) public notSenderAddress(recipient)

@filip who pays the resources spent in a transaction if a require throws an error?

1 Like

nobody, there are no spend of resources when hitting a require statement, because they are use to verify if the inputted data is valid before the execution.

If you have any more questions, please let us know so we can help you! :slight_smile:

Carlos Z.

1 Like

Thank you for the answer @thecil !! but the require check could have a relative high cost of energy if I would like to make the network slow.

Hey @danielmain

Keep in mind that you first priority when coding a smart contract is not to save as much gas as you can but rather to make is secure.
You should always check the input that your contract receives and make sure they are correct.
Use a require statement is not an ‘waste’ of gas, because all the gas left will be refunded to the address that triggered the transaction.

Coding smart contracts is different than coding in c++ of js, security must be your first priority.

Happy coding,
Dani

2 Likes

Hi Dani, yes thank you for your reply :! But I never spoke about the gas because as far I understand nobody pays the bill if any require returns false.

Does not need the assert await for the transfer first? I assume that the transfer take its time, right?

What happens if the assert in line 30 (video about Assert) returns false? Is the transaction (transfer included) rollback?

Sorry @filip or bombarding you with questions:

Why do I need to add a _; at the end of the modifiers? Is it not obvious that the ‘modifiers’ needs to be executed? What if I do not specify it?

Thank you in advance

How do I use the Remix DEBUGGER to identify the specific input and/or False condition result that throws an error?

Applying the example in this exercise “assert(people[creator].age == 10)” naturally throws an error which is reported in the transaction box at the bottom of the Remix window (“transact to HelloWorld.deletePerson errored: VM error: invalid opcode. invalid opcode The execution might have thrown. Debug the transaction to get more information.”)

But I don’t see anything, or it’s there but I’m not able to ID it, specific to that error in the DEBUGGER.

Hey @danielmain

But I never spoke about the gas because as far I understand nobody pays the bill if any require returns false.

Whenever a transaction hits a revert (for example when a require statement does not pass), the remaining gas is refunded to the user. Which means that the user will pay gas only for the portion of code that was executed.

In case a transfer method fails, it indeed reverts and the remaining gas if refunded.

Why do I need to add a _; at the end of the modifiers? Is it not obvious that the ‘modifiers’ needs to be executed? What if I do not specify it?

The _ at the end of a modifier tells you compiler that the checks are completed therefore it has to keep executing the code of the function where the modified is attached to.

Happy learning,
Dani

Hey @novosel

Here the Remix docs about its debugger functionality: https://remix-ide.readthedocs.io/en/latest/debugger.html#debugger

Another way to debug your code, can be to emit events (with the information you want to check) right where you need them.

Let’s assume that you want to know the value of c in the example below.
You can emit it and check in the transaction logs.


event check (uint);

function sum (uint _a, uint _b) public {
     
     uint c = _a + _b;
     emit check (c); 

}

Cheers,
Dani

1 Like

You can explain the difference between require() and assert() is “user error” vs. “programmer error”.

require catches users doing something bad.

asset catches something the programmer did bad in the code.

How difficult is it to forge a sender address?

Also, I should think that there should be a require statement to make sure the recipient exists otherwise the sender will lose the tokens (if for example the recipient was his “other” account address on an exchange or something) Now, in doing my own research it seems it is not possible to know if a mapping key does not exist already so how did the creators of this language overlook that simple goof? Is this why people lose Ethereum or ERC20 tokens by “accidentally” sending tokens to the wrong address? Or am I mistaken here?

image

Hi I cant type anything in Remix. Can any one advise me ?

Hey @Placebo

There is a whole category about require and assert statements, check it out:
https://academy.ivanontech.com/products/old-ethereum-smart-contract-programming-101/categories/1774681

How difficult is it to forge a sender address?
Can you elaborate?

Also, I should think that there should be a require statement to make sure the recipient exists otherwise the sender will lose the tokens

Wallets do checksum the addresses to see if the “syntax” of it is valid or not, if the address is valid you will be able to send ether/tokens to it.
By default you have no way to know who is the owner of that address, this is one of the cryptocurrency fundamental feature.
Crypto give you freedom to do what you want with your money, they also give you full responsibility of it.

Happy coding,
Dani

Hi @M.K

It looks like you haven’t created a file to write on.
Click here:

image

1 Like

HI dan-i,

I realised my saved files will not be saved , because remix is not loaded into my computer, Do i need to download remix into my computer for this smart contract programming course?

Hey @M.K

Remix in a browser editor that allows you to write and compile Solidity code.

You have to:

  • Create a new file;
  • Name your file;
  • Write code;

image

If for any reason does not work try with a different browser.

Cheers,
Dani

1 Like

Hi,

I watched the part about Require() and I was wondering the following:
if the EVM gives you a full refund of all gas costs when the require() conditions fail, but I imagine that it still takes some computing power and time for these conditions to be checked, why then can I not just spam the network with transactions for which I know they will fail the require() and so for which I will always be fully refunded?

thank you!