Base — это безопасный, доступный и удобный для разработчиков Ethereum L2, призванный привлечь следующий миллиард пользователей в web3. Созданный в рамках Coinbase и планирующий прогрессивную децентрализацию, Base стремится создать открытую, глобальную криптоэкономику, доступную всем
За данную активность можно будет получить важную роль в дискорде, а ей владеют всего лишь 25к+ людей из 400к
Получить её достаточно просто, но, займёт немного времени для деплоев, зато всё бесплатно и понятно, особенно, когда есть гайд на русском языке.
Также повторюсь, знания в IT вам не потребуется, справиться каждый человек! Не пугайтесь вы этих цифр и букв)
Что делать?
- Переходим по ссылке и коннектим EVM кошелек
- Добавиться сеть Base Sepolia — добавляем
- Далее идём к крану и запрашиваем тестовые $ETH в сети Base Sepolia
- Переходим к Remix и сбрасываем куки
- Слева тыкаем значок двух папок — далее снизу на папку contracts — теперь тыкаем на 2_Owner.sol
- Далее слева тыкаем на значок и прожимаем синюю кнопку
- Далее тыкаем на значок Ethereum — сверху выбираем EVM кошелек (Metamask или Rabby) — Коннектим кошелек
- Прожимаем кнопку Deploy
- Но за ранее в EVM кошельке поставьте Base Sepolia
- Подтверждаем транзакцию в сети Base Sepolia
- Тыкаем по значку папок — далее создаем файл — называем его BasicMath— тыкаем на него
- Справа откроется консолька, вписываем туда вот это:
// 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
- Далее тыкаем слева на значок и прожимаем синюю кнопку
- Делаем Deploy
- Подтверждаем транзакцию в EVM
- После успешного развертывания контракта перейдите на левую боковую панель и прокрутите вниз, чтобы просмотреть код контракта BaseToken
- Копируем адрес
- Переходим на страничку разработчика и вставляем этот адрес — тыкаем Sumbit
- Отлично! Вот должно получиться что то тип такого (как скрине)
Осталось осталось сделать 13 контрактов, и процесс будет аналогичным
- Слева тыкаем значок двух папок — далее снизу на папку contracts — создаем файл ControlStructures — тыкаем на него
- Вставляем этот текст в пустую консольку справа
// 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
- Делаем все тоже самое, что и делали ранее
- Приложу скрины
- Копируем контракт
- Отправляем сюда и вставляем контракт — прожимаем Sumbit
- Должно быть 2 галочки (как на скрине)
- Продолжаем! Создаем новый файл Storage
- Копируем текст и вставляем в консольку
// 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
- Далее синюю кнопку
- Далее выбираем EVM — и вписываем данные снизу
shares
— 1000name
— Patsalary
— 50000idNumber
— 112358132134
- Копируем деплой
- Отправляем сюда и вставляем контракт — прожимаем Sumbit
- Должно быть 4 галочки (как на скрине)
- Далее создаем файл Arrays
- Копируем текст и вставляем в консольку
// 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 uint[](numbers.length); // 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 uint256[](counter); address[] memory sendersAfterY2K = new address[](counter); // 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; } }
- Тыкаем на синюю кнопку
- Делаем деплой
- Копируем контракт
- Отправляем сюда и вставляем контракт — прожимаем Sumbit
- Должно быть 2 галочки (как на скрине)
- Создаем файл Mapping
- Копируем текст и вставляем в консольку
// 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]; } }
- Тыкаем на синюю кнопку
- Делаем деплой
- Копируем адрес контракта
- Отправляем сюда и вставляем контракт — прожимаем Sumbit
- Должно быть 2 галочки (как на скрине)
- Создаем файл Structs
- Копируем текст и вставляем в консольку
// 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]; } }
- Тыкаем на синюю кнопку
- Делаем деплой
- Копируем адрес контракта
- Отправляем сюда и вставляем контракт — прожимаем Sumbit
- Должно быть 1 галочка (как на скрине)
- Создаем файл Inheritance
- Копируем текст и вставляем в консольку
// 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; } }
- Тыкаем на синюю кнопку
- Далее делаем деплой, но в Contract выбираем Salesperson
- Тыкаем на стрелочку и вписываем цифры — тыкаем на transact — подтверждаем транзакцию
Id Number: 55555 Manager id: 12345 Salary: 20
- Далее снова выбираем Contract и тыкаем на EngineeringManager
- Вписываем эти данные
Id Number: 54321 Manager id: 11111 Annual salary: 200000
- Тыкаем на стрелочку и вписываем цифры — тыкаем на transact — подтверждаем транзакцию
- Далее тыкаем на Contract выбираем InheritanceSubmission
- Спускаемся вниз и копируем 1. Salesperon контракт адрес; 2. EngineeringManager контракт адрес и вписываем их выше (как на скрине)
- Тыкаем transact и подтверждаем транзу
- Копируем Inheritance контракт адрес
- Отправляем сюда и вставляем контракт — прожимаем Sumbit
- Должно быть 4 галочки (как на скрине)
- Создаем новый файл SillyStringUtils
- Копируем текст и вставляем в консольку
// 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" 🤷"); } }
- Копируем и вставляем текст
- Далее создаем файл Imports
- Копируем текст и вставляем в консольку
// 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; } }
- Синяя кнопка
- Делаем деплой и копируем адрес контракта
- Отправляем сюда и вставляем контракт — прожимаем Sumbit
- Должно быть 1 галочка (как на скрине)
- Далее создаем файл Errors
- Копируем текст и вставляем в консольку
// 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 uint[](3); // 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; } }
- Синяя кнопка
- Делаем деплой и копируем адрес контракта
- Отправляем сюда и вставляем контракт — прожимаем Sumbit
- Должно быть 3 галочки (как на скрине)
- Создаем файл AddressBook
- Копируем текст и вставляем в консольку
// 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; } }
- Далее создаем файл Other Contracts
- Копируем текст и вставляем в консольку
// 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; } }
- Далее отправляемся к синей кнопке, и сверху ставим версию 0.8.20
- Тыкаем на синюю кнопку
- Делаем деплой и копируем адрес контракта
- Отправляем сюда и вставляем контракт — прожимаем Sumbit
- Должно быть 2 галочки (как на скрине)
- Создаем файл Minimal Token
- Копируем текст и вставляем в консольку
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // Contract for an unburnable token contract UnburnableToken { string private salt = "123456"; // 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; } }
- Синяя кнопка
- Делаем деплой и копируем адрес контракта
- Отправляем сюда и вставляем контракт — прожимаем Sumbit
- Должно быть 3 галочки (как на скрине)
- Создаем файл ERC20
- Копируем текст и вставляем в консольку
// 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 = "CHASE"; // 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
- Синяя кнопка
- Делаем деплой, но для начала тыкаем на стрелку и вписываем CHASE — далее transact
- Теперь Deploy и копируем адрес контракта
- Отправляем сюда и вставляем контракт — прожимаем Sumbit
- Должно быть 3 галочки (как на скрине)
- Создаем файл ERC721
- Копируем текст и вставляем в консольку
// 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 Haiku[](sharedHaikuCount); 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
- Синяя кнопка
- Делаем деплой и копируем адрес контракта
- Отправляем сюда и вставляем контракт — прожимаем Sumbit
- Должно быть 2 галочки (как на скрине)
- Еще можно получить дополнительную роль, нужно будет привязать Github
- Также забираем немного Score в Talent Protocol
Источник: https://teletype.in/@cryptoforto/base-guide-deploy-roles-testnet