├── AddressBook ├── Arrays ├── BasicMath ├── Control Structures ├── ERC20 ├── ERC721 ├── Errors ├── Imports ├── Inheritance ├── Mapping ├── Minimal Token ├── Other Contracts ├── README.md ├── SillyStringUtils ├── Storage └── Structs /AddressBook: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.8; 3 | 4 | import "@openzeppelin/contracts/access/Ownable.sol"; 5 | 6 | contract AddressBook is Ownable(msg.sender) { 7 | // Define a private salt value for internal use 8 | string private salt = "value"; 9 | 10 | // Define a struct to represent a contact 11 | struct Contact { 12 | uint id; // Unique identifier for the contact 13 | string firstName; // First name of the contact 14 | string lastName; // Last name of the contact 15 | uint[] phoneNumbers; // Array to store multiple phone numbers for the contact 16 | } 17 | 18 | // Array to store all contacts 19 | Contact[] private contacts; 20 | 21 | // Mapping to store the index of each contact in the contacts array using its ID 22 | mapping(uint => uint) private idToIndex; 23 | 24 | // Variable to keep track of the ID for the next contact 25 | uint private nextId = 1; 26 | 27 | // Custom error for when a contact is not found 28 | error ContactNotFound(uint id); 29 | 30 | // Function to add a new contact 31 | function addContact(string calldata firstName, string calldata lastName, uint[] calldata phoneNumbers) external onlyOwner { 32 | // Create a new contact with the provided details and add it to the contacts array 33 | contacts.push(Contact(nextId, firstName, lastName, phoneNumbers)); 34 | // Map the ID of the new contact to its index in the array 35 | idToIndex[nextId] = contacts.length - 1; 36 | // Increment the nextId for the next contact 37 | nextId++; 38 | } 39 | 40 | // Function to delete a contact by its ID 41 | function deleteContact(uint id) external onlyOwner { 42 | // Get the index of the contact to be deleted 43 | uint index = idToIndex[id]; 44 | // Check if the index is valid and if the contact with the provided ID exists 45 | if (index >= contacts.length || contacts[index].id != id) revert ContactNotFound(id); 46 | 47 | // Replace the contact to be deleted with the last contact in the array 48 | contacts[index] = contacts[contacts.length - 1]; 49 | // Update the index mapping for the moved contact 50 | idToIndex[contacts[index].id] = index; 51 | // Remove the last contact from the array 52 | contacts.pop(); 53 | // Delete the mapping entry for the deleted contact ID 54 | delete idToIndex[id]; 55 | } 56 | 57 | // Function to retrieve a contact by its ID 58 | function getContact(uint id) external view returns (Contact memory) { 59 | // Get the index of the contact 60 | uint index = idToIndex[id]; 61 | // Check if the index is valid and if the contact with the provided ID exists 62 | if (index >= contacts.length || contacts[index].id != id) revert ContactNotFound(id); 63 | // Return the contact details 64 | return contacts[index]; 65 | } 66 | 67 | // Function to retrieve all contacts 68 | function getAllContacts() external view returns (Contact[] memory) { 69 | // Return the array of all contacts 70 | return contacts; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Arrays: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.17; 3 | 4 | contract ArraysExercise { 5 | // Declare state variables to store arrays of numbers, timestamps, and senders 6 | uint[] numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // Array of numbers initialized with values 7 | uint[] timestamps; // Dynamic array to store timestamps 8 | address[] senders; // Dynamic array to store sender addresses 9 | 10 | uint256 constant Y2K = 946702800; // Constant representing the Unix timestamp for the year 2000 11 | 12 | // Function to retrieve the array of numbers 13 | function getNumbers() external view returns (uint[] memory) { 14 | // Create a memory array to hold the numbers 15 | uint[] memory results = new uint[](numbers.length); 16 | 17 | // Copy the numbers from the state array to the memory array 18 | for(uint i=0; i Y2K) { 55 | counter++; 56 | } 57 | } 58 | 59 | // Initialize memory arrays to hold timestamps and senders after Y2K 60 | uint256[] memory timestampsAfterY2K = new uint256[](counter); 61 | address[] memory sendersAfterY2K = new address[](counter); 62 | 63 | // Initialize index for inserting elements into memory arrays 64 | uint256 index = 0; 65 | 66 | // Iterate through timestamps and senders arrays to extract elements after Y2K 67 | for (uint i = 0; i < timestamps.length; i++) { 68 | if (timestamps[i] > Y2K) { 69 | timestampsAfterY2K[index] = timestamps[i]; 70 | sendersAfterY2K[index] = senders[i]; 71 | index++; 72 | } 73 | } 74 | 75 | // Return timestamps and senders after Y2K 76 | return (timestampsAfterY2K, sendersAfterY2K); 77 | } 78 | 79 | // Function to reset the senders array 80 | function resetSenders() public { 81 | delete senders; 82 | } 83 | 84 | // Function to reset the timestamps array 85 | function resetTimestamps() public { 86 | delete timestamps; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /BasicMath: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | contract BasicMath { 5 | uint256 constant MAX_INT = type(uint256).max; 6 | 7 | function adder(uint256 _a, uint256 _b) external pure returns (uint256 sum, bool error) { 8 | if (_b > MAX_INT - _a) { 9 | return (0, true); // Overflow occurred 10 | } 11 | return (_a + _b, false); 12 | } 13 | 14 | function subtractor(uint256 _a, uint256 _b) external pure returns (uint256 difference, bool error) { 15 | if (_b > _a) { 16 | return (0, true); // Underflow occurred 17 | } 18 | return (_a - _b, false); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Control Structures: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.17; 3 | 4 | contract ControlStructures { 5 | // Define custom errors for use within the contract 6 | error AfterHours(uint256 time); 7 | error AtLunch(); 8 | 9 | // Function to determine the response based on the input number 10 | function fizzBuzz(uint256 _number) public pure returns (string memory response) { 11 | // Check if the number is divisible by both 3 and 5 12 | if (_number % 3 == 0 && _number % 5 == 0) { 13 | return "FizzBuzz"; // Return "FizzBuzz" if divisible by both 3 and 5 14 | } 15 | // Check if the number is divisible by 3 16 | else if (_number % 3 == 0) { 17 | return "Fizz"; // Return "Fizz" if divisible by 3 18 | } 19 | // Check if the number is divisible by 5 20 | else if (_number % 5 == 0) { 21 | return "Buzz"; // Return "Buzz" if divisible by 5 22 | } 23 | // If none of the above conditions are met 24 | else { 25 | return "Splat"; // Return "Splat" if none of the conditions are met 26 | } 27 | } 28 | 29 | // Function to determine the response based on the input time 30 | function doNotDisturb(uint256 _time) public pure returns (string memory result) { 31 | // Ensure the input time is within valid bounds (less than 2400) 32 | assert(_time < 2400); 33 | 34 | // Check different time ranges and return appropriate responses or revert with errors 35 | if (_time > 2200 || _time < 800) { 36 | revert AfterHours(_time); // Revert with custom error if it's after 10:00 PM or before 8:00 AM 37 | } 38 | else if (_time >= 1200 && _time <= 1299) { 39 | revert AtLunch(); // Revert with custom error if it's between 12:00 PM and 1:00 PM 40 | } 41 | else if (_time >= 800 && _time <= 1199) { 42 | return "Morning!"; // Return "Morning!" if it's between 8:00 AM and 11:59 AM 43 | } 44 | else if (_time >= 1300 && _time <= 1799) { 45 | return "Afternoon!"; // Return "Afternoon!" if it's between 1:00 PM and 5:59 PM 46 | } 47 | else if (_time >= 1800 && _time <= 2200) { 48 | return "Evening!"; // Return "Evening!" if it's between 6:00 PM and 10:00 PM 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ERC20: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.17; 3 | 4 | // Importing OpenZeppelin contracts for ERC20 and EnumerableSet functionalities 5 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; 7 | 8 | // Contract for weighted voting using ERC20 token 9 | contract WeightedVoting is ERC20 { 10 | string private salt = "value"; // A private string variable 11 | using EnumerableSet for EnumerableSet.AddressSet; // Importing EnumerableSet for address set functionality 12 | 13 | // Custom errors 14 | error TokensClaimed(); // Error for attempting to claim tokens again 15 | error AllTokensClaimed(); // Error for attempting to claim tokens when all are already claimed 16 | error NoTokensHeld(); // Error for attempting to perform an action without holding tokens 17 | error QuorumTooHigh(); // Error for setting a quorum higher than total supply 18 | error AlreadyVoted(); // Error for attempting to vote more than once 19 | error VotingClosed(); // Error for attempting to vote on a closed issue 20 | 21 | // Struct to represent an issue 22 | struct Issue { 23 | EnumerableSet.AddressSet voters; // Set of voters 24 | string issueDesc; // Description of the issue 25 | uint256 quorum; // Quorum required to close the issue 26 | uint256 totalVotes; // Total number of votes casted 27 | uint256 votesFor; // Total number of votes in favor 28 | uint256 votesAgainst; // Total number of votes against 29 | uint256 votesAbstain; // Total number of abstained votes 30 | bool passed; // Flag indicating if the issue passed 31 | bool closed; // Flag indicating if the issue is closed 32 | } 33 | 34 | // Struct to represent a serialized issue 35 | struct SerializedIssue { 36 | address[] voters; // Array of voters 37 | string issueDesc; // Description of the issue 38 | uint256 quorum; // Quorum required to close the issue 39 | uint256 totalVotes; // Total number of votes casted 40 | uint256 votesFor; // Total number of votes in favor 41 | uint256 votesAgainst; // Total number of votes against 42 | uint256 votesAbstain; // Total number of abstained votes 43 | bool passed; // Flag indicating if the issue passed 44 | bool closed; // Flag indicating if the issue is closed 45 | } 46 | 47 | // Enum to represent different vote options 48 | enum Vote { 49 | AGAINST, 50 | FOR, 51 | ABSTAIN 52 | } 53 | 54 | // Array to store all issues 55 | Issue[] internal issues; 56 | 57 | // Mapping to track if tokens are claimed by an address 58 | mapping(address => bool) public tokensClaimed; 59 | 60 | uint256 public maxSupply = 1000000; // Maximum supply of tokens 61 | uint256 public claimAmount = 100; // Amount of tokens to be claimed 62 | 63 | string saltt = "any"; // Another string variable 64 | 65 | // Constructor to initialize ERC20 token with a name and symbol 66 | constructor(string memory _name, string memory _symbol) 67 | ERC20(_name, _symbol) 68 | { 69 | issues.push(); // Pushing an empty issue to start from index 1 70 | } 71 | 72 | // Function to claim tokens 73 | function claim() public { 74 | // Check if all tokens have been claimed 75 | if (totalSupply() + claimAmount > maxSupply) { 76 | revert AllTokensClaimed(); 77 | } 78 | // Check if the caller has already claimed tokens 79 | if (tokensClaimed[msg.sender]) { 80 | revert TokensClaimed(); 81 | } 82 | // Mint tokens to the caller 83 | _mint(msg.sender, claimAmount); 84 | tokensClaimed[msg.sender] = true; // Mark tokens as claimed 85 | } 86 | 87 | // Function to create a new voting issue 88 | function createIssue(string calldata _issueDesc, uint256 _quorum) 89 | external 90 | returns (uint256) 91 | { 92 | // Check if the caller holds any tokens 93 | if (balanceOf(msg.sender) == 0) { 94 | revert NoTokensHeld(); 95 | } 96 | // Check if the specified quorum is higher than total supply 97 | if (_quorum > totalSupply()) { 98 | revert QuorumTooHigh(); 99 | } 100 | // Create a new issue and return its index 101 | Issue storage _issue = issues.push(); 102 | _issue.issueDesc = _issueDesc; 103 | _issue.quorum = _quorum; 104 | return issues.length - 1; 105 | } 106 | 107 | // Function to get details of a voting issue 108 | function getIssue(uint256 _issueId) 109 | external 110 | view 111 | returns (SerializedIssue memory) 112 | { 113 | Issue storage _issue = issues[_issueId]; 114 | return 115 | SerializedIssue({ 116 | voters: _issue.voters.values(), 117 | issueDesc: _issue.issueDesc, 118 | quorum: _issue.quorum, 119 | totalVotes: _issue.totalVotes, 120 | votesFor: _issue.votesFor, 121 | votesAgainst: _issue.votesAgainst, 122 | votesAbstain: _issue.votesAbstain, 123 | passed: _issue.passed, 124 | closed: _issue.closed 125 | }); 126 | } 127 | 128 | // Function to cast a vote on a voting issue 129 | function vote(uint256 _issueId, Vote _vote) public { 130 | Issue storage _issue = issues[_issueId]; 131 | 132 | // Check if the issue is closed 133 | if (_issue.closed) { 134 | revert VotingClosed(); 135 | } 136 | // Check if the caller has already voted 137 | if (_issue.voters.contains(msg.sender)) { 138 | revert AlreadyVoted(); 139 | } 140 | 141 | uint256 nTokens = balanceOf(msg.sender); 142 | // Check if the caller holds any tokens 143 | if (nTokens == 0) { 144 | revert NoTokensHeld(); 145 | } 146 | 147 | // Update vote counts based on the vote option 148 | if (_vote == Vote.AGAINST) { 149 | _issue.votesAgainst += nTokens; 150 | } else if (_vote == Vote.FOR) { 151 | _issue.votesFor += nTokens; 152 | } else { 153 | _issue.votesAbstain += nTokens; 154 | } 155 | 156 | // Add the caller to the list of voters and update total votes count 157 | _issue.voters.add(msg.sender); 158 | _issue.totalVotes += nTokens; 159 | 160 | // Close the issue if quorum is reached and determine if it passed 161 | if (_issue.totalVotes >= _issue.quorum) { 162 | _issue.closed = true; 163 | if (_issue.votesFor > _issue.votesAgainst) { 164 | _issue.passed = true; 165 | } 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /ERC721: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | // Importing OpenZeppelin ERC721 contract 5 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol"; 6 | 7 | // Interface for interacting with a submission contract 8 | interface ISubmission { 9 | // Struct representing a haiku 10 | struct Haiku { 11 | address author; // Address of the haiku author 12 | string line1; // First line of the haiku 13 | string line2; // Second line of the haiku 14 | string line3; // Third line of the haiku 15 | } 16 | 17 | // Function to mint a new haiku 18 | function mintHaiku( 19 | string memory _line1, 20 | string memory _line2, 21 | string memory _line3 22 | ) external; 23 | 24 | // Function to get the total number of haikus 25 | function counter() external view returns (uint256); 26 | 27 | // Function to share a haiku with another address 28 | function shareHaiku(uint256 _id, address _to) external; 29 | 30 | // Function to get haikus shared with the caller 31 | function getMySharedHaikus() external view returns (Haiku[] memory); 32 | } 33 | 34 | // Contract for managing Haiku NFTs 35 | contract HaikuNFT is ERC721, ISubmission { 36 | Haiku[] public haikus; // Array to store haikus 37 | mapping(address => mapping(uint256 => bool)) public sharedHaikus; // Mapping to track shared haikus 38 | uint256 public haikuCounter; // Counter for total haikus minted 39 | 40 | // Constructor to initialize the ERC721 contract 41 | constructor() ERC721("HaikuNFT", "HAIKU") { 42 | haikuCounter = 1; // Initialize haiku counter 43 | } 44 | 45 | string salt = "value"; // A private string variable 46 | 47 | // Function to get the total number of haikus 48 | function counter() external view override returns (uint256) { 49 | return haikuCounter; 50 | } 51 | 52 | // Function to mint a new haiku 53 | function mintHaiku( 54 | string memory _line1, 55 | string memory _line2, 56 | string memory _line3 57 | ) external override { 58 | // Check if the haiku is unique 59 | string[3] memory haikusStrings = [_line1, _line2, _line3]; 60 | for (uint256 li = 0; li < haikusStrings.length; li++) { 61 | string memory newLine = haikusStrings[li]; 62 | for (uint256 i = 0; i < haikus.length; i++) { 63 | Haiku memory existingHaiku = haikus[i]; 64 | string[3] memory existingHaikuStrings = [ 65 | existingHaiku.line1, 66 | existingHaiku.line2, 67 | existingHaiku.line3 68 | ]; 69 | for (uint256 eHsi = 0; eHsi < 3; eHsi++) { 70 | string memory existingHaikuString = existingHaikuStrings[ 71 | eHsi 72 | ]; 73 | if ( 74 | keccak256(abi.encodePacked(existingHaikuString)) == 75 | keccak256(abi.encodePacked(newLine)) 76 | ) { 77 | revert HaikuNotUnique(); 78 | } 79 | } 80 | } 81 | } 82 | 83 | // Mint the haiku NFT 84 | _safeMint(msg.sender, haikuCounter); 85 | haikus.push(Haiku(msg.sender, _line1, _line2, _line3)); 86 | haikuCounter++; 87 | } 88 | 89 | // Function to share a haiku with another address 90 | function shareHaiku(uint256 _id, address _to) external override { 91 | require(_id > 0 && _id <= haikuCounter, "Invalid haiku ID"); 92 | 93 | Haiku memory haikuToShare = haikus[_id - 1]; 94 | require(haikuToShare.author == msg.sender, "NotYourHaiku"); 95 | 96 | sharedHaikus[_to][_id] = true; 97 | } 98 | 99 | // Function to get haikus shared with the caller 100 | function getMySharedHaikus() 101 | external 102 | view 103 | override 104 | returns (Haiku[] memory) 105 | { 106 | uint256 sharedHaikuCount; 107 | for (uint256 i = 0; i < haikus.length; i++) { 108 | if (sharedHaikus[msg.sender][i + 1]) { 109 | sharedHaikuCount++; 110 | } 111 | } 112 | 113 | Haiku[] memory result = new Haiku[](sharedHaikuCount); 114 | uint256 currentIndex; 115 | for (uint256 i = 0; i < haikus.length; i++) { 116 | if (sharedHaikus[msg.sender][i + 1]) { 117 | result[currentIndex] = haikus[i]; 118 | currentIndex++; 119 | } 120 | } 121 | 122 | if (sharedHaikuCount == 0) { 123 | revert NoHaikusShared(); 124 | } 125 | 126 | return result; 127 | } 128 | 129 | // Custom errors 130 | error HaikuNotUnique(); // Error for attempting to mint a non-unique haiku 131 | error NotYourHaiku(); // Error for attempting to share a haiku not owned by the caller 132 | error NoHaikusShared(); // Error for no haikus shared with the caller 133 | } 134 | -------------------------------------------------------------------------------- /Errors: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.17; 4 | 5 | contract ErrorTriageExercise { 6 | /** 7 | * @dev Finds the difference between each uint with its neighbor (a to b, b to c, etc.) 8 | * and returns a uint array with the absolute integer difference of each pairing. 9 | * 10 | * @param _a The first unsigned integer. 11 | * @param _b The second unsigned integer. 12 | * @param _c The third unsigned integer. 13 | * @param _d The fourth unsigned integer. 14 | * 15 | * @return results An array containing the absolute differences between each pair of integers. 16 | */ 17 | function diffWithNeighbor( 18 | uint _a, 19 | uint _b, 20 | uint _c, 21 | uint _d 22 | ) public pure returns (uint[] memory) { 23 | // Initialize an array to store the differences 24 | uint[] memory results = new uint[](3); 25 | 26 | // Calculate the absolute difference between each pair of integers and store it in the results array 27 | results[0] = _a > _b ? _a - _b : _b - _a; 28 | results[1] = _b > _c ? _b - _c : _c - _b; 29 | results[2] = _c > _d ? _c - _d : _d - _c; 30 | 31 | // Return the array of differences 32 | return results; 33 | } 34 | 35 | /** 36 | * @dev Changes the base by the value of the modifier. Base is always >= 1000. Modifiers can be 37 | * between positive and negative 100. 38 | * 39 | * @param _base The base value to be modified. 40 | * @param _modifier The value by which the base should be modified. 41 | * 42 | * @return returnValue The modified value of the base. 43 | */ 44 | function applyModifier( 45 | uint _base, 46 | int _modifier 47 | ) public pure returns (uint returnValue) { 48 | // Apply the modifier to the base value 49 | if(_modifier > 0) { 50 | return _base + uint(_modifier); 51 | } 52 | return _base - uint(-_modifier); 53 | } 54 | 55 | 56 | uint[] arr; 57 | 58 | function popWithReturn() public returns (uint returnNum) { 59 | if(arr.length > 0) { 60 | uint result = arr[arr.length - 1]; 61 | arr.pop(); 62 | return result; 63 | } 64 | } 65 | 66 | // The utility functions below are working as expected 67 | function addToArr(uint _num) public { 68 | arr.push(_num); 69 | } 70 | 71 | function getArr() public view returns (uint[] memory) { 72 | return arr; 73 | } 74 | 75 | function resetArr() public { 76 | delete arr; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Imports: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | // Importing the SillyStringUtils library 4 | import "./SillyStringUtils.sol"; 5 | 6 | pragma solidity 0.8.17; 7 | 8 | contract ImportsExercise { 9 | // Using the SillyStringUtils library for string manipulation 10 | using SillyStringUtils for string; 11 | 12 | // Declaring a public variable to store a Haiku 13 | SillyStringUtils.Haiku public haiku; 14 | 15 | // Function to save a Haiku 16 | function saveHaiku(string memory _line1, string memory _line2, string memory _line3) public { 17 | haiku.line1 = _line1; 18 | haiku.line2 = _line2; 19 | haiku.line3 = _line3; 20 | } 21 | 22 | // Function to retrieve the saved Haiku 23 | function getHaiku() public view returns (SillyStringUtils.Haiku memory) { 24 | return haiku; 25 | } 26 | 27 | // Function to append a shrugging emoji to the third line of the Haiku 28 | function shruggieHaiku() public view returns (SillyStringUtils.Haiku memory) { 29 | // Creating a copy of the Haiku 30 | SillyStringUtils.Haiku memory newHaiku = haiku; 31 | // Appending the shrugging emoji to the third line using the shruggie function from the SillyStringUtils library 32 | newHaiku.line3 = newHaiku.line3.shruggie(); 33 | return newHaiku; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Inheritance: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.17; 4 | 5 | /** 6 | * @title Employee 7 | * @dev Abstract contract defining common properties and behavior for employees. 8 | */ 9 | abstract contract Employee { 10 | uint public idNumber; // Unique identifier for the employee 11 | uint public managerId; // Identifier of the manager overseeing the employee 12 | 13 | /** 14 | * @dev Constructor to initialize idNumber and managerId. 15 | * @param _idNumber The unique identifier for the employee. 16 | * @param _managerId The identifier of the manager overseeing the employee. 17 | */ 18 | constructor(uint _idNumber, uint _managerId) { 19 | idNumber = _idNumber; 20 | managerId = _managerId; 21 | } 22 | 23 | /** 24 | * @dev Abstract function to be implemented by derived contracts to get the annual cost of the employee. 25 | * @return The annual cost of the employee. 26 | */ 27 | function getAnnualCost() public virtual returns (uint); 28 | } 29 | 30 | /** 31 | * @title Salaried 32 | * @dev Contract representing employees who are paid an annual salary. 33 | */ 34 | contract Salaried is Employee { 35 | uint public annualSalary; // The annual salary of the employee 36 | 37 | /** 38 | * @dev Constructor to initialize the Salaried contract. 39 | * @param _idNumber The unique identifier for the employee. 40 | * @param _managerId The identifier of the manager overseeing the employee. 41 | * @param _annualSalary The annual salary of the employee. 42 | */ 43 | constructor(uint _idNumber, uint _managerId, uint _annualSalary) Employee(_idNumber, _managerId) { 44 | annualSalary = _annualSalary; 45 | } 46 | 47 | /** 48 | * @dev Overrides the getAnnualCost function to return the annual salary of the employee. 49 | * @return The annual salary of the employee. 50 | */ 51 | function getAnnualCost() public override view returns (uint) { 52 | return annualSalary; 53 | } 54 | } 55 | 56 | /** 57 | * @title Hourly 58 | * @dev Contract representing employees who are paid an hourly rate. 59 | */ 60 | contract Hourly is Employee { 61 | uint public hourlyRate; // The hourly rate of the employee 62 | 63 | /** 64 | * @dev Constructor to initialize the Hourly contract. 65 | * @param _idNumber The unique identifier for the employee. 66 | * @param _managerId The identifier of the manager overseeing the employee. 67 | * @param _hourlyRate The hourly rate of the employee. 68 | */ 69 | constructor(uint _idNumber, uint _managerId, uint _hourlyRate) Employee(_idNumber, _managerId) { 70 | hourlyRate = _hourlyRate; 71 | } 72 | 73 | /** 74 | * @dev Overrides the getAnnualCost function to calculate the annual cost based on the hourly rate. 75 | * Assuming a full-time workload of 2080 hours per year. 76 | * @return The annual cost of the employee. 77 | */ 78 | function getAnnualCost() public override view returns (uint) { 79 | return hourlyRate * 2080; 80 | } 81 | } 82 | 83 | /** 84 | * @title Manager 85 | * @dev Contract managing a list of employee IDs. 86 | */ 87 | contract Manager { 88 | uint[] public employeeIds; // List of employee IDs 89 | 90 | /** 91 | * @dev Function to add a new employee ID to the list. 92 | * @param _reportId The ID of the employee to be added. 93 | */ 94 | function addReport(uint _reportId) public { 95 | employeeIds.push(_reportId); 96 | } 97 | 98 | /** 99 | * @dev Function to reset the list of employee IDs. 100 | */ 101 | function resetReports() public { 102 | delete employeeIds; 103 | } 104 | } 105 | 106 | /** 107 | * @title Salesperson 108 | * @dev Contract representing salespeople who are paid hourly. 109 | */ 110 | contract Salesperson is Hourly { 111 | /** 112 | * @dev Constructor to initialize the Salesperson contract. 113 | * @param _idNumber The unique identifier for the employee. 114 | * @param _managerId The identifier of the manager overseeing the employee. 115 | * @param _hourlyRate The hourly rate of the employee. 116 | */ 117 | constructor(uint _idNumber, uint _managerId, uint _hourlyRate) 118 | Hourly(_idNumber, _managerId, _hourlyRate) {} 119 | } 120 | 121 | /** 122 | * @title EngineeringManager 123 | * @dev Contract representing engineering managers who are paid an annual salary and have managerial responsibilities. 124 | */ 125 | contract EngineeringManager is Salaried, Manager { 126 | /** 127 | * @dev Constructor to initialize the EngineeringManager contract. 128 | * @param _idNumber The unique identifier for the employee. 129 | * @param _managerId The identifier of the manager overseeing the employee. 130 | * @param _annualSalary The annual salary of the employee. 131 | */ 132 | constructor(uint _idNumber, uint _managerId, uint _annualSalary) 133 | Salaried(_idNumber, _managerId, _annualSalary) {} 134 | } 135 | 136 | /** 137 | * @title InheritanceSubmission 138 | * @dev Contract for deploying instances of Salesperson and EngineeringManager. 139 | */ 140 | contract InheritanceSubmission { 141 | address public salesPerson; // Address of the deployed Salesperson instance 142 | address public engineeringManager; // Address of the deployed EngineeringManager instance 143 | 144 | /** 145 | * @dev Constructor to initialize the InheritanceSubmission contract. 146 | * @param _salesPerson Address of the deployed Salesperson instance. 147 | * @param _engineeringManager Address of the deployed EngineeringManager instance. 148 | */ 149 | constructor(address _salesPerson, address _engineeringManager) { 150 | salesPerson = _salesPerson; 151 | engineeringManager = _engineeringManager; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /Mapping: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.17; 3 | 4 | /** 5 | * @title FavoriteRecords 6 | * @dev Contract to manage a list of approved music records and allow users to add them to their favorites 7 | */ 8 | contract FavoriteRecords { 9 | // Mapping to store whether a record is approved 10 | mapping(string => bool) private approvedRecords; 11 | // Array to store the index of approved records 12 | string[] private approvedRecordsIndex; 13 | 14 | // Mapping to store user's favorite records 15 | mapping(address => mapping(string => bool)) public userFavorites; 16 | // Mapping to store the index of user's favorite records 17 | mapping(address => string[]) private userFavoritesIndex; 18 | 19 | // Custom error to handle unapproved records 20 | error NotApproved(string albumName); 21 | 22 | /** 23 | * @dev Constructor that initializes the approved records list 24 | */ 25 | constructor() { 26 | // Predefined list of approved records 27 | approvedRecordsIndex = [ 28 | "Thriller", 29 | "Back in Black", 30 | "The Bodyguard", 31 | "The Dark Side of the Moon", 32 | "Their Greatest Hits (1971-1975)", 33 | "Hotel California", 34 | "Come On Over", 35 | "Rumours", 36 | "Saturday Night Fever" 37 | ]; 38 | // Initialize the approved records mapping 39 | for (uint i = 0; i < approvedRecordsIndex.length; i++) { 40 | approvedRecords[approvedRecordsIndex[i]] = true; 41 | } 42 | } 43 | 44 | /** 45 | * @dev Returns the list of approved records 46 | * @return An array of approved record names 47 | */ 48 | function getApprovedRecords() public view returns (string[] memory) { 49 | return approvedRecordsIndex; 50 | } 51 | 52 | /** 53 | * @dev Adds an approved record to the user's favorites 54 | * @param _albumName The name of the album to be added 55 | */ 56 | function addRecord(string memory _albumName) public { 57 | // Check if the record is approved 58 | if (!approvedRecords[_albumName]) { 59 | revert NotApproved({albumName: _albumName}); 60 | } 61 | // Check if the record is not already in the user's favorites 62 | if (!userFavorites[msg.sender][_albumName]) { 63 | // Add the record to the user's favorites 64 | userFavorites[msg.sender][_albumName] = true; 65 | // Add the record to the user's favorites index 66 | userFavoritesIndex[msg.sender].push(_albumName); 67 | } 68 | } 69 | 70 | /** 71 | * @dev Returns the list of a user's favorite records 72 | * @param _address The address of the user 73 | * @return An array of user's favorite record names 74 | */ 75 | function getUserFavorites(address _address) public view returns (string[] memory) { 76 | return userFavoritesIndex[_address]; 77 | } 78 | 79 | /** 80 | * @dev Resets the caller's list of favorite records 81 | */ 82 | function resetUserFavorites() public { 83 | // Iterate through the user's favorite records 84 | for (uint i = 0; i < userFavoritesIndex[msg.sender].length; i++) { 85 | // Delete each record from the user's favorites mapping 86 | delete userFavorites[msg.sender][userFavoritesIndex[msg.sender][i]]; 87 | } 88 | // Delete the user's favorites index 89 | delete userFavoritesIndex[msg.sender]; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Minimal Token: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | // Contract for an unburnable token 5 | contract UnburnableToken { 6 | string private salt = "value"; // A private string variable 7 | 8 | // Mapping to track token balances of addresses 9 | mapping(address => uint256) public balances; 10 | 11 | uint256 public totalSupply; // Total supply of tokens 12 | uint256 public totalClaimed; // Total number of tokens claimed 13 | mapping(address => bool) private claimed; // Mapping to track whether an address has claimed tokens 14 | 15 | // Custom errors 16 | error TokensClaimed(); // Error for attempting to claim tokens again 17 | error AllTokensClaimed(); // Error for attempting to claim tokens when all are already claimed 18 | error UnsafeTransfer(address _to); // Error for unsafe token transfer 19 | 20 | // Constructor to set the total supply of tokens 21 | constructor() { 22 | totalSupply = 100000000; // Set the total supply of tokens 23 | } 24 | 25 | // Public function to claim tokens 26 | function claim() public { 27 | // Check if all tokens have been claimed 28 | if (totalClaimed >= totalSupply) revert AllTokensClaimed(); 29 | 30 | // Check if the caller has already claimed tokens 31 | if (claimed[msg.sender]) revert TokensClaimed(); 32 | 33 | // Update balances and claimed status 34 | balances[msg.sender] += 1000; 35 | totalClaimed += 1000; 36 | claimed[msg.sender] = true; 37 | } 38 | 39 | // Public function for safe token transfer 40 | function safeTransfer(address _to, uint256 _amount) public { 41 | // Check for unsafe transfer conditions, including if the target address has a non-zero ether balance 42 | if (_to == address(0) || _to.balance == 0) revert UnsafeTransfer(_to); 43 | 44 | // Ensure the sender has enough balance to transfer 45 | require(balances[msg.sender] >= _amount, "Insufficient balance"); 46 | 47 | // Perform the transfer 48 | balances[msg.sender] -= _amount; 49 | balances[_to] += _amount; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Other Contracts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.8; 3 | 4 | // Import the AddressBook contract to interact with it 5 | import "./AddressBook.sol"; 6 | 7 | // Contract for creating new instances of AddressBook 8 | contract AddressBookFactory { 9 | // Define a private salt value for internal use 10 | string private salt = "value"; 11 | 12 | // Function to deploy a new instance of AddressBook 13 | function deploy() external returns (AddressBook) { 14 | // Create a new instance of AddressBook 15 | AddressBook newAddressBook = new AddressBook(); 16 | 17 | // Transfer ownership of the new AddressBook contract to the caller of this function 18 | newAddressBook.transferOwnership(msg.sender); 19 | 20 | // Return the newly created AddressBook contract 21 | return newAddressBook; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BaseCamp 2 | BaseCamp Contracts 3 | -------------------------------------------------------------------------------- /SillyStringUtils: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.17; 4 | 5 | library SillyStringUtils { 6 | 7 | struct Haiku { 8 | string line1; 9 | string line2; 10 | string line3; 11 | } 12 | 13 | function shruggie(string memory _input) internal pure returns (string memory) { 14 | return string.concat(_input, unicode" 🤷"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Storage: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.17; 3 | 4 | contract EmployeeStorage { 5 | // Declare private state variables to store employee data 6 | uint16 private shares; // Number of shares owned by the employee (private to contract) 7 | uint32 private salary; // Monthly salary of the employee (private to contract) 8 | uint256 public idNumber; // Unique identification number of the employee (publicly accessible) 9 | string public name; // Name of the employee (publicly accessible) 10 | 11 | // Constructor to initialize employee data when contract is deployed 12 | constructor(uint16 _shares, string memory _name, uint32 _salary, uint _idNumber) { 13 | shares = _shares; // Initialize shares 14 | name = _name; // Initialize name 15 | salary = _salary; // Initialize salary 16 | idNumber = _idNumber; // Initialize idNumber 17 | } 18 | 19 | // View function to retrieve the number of shares owned by the employee 20 | function viewShares() public view returns (uint16) { 21 | return shares; 22 | } 23 | 24 | // View function to retrieve the monthly salary of the employee 25 | function viewSalary() public view returns (uint32) { 26 | return salary; 27 | } 28 | 29 | // Custom error declaration 30 | error TooManyShares(uint16 _shares); 31 | 32 | // Function to grant additional shares to the employee 33 | function grantShares(uint16 _newShares) public { 34 | // Check if the requested shares exceed the limit 35 | if (_newShares > 5000) { 36 | revert("Too many shares"); // Revert with error message 37 | } else if (shares + _newShares > 5000) { 38 | revert TooManyShares(shares + _newShares); // Revert with custom error message 39 | } 40 | shares += _newShares; // Grant the new shares 41 | } 42 | 43 | // Function used for testing packing of storage variables (not relevant to main functionality) 44 | function checkForPacking(uint _slot) public view returns (uint r) { 45 | assembly { 46 | r := sload (_slot) 47 | } 48 | } 49 | 50 | // Function to reset shares for debugging purposes (not relevant to main functionality) 51 | function debugResetShares() public { 52 | shares = 1000; // Reset shares to 1000 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Structs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.17; 3 | 4 | /** 5 | * @title GarageManager 6 | * @dev Contract to manage a garage of cars for each user 7 | */ 8 | contract GarageManager { 9 | // Mapping to store the garage of cars for each user 10 | mapping(address => Car[]) private garages; 11 | 12 | // Struct to represent a car 13 | struct Car { 14 | string make; // Make of the car 15 | string model; // Model of the car 16 | string color; // Color of the car 17 | uint numberOfDoors; // Number of doors of the car 18 | } 19 | 20 | // Custom error for handling invalid car index 21 | error BadCarIndex(uint256 index); 22 | 23 | /** 24 | * @dev Adds a new car to the caller's garage 25 | * @param _make The make of the car 26 | * @param _model The model of the car 27 | * @param _color The color of the car 28 | * @param _numberOfDoors The number of doors of the car 29 | */ 30 | function addCar(string memory _make, string memory _model, string memory _color, uint _numberOfDoors) external { 31 | // Push a new car struct with the provided details to the caller's garage 32 | garages[msg.sender].push(Car(_make, _model, _color, _numberOfDoors)); 33 | } 34 | 35 | /** 36 | * @dev Retrieves the caller's array of cars 37 | * @return An array of `Car` structs 38 | */ 39 | function getMyCars() external view returns (Car[] memory) { 40 | // Return the array of cars stored in the caller's garage 41 | return garages[msg.sender]; 42 | } 43 | 44 | /** 45 | * @dev Retrieves a specific user's array of cars 46 | * @param _user The address of the user 47 | * @return An array of `Car` structs 48 | */ 49 | function getUserCars(address _user) external view returns (Car[] memory) { 50 | // Return the array of cars stored in the garage of the specified user 51 | return garages[_user]; 52 | } 53 | 54 | /** 55 | * @dev Updates a specific car in the caller's garage 56 | * @param _index The index of the car in the garage array 57 | * @param _make The new make of the car 58 | * @param _model The new model of the car 59 | * @param _color The new color of the car 60 | * @param _numberOfDoors The new number of doors of the car 61 | */ 62 | function updateCar(uint256 _index, string memory _make, string memory _model, string memory _color, uint _numberOfDoors) external { 63 | // Check if the provided index is valid 64 | if (_index >= garages[msg.sender].length) { 65 | revert BadCarIndex({index: _index}); // Revert with custom error if the index is invalid 66 | } 67 | // Update the specified car with the new details 68 | garages[msg.sender][_index] = Car(_make, _model, _color, _numberOfDoors); 69 | } 70 | 71 | /** 72 | * @dev Deletes all cars in the caller's garage 73 | */ 74 | function resetMyGarage() external { 75 | // Delete all cars from the caller's garage 76 | delete garages[msg.sender]; 77 | } 78 | } 79 | --------------------------------------------------------------------------------