CryptoFortochka — гайды, ноды, новости, тестнеты
Base — это безопасный, доступный и удобный для разработчиков Ethereum L2, призванный привлечь следующий миллиард пользователей в web3. Созданный в рамках Coinbase и планирующий прогрессивную децентрализацию, Base стремится создать открытую, глобальную криптоэкономику, доступную всем
Инвесторы: Coinbase Ventures
Арендовать сервер: PqHosting, XorekCloud, AEZA , Hetzner, Contabo
Чат с поддержкой: https://t.me/fortochat
Вчера наткнулся на активность в тестовой сети Base, за который можно будет получить важную роль в дискорде, а ей владеют всего лишь 25к+ людей из 400к
Получить её достаточно просто, но, займёт немного времени для деплоев, зато всё бесплатно и понятно, особенно, когда есть гайд на русском языке. По этому я настоятельно рекомендую проделать эту активность, лишним точно не будет
Также повторюсь, знания в IT вам не потребуется, справиться каждый человек! Не пугайтесь вы этих цифр и букв)
Переходим к Remix и сбрасываем куки
Слева тыкаем значок двух папок — далее снизу на папку contracts — теперь тыкаем на 2_Owner.sol
Прожимаем кнопку Deploy
Но за ранее в EVM кошельке поставьте Base Sepolia
Отлично! Теперь давайте сделаем еще один контракт
// 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
Копируем адрес
Осталось осталось сделать 13 контрактов, и процесс будет аналогичным
// 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 галочки (как на скрине)
// 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
- 1000
name
- Pat
salary
- 50000
idNumber
- 112358132134
Далее создаем файл 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;
}
}
// 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];
}
}
// 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];
}
}
// 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;
}
}
Id Number: 55555
Manager id: 12345
Salary: 20
Id Number: 54321
Manager id: 11111
Annual salary: 200000
// 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" 🤷");
}
}
// 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;
}
}
// 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;
}
}
// 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
Тыкаем на синюю кнопку
// 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;
}
}
// 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 и копируем адрес контракта
// 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
Молодцы! На этом мы закончили делать деплои