Inheritance Programming Assignment

I was wondering how does a new owner type in that he has a cat, how to push that and how to return it ?

function _addAnimal(string memory _name, uint _age, AnimalType _animalType) internal returns (uint){
return ownerToAnimals[msg.sender].push(Animal(_name, _age, _animalType)) - 1;
}

Because _animalType has an input type of value so in this case you type in “filip”, 10, 1 , how does the user know from what type of animals to choose, is there any way to have an input as a string ?
thx

@filip will help you as soon as he has time

Ok thanks, Im just having a hard time about the enum being called from struct and that struct being mapped to an address :frowning: Maybe its a weird question but im just stuck here. I wrote my own contract as this is the best way I learn code and meaning of it .Here is the code …
pragma solidity 0.5.1;

contract Person{

  constructor ()public{
            
            owner = msg.sender ; 
            
            
            
        }
address owner ; 

enum Gender  {female, male}

struct Person {
    string name;
    string lastName;
    uint age;
    Gender varGender;
    
    
    
    
}

mapping (address => Person[]) mapPerson; 


function addPerson ( string memory _name, string memory _lname, uint _age, Gender _gender )  public returns (uint){
   return mapPerson[msg.sender].push(Person(_name, _lname, _age, _gender)) ; // how can an user select the gender , by typing jjust 0,1 ? 
    
}

      
   function callPerson (uint id)  view public returns (string memory){
       
      return  mapPerson[owner][id].; // how can a user print a gender ? 
       
   }    

}

Maybe im just not getting it… thanks :slight_smile:

Hi @tinyHamster

I had modify a bit your sample to answer your questions you can find it bellow
When passing a gender to the addPerson function the number you pass should be existing in the enum:
An enum start from 0 and increments itself automatically, so for your Gender enum it will have only 0 and 1 available as gender.
addPerson -> “joe”,“foo”,20,1 //is correct
addPerson -> “sarah”,“bar”,24,0 //is correct
addPerson -> “egg”,“fried”,12,6 // will fail and trow an error “transact to PersonContract.addPerson errored: VM error: invalid opcode”

Because 6 is not define in your enum.

To display the available value of an enum you have different options the one i prefer is to add a “last” enum and to display the value of the last enum -1.
You can also hard code it in a string.

Let me know if you want more information and if i had answer your questions :wink:

pragma solidity 0.5.1;

contract PersonContract{

    constructor () public {
        owner = msg.sender ; 
    }
 
    address owner ; 

    /*
     * If you don't set a value to the first enum 
     * the value of the first enum will be zero
     * so in this case female ==0 and male==1
    */
    enum Gender  {female, male, notBinary, last}

    struct Person {
        string name;
        string lastName;
        uint age;
        Gender varGender;
    }

    mapping (address => Person[]) mapPerson; 


    function addPerson ( string memory _name, string memory _lname, uint _age, Gender _gender )  public returns (uint){
        require(_gender == Gender.female || _gender == Gender.male,
                 "Gender should be 0 for female and 1 for male");
        return mapPerson[msg.sender].push(Person(_name, _lname, _age, _gender))-1 ; // how can an user select the gender , by typing jjust 0,1 ? 
    }

    // Here we show that 2 is the maximum value female=0,male=1,notBinary=2
    function MaximumValueForGender() pure public returns(uint){
        return uint(Gender.last) - 1;
    }
    
    function showGendersWithString() pure public returns(string memory){
        return ("Directly write the option here: female=0,male=1,notBinary=2");
    }

    function callPersonGender (uint id)  view public returns (string memory){
        string memory gender;
        if (mapPerson[owner][id].varGender == Gender.male)
            gender = "male";
        else if (mapPerson[owner][id].varGender == Gender.female)
            gender = "female";
        return  gender; 
    }
}

Edit:

You can also use an input as a string but it ll cost more gas to compare the string passed as argument.

    function compareString(string memory _name) pure public returns(Gender){
        if(uint(keccak256(abi.encodePacked("male"))) == uint(keccak256(abi.encodePacked(_name)))) {
            return Gender.male;
        }else if(uint(keccak256(abi.encodePacked("female"))) == uint(keccak256(abi.encodePacked(_name)))) {
            return Gender.female;
        } else{
            return Gender.notBinary;
        }
    }

    function addPersonWithString ( string memory _name, string memory _lname, uint _age, string memory _gender )  public returns (uint){
        require(compareString(_gender) == Gender.notBinary,
                 "Gender should be 'male' or 'female'");
        return mapPerson[msg.sender].push(Person(_name, _lname, _age, compareString(_gender)))-1 ; 
    }

