Solidity Error Handling Assignment

pragma solidity 0.5.1;

contract DogContract{

struct Dog{
    string name;
    uint age;
}

mapping (address => Dog) ownerToDog;

function addDog(string memory _name, uint _age) public {
    require(ownerToDog[msg.sender].age == 0);
    
    Dog memory currentDog = Dog(_name, _age);
    ownerToDog[msg.sender] = currentDog;
  
}

function getDog() public view returns (string memory) {
    address owner = msg.sender;
    return ownerToDog[owner].name;
}    

}

Here it is, but when I “addDog” I get this error message.

transact to DogContract.addDog errored: Error encoding arguments: SyntaxError: Unexpected token d in JSON at position 1

1 Like

Works for me. Did you submit your name as a string, with quotes around it? Like “Dogname”

1 Like

Thank you… will do that

1 Like

I get the same error msg

Did you submit it with quotes as I said?

function addDog(string memory _name, uint _age) public {
        
        require(ownerToDog[msg.sender].age == 0);      // To verify that the owner has no dog yet
                                                                                                    
        Dog memory currentDog = Dog(_name, _age);       
        ownerToDog[msg.sender] = currentDog;     
    
        // assert(ownerToDog[msg.sender].age != 0);       // To verify correct user input: His dog must be older than 0. Maybe a bit overkill to use the hard Error version here -- Bad Idea to verify user input 
         assert(ownerOfDog[msg.sender].age == _age);        // Use assert to make sure the conditions are right: Dogs age of the owner has to be the the age of user input like this                                    
    }

It is not perfect as dogs age can be less than 1 year in real.
And maybe it is possible to have multiple dog related to one address? …

Good improvement suggestions. How would you implement that? It’s a great exercise :slight_smile:

As I already have watched more of your videos, I cloud do something like that. :sweat_smile:

pragma solidity 0.5.1;

contract DogContract {
    
    struct Dog {
        string name;
        uint age;
    }
    
    mapping(address => Dog[]) ownerToDogs; 
    
    function addDog(string memory _name, uint _age) public{     // function to add dog to owner 
        require(_age > 0);
        Dog memory newDog = Dog(_name, _age);
        ownerToDogs[msg.sender].push(newDog);
        }
    
    function getNumberOfDogs() public view returns (uint) {     // function retuns the numer of dogs the owner owns 
        return ownerToDogs[msg.sender].length;      
    }
    
    function getAllDogs() public view returns (Dog[] memory) {        // this function does not work yet unfortunately  :/; it should return all owned dogs.... probability i have overlook something, as dealing with solidity does not feel intuitive for me. XD
        return ownerToDogs[msg.sender];      // should return a array of Dog type Variable (pushed) something like [{"Tim", 5},{"Jerry", 10},{"Terry", 6} etc.
    }
    
}
1 Like

I have used the require as we are validating the input.

function addDog(string memory _name, uint _age) public {
        require (ownerToDog[msg.sender].age == 0); // softer way of throwing an error, stops execution and refunds used the gas so far; usually validates the inputs
        // assert (ownerToDog[msg.sender].age == 0) // at the end of function to check the conditions that will never should be possible; 
        // if (ownerToDog[msg.sender].age == 0){ // one key can map to only one value
            Dog memory currentDog = Dog(_name, _age); // we create a dog; Dog memory is the type of the variable currentDog, 
                                                      // just like e.g. string memory
        
            // then we add it to the mapping; mapping it from the owner to the dog
            ownerToDog[msg.sender] = currentDog; // msg.sender is an address of person that call this function; 
                                                 // we associate the address of the account that used the addDog function with created Dog        
        // }
        // assert (ownerToDog[msg.sender].age == _age); // reverts all the changes and consume the gas
    }
1 Like

Hello Filip,

It gives and ability to add Dog with 0 age, and I can add more and more dogs with overwrite with 0 age, so I’ve added greater than check for age.

And as programmer with exp. I can say: " Holly macaroni what an ugly syntax in this solidity". And memory word I think is to separate pointers from values.

pragma solidity 0.5.11;

contract DogContract {
    
    struct Dog{
        string name;
        uint age;
    }
    
    mapping(address => Dog) ownerToDog;
    
    function addDog(string memory _name, uint _age) public {
        require(_age > 0, "Parameters are invalid, age shoud be greater than 0");
        require(ownerToDog[msg.sender].age == 0, "You already have a dog!");
        ownerToDog[msg.sender] = Dog(_name, _age);
        
        assert(ownerToDog[msg.sender].age == _age);
    }
    
   function getDog() public view returns (string memory) {
        return ownerToDog[msg.sender].name;
    } 
    
}
1 Like

require(ownerToDog[msg.sender].age == 0 );

also tried this to validate inputs. … but had the error of != invalid for string, found later that should convert it
require(_age != 0 );
require(_name != “” ); wrong – should use keccak256

