Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dylan Reid - Pet Park Assignment #37

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 108 additions & 1 deletion contracts/PetPark.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,114 @@
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;


contract PetPark {
address owner;

// define struct of animal type, age, and gender
struct animalAndDemo {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The general convention is to have the first letter as uppercase in names of structs, classes and events

uint animalType;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use enums for animal type and gender

uint age;
uint gender;
}

// animals in zoo: animalType and count of that animal in the zoo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In solidity it is recommended to use Natspec format for commenting

mapping (uint => uint) public animalsInZoo;
// borrwed animals: address -> animal type and demo of owner
mapping (address => animalAndDemo) public borrowedAnimal;

constructor() {
owner = msg.sender;
}

modifier animalRange(uint animalType) {
// revert when animal type is invalid
require(animalType > 0 && animalType < 6, "Invalid animal type");
_;
}

// define events
event Added(uint animalType, uint animalCount);
event Borrowed(uint animalType);
event Returned(uint animalType);

function add(uint animalType, uint count) public animalRange(animalType) {
// check that only owner has access
require(owner == msg.sender, "Not an owner");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to check this with a modifier as it make the code more readable


// increase the animals in the zoo of that type by the count
animalsInZoo[animalType] += count;

// emit added event
emit Added(animalType, count);
}

function borrow(uint age, uint gender, uint animalType) public animalRange(animalType) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be marked external since it is not being called anywhere internally


animalAndDemo memory currentBorrow = borrowedAnimal[msg.sender];

// revert when age is zero
require(age > 0, "Invalid Age");

// revert when animal not available in park
require(animalsInZoo[animalType] > 0, "Selected animal not available");

// revert when address details do not match from previous calls
if (currentBorrow.age > 0) {
// check age
require(currentBorrow.age == age, "Invalid Age");
// check gender
require(currentBorrow.gender == gender, "Invalid Gender");
}

// revert when pet is already borrowed
require(currentBorrow.animalType == 0, "Already adopted a pet");

// revert when men attempt to borrow animals other than fish and dog
if (gender == 0) {
require(animalType == 1 || animalType == 3, "Invalid animal for men");
}

// revert when women under 40 attempt to borrow cat
if (gender == 1) {
if (age < 40) {
require(animalType != 2, "Invalid animal for women under 40");
}
}

// set up the animal and demo of the item to be added
animalAndDemo memory animalAndDemoToAdd = animalAndDemo(animalType, age, gender);

// store info into borrowedAnimal mapping
borrowedAnimal[msg.sender] = animalAndDemoToAdd;

// remove from zoo
animalsInZoo[animalType]--;

// emit borrowed event
emit Borrowed(animalType);
}

function giveBackAnimal() public {
// set current amimal variable
uint currentAnimal = borrowedAnimal[msg.sender].animalType;

// ensure that there are no borrowed pets
require(currentAnimal > 0, "No borrowed pets");

// set animal type back to zero in borrow mapping
uint currentAge = borrowedAnimal[msg.sender].age;
uint currentGender = borrowedAnimal[msg.sender].gender;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since borrowedAnimal[msg.sender] is being used multiple times it can be stored in a single memory variable. Later in the course you will learn that it is a gas optimisation technique

animalAndDemo memory inputAnimalAndDemo = animalAndDemo(0, currentAge, currentGender);
borrowedAnimal[msg.sender] = inputAnimalAndDemo;

// increment animal count in zoo
animalsInZoo[currentAnimal]++;

// emit returned event
emit Returned(currentAnimal);
}

function animalCounts(uint animalType) public view returns(uint) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since solidity public mappings are automatically exposed as functions, you can just make animalCounts as a public mapping. Here you just have to rename animalsInZoo to animalCounts

return animalsInZoo[animalType];
}
}
Loading