# Base: contract deployment

By [Atoms Research](https://paragraph.com/@atoms-research) · 2024-07-20

---

[**Base**](https://x.com/base) is an Ethereum L2, incubated by Coinbase and built on the open-source OP Stack

Coinbase [raised](https://cryptorank.io/ico/coinbase#funding-rounds) $574.2M from a16z, Polychain Capital, and others

### What to do:

• Add the [testnet network](https://chainlist.org/chain/84532) to your wallet

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

• Request test tokens from the [faucet](https://www.alchemy.com/faucets/base-sepolia)

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

• Go to [Remix](https://remix.ethereum.org/) and create a new workspace

• Visit the “Solidity Compiler” tab

• Select version 0.8.0 and click “Auto Compile”

• Open the “Deploy Transactions” tab

• Select MetaMask as Environment

• Create a new file and paste this code:

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    contract BasicMath {
    function adder(uint _a, uint _b) external pure returns (uint sum, bool error) {
    unchecked {
    uint result = _a + _b;
    if (result >= _a && result >= _b) {
    return (result, false);
    } else {
    return (0, true);
    }
    }
    }
    
    function subtractor(uint _a, uint _b) external pure returns (uint difference, bool error) {
    unchecked {
    if (_b <= _a) {
    return (_a - _b, false);
    } else {
    return (0, true);
    }
    }
    }
    }
    

• Deploy the contract and verify the transaction [here](https://docs.base.org/base-camp/docs/deployment-to-testnet/deployment-to-testnet-exercise/)

• Create a new file again and paste this code:

    // SPDX-License-Identifier: MIT
    
    pragma solidity 0.8.17;
    
    contract ControlStructures {
    error AfterHours(uint256 time);
    error AtLunch();
    
    function fizzBuzz(uint256 _number) public pure returns (string memory response) {
    if (_number % 3 == 0 && _number % 5 == 0) {
    return "FizzBuzz";
    } else if (_number % 3 == 0) {
    return "Fizz";
    } else if (_number % 5 == 0) {
    return "Buzz";
    } else {
    return "Splat";
    }
    }
    
    function doNotDisturb(uint256 _time) public pure returns (string memory result) {
    assert(_time < 2400);
    
    if (_time > 2200 || _time < 800) {
    revert AfterHours(_time);
    } else if (_time >= 1200 && _time <= 1299) {
    revert("At lunch!");
    } else if (_time >= 800 && _time <= 1199) {
    return "Morning!";
    } else if (_time >= 1300 && _time <= 1799) {
    return "Afternoon!";
    } else if (_time >= 1800 && _time <= 2200) {
    return "Evening!";
    }
    }
    }
    

• Deploy the contract and verify the transaction [here](https://docs.base.org/base-camp/docs/control-structures/control-structures-exercise/)

• Do the same with the following codes

• Code (3):

    // SPDX-License-Identifier: MIT
    
    pragma solidity ^0.8.17;
    
    contract EmployeeStorage {
    uint16 private shares;
    uint32 private salary;
    uint256 public idNumber;
    string public name;
    
    constructor(uint16 _shares, string memory _name, uint32 _salary, uint _idNumber) {
    shares = _shares;
    name = _name;
    salary = _salary;
    idNumber = _idNumber;
    }
    
    function viewShares() public view returns (uint16) {
    return shares;
    }
    
    function viewSalary() public view returns (uint32) {
    return salary;
    }
    
    error TooManyShares(uint16 _shares);
    function grantShares(uint16 _newShares) public {
    if (_newShares > 5000) {
    revert("Too many shares");
    } else if (shares + _newShares > 5000) {
    revert TooManyShares(shares + _newShares);
    }
    shares += _newShares;
    }
    
    /**
    * Do not modify this function. It is used to enable the unit test for this pin
    * to check whether or not you have configured your storage variables to make
    * use of packing.
    *
    * If you wish to cheat, simply modify this function to always return `0`
    * I'm not your boss ¯\_(ツ)_/¯
    *
    * Fair warning though, if you do cheat, it will be on the blockchain having been
    * deployed by you wallet....FOREVER!
    */
    function checkForPacking(uint _slot) public view returns (uint r) {
    assembly {
    r := sload (_slot)
    }
    }
    
    /**
    * Warning: Anyone can use this function at any time!
    */
    function debugResetShares() public {
    shares = 1000;
    }
    }
    

• [Verify](https://docs.base.org/base-camp/docs/storage/storage-exercise/)

• Code (4):

    // SPDX-License-Identifier: MIT
    
    pragma solidity ^0.8.17;
    
    contract ArraysExercise {
    uint[] numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    uint[] timestamps;
    address[] senders;
    
    uint256 constant Y2K = 946702800;
    
    function getNumbers() external view returns (uint[] memory) {
    uint[] memory results = new uintUnsupported embed;
    
    for(uint i=0; i<numbers.length; i++) {
    results[i] = numbers[i];
    }
    
    return results;
    }
    
    function resetNumbers() public {
    numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    }
    
    function appendToNumbers(uint[] calldata _toAppend) public {
    uint _counter = _toAppend.length;
    for (uint i; i < _counter; i++) {
    numbers.push(_toAppend[i]);
    }
    }
    
    function saveTimestamp(uint _unixTimestamp) public {
    timestamps.push(_unixTimestamp);
    senders.push(msg.sender);
    }
    
    function afterY2K() public view returns (uint256[] memory, address[] memory) {
    
    uint256 counter = 0;
    
    for (uint i = 0; i < timestamps.length; i++) {
    if (timestamps[i] > Y2K) {
    counter++;
    }
    }
    
    uint256[] memory timestampsAfterY2K = new uint256Unsupported embed;
    address[] memory sendersAfterY2K = new addressUnsupported embed;
    
    uint256 index = 0;
    
    for (uint i = 0; i < timestamps.length; i++) {
    if (timestamps[i] > Y2K) {
    timestampsAfterY2K[index] = timestamps[i];
    sendersAfterY2K[index] = senders[i];
    index++;
    }
    }
    
    return (timestampsAfterY2K, sendersAfterY2K);
    }
    
    function resetSenders() public {
    delete senders;
    }
    
    function resetTimestamps() public {
    delete timestamps;
    }
    }
    

• [Verify](https://docs.base.org/base-camp/docs/arrays/arrays-exercise/)

• Code (5):

    // 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(string => bool) private approvedRecords;
    string[] private approvedRecordsIndex;
    
    mapping(address => mapping(string => bool)) public userFavorites;
    mapping(address => string[]) private userFavoritesIndex;
    
    error NotApproved(string albumName);
    
    /**
    * @dev Constructor that initializes the approved records list
    */
    constructor() {
    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"];
    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 {
    if (!approvedRecords[_albumName]) {
    revert NotApproved({albumName: _albumName});
    }
    if (!userFavorites[msg.sender][_albumName]) {
    userFavorites[msg.sender][_albumName] = true;
    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 {
    for (uint i = 0; i < userFavoritesIndex[msg.sender].length; i++) {
    delete userFavorites[msg.sender][userFavoritesIndex[msg.sender][i]];
    }
    delete userFavoritesIndex[msg.sender];
    }
    }
    

• [Verify](https://docs.base.org/base-camp/docs/mappings/mappings-exercise/)

• Code (6):

    // 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(address => Car[]) private garages;
    
    struct Car {
    string make;
    string model;
    string color;
    uint numberOfDoors;
    }
    
    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 {
    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 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 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 {
    if (_index >= garages[msg.sender].length) {
    revert BadCarIndex({index: _index});
    }
    garages[msg.sender][_index] = Car(_make, _model, _color, _numberOfDoors);
    }
    
    /**
    * @dev Deletes all cars in the caller's garage
    */
    function resetMyGarage() external {
    delete garages[msg.sender];
    }
    }
    

• [Verify](https://docs.base.org/base-camp/docs/structs/structs-exercise/)

• Code (7):

    // SPDX-License-Identifier: MIT
    
    pragma solidity 0.8.17;
    
    
    abstract contract Employee
    {
    uint public idNumber;
    uint public managerId;
    
    constructor(uint _idNumber, uint _managerId)
    {
    idNumber = _idNumber;
    managerId = _managerId;
    }
    
    function getAnnualCost() public virtual returns (uint);
    }
    
    contract Salaried is Employee
    {
    uint public annualSalary;
    
    constructor(uint _idNumber, uint _managerId, uint _annualSalary)
    Employee(_idNumber, _managerId)
    {
    annualSalary = _annualSalary;
    }
    
    function getAnnualCost() public override view returns (uint)
    {
    return annualSalary;
    }
    }
    
    contract Hourly is Employee
    {
    uint public hourlyRate;
    
    constructor(uint _idNumber, uint _managerId, uint _hourlyRate) Employee(_idNumber, _managerId)
    {
    hourlyRate = _hourlyRate;
    }
    
    function getAnnualCost() public override view returns (uint)
    {
    return hourlyRate * 2080;
    }
    }
    
    contract Manager
    {
    uint[] public employeeIds;
    
    function addReport(uint _reportId) public
    {
    employeeIds.push(_reportId);
    }
    
    function resetReports() public
    {
    delete employeeIds;
    }
    }
    
    contract Salesperson is Hourly
    {
    constructor(uint _idNumber, uint _managerId, uint _hourlyRate)
    Hourly(_idNumber, _managerId, _hourlyRate) {}
    }
    
    
    contract EngineeringManager is Salaried, Manager
    {
    constructor(uint _idNumber, uint _managerId, uint _annualSalary)
    Salaried(_idNumber, _managerId, _annualSalary) {}
    }
    
    contract InheritanceSubmission {
    address public salesPerson;
    address public engineeringManager;
    
    constructor(address _salesPerson, address _engineeringManager) {
    salesPerson = _salesPerson;
    engineeringManager = _engineeringManager;
    }
    }
    

• On the “Deploy” tab select the same as in the first screenshot

• Click “Transact” and save the contract address

• Now do the same as indicated in the second screenshot

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

• Press “Transact” again and save the contract address

• Change the contract again and enter the addresses you copied earlier and press “Transact”

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

• Paste the contract address and confirm the transaction [here](https://docs.base.org/base-camp/docs/inheritance/inheritance-exercise/)

• Next, you need to create two new files: Imports and SillyStringUtils

• Paste a code (8):

    // SPDX-License-Identifier: MIT
    
    pragma solidity ^0.8.17;
    
    contract ErrorTriageExercise {
    /**
    * Finds the difference between each uint with it's neighbor (a to b, b to c, etc.)
    * and returns a uint array with the absolute integer difference of each pairing.
    */
    function diffWithNeighbor(
    uint _a,
    uint _b,
    uint _c,
    uint _d
    ) public pure returns (uint[] memory) {
    uint[] memory results = new uintUnsupported embed;
    
    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 results;
    }
    
    /**
    * Changes the _base by the value of _modifier. Base is always >= 1000. Modifiers can be
    * between positive and negative 100;
    */
    function applyModifier(
    uint _base,
    int _modifier
    ) public pure returns (uint returnValue) {
    if(_modifier > 0) {
    return _base + uint(_modifier);
    }
    return _base - uint(-_modifier);
    }
    
    /**
    * Pop the last element from the supplied array, and return the popped
    * value (unlike the built-in function)
    */
    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;
    }
    }
    

• [Verify](https://docs.base.org/base-camp/docs/imports/imports-exercise/)

• Code (9):

    AddressBook.sol
    
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.8;
    
    import "@openzeppelin/contracts/access/Ownable.sol";
    
    contract AddressBook is Ownable(msg.sender) {
    string private salt = "value";
    struct Contact {
    uint id;
    string firstName;
    string lastName;
    uint[] phoneNumbers;
    }
    
    Contact[] private contacts;
    mapping(uint => uint) private idToIndex;
    uint private nextId = 1;
    
    error ContactNotFound(uint id);
    
    function addContact(string calldata firstName, string calldata lastName, uint[] calldata phoneNumbers) external onlyOwner {
    contacts.push(Contact(nextId, firstName, lastName, phoneNumbers));
    idToIndex[nextId] = contacts.length - 1;
    nextId++;
    }
    
    function deleteContact(uint id) external onlyOwner {
    uint index = idToIndex[id];
    if (index >= contacts.length || contacts[index].id != id) revert ContactNotFound(id);
    
    contacts[index] = contacts[contacts.length - 1];
    idToIndex[contacts[index].id] = index;
    contacts.pop();
    delete idToIndex[id];
    }
    
    function getContact(uint id) external view returns (Contact memory) {
    uint index = idToIndex[id];
    if (index >= contacts.length || contacts[index].id != id) revert ContactNotFound(id);
    return contacts[index];
    }
    
    function getAllContacts() external view returns (Contact[] memory) {
    return contacts;
    }
    }
    
    
    Other contract:
    
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.8;
    
    import "./AddressBook.sol";
    
    contract AddressBookFactory {
    string private salt = "value";
    function deploy() external returns (AddressBook) {
    AddressBook newAddressBook = new AddressBook();
    newAddressBook.transferOwnership(msg.sender);
    return newAddressBook;
    }
    }
    

• Code (9.1):

• Create another file and paste the second part of the code

• In the 4th field, enter the name of the file that you created before

• Copy and deploy the last file

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.8;
    
    import "./9.sol";
    
    contract AddressBookFactory {
    string private salt = "value";
    function deploy() external returns (AddressBook) {
    AddressBook newAddressBook = new AddressBook();
    newAddressBook.transferOwnership(msg.sender);
    return newAddressBook;
    }
    }
    

• [Verify](https://docs.base.org/base-camp/docs/error-triage/error-triage-exercise/)

• Code (10):

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    contract UnburnableToken {
    string private salt = "value";
    mapping(address => uint256) public balances;
    uint256 public totalSupply;
    uint256 public totalClaimed;
    mapping(address => bool) private claimed;
    
    // Custom errors
    error TokensClaimed();
    error AllTokensClaimed();
    error UnsafeTransfer(address _to);
    
    constructor() {
    totalSupply = 100000000; // Set the total supply of tokens
    }
    
    // Public function to claim tokens
    function claim() public {
    if (totalClaimed >= totalSupply) revert AllTokensClaimed(); // Check if all tokens have been claimed
    if (claimed[msg.sender]) revert TokensClaimed(); // Check if the caller has already claimed tokens
    
    // 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;
    }
    }
    

• [Verify](https://docs.base.org/base-camp/docs/minimal-tokens/minimal-tokens-exercise/)

• Code (11):

    // SPDX-License-Identifier: UNLICENSED
    
    pragma solidity ^0.8.17;
    
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
    
    contract WeightedVoting is ERC20 {
    string private salt = "value";
    using EnumerableSet for EnumerableSet.AddressSet;
    
    error TokensClaimed();
    error AllTokensClaimed();
    error NoTokensHeld();
    error QuorumTooHigh();
    error AlreadyVoted();
    error VotingClosed();
    
    struct Issue {
    EnumerableSet.AddressSet voters;
    string issueDesc;
    uint256 quorum;
    uint256 totalVotes;
    uint256 votesFor;
    uint256 votesAgainst;
    uint256 votesAbstain;
    bool passed;
    bool closed;
    }
    struct SerializedIssue {
    address[] voters;
    string issueDesc;
    uint256 quorum;
    uint256 totalVotes;
    uint256 votesFor;
    uint256 votesAgainst;
    uint256 votesAbstain;
    bool passed;
    bool closed;
    }
    
    enum Vote {
    AGAINST,
    FOR,
    ABSTAIN
    }
    Issue[] internal issues;
    mapping(address => bool) public tokensClaimed;
    uint256 public maxSupply = 1000000;
    uint256 public claimAmount = 100;
    string saltt = "any";
    
    constructor(string memory _name, string memory _symbol)
    ERC20(_name, _symbol)
    {
    issues.push();
    }
    
    
    function claim() public {
    if (totalSupply() + claimAmount > maxSupply) {
    revert AllTokensClaimed();
    }
    if (tokensClaimed[msg.sender]) {
    revert TokensClaimed();
    }
    _mint(msg.sender, claimAmount);
    tokensClaimed[msg.sender] = true;
    }
    
    
    function createIssue(string calldata _issueDesc, uint256 _quorum)
    external
    returns (uint256)
    {
    if (balanceOf(msg.sender) == 0) {
    revert NoTokensHeld();
    }
    if (_quorum > totalSupply()) {
    revert QuorumTooHigh();
    }
    Issue storage _issue = issues.push();
    _issue.issueDesc = _issueDesc;
    _issue.quorum = _quorum;
    return issues.length - 1;
    }
    
    
    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 vote(uint256 _issueId, Vote _vote) public {
    Issue storage _issue = issues[_issueId];
    
    if (_issue.closed) {
    revert VotingClosed();
    }
    if (_issue.voters.contains(msg.sender)) {
    revert AlreadyVoted();
    }
    
    uint256 nTokens = balanceOf(msg.sender);
    if (nTokens == 0) {
    revert NoTokensHeld();
    }
    
    if (_vote == Vote.AGAINST) {
    _issue.votesAgainst += nTokens;
    } else if (_vote == Vote.FOR) {
    _issue.votesFor += nTokens;
    } else {
    _issue.votesAbstain += nTokens;
    }
    
    _issue.voters.add(msg.sender);
    _issue.totalVotes += nTokens;
    
    if (_issue.totalVotes >= _issue.quorum) {
    _issue.closed = true;
    if (_issue.votesFor > _issue.votesAgainst) {
    _issue.passed = true;
    }
    }
    }
    }
    

• [Verify](https://docs.base.org/base-camp/docs/erc-20-token/erc-20-exercise/)

• Code (12):

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol";
    
    interface ISubmission {
    struct Haiku {
    address author;
    string line1;
    string line2;
    string line3;
    }
    
    function mintHaiku(
    string memory _line1,
    string memory _line2,
    string memory _line3
    ) external;
    
    // function ownerOf(uint256 _id) external view returns (address);
    
    function counter() external view returns (uint256);
    
    function shareHaiku(uint256 _id, address _to) external;
    
    function getMySharedHaikus() external view returns (Haiku[] memory);
    }
    
    contract HaikuNFT is ERC721, ISubmission {
    Haiku[] public haikus;
    mapping(address => mapping(uint256 => bool)) public sharedHaikus;
    uint256 public haikuCounter;
    
    constructor() ERC721("HaikuNFT", "HAIKU") {
    haikuCounter = 1;
    }
    
    string salt = "value";
    
    function counter() external view override returns (uint256) {
    return haikuCounter;
    }
    
    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];
    // string memory newHaikuString = string(
    // abi.encodePacked(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 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 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;
    }
    
    error HaikuNotUnique();
    error NotYourHaiku();
    error NoHaikusShared();
    }
    

• [Verify](https://docs.base.org/base-camp/docs/erc-721-token/erc-721-exercise/)

* * *

**✅ That’s all!**

🌐 [FOLLOW OUR SOCIALS](https://linktr.ee/atoms_research)

**✨ Collect this entry showing your support to our team! More collects-more guides!**

---

*Originally published on [Atoms Research](https://paragraph.com/@atoms-research/base-contract-deployment)*