1 Like
pragma solidity >=0.5.0 <0.7.0;

contract DogContract{
    
    struct Dog {
        string name;
        uint age;
    }
    
    mapping(address => Dog) ownerToDog;
    
    function addDog(string memory _name, uint _age) public {
        require(ownerToDog[msg.sender].age == 0);
        
        Dog memory currentDog = Dog(_name, _age);
        ownerToDog[msg.sender] = currentDog;
    }
    
    function getDog() public view returns (string memory) {
        address owner = msg.sender;
        return ownerToDog[owner].name;
    }
}

I noticed that I can keep adding dogs of age 0 as many times as I want. Then after I add the first one with a positive integer, I am unable to add anymore dogs. I understand that require can be used in place of an if statement to check for valid input, but is the part of the code checking for 0, require(ownerToDog[msg.sender].age == 0);, comparing with my input or the index of the first dog?

If it’s comparing 0 with my input, why am I able to input a dog of an age above zero at least once before getting an error? My input was above 0 so shouldn’t it return false from the start?

The reason we have require(ownerToDog[msg.sender].age == 0); is because it’s the best way for us to check if a dog already has been added or not.

Because we don’t want to allow anyone to add more than 1 dog. This works, unless you input 0 for age. But to be fair, that’s not a dog :wink:

The first time you add anything, ownerToDog[msg.sender].age will always be 0. After that, ownerToDog[msg.sender].age will be the age you set, for example 10. Next time you try to add it’s 10, not 0, therefor you can’t add another one.

Other people can still add dogs though. It checks for msg.sender.

Ahh, I see. I was confused because I was overlooking the limit of 1 dog per address. But it makes sense when taking that into consideration and testing the code with each address.

Haha, definitely not a dog I’d want to see irl. Thanks for the clarification!

1 Like

I think we should use require, because it’s not very crucial when the age is not set.

1 Like

pragma solidity 0.5.1;

contract DogContract{

struct Dog{
   string name;
   uint age;
}

mapping(address => Dog) ownerToDog;

function addDog (string memory _name, uint _age) public {
    require (ownerToDog[msg.sender].age == 0);
    Dog memory currentDog = Dog(_name, _age);
    ownerToDog[msg.sender] = currentDog;
    }
    

function getDog() public view returns (string memory) {
    address owner = msg.sender;
    return ownerToDog[owner].name;
    
}

}

1 Like

pragma solidity 0.5.1;

contract DogContract {
struct Dog {
string name;
uint age;
}

mapping (address => Dog) ownerOfDog;

function addDog(string memory _name, uint _age) public {
    require(ownerOfDog[msg.sender].age == 0);
    Dog memory currentDog = Dog(_name,_age);
    ownerOfDog[msg.sender] = currentDog;
    assert(ownerOfDog[msg.sender].age == _age);
}

function getDog() public view returns (string memory) {
    address owner = msg.sender;
    return ownerOfDog[owner].name;
}

}

1 Like
  function addDog(string memory _name, uint _age) public {
        require(ownerToDog[msg.sender].age == 0, "already is use");
        ownerToDog[msg.sender] = Dog(_name, _age);
        assert(ownerToDog[msg.sender].age == _age);
    }
1 Like

So I’ve gone over 50 different answers to this now. I’m not confused as to whether it should be required or assert. It seems since the code is a zero risk construction since the developer(me) don’t have to worry about hackers at this stage and thus don’t need any assert commands to discourage meddling.
What I’m more confused by and would appreciate some answers on is

  1. Why am I making a function to set an age when the age doesn’t show in the string when I deploy the contract?
  2. Why can’t I deploy several dogs?

pragma solidity 0.5.1;

contract DogContract{

struct Dog{
    string name;
    uint age;
    
}

mapping (address => Dog) ownerToDog;

function addDog (string memory _name, uint _age) public {
    
    require (ownerToDog[msg.sender].age == 0);
    
    Dog memory currentDog = Dog (_name, _age);
    ownerToDog[msg.sender] = currentDog;
}

function getDog() public view returns (string memory){
    
    return ownerToDog[msg.sender].name;
} 

}

Hello, here is my answer for the error handling assignment. I am having a hard time understanding Solidity, can you guys give me an effective videos online that explains the language in an easy way? I was just tinkering stuff in the problem below, not sure if I am grasping the lectures correctly.

Thank you.

ragma solidity 0.5.1;

contract DogContract {
    
    struct Dog {
        string name;
        uint age;
    
    }
    
    mapping(address => Dog) ownerToDog;
    
    function addDog(string memory _name, uint _age) public {
        require(ownerToDog[msg.sender].age == 0, "Dog already registered");
                Dog memory currentDog = Dog(_name, _age);
                    ownerToDog[msg.sender] = currentDog;

    }
    
    function getDog() public view returns (string memory) {
        address owner = msg.sender;
         return ownerToDog[owner].name;
    }  
    
}