my answer:


pragma solidity 0.5.1;

contract Ownable{

    address public owner;

    constructor() public{
        owner = msg.sender;
    }
    
    modifier onlyOwner(){
        require(msg.sender == owner);
        _;
    }

    function changeOwnership(address _newOwner) public onlyOwner{
        require(owner != _newOwner,
        "The address should be different than the last one");
        owner = _newOwner;
    }
}

Hey, thanks for the help i was playing around with the code , so in the line" mapPerson[owner][id].varGender == Gender.male" , the “mapPerson[owner][id].varGender” is the locations in the array and the “Gender.male " is the value ? I was playing around with the code, is there a particular reason you went with " enum Gender {female, male, notBinary, last}” and not without the "last " in the array and just delete the -1 when called, it shows the 2 in both cases ?
Thanks, really appreciate the help :wink:

Hey
So in mapPerson[owner][id].varGender:
The ‘owner’ is the address of the mapping we use to store a Person array.
The ‘id’ is the index where we store a Person structure (see that as an object) in the Person array.
Then we can access to all the element of this structure (or object) mapPerson[owner][id].name , mapPerson[owner][id].lastName, mapPerson[owner][id].age, mapPerson[owner][id].varGender.

I used Gender.last as a delimiter you are right i can remove the -1 and Gender.last it will return 2.
But in case of enum if i want to add let’s say :
enum Gender {female, male, notBinary, yellow, red, blue}
i will have to change my function with:

     function MaximumValueForGender() pure public returns(uint){
         return uint(Gender.blue) ;
     }

If i use Gender.last -1 i just change my enum not my function (it’s just a lazy way to do less lol)

Could you clarify your question? The code in your post accomplishes almost all of that. You can’t however return a struct. So that’s why we return the position in the array.

Yeah I see what u did there, hehe didn’t occur to me :smiley: "you gotta excuse my friend here, hes a little slow " :slight_smile: thanks for the help :slight_smile:

pragma solidity 0.5.1;
contract Ownable{
address public owner;
modifier onlyOwner(){
require(msg.sender == owner);
_;
}
constructor() public{
owner = msg.sender;
}

function ownerChange(address _newOwner) public onlyOwner(){
owner = _newOwner;
}
}

    function setNewOwner(address _newOwner) public onlyOwner returns(address) {
        //creating a function called setNewOwner, taking an eth address as its parameter.
        //it is public because it needs to be accessible from the outside
        //onlyOwner modifier is used so that only the initial owner of the contract can call the function
        //the function should return the new owner's address
        return owner = _newOwner;
    }

@filip Hi, sorry to bother you, I have used a return in my function, as I thought it useful to return the new address. The behavior the contract is OK, but I was wondering whether there are side effects to doing this, as opposed to implementing it without the return? Thanks in advance for your help.

Yes, that looks fine to me.

function moveOwner(address newOwner) public onlyOwner {
// require(newOwner != address (0));
owner = newOwner;

}

1 Like
pragma solidity 0.5.1;

contract Ownable{
    
    address public owner;
    
    modifier onlyOwner(){
          require (msg.sender == owner, "Only the owner of the contract can perform this task.");
        _;
    }
    
    constructor() public{
           owner = msg.sender;
    }
    
    function newOwner(address _address) public onlyOwner returns (address){
        owner = _address;
        return owner;
    }
}
1 Like

Only the owner can specify a new owner. Require that it’s a different owner than the current owner.

function newOwner(address _newOwner) public onlyOwner{
    require(owner!=_newOwner);
    owner = _newOwner;
}
1 Like

I ended up with this:

    function setNewOwner(address _newOwner) public onlyOwner returns (address) {
        owner = _newOwner;
        return owner;
    }
1 Like
pragma solidity 0.5.1;

contract Ownable{
    
    address public owner;
    
    modifier onlyOwner(){
        require(msg.sender == owner);
        _;
    }
    
    constructor() public {
        owner = msg.sender;
    }
    
    function changeOwner(address newOwner) public onlyOwner{
        owner = newOwner;
    }
}
1 Like

pragma solidity 0.5.1;

contract Ownable{

address public owner;

modifier onlyOwner(){
    require(msg.sender == owner);
    _;
}

constructor() public{
    owner = msg.sender;
}

function transferOwnership(address newOwner) public onlyOwner {
    require(newOwner != address(0));
    owner = newOwner;
}

}