# Mega guide on snagging a spot for the potential base developer airdrop!

By [Abraham Chase.](https://paragraph.com/@abraham-chase) · 2024-05-04

---

Have you seen those recent airdrops? developers getting treated right. There’s a bunch of contract deployment tasks up for grabs on @base where you can bag all the badges for zero cost!

Only 11k completed the task. That’s a huge edge for us! 🔥

Gonna be a bit of a long one, not everyone’s going to vibe with it, but hey, that’s where we shine.

First of all, last year we minted this builder NFT when the base hit testnet. Now? You can totally claim your builder NFT on Mainnet right here: [https://www.base.org/builder-anniversary-nft](https://www.base.org/builder-anniversary-nft)

No coding skills? No worries. Just cruise through this guide. You’ll bump into some code snippets to copy-paste. I know X will mess up my tweet, so, as always, catch the full guide on here.

![](https://storage.googleapis.com/papyrus_images/668bb7f4d4ae9b19eafaa492f216928a64c02da4adf006eaff3fbc39cae54f1f.png)

> _First, you need to open up some websites. I’ll name them to make our journey easier._

1.  Base developer page: [here](https://docs.base.org/base-camp/docs/deployment-to-testnet/deployment-to-testnet-exercise/).
    
2.  Remix page: [here](https://remix.ethereum.org/#lang=en&optimize=false&runs=200&evmVersion=null).
    
3.  Testnet page: [here](https://www.alchemy.com/faucets/base-sepolia).
    
4.  Guild page: [here](https://guild.xyz/base/base-camp).
    

Now, on the developer page, you can connect your wallet. It will prompt you to add the “base sepolia” network where all the tasks will be carried out.

![](https://storage.googleapis.com/papyrus_images/5a41f9eae63640179959673062bba5732ca2c367f9329c9599a6d9a516df7da9.png)

After adding network in your wallet, let’s get some faucet by going [here](https://www.alchemy.com/faucets/base-sepolia).

![](https://storage.googleapis.com/papyrus_images/ed03dd386ea05ae8af66e488c1eac96d832029906bc7081b48f78f8c9b3191d2.png)

Next, navigate to the remix tool and locate the “owner.sol” file under the contracts folder. Click on the file, and on the left sidebar, you will find the “Solidity compiler” tab. Click on “compile.”

![](https://storage.googleapis.com/papyrus_images/558c11f8d34f30f43614f885ecb9e64ca7e839e9dc0ff5862890cd10ffdf8e14.png)

Next, go to the deploy tab and choose the environment as “Injected provider — Metamask”. Once your wallet is connected, click on deploy.

![](https://storage.googleapis.com/papyrus_images/9a41c9c3a4351e4e81eebde3e4c45324c9559e4678aae3c29b3e2c3fefada712.png)

Great! Now, let’s deploy another contract. On the remix page, go to the contracts folder and create a new file following the example in the image below.

Next, name the file “BasicMath.” Simply copy the name and paste it in the required location. The file name should remain unchanged.

![](https://storage.googleapis.com/papyrus_images/77b86433ebf55dc24b1b5a468e9f4b8db4918b54257e4cce6cbc817b90044762.png)

Next, the console will open on the right side of the screen. Paste the following code in it.

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    contract BasicMath {
        uint256 constant MAX_INT = type(uint256).max;    function adder(uint256 _a, uint256 _b) external pure returns (uint256 sum, bool error) {
            if (_b > MAX_INT - _a) {
                return (0, true); // Overflow occurred
            }
            return (_a + _b, false);
        }    function subtractor(uint256 _a, uint256 _b) external pure returns (uint256 difference, bool error) {
            if (_b > _a) {
                return (0, true); // Underflow occurred
            }
            return (_a - _b, false);
        }
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/96d61c9d50f1b9ffce39d8609d76ae9499b3c01c1671bd9db2c7f8958de4c9fb.png)

Then on the left sidebar, click on “Solidity Compiler” and then compile BasicMath.sol

![](https://storage.googleapis.com/papyrus_images/c72570c6f4b9960b67ae35026090c521ba49036a95b8c92b892362c3b1586e5e.png)

Once the contract has been successfully deployed, navigate to the left sidebar and scroll down to view the BasicMath contract code. Copy it and go to the developer page.

![](https://storage.googleapis.com/papyrus_images/f8a31e742efa1ad684ed9089c48622a9670f90c2d9c5232ad19db85193d91e08.png)

![](https://storage.googleapis.com/papyrus_images/995bbe8f39eb1e0a96d018095b7739c2599766461895290860840b23d066ebbe.png)

You should see something similar after selecting “Submit.”

![](https://storage.googleapis.com/papyrus_images/9df119c3d0ab24451a7576a5780d191864cb0c9789aa43b58bb5a459fb8228c2.png)

Great, the first deployment is complete. We have 13 more contracts to deploy, and the process will be similar. Let’s keep going.

**Contract 2: Control Structures**

Make a new file called “Control Structures” in the contracts folder.

Next, insert the code below on the code panel’s right side.

    // SPDX-License-Identifier: MIT
    pragma solidity 0.8.17;
    
    contract ControlStructures {
        // Define custom errors for use within the contract
        error AfterHours(uint256 time);
        error AtLunch();    // Function to determine the response based on the input number
        function fizzBuzz(uint256 _number) public pure returns (string memory response) {
            // Check if the number is divisible by both 3 and 5
            if (_number % 3 == 0 && _number % 5 == 0) {
                return "FizzBuzz"; // Return "FizzBuzz" if divisible by both 3 and 5
            } 
            // Check if the number is divisible by 3
            else if (_number % 3 == 0) {
                return "Fizz"; // Return "Fizz" if divisible by 3
            } 
            // Check if the number is divisible by 5
            else if (_number % 5 == 0) {
                return "Buzz"; // Return "Buzz" if divisible by 5
            } 
            // If none of the above conditions are met
            else {
                return "Splat"; // Return "Splat" if none of the conditions are met
            }
        }    // Function to determine the response based on the input time
        function doNotDisturb(uint256 _time) public pure returns (string memory result) {
            // Ensure the input time is within valid bounds (less than 2400)
            assert(_time < 2400);        // Check different time ranges and return appropriate responses or revert with errors
            if (_time > 2200 || _time < 800) {
                revert AfterHours(_time); // Revert with custom error if it's after 10:00 PM or before 8:00 AM
            } 
            else if (_time >= 1200 && _time <= 1299) {
                revert AtLunch(); // Revert with custom error if it's between 12:00 PM and 1:00 PM
            } 
            else if (_time >= 800 && _time <= 1199) {
                return "Morning!"; // Return "Morning!" if it's between 8:00 AM and 11:59 AM
            } 
            else if (_time >= 1300 && _time <= 1799) {
                return "Afternoon!"; // Return "Afternoon!" if it's between 1:00 PM and 5:59 PM
            } 
            else if (_time >= 1800 && _time <= 2200) {
                return "Evening!"; // Return "Evening!" if it's between 6:00 PM and 10:00 PM
            }
        }
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/ec448f8d5b760aa6699389d92208fee345407e813c4634a9ee53730980fc329c.png)

Next, in the same manner, compile the file, deploy the contract and validate the metamask transaction.

Then copy the contract code by scrolling down on the left sidebar.

![](https://storage.googleapis.com/papyrus_images/170bd43fabcbf3b32cbf27937c78d973b11d544cbf37622f8b97a48d3bebaf6d.png)

Then go over [here](https://docs.base.org/base-camp/docs/control-structures/control-structures-exercise) and paste your contract code, and click on “Submit.”

![](https://storage.googleapis.com/papyrus_images/5640f35b3fdc93cb4dd4c72392bb82f8d3b52469247a4472b49dc3f7f258e66a.png)

**Contract 3: Storage**

Make a new file called “Storage” in the contracts folder.

Next, insert the code below on the code panel’s right side.

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.17;
    
    contract EmployeeStorage {
        // Declare private state variables to store employee data
        uint16 private shares; // Number of shares owned by the employee (private to contract)
        uint32 private salary; // Monthly salary of the employee (private to contract)
        uint256 public idNumber; // Unique identification number of the employee (publicly accessible)
        string public name; // Name of the employee (publicly accessible)    // Constructor to initialize employee data when contract is deployed
        constructor(uint16 _shares, string memory _name, uint32 _salary, uint _idNumber) {
            shares = _shares; // Initialize shares
            name = _name; // Initialize name
            salary = _salary; // Initialize salary
            idNumber = _idNumber; // Initialize idNumber
        }    // View function to retrieve the number of shares owned by the employee
        function viewShares() public view returns (uint16) {
            return shares;
        }
        
        // View function to retrieve the monthly salary of the employee
        function viewSalary() public view returns (uint32) {
            return salary;
        }    // Custom error declaration
        error TooManyShares(uint16 _shares);
        
        // Function to grant additional shares to the employee
        function grantShares(uint16 _newShares) public {
            // Check if the requested shares exceed the limit
            if (_newShares > 5000) {
                revert("Too many shares"); // Revert with error message
            } else if (shares + _newShares > 5000) {
                revert TooManyShares(shares + _newShares); // Revert with custom error message
            }
            shares += _newShares; // Grant the new shares
        }    // Function used for testing packing of storage variables (not relevant to main functionality)
        function checkForPacking(uint _slot) public view returns (uint r) {
            assembly {
                r := sload (_slot)
            }
        }    // Function to reset shares for debugging purposes (not relevant to main functionality)
        function debugResetShares() public {
            shares = 1000; // Reset shares to 1000
        }
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/b00675ba73fcc74b3cd796884dc9c34b305fffe8c51473fbbf1946f28ae45835.png)

Now on the deploy tab, we need to make some changes.

Select the dropdown menu as indicated by the picture. Then fill out the details.

![](https://storage.googleapis.com/papyrus_images/d4497a2bcecf746c03191786a3bc9099584b4cbfe55109718125de98d7a7f89d.png)

*   `shares` - 1000
    
*   `name` - Pat
    
*   `salary` - 50000
    
*   `idNumber` - 112358132134
    

Then click on “Transact” and confirm the metamask popup.

Then copy the contract code by scrolling down on the left sidebar.

![](https://storage.googleapis.com/papyrus_images/285df76d40b28c9640c5bd91eca3cee746f47a0f58a341db0108b6f38a5dfd43.png)

Then go over [here](https://docs.base.org/base-camp/docs/storage/storage-exercise/) paste your contract code, and click on “Submit.”

![](https://storage.googleapis.com/papyrus_images/e4ffa4a990ea205460f18c0a6ce672bb8e60a3bbf3128942aadab20d0c88b8c8.png)

**Contract 4: Arrays**

Make a new file called “Arrays” in the contracts folder.

Next, insert the code below on the code panel’s right side.

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.17;
    
    contract ArraysExercise {
        // Declare state variables to store arrays of numbers, timestamps, and senders
        uint[] numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // Array of numbers initialized with values
        uint[] timestamps; // Dynamic array to store timestamps
        address[] senders; // Dynamic array to store sender addresses    uint256 constant Y2K = 946702800; // Constant representing the Unix timestamp for the year 2000    // Function to retrieve the array of numbers
        function getNumbers() external view returns (uint[] memory) {
            // Create a memory array to hold the numbers
            uint[] memory results = new uintUnsupported embed;        // Copy the numbers from the state array to the memory array
            for(uint i=0; i<numbers.length; i++) {
                results[i] = numbers[i];
            }        // Return the memory array
            return results;
        }    // Function to reset the numbers array to its initial values
        function resetNumbers() public {
            numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        }    // Function to append new numbers to the numbers array
        function appendToNumbers(uint[] calldata _toAppend) public {
            // Iterate through the array to be appended
            for (uint i = 0; i < _toAppend.length; i++) {
                // Push each element of the array to be appended to the numbers array
                numbers.push(_toAppend[i]);
            }
        }    // Function to save a timestamp along with the sender's address
        function saveTimestamp(uint _unixTimestamp) public {
            // Push the timestamp and sender's address to their respective arrays
            timestamps.push(_unixTimestamp);
            senders.push(msg.sender);
        }    // Function to retrieve timestamps and senders after the year 2000
        function afterY2K() public view returns (uint256[] memory, address[] memory) {
            // Initialize counter for timestamps after Y2K
            uint256 counter = 0;        // Count the number of timestamps after Y2K
            for (uint i = 0; i < timestamps.length; i++) {
                if (timestamps[i] > Y2K) {
                    counter++;
                }
            }        // Initialize memory arrays to hold timestamps and senders after Y2K
            uint256[] memory timestampsAfterY2K = new uint256Unsupported embed;
            address[] memory sendersAfterY2K = new addressUnsupported embed;        // Initialize index for inserting elements into memory arrays
            uint256 index = 0;        // Iterate through timestamps and senders arrays to extract elements after Y2K
            for (uint i = 0; i < timestamps.length; i++) {
                if (timestamps[i] > Y2K) {
                    timestampsAfterY2K[index] = timestamps[i];
                    sendersAfterY2K[index] = senders[i];
                    index++;
                }
            }        // Return timestamps and senders after Y2K
            return (timestampsAfterY2K, sendersAfterY2K);
        }    // Function to reset the senders array
        function resetSenders() public {
            delete senders;
        }    // Function to reset the timestamps array
        function resetTimestamps() public {
            delete timestamps;
        }
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/d302b7cc7512c7d10f439535eab3c5726834a5dfa1445e5518c43f3d105e6e9a.png)

Next, in the same manner, compile the file, deploy the contract, and validate the metamask transaction.

Then copy the contract code by scrolling down on the left sidebar.

![](https://storage.googleapis.com/papyrus_images/295d2a5db685e326abdf13762e81d6edd714187897fee4098530ac4b4211708b.png)

Then go over [here](https://docs.base.org/base-camp/docs/arrays/arrays-exercise) and paste your contract code, and click on “Submit.”

![](https://storage.googleapis.com/papyrus_images/2fc307c0d061235c49832f8f2837897467d4d608fa120a567f88088da8317201.png)

**Contract 5: Mapping**

Make a new file called “Mapping” in the contracts folder.

Next, insert the code below on the code panel’s right side.

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.17;
    
    /**
     * @title FavoriteRecords
     * @dev Contract to manage a list of approved music records and allow users to add them to their favorites
     */
    contract FavoriteRecords {
        // Mapping to store whether a record is approved
        mapping(string => bool) private approvedRecords;
        // Array to store the index of approved records
        string[] private approvedRecordsIndex;    // Mapping to store user's favorite records
        mapping(address => mapping(string => bool)) public userFavorites;
        // Mapping to store the index of user's favorite records
        mapping(address => string[]) private userFavoritesIndex;    // Custom error to handle unapproved records
        error NotApproved(string albumName);    /**
         * @dev Constructor that initializes the approved records list
         */
        constructor() {
            // Predefined list of approved records
            approvedRecordsIndex = [
                "Thriller", 
                "Back in Black", 
                "The Bodyguard", 
                "The Dark Side of the Moon", 
                "Their Greatest Hits (1971-1975)", 
                "Hotel California", 
                "Come On Over", 
                "Rumours", 
                "Saturday Night Fever"
            ];
            // Initialize the approved records mapping
            for (uint i = 0; i < approvedRecordsIndex.length; i++) {
                approvedRecords[approvedRecordsIndex[i]] = true;
            }
        }    /**
         * @dev Returns the list of approved records
         * @return An array of approved record names
         */
        function getApprovedRecords() public view returns (string[] memory) {
            return approvedRecordsIndex;
        }    /**
         * @dev Adds an approved record to the user's favorites
         * @param _albumName The name of the album to be added
         */
        function addRecord(string memory _albumName) public {
            // Check if the record is approved
            if (!approvedRecords[_albumName]) {
                revert NotApproved({albumName: _albumName});
            }
            // Check if the record is not already in the user's favorites
            if (!userFavorites[msg.sender][_albumName]) {
                // Add the record to the user's favorites
                userFavorites[msg.sender][_albumName] = true;
                // Add the record to the user's favorites index
                userFavoritesIndex[msg.sender].push(_albumName);
            }
        }    /**
         * @dev Returns the list of a user's favorite records
         * @param _address The address of the user
         * @return An array of user's favorite record names
         */
        function getUserFavorites(address _address) public view returns (string[] memory) {
            return userFavoritesIndex[_address];
        }    /**
         * @dev Resets the caller's list of favorite records
         */
        function resetUserFavorites() public {
            // Iterate through the user's favorite records
            for (uint i = 0; i < userFavoritesIndex[msg.sender].length; i++) {
                // Delete each record from the user's favorites mapping
                delete userFavorites[msg.sender][userFavoritesIndex[msg.sender][i]];
            }
            // Delete the user's favorites index
            delete userFavoritesIndex[msg.sender];
        }
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/b7e6248f268a0a15d9360f663728243789073e5d66d32ab927364d7aedceb10d.png)

Next, in the same manner, compile the file, deploy the contract, and validate the metamask transaction.

Then copy the contract code by scrolling down on the left sidebar.

![](https://storage.googleapis.com/papyrus_images/dbeb9850770053d78827e09ae91bc64d25965366ba11d80f849a3a240e9ce132.png)

Then go over [here](https://docs.base.org/base-camp/docs/mappings/mappings-exercise) and paste your contract code, and click on “Submit.”

![](https://storage.googleapis.com/papyrus_images/8b82c001ddeeb81ee583d60d599325951c0f2b40382164ff1b6f532f094616cf.png)

**Contract 6: Structs**

Make a new file called “Structs” in the contracts folder.

Next, insert the code below on the code panel’s right side.

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.17;
    
    /**
     * @title GarageManager
     * @dev Contract to manage a garage of cars for each user
     */
    contract GarageManager {
        // Mapping to store the garage of cars for each user
        mapping(address => Car[]) private garages;    // Struct to represent a car
        struct Car {
            string make; // Make of the car
            string model; // Model of the car
            string color; // Color of the car
            uint numberOfDoors; // Number of doors of the car
        }    // Custom error for handling invalid car index
        error BadCarIndex(uint256 index);    /**
         * @dev Adds a new car to the caller's garage
         * @param _make The make of the car
         * @param _model The model of the car
         * @param _color The color of the car
         * @param _numberOfDoors The number of doors of the car
         */
        function addCar(string memory _make, string memory _model, string memory _color, uint _numberOfDoors) external {
            // Push a new car struct with the provided details to the caller's garage
            garages[msg.sender].push(Car(_make, _model, _color, _numberOfDoors));
        }    /**
         * @dev Retrieves the caller's array of cars
         * @return An array of `Car` structs
         */
        function getMyCars() external view returns (Car[] memory) {
            // Return the array of cars stored in the caller's garage
            return garages[msg.sender];
        }    /**
         * @dev Retrieves a specific user's array of cars
         * @param _user The address of the user
         * @return An array of `Car` structs
         */
        function getUserCars(address _user) external view returns (Car[] memory) {
            // Return the array of cars stored in the garage of the specified user
            return garages[_user];
        }    /**
         * @dev Updates a specific car in the caller's garage
         * @param _index The index of the car in the garage array
         * @param _make The new make of the car
         * @param _model The new model of the car
         * @param _color The new color of the car
         * @param _numberOfDoors The new number of doors of the car
         */
        function updateCar(uint256 _index, string memory _make, string memory _model, string memory _color, uint _numberOfDoors) external {
            // Check if the provided index is valid
            if (_index >= garages[msg.sender].length) {
                revert BadCarIndex({index: _index}); // Revert with custom error if the index is invalid
            }
            // Update the specified car with the new details
            garages[msg.sender][_index] = Car(_make, _model, _color, _numberOfDoors);
        }    /**
         * @dev Deletes all cars in the caller's garage
         */
        function resetMyGarage() external {
            // Delete all cars from the caller's garage
            delete garages[msg.sender];
        }
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/7b3c8ac6b5dece7ceed2bd4f042b7a4f426bb4b27cc5d494266baf0ccd67ef8c.png)

Next, in the same manner, compile the file, deploy the contract, and validate the metamask transaction.

Then copy the contract code by scrolling down on the left sidebar.

![](https://storage.googleapis.com/papyrus_images/f3500ce24cac9b0fa237242688a41900d057942ddd54648a10e64cbebcf293d3.png)

Then go over [here](https://docs.base.org/base-camp/docs/structs/structs-exercise) and paste your contract code, and click on “Submit.”

![](https://storage.googleapis.com/papyrus_images/1d9d02edf05efd12cd59c811e01b7dba82f92f4e24a8e302670d740f0c078246.png)

**Contract 7: Inheritance**

Make a new file called “Inheritance” in the contracts folder.

Next, insert the code below on the code panel’s right side.

    // SPDX-License-Identifier: MIT
    
    pragma solidity 0.8.17;/**
     * @title Employee
     * @dev Abstract contract defining common properties and behavior for employees.
     */
    abstract contract Employee {
        uint public idNumber; // Unique identifier for the employee
        uint public managerId; // Identifier of the manager overseeing the employee    /**
         * @dev Constructor to initialize idNumber and managerId.
         * @param _idNumber The unique identifier for the employee.
         * @param _managerId The identifier of the manager overseeing the employee.
         */
        constructor(uint _idNumber, uint _managerId) {
            idNumber = _idNumber;
            managerId = _managerId;
        }    /**
         * @dev Abstract function to be implemented by derived contracts to get the annual cost of the employee.
         * @return The annual cost of the employee.
         */
        function getAnnualCost() public virtual returns (uint);
    }/**
     * @title Salaried
     * @dev Contract representing employees who are paid an annual salary.
     */
    contract Salaried is Employee {
        uint public annualSalary; // The annual salary of the employee    /**
         * @dev Constructor to initialize the Salaried contract.
         * @param _idNumber The unique identifier for the employee.
         * @param _managerId The identifier of the manager overseeing the employee.
         * @param _annualSalary The annual salary of the employee.
         */
        constructor(uint _idNumber, uint _managerId, uint _annualSalary) Employee(_idNumber, _managerId) {
            annualSalary = _annualSalary;
        }    /**
         * @dev Overrides the getAnnualCost function to return the annual salary of the employee.
         * @return The annual salary of the employee.
         */
        function getAnnualCost() public override view returns (uint) {
            return annualSalary;
        }
    }/**
     * @title Hourly
     * @dev Contract representing employees who are paid an hourly rate.
     */
    contract Hourly is Employee {
        uint public hourlyRate; // The hourly rate of the employee    /**
         * @dev Constructor to initialize the Hourly contract.
         * @param _idNumber The unique identifier for the employee.
         * @param _managerId The identifier of the manager overseeing the employee.
         * @param _hourlyRate The hourly rate of the employee.
         */
        constructor(uint _idNumber, uint _managerId, uint _hourlyRate) Employee(_idNumber, _managerId) {
            hourlyRate = _hourlyRate;
        }    /**
         * @dev Overrides the getAnnualCost function to calculate the annual cost based on the hourly rate.
         * Assuming a full-time workload of 2080 hours per year.
         * @return The annual cost of the employee.
         */
        function getAnnualCost() public override view returns (uint) {
            return hourlyRate * 2080;
        }
    }/**
     * @title Manager
     * @dev Contract managing a list of employee IDs.
     */
    contract Manager {
        uint[] public employeeIds; // List of employee IDs    /**
         * @dev Function to add a new employee ID to the list.
         * @param _reportId The ID of the employee to be added.
         */
        function addReport(uint _reportId) public {
            employeeIds.push(_reportId);
        }    /**
         * @dev Function to reset the list of employee IDs.
         */
        function resetReports() public {
            delete employeeIds;
        }
    }/**
     * @title Salesperson
     * @dev Contract representing salespeople who are paid hourly.
     */
    contract Salesperson is Hourly {
        /**
         * @dev Constructor to initialize the Salesperson contract.
         * @param _idNumber The unique identifier for the employee.
         * @param _managerId The identifier of the manager overseeing the employee.
         * @param _hourlyRate The hourly rate of the employee.
         */
        constructor(uint _idNumber, uint _managerId, uint _hourlyRate) 
            Hourly(_idNumber, _managerId, _hourlyRate) {}
    }/**
     * @title EngineeringManager
     * @dev Contract representing engineering managers who are paid an annual salary and have managerial responsibilities.
     */
    contract EngineeringManager is Salaried, Manager {
        /**
         * @dev Constructor to initialize the EngineeringManager contract.
         * @param _idNumber The unique identifier for the employee.
         * @param _managerId The identifier of the manager overseeing the employee.
         * @param _annualSalary The annual salary of the employee.
         */
        constructor(uint _idNumber, uint _managerId, uint _annualSalary) 
            Salaried(_idNumber, _managerId, _annualSalary) {}
    }/**
     * @title InheritanceSubmission
     * @dev Contract for deploying instances of Salesperson and EngineeringManager.
     */
    contract InheritanceSubmission {
        address public salesPerson; // Address of the deployed Salesperson instance
        address public engineeringManager; // Address of the deployed EngineeringManager instance    /**
         * @dev Constructor to initialize the InheritanceSubmission contract.
         * @param _salesPerson Address of the deployed Salesperson instance.
         * @param _engineeringManager Address of the deployed EngineeringManager instance.
         */
        constructor(address _salesPerson, address _engineeringManager) {
            salesPerson = _salesPerson;
            engineeringManager = _engineeringManager;
        }
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/61c582f0a8ea2094975eb1aba4822745760567f42bb1aebc3bdc19403b40cbea.png)

Compile the file again in the same way, and during deployment, make some changes. In the contract drop-down, choose the “Salesperson” option.

![](https://storage.googleapis.com/papyrus_images/2f9f534f68a74dfb68d4da12e48c47284baee8f245d6d83e43f8b1bdd60eef0c.png)

Next, select the “Deploy” dropdown menu and enter the information as it appears in the figure.

Id Number: 55555

Manager id: 12345

Salary: 20

Then click on “Transact” and confirm the metamask transaction.

Now, on the next step, change the contract to “EngineeringManager.”

![](https://storage.googleapis.com/papyrus_images/a5f29b159306f306901572fa4e9e0ba62cc517101bce8d3e1a97fdc8c42d0ed7.png)

Fill in the following details on the unit detail after that.

Id Number: 54321

Manager id: 11111

Annual salary: 200000

Then click on “Transact” and confirm the metamask transaction.

Now, on the next step, change the contract to “Inheritance Submission.”

![](https://storage.googleapis.com/papyrus_images/03b90c43928039c43f3c593ef261dbb9b240523cdb4bf1837ed1f4e88aec9946.png)

You must copy the contract code and paste it into this field.

![](https://storage.googleapis.com/papyrus_images/9c6e41ca0324b271e4f3e428e08634fa2ed85e8e58816ade602d2d6183f39b3e.png)

![](https://storage.googleapis.com/papyrus_images/a2ce676303a6f29d3e7e2450b784a2d42822764db43ea68276e76b14cc32e775.png)

Then click on “Transact” and confirm the metamask transaction.

Then copy the contract code by scrolling down on the left sidebar.

Then go over [here](https://docs.base.org/base-camp/docs/inheritance/inheritance-exercise) and paste your contract code, and click on “Submit.”

![](https://storage.googleapis.com/papyrus_images/c50717b41ed77709583cba7011864ea6fc3e0edab150793f8ed9b155cf4d5120.png)

**Contract 8: SillyStringUtils/Imports**

Make a new file called “**SillyStringUtils**” in the contracts folder.

Next, insert the code below on the code panel’s right side.

    // SPDX-License-Identifier: MIT
    
    pragma solidity ^0.8.17;
    
    library SillyStringUtils {    
    
    struct Haiku {
            string line1;
            string line2;
            string line3;
        }    function shruggie(string memory _input) internal pure returns (string memory) {
            return string.concat(_input, unicode" 🤷");
        }
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/f3ace7a2f1f53887fa34fe72246c7b0671c8bf3c1409ed68e4fff11eada02366.png)

Again, Make a new file called “**Imports**” in the contracts folder.

    // SPDX-License-Identifier: MIT
    
    // Importing the SillyStringUtils library
    import "./SillyStringUtils.sol";pragma solidity 0.8.17;contract ImportsExercise {
        // Using the SillyStringUtils library for string manipulation
        using SillyStringUtils for string;    // Declaring a public variable to store a Haiku
        SillyStringUtils.Haiku public haiku;    // Function to save a Haiku
        function saveHaiku(string memory _line1, string memory _line2, string memory _line3) public {
            haiku.line1 = _line1;
            haiku.line2 = _line2;
            haiku.line3 = _line3;
        }    // Function to retrieve the saved Haiku
        function getHaiku() public view returns (SillyStringUtils.Haiku memory) {
            return haiku;
        }    // Function to append a shrugging emoji to the third line of the Haiku
        function shruggieHaiku() public view returns (SillyStringUtils.Haiku memory) {
            // Creating a copy of the Haiku
            SillyStringUtils.Haiku memory newHaiku = haiku;
            // Appending the shrugging emoji to the third line using the shruggie function from the SillyStringUtils library
            newHaiku.line3 = newHaiku.line3.shruggie();
            return newHaiku;
        }
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/1158cf346d3e7de6cd448166bba259cb34db2ff4d2c82d0a26cd87fffb123ceb.png)

Next, in the same manner, compile the file, deploy the contract, and validate the metamask transaction.

Then copy the contract code by scrolling down on the left sidebar.

![](https://storage.googleapis.com/papyrus_images/c8bef6488a759162cc3064d79054884af26665c05afa3fce8640d0c571e418e6.png)

Then go over [here](https://docs.base.org/base-camp/docs/imports/imports-exercise) and paste your contract code, and click on “Submit.”

![](https://storage.googleapis.com/papyrus_images/551b5450a3f9715232473ae565abc761a8f38fdf3bb783008d813d65d7e5c2d5.png)

**Contract 9: Errors**

Make a new file called “Errors” in the contracts folder.

Next, insert the code below on the code panel’s right side.

    // SPDX-License-Identifier: MIT
    
    pragma solidity ^0.8.17;contract ErrorTriageExercise {
        /**
         * @dev Finds the difference between each uint with its neighbor (a to b, b to c, etc.)
         * and returns a uint array with the absolute integer difference of each pairing.
         * 
         * @param _a The first unsigned integer.
         * @param _b The second unsigned integer.
         * @param _c The third unsigned integer.
         * @param _d The fourth unsigned integer.
         * 
         * @return results An array containing the absolute differences between each pair of integers.
         */
        function diffWithNeighbor(
            uint _a,
            uint _b,
            uint _c,
            uint _d
        ) public pure returns (uint[] memory) {
            // Initialize an array to store the differences
            uint[] memory results = new uintUnsupported embed;        // Calculate the absolute difference between each pair of integers and store it in the results array
            results[0] = _a > _b ? _a - _b : _b - _a;
            results[1] = _b > _c ? _b - _c : _c - _b;
            results[2] = _c > _d ? _c - _d : _d - _c;        // Return the array of differences
            return results;
        }    /**
         * @dev Changes the base by the value of the modifier. Base is always >= 1000. Modifiers can be
         * between positive and negative 100.
         * 
         * @param _base The base value to be modified.
         * @param _modifier The value by which the base should be modified.
         * 
         * @return returnValue The modified value of the base.
         */
        function applyModifier(
            uint _base,
            int _modifier
        ) public pure returns (uint returnValue) {
            // Apply the modifier to the base value
            if(_modifier > 0) {
                return _base + uint(_modifier);
            }
            return _base - uint(-_modifier);
        }
        uint[] arr;    function popWithReturn() public returns (uint returnNum) {
            if(arr.length > 0) {
                uint result = arr[arr.length - 1];
                arr.pop();
                return result;
            }
        }    // The utility functions below are working as expected
        function addToArr(uint _num) public {
            arr.push(_num);
        }    function getArr() public view returns (uint[] memory) {
            return arr;
        }    function resetArr() public {
            delete arr;
        }
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/7a189706193d6f620b054f62848a0e4620b5924b84c87da2c69434ad8966d240.png)

Next, in the same manner, compile the file, deploy the contract, and validate the metamask transaction.

Then copy the contract code by scrolling down on the left sidebar.

![](https://storage.googleapis.com/papyrus_images/7241ab586b68b0011607b2156184ebf691b967fdedb482f9c9757ad9b071353a.png)

Then go over [here](https://docs.base.org/base-camp/docs/error-triage/error-triage-exercise) and paste your contract code, and click on “Submit.”

![](https://storage.googleapis.com/papyrus_images/8a8855d16f344f8fa02f3fbdf7272ff6f164b0261f20e8d76ab35cf626694cf4.png)

**Contract 10: AddressBook**

Make a new file called “AddressBook” in the contracts folder.

Next, insert the code below on the code panel’s right side.

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.8;
    
    import "@openzeppelin/contracts/access/Ownable.sol";contract AddressBook is Ownable(msg.sender) {
        // Define a private salt value for internal use
        string private salt = "value";     // Define a struct to represent a contact
        struct Contact {
            uint id; // Unique identifier for the contact
            string firstName; // First name of the contact
            string lastName; // Last name of the contact
            uint[] phoneNumbers; // Array to store multiple phone numbers for the contact
        }    // Array to store all contacts
        Contact[] private contacts;    // Mapping to store the index of each contact in the contacts array using its ID
        mapping(uint => uint) private idToIndex;    // Variable to keep track of the ID for the next contact
        uint private nextId = 1;    // Custom error for when a contact is not found
        error ContactNotFound(uint id);    // Function to add a new contact
        function addContact(string calldata firstName, string calldata lastName, uint[] calldata phoneNumbers) external onlyOwner {
            // Create a new contact with the provided details and add it to the contacts array
            contacts.push(Contact(nextId, firstName, lastName, phoneNumbers));
            // Map the ID of the new contact to its index in the array
            idToIndex[nextId] = contacts.length - 1;
            // Increment the nextId for the next contact
            nextId++;
        }    // Function to delete a contact by its ID
        function deleteContact(uint id) external onlyOwner {
            // Get the index of the contact to be deleted
            uint index = idToIndex[id];
            // Check if the index is valid and if the contact with the provided ID exists
            if (index >= contacts.length || contacts[index].id != id) revert ContactNotFound(id);        // Replace the contact to be deleted with the last contact in the array
            contacts[index] = contacts[contacts.length - 1];
            // Update the index mapping for the moved contact
            idToIndex[contacts[index].id] = index;
            // Remove the last contact from the array
            contacts.pop();
            // Delete the mapping entry for the deleted contact ID
            delete idToIndex[id];
        }    // Function to retrieve a contact by its ID
        function getContact(uint id) external view returns (Contact memory) {
            // Get the index of the contact
            uint index = idToIndex[id];
            // Check if the index is valid and if the contact with the provided ID exists
            if (index >= contacts.length || contacts[index].id != id) revert ContactNotFound(id);
            // Return the contact details
            return contacts[index];
        }    // Function to retrieve all contacts
        function getAllContacts() external view returns (Contact[] memory) {
            // Return the array of all contacts
            return contacts;
        }
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/5ea540da876cb70653b2c20d874e3a39ed69f5cb9a67a233204e129ab5be49b5.png)

Again, Make a new file called “Other Contracts” in the contracts folder.

Next, insert the code below on the code panel’s right side.

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.8;
    
    // Import the AddressBook contract to interact with it
    import "./AddressBook.sol";// Contract for creating new instances of AddressBook
    contract AddressBookFactory {
        // Define a private salt value for internal use
        string private salt = "value";    // Function to deploy a new instance of AddressBook
        function deploy() external returns (AddressBook) {
            // Create a new instance of AddressBook
            AddressBook newAddressBook = new AddressBook();        // Transfer ownership of the new AddressBook contract to the caller of this function
            newAddressBook.transferOwnership(msg.sender);        // Return the newly created AddressBook contract
            return newAddressBook;
        }
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/19f8e3b6e1f8047a46f48ed7239102d4e8a11f30eb3c0017472dded061dab78e.png)

Next, in the same manner while compiling the contract, change the “compiler” to 0.8.20 version, deploy contract and validate the metamask transaction.

![](https://storage.googleapis.com/papyrus_images/627fce23e03e4d7cb386fba0205c2fad6e2d66e51215cc6fc52ac98cecf4a6ef.png)

Then copy the contract code by scrolling down on the left sidebar.

![](https://storage.googleapis.com/papyrus_images/e4c2036f4c6c1df704eb0908a1671d5602bce4231eebc1437497ac4eb2d144b8.png)

Then go over [here](https://docs.base.org/base-camp/docs/new-keyword/new-keyword-exercise) and paste your contract code, and click on “Submit.”

![](https://storage.googleapis.com/papyrus_images/cf778008965a3ed63e7bb5539ce63545409920fd39c31596654aa6d2dd280a8a.png)

**Contract 11: Minimal token**

Make a new file called “Minimal Token” in the contracts folder.

Next, insert the code below on the code panel’s right side.

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    // Contract for an unburnable token
    contract UnburnableToken {
        string private salt = "value"; // A private string variable    // Mapping to track token balances of addresses
        mapping(address => uint256) public balances;    uint256 public totalSupply; // Total supply of tokens
        uint256 public totalClaimed; // Total number of tokens claimed
        mapping(address => bool) private claimed; // Mapping to track whether an address has claimed tokens    // Custom errors
        error TokensClaimed(); // Error for attempting to claim tokens again
        error AllTokensClaimed(); // Error for attempting to claim tokens when all are already claimed
        error UnsafeTransfer(address _to); // Error for unsafe token transfer    // Constructor to set the total supply of tokens
        constructor() {
            totalSupply = 100000000; // Set the total supply of tokens
        }    // Public function to claim tokens
        function claim() public {
            // Check if all tokens have been claimed
            if (totalClaimed >= totalSupply) revert AllTokensClaimed();
            
            // Check if the caller has already claimed tokens
            if (claimed[msg.sender]) revert TokensClaimed();        // Update balances and claimed status
            balances[msg.sender] += 1000;
            totalClaimed += 1000;
            claimed[msg.sender] = true;
        }    // Public function for safe token transfer
        function safeTransfer(address _to, uint256 _amount) public {
            // Check for unsafe transfer conditions, including if the target address has a non-zero ether balance
            if (_to == address(0) || _to.balance == 0) revert UnsafeTransfer(_to);        // Ensure the sender has enough balance to transfer
            require(balances[msg.sender] >= _amount, "Insufficient balance");        // Perform the transfer
            balances[msg.sender] -= _amount;
            balances[_to] += _amount;
        }
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/be73819cfbd2b53153847a3bc3aed75f7b7a8b614a5c85470b57c8e8831a6fec.png)

Then change the values into “1234.”

![](https://storage.googleapis.com/papyrus_images/aea0ae794878221d2670c0dd3fe4309f5370a65443a5505691b704869c3328a6.png)

Next, in the same manner, compile the file, deploy the contract, and validate the metamask transaction.

Then copy the contract code by scrolling down on the left sidebar.

![](https://storage.googleapis.com/papyrus_images/ab5f15deecb288dab8f1036967b811539e5b181ab38e7a0e79215592ba272615.png)

Then go over [here](https://docs.base.org/base-camp/docs/minimal-tokens/minimal-tokens-exercise) and paste your contract code, and click on “Submit.”

![](https://storage.googleapis.com/papyrus_images/505e29562eac637653ffb8dabbc1020d0a339911e1656cd4ec2aced9fb964131.png)

**Contract 12: ERC20**

Make a new file called “ERC20” in the contracts folder.

Next, insert the code below on the code panel’s right side.

    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.17;
    
    // Importing OpenZeppelin contracts for ERC20 and EnumerableSet functionalities
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";// Contract for weighted voting using ERC20 token
    contract WeightedVoting is ERC20 {
        string private salt = "value"; // A private string variable
        using EnumerableSet for EnumerableSet.AddressSet; // Importing EnumerableSet for address set functionality    // Custom errors
        error TokensClaimed(); // Error for attempting to claim tokens again
        error AllTokensClaimed(); // Error for attempting to claim tokens when all are already claimed
        error NoTokensHeld(); // Error for attempting to perform an action without holding tokens
        error QuorumTooHigh(); // Error for setting a quorum higher than total supply
        error AlreadyVoted(); // Error for attempting to vote more than once
        error VotingClosed(); // Error for attempting to vote on a closed issue    // Struct to represent an issue
        struct Issue {
            EnumerableSet.AddressSet voters; // Set of voters
            string issueDesc; // Description of the issue
            uint256 quorum; // Quorum required to close the issue
            uint256 totalVotes; // Total number of votes casted
            uint256 votesFor; // Total number of votes in favor
            uint256 votesAgainst; // Total number of votes against
            uint256 votesAbstain; // Total number of abstained votes
            bool passed; // Flag indicating if the issue passed
            bool closed; // Flag indicating if the issue is closed
        }    // Struct to represent a serialized issue
        struct SerializedIssue {
            address[] voters; // Array of voters
            string issueDesc; // Description of the issue
            uint256 quorum; // Quorum required to close the issue
            uint256 totalVotes; // Total number of votes casted
            uint256 votesFor; // Total number of votes in favor
            uint256 votesAgainst; // Total number of votes against
            uint256 votesAbstain; // Total number of abstained votes
            bool passed; // Flag indicating if the issue passed
            bool closed; // Flag indicating if the issue is closed
        }    // Enum to represent different vote options
        enum Vote {
            AGAINST,
            FOR,
            ABSTAIN
        }    // Array to store all issues
        Issue[] internal issues;    // Mapping to track if tokens are claimed by an address
        mapping(address => bool) public tokensClaimed;    uint256 public maxSupply = 1000000; // Maximum supply of tokens
        uint256 public claimAmount = 100; // Amount of tokens to be claimed    string saltt = "any"; // Another string variable    // Constructor to initialize ERC20 token with a name and symbol
        constructor(string memory _name, string memory _symbol)
            ERC20(_name, _symbol)
        {
            issues.push(); // Pushing an empty issue to start from index 1
        }    // Function to claim tokens
        function claim() public {
            // Check if all tokens have been claimed
            if (totalSupply() + claimAmount > maxSupply) {
                revert AllTokensClaimed();
            }
            // Check if the caller has already claimed tokens
            if (tokensClaimed[msg.sender]) {
                revert TokensClaimed();
            }
            // Mint tokens to the caller
            _mint(msg.sender, claimAmount);
            tokensClaimed[msg.sender] = true; // Mark tokens as claimed
        }    // Function to create a new voting issue
        function createIssue(string calldata _issueDesc, uint256 _quorum)
            external
            returns (uint256)
        {
            // Check if the caller holds any tokens
            if (balanceOf(msg.sender) == 0) {
                revert NoTokensHeld();
            }
            // Check if the specified quorum is higher than total supply
            if (_quorum > totalSupply()) {
                revert QuorumTooHigh();
            }
            // Create a new issue and return its index
            Issue storage _issue = issues.push();
            _issue.issueDesc = _issueDesc;
            _issue.quorum = _quorum;
            return issues.length - 1;
        }    // Function to get details of a voting issue
        function getIssue(uint256 _issueId)
            external
            view
            returns (SerializedIssue memory)
        {
            Issue storage _issue = issues[_issueId];
            return
                SerializedIssue({
                    voters: _issue.voters.values(),
                    issueDesc: _issue.issueDesc,
                    quorum: _issue.quorum,
                    totalVotes: _issue.totalVotes,
                    votesFor: _issue.votesFor,
                    votesAgainst: _issue.votesAgainst,
                    votesAbstain: _issue.votesAbstain,
                    passed: _issue.passed,
                    closed: _issue.closed
                });
        }    // Function to cast a vote on a voting issue
        function vote(uint256 _issueId, Vote _vote) public {
            Issue storage _issue = issues[_issueId];        // Check if the issue is closed
            if (_issue.closed) {
                revert VotingClosed();
            }
            // Check if the caller has already voted
            if (_issue.voters.contains(msg.sender)) {
                revert AlreadyVoted();
            }        uint256 nTokens = balanceOf(msg.sender);
            // Check if the caller holds any tokens
            if (nTokens == 0) {
                revert NoTokensHeld();
            }        // Update vote counts based on the vote option
            if (_vote == Vote.AGAINST) {
                _issue.votesAgainst += nTokens;
            } else if (_vote == Vote.FOR) {
                _issue.votesFor += nTokens;
            } else {
                _issue.votesAbstain += nTokens;
            }        // Add the caller to the list of voters and update total votes count
            _issue.voters.add(msg.sender);
            _issue.totalVotes += nTokens;        // Close the issue if quorum is reached and determine if it passed
            if (_issue.totalVotes >= _issue.quorum) {
                _issue.closed = true;
                if (_issue.votesFor > _issue.votesAgainst) {
                    _issue.passed = true;
                }
            }
        }
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/7f19e68741ccc6e973ddf8cd8602a98b7de9fed23f043d20b8b431a471056517.png)

Then change the values into “CHASE.”

![](https://storage.googleapis.com/papyrus_images/c7c9a914bc993986687b69f062b68994b27d29a3dbd7488e9830160781ccfa95.png)

Then, compile the file in the same way, deploy the contract, fill in the following details, and validate the metamask transaction.

![](https://storage.googleapis.com/papyrus_images/60a1034be792e02e91472d554b3dffc430bd40dabd4f04123815aec8de158a56.png)

Then click on “Transact.”

Then copy the contract code by scrolling down on the left sidebar.

![](https://storage.googleapis.com/papyrus_images/61f8bada4ebe59c07a2c001388f9fdb24c4f8fc66c30e78e1581a51c4a0c1005.png)

Then go over [here](https://docs.base.org/base-camp/docs/erc-20-token/erc-20-exercise) and paste your contract code, and click on “Submit.”

![](https://storage.googleapis.com/papyrus_images/f132f40559bfcfd44b62b7d83a4120300aa304684281f040c67e4730dcc91626.png)

**Contract 13: ERC721**

Make a new file called “ERC721” in the contracts folder.

Next, insert the code below on the code panel’s right side.

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    // Importing OpenZeppelin ERC721 contract
    import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol";// Interface for interacting with a submission contract
    interface ISubmission {
        // Struct representing a haiku
        struct Haiku {
            address author; // Address of the haiku author
            string line1; // First line of the haiku
            string line2; // Second line of the haiku
            string line3; // Third line of the haiku
        }    // Function to mint a new haiku
        function mintHaiku(
            string memory _line1,
            string memory _line2,
            string memory _line3
        ) external;    // Function to get the total number of haikus
        function counter() external view returns (uint256);    // Function to share a haiku with another address
        function shareHaiku(uint256 _id, address _to) external;    // Function to get haikus shared with the caller
        function getMySharedHaikus() external view returns (Haiku[] memory);
    }// Contract for managing Haiku NFTs
    contract HaikuNFT is ERC721, ISubmission {
        Haiku[] public haikus; // Array to store haikus
        mapping(address => mapping(uint256 => bool)) public sharedHaikus; // Mapping to track shared haikus
        uint256 public haikuCounter; // Counter for total haikus minted    // Constructor to initialize the ERC721 contract
        constructor() ERC721("HaikuNFT", "HAIKU") {
            haikuCounter = 1; // Initialize haiku counter
        }    string salt = "value"; // A private string variable    // Function to get the total number of haikus
        function counter() external view override returns (uint256) {
            return haikuCounter;
        }    // Function to mint a new haiku
        function mintHaiku(
            string memory _line1,
            string memory _line2,
            string memory _line3
        ) external override {
            // Check if the haiku is unique
            string[3] memory haikusStrings = [_line1, _line2, _line3];
            for (uint256 li = 0; li < haikusStrings.length; li++) {
                string memory newLine = haikusStrings[li];
                for (uint256 i = 0; i < haikus.length; i++) {
                    Haiku memory existingHaiku = haikus[i];
                    string[3] memory existingHaikuStrings = [
                        existingHaiku.line1,
                        existingHaiku.line2,
                        existingHaiku.line3
                    ];
                    for (uint256 eHsi = 0; eHsi < 3; eHsi++) {
                        string memory existingHaikuString = existingHaikuStrings[
                            eHsi
                        ];
                        if (
                            keccak256(abi.encodePacked(existingHaikuString)) ==
                            keccak256(abi.encodePacked(newLine))
                        ) {
                            revert HaikuNotUnique();
                        }
                    }
                }
            }        // Mint the haiku NFT
            _safeMint(msg.sender, haikuCounter);
            haikus.push(Haiku(msg.sender, _line1, _line2, _line3));
            haikuCounter++;
        }    // Function to share a haiku with another address
        function shareHaiku(uint256 _id, address _to) external override {
            require(_id > 0 && _id <= haikuCounter, "Invalid haiku ID");        Haiku memory haikuToShare = haikus[_id - 1];
            require(haikuToShare.author == msg.sender, "NotYourHaiku");        sharedHaikus[_to][_id] = true;
        }    // Function to get haikus shared with the caller
        function getMySharedHaikus()
            external
            view
            override
            returns (Haiku[] memory)
        {
            uint256 sharedHaikuCount;
            for (uint256 i = 0; i < haikus.length; i++) {
                if (sharedHaikus[msg.sender][i + 1]) {
                    sharedHaikuCount++;
                }
            }        Haiku[] memory result = new HaikuUnsupported embed;
            uint256 currentIndex;
            for (uint256 i = 0; i < haikus.length; i++) {
                if (sharedHaikus[msg.sender][i + 1]) {
                    result[currentIndex] = haikus[i];
                    currentIndex++;
                }
            }        if (sharedHaikuCount == 0) {
                revert NoHaikusShared();
            }        return result;
        }    // Custom errors
        error HaikuNotUnique(); // Error for attempting to mint a non-unique haiku
        error NotYourHaiku(); // Error for attempting to share a haiku not owned by the caller
        error NoHaikusShared(); // Error for no haikus shared with the caller
    }//CHASE
    

![](https://storage.googleapis.com/papyrus_images/047609664ff77d0edf34a9687cf2093b6dedc9bb682e4a3459e035715aadc993.png)

Then, compile the file in the same way, deploy the contract and validate the metamask transaction.

Then copy the contract code by scrolling down on the left sidebar.

![](https://storage.googleapis.com/papyrus_images/b93575b34330f7969c25f521d20f40a4b34a9351675e8ef94dddb07ac3f1f800.png)

Then go over [here](https://docs.base.org/base-camp/docs/erc-721-token/erc-721-exercise) and paste your contract code, and click on “Submit.”

![](https://storage.googleapis.com/papyrus_images/5f9edeb81a89b7a45ae18dbcb963cbcafcac7cc04881824e6a8d41591371efa6.png)

**_Congratulations! You’ve completed all the tasks, and you’re now a kind of developer. If you’ve made it this far, I’m proud of you._**

Now that you’ve collected all the badges/NFTs, head to the guild page and verify all the roles.

Guild link: [https://guild.xyz/base/base-camp](https://guild.xyz/base/base-camp)

Great! You can now check these roles by messaging in the base server.

Congratulations on dedicating your time on this. Your efforts will surely pay off.

If you run into any trouble, leave a comment and I’ll assist you.

---

*Originally published on [Abraham Chase.](https://paragraph.com/@abraham-chase/mega-guide-on-snagging-a-spot-for-the-potential-base-developer-airdrop)*
