Пиздец, я последний раз был в школе 7 лет назад. Как давно же это было...
Завтра добью гайд по Base и надо срочно садиться за Hyperlane, а там и Monad с Linea подтянутся.
В целом лето получилось продуктивным, но не особо профитным, хоть и сделано было многое. В сентябре я не жду кардинальной смены настроения и ситуации на рынке, но я уверен что с каждым месяцем мы близимся к той самой заветной бычке.
Скажите, а бычка с нами в одной комнате?
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9
К сожалению в столь обширной экосистеме порой сложно не упустить ничего, поэтому в этой части гайда мы поговорим о том, что я забыл упомянуть в первых трех частях гайда.
В этой категории помимо двух ролей связанных с деплоями контрактов в Base Mainnet, есть еще две секретные роли.
- Testnet Dev (Секретная роль): деплойнуть один контракт в Base Testnet
- Testnet Activity 10+ (Секретная роль) - десять транзакций в Base Testnet, деплой контрактов учитывается
По сути выполняя задания из
Здесь апдейтов нет
- Day 1 Adopter: холдить Base, Introduced NFT (OpenSea)
Прошлый раз я писал о том, что не знаю какая NFT должна быть. Сейчас исправляюсь, рекомендую к получению, так как она стоит сущие копейки
- Based and Optimistic: холить "BASEd and Optimistic" NFT [OpenSea]
Вот ее уже точно не получить, торги на OpenSea не идут уже как 9 месяцев
- Shadowy Super Coder: даем звезду на этот или этот репозиторий Github
Для этого мы должны подключить наш Github аккаунт к Base Guild, а также получить роль Github в Дискорде Base:
• Переходим в Дискорд Base
• Левый верхний угол, где название сервера Base нажимаете на стрелочку вниз
• Четвертая по счету будет "Привязанные роли"
• Нажимаете и подключаете ваш Github
теперь у вас появится в Base Guild дополнительная ветка заданий, полностью секретная
- Developer: секретные требования, у меня есть эта роль. Ее получило всего 1700 человек
- Has GitHub account: иметь Github аккаунт старше одного дня
- Commit activity in last 30d: иметь как минимум 1 commit за последний месяц
Без изменений
Вновь без изменений, ответы будут публиковаться в следующих постах, в контексте гайда
Без изменений
Без изменений
Без изменений
Теперь возвращаемся к главной странице Base Guild
.base.eth в ваш ник в Farcaster или XЗаключительные две роли, которые я не знал как получить и поэтому написал что сейчас они невозможны к получению, оказывается получить более чем реально
Вот теперь точно все с Base Guild и ролями в Дискорде Base, осталось только
Please open Telegram to view this post
VIEW IN TELEGRAM
6🐳14❤5🔥3
Инструкция из третьей части Ультимативного гайда на Base общая и подходит для каждого задания
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
contract ControlStructures {
function fizzBuzz(uint _number) public pure returns (string memory) {
if (_number % 3 == 0 && _number % 5 == 0) {
return "FizzBuzz";
} else if (_number % 3 == 0) {
return "Fizz";
} else if (_number % 5 == 0) {
return "Buzz";
} else {
return "Splat";
}
}
error AfterHours(uint time);
function doNotDisturb(uint _time) public pure returns (string memory) {
assert (_time < 2400);
if (_time > 2200 || _time < 800) {
revert AfterHours(_time);
}
if (_time >= 1200 && _time <= 1259) {
revert("At lunch!");
}
if (_time >= 800 && _time <= 1199) {
return "Morning!";
}
if (_time >= 1300 && _time <= 1799) {
return "Afternoon!";
}
if (_time >= 1800 && _time <= 2200) {
return "Evening!";
}
return "";
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
contract EmployeeStorage {
uint16 private shares;
uint32 private salary;
uint192 public idNumber;
string public name;
error TooManyShares(uint16 newShareCount);
constructor() {
shares = 1000;
name = "Pat";
salary = 50000;
idNumber = 112358132134;
}
function viewSalary() public view returns (uint) {
return salary;
}
function viewShares() public view returns (uint) {
return shares;
}
function grantShares(uint16 _newShares) public {
uint16 newShareCount = shares + _newShares;
require(_newShares <= 5000, "Too many shares");
if (newShareCount > 5000) {
revert TooManyShares(newShareCount);
}
shares = newShareCount;
}
function checkForPacking(uint _slot) public view returns (uint r) {
assembly {
r := sload(_slot)
}
}
function debugResetShares() public {
shares = 1000;
}
}
Если вдруг у кого-то возникнут проблемы с выполнением этих и последующих заданий - буду рад помочь в комментариях
Please open Telegram to view this post
VIEW IN TELEGRAM
5🐳12❤6🔥5
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
contract ArraysExercise {
uint[] public numbers = [1,2,3,4,5,6,7,8,9,10];
address[] public senders;
uint[] public timestamps;
function getNumbers() public view returns (uint[] memory) {
return numbers;
}
function resetNumbers() public {
delete numbers;
numbers = [1,2,3,4,5,6,7,8,9,10];
}
function appendToNumbers(uint[] calldata _toAppend) public {
for (uint i = 0; i < _toAppend.length; i++) {
numbers.push(_toAppend[i]);
}
}
function saveTimestamp(uint _unixTimestamp) public {
senders.push(msg.sender);
timestamps.push(_unixTimestamp);
}
function afterY2K() public view returns (uint[] memory, address[] memory) {
uint count;
for (uint i = 0; i < timestamps.length; i++) {
if (timestamps[i] > 946702800) {
count++;
}
}
uint[] memory filteredTimestamps = new uint[](count);
address[] memory filteredSenders = new address[](count);
uint index;
for (uint i = 0; i < timestamps.length; i++) {
if (timestamps[i] > 946702800) {
filteredTimestamps[index] = timestamps[i];
filteredSenders[index] = senders[i];
index++;
}
}
return (filteredTimestamps, filteredSenders);
}
function resetSenders() public {
delete senders;
}
function resetTimestamps() public {
delete timestamps;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/**
* @noscript FavoriteRecords
* @dev Contract to manage a list of approved music records and allow users to add them to their favorites
*/
contract FavoriteRecords {
mapping(string => bool) private approvedRecords;
string[] private approvedRecordsIndex;
mapping(address => mapping(string => bool)) public userFavorites;
mapping(address => string[]) private userFavoritesIndex;
error NotApproved(string albumName);
/**
* @dev Constructor that initializes the approved records list
*/
constructor() {
approvedRecordsIndex = ["Thriller","Back in Black","The Bodyguard","The Dark Side of the Moon","Their Greatest Hits (1971-1975)","Hotel California","Come On Over","Rumours","Saturday Night Fever"];
for (uint i = 0; i < approvedRecordsIndex.length; i++)
{
approvedRecords[approvedRecordsIndex[i]] = true;
}
}
/**
* @dev Returns the list of approved records
* @return An array of approved record names
*/
function getApprovedRecords() public view returns (string[] memory) {
return approvedRecordsIndex;
}
/**
* @dev Adds an approved record to the user's favorites
* @param _albumName The name of the album to be added
*/
function addRecord(string memory _albumName) public {
if (!approvedRecords[_albumName]) {
revert NotApproved({albumName: _albumName});
}
if (!userFavorites[msg.sender][_albumName]) {
userFavorites[msg.sender][_albumName] = true;
userFavoritesIndex[msg.sender].push(_albumName);
}
}
/**
* @dev Returns the list of a user's favorite records
* @param _address The address of the user
* @return An array of user's favorite record names
*/
function getUserFavorites(address _address) public view returns (string[] memory) {
return userFavoritesIndex[_address];
}
/**
* @dev Resets the caller's list of favorite records
*/
function resetUserFavorites() public {
for (uint i = 0; i < userFavoritesIndex[msg.sender].length; i++) {
delete userFavorites[msg.sender][userFavoritesIndex[msg.sender][i]];
}
delete userFavoritesIndex[msg.sender];
}
}
Двигаем дальше, славяне
Please open Telegram to view this post
VIEW IN TELEGRAM
5🐳10🔥5👍3
Я толком то и ни разу не делал праздничный пост с отметкой перехода порога в какое-то количество подписчиков. Этот пост тоже не будет таким, я скорее хотел бы посоветоваться и получить фидбек от каждого, кто читает этот пост, так как мне это очень важно.
Когда я решил активно вести канал, в марте 2024, у меня было ровно 50 подписчиков, и то это была старая аудитория, набранная еще в далеком 2022-м. Худо, бедно органически рост шел, я пробовал светиться в чатах, начал участвовать в папках и недавно купил свою первую рекламу.
Покупая папки и участвуя в них, я столкнулся с тем что это преимущественно не та аудитория, которую я хотел бы, так как при моем кол-ве подписчиков и охватах моя участь - участие в папке с помойками в виде тапалок, сигналов, трейдинга или просто рерайт канала. Я буквально узник долбоебских каналов, капитализация аудитории которых, дай Бог, переваливает за 1000$. Мне бы не хотелось такой аудитории, пусть меньше, но качественнее. Ибо эта аудитория подписывается, заходит на канал, не видит тут супер-мега нереально гемного тестнета, где он сможет словить ченжлайф с затратами 10 минут времени и трех копеек, отобранных у бомжа под падиком, за выполнение социалок и одного рефа - это тело уходит, оставаясь мертвым грузом в канале. Мне честно охота рыгать, когда меня просят запостить пост, который начинается так: "ЭТИ ПАРНИ ЗАРАБОТАЛИ 100500$ ЗА ПРОШЛУЮ НЕДЕЛЮ" и т.п., а в папке каналы, админы долбоебы которых постят хуйню про тапалки, сигналы и прочее, так еще и рерайт с другого такого же убогого канала просто более крупного.
И тут случается дилема, люди стадные существа и гораздо охотнее подписываются на канал где больше подписчиков, чем на маленький канал. Исходя из этого, нужно участвовать в папках, но этот рост меня огорчает, потому что эти трехзубые крестьяне, которые пришли ко мне из тапательного канала - здесь не задержатся, им не нужен такой контент, как у меня.
Изначально, при перезапуске канала, я хотел удовлетворить в первую очередь свой запрос на контент. Ибо нет канала в CIS сегменте Телеграма, который бы в полной мере удовлетворял мой запрос - поэтому я решил создать тот самый канал. Ведь если у меня есть такой неудовлетворенный запрос, значит у кого-то он тоже есть и это и будет моя аудитория.
Я рассматривал вариант ведения своего тик-тока, но мой контент не для тиктока. Там сидит такой же отсталый плебс, как и в сигнальных каналах. Им не нужны замороченные гайды, они хотят нажимать кнопку бабло и дюпать бабки. А если тикток стрельнет, то канал наводнят нищие бомжи, и самая ненавистная мне категория людей - те, которые не хотят самостоятельно в чем-то разобраться. По итогу мой канал скатится в пучину говна, с средним индексом платежеспособности на уровне индуского мальчика, а комментарии наводнят вопросы: "Что такое метамаск?" и "Как добавить сеть?".
Изначально я не планировал делать канал коммерческим, но если я хочу качественную аудиторию, то нужно ее покупать в тех каналах, где она водится. Таких каналов не так много на просторах CIS TG и узнавая за рекламу, я нарвался на неподъемные цены: 800$/пост. Приход будет вероятнее всего довольно скромным, и цена за подписчика будет доходить до 5-7$, что крайне дорого. Сейчас рынок не тот, чтобы я мог вынимать на постоянной основе по 800$ из кармана. Небольших каналов, где я мог бы взять рекламу по подходящей для себе цене, с нужной мне аудиторией можно пересчитать по пальцам.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8🐳5🔥2
Я решил пойти от обратного и таким образом прийти к какой-то здравой середине
• Однозначно скипать 90% папок с помойными каналами
Папки на самом деле не такой плохой способ продвижения, объясню почему я так считаю. Например я добавляю к себе все папки, которые вижу и сразу же их просеиваю, с большой долей вероятности я сразу же отпишусь от большинства каналов или кину в папку Trash, где им самое место, но порой получается найти неплохие каналы. К сожалею большинство людей идут по пути меньшего сопротивления, им впадлу расширять свое инфополе и они просто не подписываются, либо бездумно подписываются и даже не заходят на канал. Но я уверен, что есть такие дотошные как я, которые пересматриваю все каналы, и мой канал такому человек зайдет.
• Продавать рекламу на канале
Я вступил в рекламное DAO и вероятнее всего буду продавать рекламу, но не всю подряд, а выборочно - это исключает рекламу щитков, пирамид и пр., за что платят больше всего и что принесет мне угрызения совести. Каждый оффер с рекламой буду рассматривать индивидуально и скрупулёзно, чтобы потом мне не было стыдно за эту публикацию. Все полученные деньги пройдут мимо моего кармана, в него не упадет ни цента, зато таким образом я смогу сформировать небольшой капитал для закупа рекламы в крупных, интересных мне каналах.
Пока что это просто мысли, возможно правда стоит дождаться оживления на рынке и дать каналу рости органически? Не знаю, поэтому хотелось бы увидеть фидбек и почитать ваши мысли.
Всем work, славяне
Please open Telegram to view this post
VIEW IN TELEGRAM
❤19🔥8🕊4
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/**
* @noscript GarageManager
* @dev Contract to manage a garage of cars for each user
*/
contract GarageManager {
mapping(address => Car[]) private garages;
struct Car {
string make;
string model;
string color;
uint numberOfDoors;
}
error BadCarIndex(uint256 index);
/**
* @dev Adds a new car to the caller's garage
* @param _make The make of the car
* @param _model The model of the car
* @param _color The color of the car
* @param _numberOfDoors The number of doors of the car
*/
function addCar(string memory _make, string memory _model, string memory _color, uint _numberOfDoors) external {
garages[msg.sender].push(Car(_make, _model, _color, _numberOfDoors));
}
/**
* @dev Retrieves the caller's array of cars
* @return An array of `Car` structs
*/
function getMyCars() external view returns (Car[] memory) {
return garages[msg.sender];
}
/**
* @dev Retrieves a specific user's array of cars
* @param _user The address of the user
* @return An array of `Car` structs
*/
function getUserCars(address _user) external view returns (Car[] memory) {
return garages[_user];
}
/**
* @dev Updates a specific car in the caller's garage
* @param _index The index of the car in the garage array
* @param _make The new make of the car
* @param _model The new model of the car
* @param _color The new color of the car
* @param _numberOfDoors The new number of doors of the car
*/
function updateCar(uint256 _index, string memory _make, string memory _model, string memory _color, uint _numberOfDoors) external {
if (_index >= garages[msg.sender].length) {
revert BadCarIndex({index: _index});
}
garages[msg.sender][_index] = Car(_make, _model, _color, _numberOfDoors);
}
/**
* @dev Deletes all cars in the caller's garage
*/
function resetMyGarage() external {
delete garages[msg.sender];
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍7🐳5🔥2
Здесь у нас начинает танец с бубном, поэтому для этого задания отдельная инструкция:
• Создаете файл .sol
• Копируете контракт и вставляете в созданный файл
• В разделе Contract выбираете Salesperson и деплоите
• Вновь в разделе Contract выбираете выбираете EngineeringManager и деплоите
• Теперь в разделе Contract выбираете InheritanceSubmission
• Копируете снизу ваши контракты Salesperson и EngineeringManager
• Вставляете в появившиеся поля (см. скриншоты в комментариях)
• Деплоите и готово
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
abstract contract Employee
{
uint public idNumber;
uint public managerId;
constructor(uint _idNumber, uint _managerId)
{
idNumber = _idNumber;
managerId = _managerId;
}
function getAnnualCost() public virtual returns (uint);
}
contract Salaried is Employee
{
uint public annualSalary;
constructor(uint _idNumber, uint _managerId, uint _annualSalary)
Employee(_idNumber, _managerId)
{
annualSalary = _annualSalary;
}
function getAnnualCost() public override view returns (uint)
{
return annualSalary;
}
}
contract Hourly is Employee
{
uint public hourlyRate;
constructor(uint _idNumber, uint _managerId, uint _hourlyRate) Employee(_idNumber, _managerId)
{
hourlyRate = _hourlyRate;
}
function getAnnualCost() public override view returns (uint)
{
return hourlyRate * 2080;
}
}
contract Manager
{
uint[] public employeeIds;
function addReport(uint _reportId) public
{
employeeIds.push(_reportId);
}
function resetReports() public
{
delete employeeIds;
}
}
contract Salesperson is Hourly
{
constructor(uint _idNumber, uint _managerId, uint _hourlyRate)
Hourly(_idNumber, _managerId, _hourlyRate) {}
}
contract EngineeringManager is Salaried, Manager
{
constructor(uint _idNumber, uint _managerId, uint _annualSalary)
Salaried(_idNumber, _managerId, _annualSalary) {}
}
contract InheritanceSubmission {
address public salesPerson;
address public engineeringManager;
constructor(address _salesPerson, address _engineeringManager) {
salesPerson = _salesPerson;
engineeringManager = _engineeringManager;
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
7🐳9❤3👍3
Здесь нам нужно создать два контракта, для выполнения этого задания
Создаем файл с названием
SillyStringUtils.sol, оно должно быть именно таким. Вставляем код: // 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.sol и вставляем код:// SPDX-License-Identifier: MIT
import "./SillyStringUtils.sol";
pragma solidity 0.8.17;
contract ImportsExercise {
using SillyStringUtils for string;
SillyStringUtils.Haiku public haiku;
function saveHaiku(string memory _line1, string memory _line2, string memory _line3) public {
haiku.line1 = _line1;
haiku.line2 = _line2;
haiku.line3 = _line3;
}
function getHaiku() public view returns (SillyStringUtils.Haiku memory) {
return haiku;
}
function shruggieHaiku() public view returns (SillyStringUtils.Haiku memory) {
SillyStringUtils.Haiku memory newHaiku = haiku;
newHaiku.line3 = newHaiku.line3.shruggie();
return newHaiku;
}
}
Все готово, можно деплоить
Please open Telegram to view this post
VIEW IN TELEGRAM
8🐳13🔥4🦄2
В целом подбиваем итог по Pendle
Сегодня был завершен второй сезон фарма дропа от Ethena. Капитализация USDe выросла до трех миллиардов и бла-бла-бла... Не интересно, давайте перейдем к сути.
• 5% от саплая пойдет на дроп за Sats во втором сезоне
• Проверить свою аллокацию можно будет 9 сентября здесь
• Клейм 30 сентября
• Сразу стартует 3-й сезон (я планирую скипать)
Общий саплай ENA 15B, а на дроп выделено 5%, что составляет 750М $ENA. За второй сезон нафармлено 11.64T Sats, получается что количество приходящихся токенов $ENA на 1 Sats составляет 0,0000644. Теперь умножаете ваше кол-во Sats на 0,0000644 и получаете кол-во токенов, которые вы получите.
У меня 112.680.000 Sats, следовательно получу я 7256.5 $ENA
Любой пользователь, который уменьшит свой баланс USDe в своем кошельке до распределения токенов ниже своего среднего баланса за 30 дней по состоянию на момент снимка 1 сентября, получит пропорциональное сокращение распределения токенов (на процент нехватки) и перераспределение среди других пользователей в заблокированных пулах ENA или sENA (представленных ниже).
Тоже самое относится и к YT Pendle, снимки проходили в период с 1-го августа по 1-е сентября, 1 YT = 1 USDe. Я все выспросил в тикете саппорта:
• Как мне узнать сколько USDe необходимо холдить?
- В скором времени, в интерфейсе, вы получите точную цифру
• Как мне нужно холдить USDe: просто на кошельке или нужно лочить в пуле?
- Оба варианта будут засчитаны
Проще говоря, скоро, вероятнее всего до 9-го сентября у нас где-то на сайте Ethena появится цифра USDe, которую нам необходимо холдить для получения дропа. Максимально пидорский и гнусный мув со стороны фаундеров, но имеем что имеем
Фармил я через YT: Ethena, Zircuit, EtherFI, EigenLayer и совсем чуть чуть Karak
Затраты составили: -5350$, накинем комиссии и округлим до -5400$
Что по профиту?
Поинты
Я больше ничего целенаправленно не фармил, но какой-то минимальный дроп получу
Очень грубо говоря там Zircuit накинет, когда-то там, 1000-1500 $ZRC, EtherFI надеюсь 100 $ETHFI навалит, от Karak'a вообще ничего не жду и только EigenLayer может быть как-то порадует.
По факту, на момент сейчас, общий доход составляет чуть меньше 3900$. Итоговый P&L -1500$. Разумеется можно понадеяться на восстановление рынка альтов, хотя бы до июльских значений и тогда эта история на бумаге будет пахнуть БУ, но на деле залоченые/сожженные деньги на довольно долгий промежуток времени, который не работали там, где они могли принести потенциальную прибыль все равно сводит к тому, что ситуация не радужная. В чем ошибка? В том что я нафантазировал себе то, что на дроп на второй сезон Ethena пойдет 10% токенов без подтверждений этого, и ожидал сумму $ENA ровно в два раза больше, тогда бы даже по нынешним ужасным котировкам история была бы на момент сейчас уже безубыточной и оставалось дело за принятием решения: Продажа и закрытие в БУ либо Холд и попытка закрыть в профит.
Разумеется Zircuit, EtherFI и Karak накинут какую-то копейку. Возьмем условно пусть это будет 200$ в сумме. Тогда P&L составит -1300$, но я жду что порадует мастодонт - EigenLayer и как-то спасет ситуацию. В общем, даже по текущим котировкам, при текущей ситуации допускаю выход в номинальный БУ, а также не игнорирую тот факт, что я все таки жду роста альткоинов.
Такие пироги, славяне
Please open Telegram to view this post
VIEW IN TELEGRAM
5🐳8❤2🦄2
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract ErrorTriageExercise {
/**
* Finds the difference between each uint with it's neighbor (a to b, b to c, etc.)
* and returns a uint array with the absolute integer difference of each pairing.
*/
function diffWithNeighbor(
uint _a,
uint _b,
uint _c,
uint _d
) public pure returns (uint[] memory) {
uint[] memory results = new uint[](3);
results[0] = _a > _b ? _a - _b : _b - _a;
results[1] = _b > _c ? _b - _c : _c - _b;
results[2] = _c > _d ? _c - _d : _d - _c;
return results;
}
/**
* Changes the _base by the value of _modifier. Base is always >= 1000. Modifiers can be
* between positive and negative 100;
*/
function applyModifier(
uint _base,
int _modifier
) public pure returns (uint returnValue) {
if(_modifier > 0) {
return _base + uint(_modifier);
}
return _base - uint(-_modifier);
}
/**
* Pop the last element from the supplied array, and return the popped
* value (unlike the built-in function)
*/
uint[] arr;
function popWithReturn() public returns (uint returnNum) {
if(arr.length > 0) {
uint result = arr[arr.length - 1];
arr.pop();
return result;
}
}
// The utility functions below are working as expected
function addToArr(uint _num) public {
arr.push(_num);
}
function getArr() public view returns (uint[] memory) {
return arr;
}
function resetArr() public {
delete arr;
}
}
Заманал меня этот Base Learn, хочется уже перейти к экосистеме
Please open Telegram to view this post
VIEW IN TELEGRAM
5🐳5🔥3
Здесь мы проведем несколько манипуляций
В обоих контрактах заменить value на любое число, которое вам по душе
string private salt = "value" -> string private salt = "777"
Сначала мы создаем файл с названием
AddressBook.sol// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import "@openzeppelin/contracts/access/Ownable.sol";
contract AddressBook is Ownable(msg.sender) {
string private salt = "value";
struct Contact {
uint id;
string firstName;
string lastName;
uint[] phoneNumbers;
}
Contact[] private contacts;
mapping(uint => uint) private idToIndex;
uint private nextId = 1;
error ContactNotFound(uint id);
function addContact(string calldata firstName, string calldata lastName, uint[] calldata phoneNumbers) external onlyOwner {
contacts.push(Contact(nextId, firstName, lastName, phoneNumbers));
idToIndex[nextId] = contacts.length - 1;
nextId++;
}
function deleteContact(uint id) external onlyOwner {
uint index = idToIndex[id];
if (index >= contacts.length || contacts[index].id != id) revert ContactNotFound(id);
contacts[index] = contacts[contacts.length - 1];
idToIndex[contacts[index].id] = index;
contacts.pop();
delete idToIndex[id];
}
function getContact(uint id) external view returns (Contact memory) {
uint index = idToIndex[id];
if (index >= contacts.length || contacts[index].id != id) revert ContactNotFound(id);
return contacts[index];
}
function getAllContacts() external view returns (Contact[] memory) {
return contacts;
}
}
Теперь деплоим этот контракт и создаем новый файл, тут уже название произвольное
Второй контракт:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import "./AddressBook.sol";
contract AddressBookFactory {
string private salt = "value";
function deploy() external returns (AddressBook) {
AddressBook newAddressBook = new AddressBook();
newAddressBook.transferOwnership(msg.sender);
return newAddressBook;
}
}
И уже этот контракт мы деплоим, копируем адрес и вставляем в чекер
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍6🔥3
Отныне появится новая рубрика на канале, часто бывает такое, что какая-то короткая новость появляется и из нее ты и пост не слепишь, а тем не менее она важна. Будет выходить пост-дайджест, со сводкой апдейтов по проектам
Как вам новая рубрика, славяне?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🙏1🐳1
Сейчас ивент идет, через 8 часов кончается. Можно залутать легкие бонусные поинты, но лично я скипнул первую фазу и там у меня по нулям. Полностью пробриджить весь ивент стоит чуть больше 100$.
Делаете славяне? Что скажете?
Upd. Ага, не стоит это делать. Они перезапустили ивент и тупо моют поинты.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7
Замените value на любое число, которое вам по душе
string private salt = "value"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract UnburnableToken {
string private salt = "value";
mapping(address => uint256) public balances;
uint256 public totalSupply;
uint256 public totalClaimed;
mapping(address => bool) private claimed;
// Custom errors
error TokensClaimed();
error AllTokensClaimed();
error UnsafeTransfer(address _to);
constructor() {
totalSupply = 100000000; // Set the total supply of tokens
}
// Public function to claim tokens
function claim() public {
if (totalClaimed >= totalSupply) revert AllTokensClaimed(); // Check if all tokens have been claimed
if (claimed[msg.sender]) revert TokensClaimed(); // Check if the caller has already claimed tokens
// Update balances and claimed status
balances[msg.sender] += 1000;
totalClaimed += 1000;
claimed[msg.sender] = true;
}
// Public function for safe token transfer
function safeTransfer(address _to, uint256 _amount) public {
// Check for unsafe transfer conditions, including if the target address has a non-zero ether balance
if (_to == address(0) || _to.balance == 0) revert UnsafeTransfer(_to);
// Ensure the sender has enough balance to transfer
require(balances[msg.sender] >= _amount, "Insufficient balance");
// Perform the transfer
balances[msg.sender] -= _amount;
balances[_to] += _amount;
}
}
Контракты занимают много места, поэтому не получается к сожалению уместить 2 контракта в один пост
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥6🐳4
Замените value на любое число, которое вам по душе
string private salt = "value"
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
contract WeightedVoting is ERC20 {
string private salt = "value";
using EnumerableSet for EnumerableSet.AddressSet;
error TokensClaimed();
error AllTokensClaimed();
error NoTokensHeld();
error QuorumTooHigh();
error AlreadyVoted();
error VotingClosed();
struct Issue {
EnumerableSet.AddressSet voters;
string issueDesc;
uint256 quorum;
uint256 totalVotes;
uint256 votesFor;
uint256 votesAgainst;
uint256 votesAbstain;
bool passed;
bool closed;
}
struct SerializedIssue {
address[] voters;
string issueDesc;
uint256 quorum;
uint256 totalVotes;
uint256 votesFor;
uint256 votesAgainst;
uint256 votesAbstain;
bool passed;
bool closed;
}
enum Vote {
AGAINST,
FOR,
ABSTAIN
}
Issue[] internal issues;
mapping(address => bool) public tokensClaimed;
uint256 public maxSupply = 1000000;
uint256 public claimAmount = 100;
string saltt = "any";
constructor(string memory _name, string memory _symbol)
ERC20(_name, _symbol)
{
issues.push();
}
function claim() public {
if (totalSupply() + claimAmount > maxSupply) {
revert AllTokensClaimed();
}
if (tokensClaimed[msg.sender]) {
revert TokensClaimed();
}
_mint(msg.sender, claimAmount);
tokensClaimed[msg.sender] = true;
}
function createIssue(string calldata _issueDesc, uint256 _quorum)
external
returns (uint256)
{
if (balanceOf(msg.sender) == 0) {
revert NoTokensHeld();
}
if (_quorum > totalSupply()) {
revert QuorumTooHigh();
}
Issue storage _issue = issues.push();
_issue.issueDesc = _issueDesc;
_issue.quorum = _quorum;
return issues.length - 1;
}
function getIssue(uint256 _issueId)
external
view
returns (SerializedIssue memory)
{
Issue storage _issue = issues[_issueId];
return
SerializedIssue({
voters: _issue.voters.values(),
issueDesc: _issue.issueDesc,
quorum: _issue.quorum,
totalVotes: _issue.totalVotes,
votesFor: _issue.votesFor,
votesAgainst: _issue.votesAgainst,
votesAbstain: _issue.votesAbstain,
passed: _issue.passed,
closed: _issue.closed
});
}
function vote(uint256 _issueId, Vote _vote) public {
Issue storage _issue = issues[_issueId];
if (_issue.closed) {
revert VotingClosed();
}
if (_issue.voters.contains(msg.sender)) {
revert AlreadyVoted();
}
uint256 nTokens = balanceOf(msg.sender);
if (nTokens == 0) {
revert NoTokensHeld();
}
if (_vote == Vote.AGAINST) {
_issue.votesAgainst += nTokens;
} else if (_vote == Vote.FOR) {
_issue.votesFor += nTokens;
} else {
_issue.votesAbstain += nTokens;
}
_issue.voters.add(msg.sender);
_issue.totalVotes += nTokens;
if (_issue.totalVotes >= _issue.quorum) {
_issue.closed = true;
if (_issue.votesFor > _issue.votesAgainst) {
_issue.passed = true;
}
}
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥6🐳3❤2
Замените value на любое число, которое вам по душе
string private salt = "value"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol";
interface ISubmission {
struct Haiku {
address author;
string line1;
string line2;
string line3;
}
function mintHaiku(
string memory _line1,
string memory _line2,
string memory _line3
) external;
// function ownerOf(uint256 _id) external view returns (address);
function counter() external view returns (uint256);
function shareHaiku(uint256 _id, address _to) external;
function getMySharedHaikus() external view returns (Haiku[] memory);
}
contract HaikuNFT is ERC721, ISubmission {
Haiku[] public haikus;
mapping(address => mapping(uint256 => bool)) public sharedHaikus;
uint256 public haikuCounter;
constructor() ERC721("HaikuNFT", "HAIKU") {
haikuCounter = 1;
}
string salt = "value";
function counter() external view override returns (uint256) {
return haikuCounter;
}
function mintHaiku(
string memory _line1,
string memory _line2,
string memory _line3
) external override {
// Check if the haiku is unique
string[3] memory haikusStrings = [_line1, _line2, _line3];
for (uint256 li = 0; li < haikusStrings.length; li++) {
string memory newLine = haikusStrings[li];
// string memory newHaikuString = string(
// abi.encodePacked(haikusStrings[li])
// );
for (uint256 i = 0; i < haikus.length; i++) {
Haiku memory existingHaiku = haikus[i];
string[3] memory existingHaikuStrings = [
existingHaiku.line1,
existingHaiku.line2,
existingHaiku.line3
];
for (uint256 eHsi = 0; eHsi < 3; eHsi++) {
string memory existingHaikuString = existingHaikuStrings[
eHsi
];
if (
keccak256(abi.encodePacked(existingHaikuString)) ==
keccak256(abi.encodePacked(newLine))
) {
revert HaikuNotUnique();
}
}
}
}
// Mint the haiku NFT
_safeMint(msg.sender, haikuCounter);
haikus.push(Haiku(msg.sender, _line1, _line2, _line3));
haikuCounter++;
}
function shareHaiku(uint256 _id, address _to) external override {
require(_id > 0 && _id <= haikuCounter, "Invalid haiku ID");
Haiku memory haikuToShare = haikus[_id - 1];
require(haikuToShare.author == msg.sender, "NotYourHaiku");
sharedHaikus[_to][_id] = true;
}
function getMySharedHaikus()
external
view
override
returns (Haiku[] memory)
{
uint256 sharedHaikuCount;
for (uint256 i = 0; i < haikus.length; i++) {
if (sharedHaikus[msg.sender][i + 1]) {
sharedHaikuCount++;
}
}
Haiku[] memory result = new 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;
}
error HaikuNotUnique();
error NotYourHaiku();
error NoHaikusShared();
}
Вот и все, теперь у нас есть полный комплект из 13-ти бейджей за
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍7❤🔥4🔥3
Я надеялся, что уже на этом моменте мы перейдем к экосистеме Base, но как бы ни так
Исходя из перечисленных требований можно сделать следующие выводы:
• Активность должна быть как в сети Base, так и в Ethereum
• Акцент они ставят на кол-во дней и стрик дней, что и не мудрено, ведь за такой долгий промежуток времени набить больше кол-во недель и месяцев активности - не сложно. Количество активных дней, хоть как-то выделяет тру беливеров.
• Не вижу к сожалению требований по кол-ву транзакций, а скорее идет упор на качество транз и взаимодействие с ликвидностью внутри сети: бриджи, свапы и лендинговые протоколы.
• Ну и очевидно, ведь у Base эрекция на девелоперов, - есть графа с количество деплойнутых смарт контрактов. Учитываются контракты как в Mainnet, так и в Testnet. Можно деплоить через Owlto или Merkly, но это гораздо дороже, чем если делать это самому через Remix, а контракты можно использовать те, которые мы юзали для Base Learn.
- Минтим NFT и заполняем форму
- Переходим на Galxe и выполняем простые квесты
- Теперь переходим на страницу активности на Galxe и выполняем каждую копанию Base Bonanza
- Переходите сюда, подключаете кош и создаете аватар (минтить ничего не нужно). Если покупали боксы Adiddas x Doodles, то у вас вероятнее всего будут какие то шмотки - можете их применить.
- Подписаться на BSX в Twitter
- Переходим на BSX1000
- Подключаем кошелек и пополняем баланс на 11 USDC. Это лудилка, с огромными плечами, занижаете плечо до минимального - х100 и открываете позицию на 10 USDC. Очень важно ее продержать более 30 секунд и можете закрывать. Ставите ваши USDC на вывод, fee 1$.
- Вступаете в General chat в Телеге
- Вступаете в Discord и верифаетесь
- Заминтить эту NFT
- На Galxe подписываете на HyperSub
- Подписываетесь на них в Твиттере
- Оплачиваете подписку за 0.002ETH
- Переходите на DEX и совершаете свап
- Подписаться на их Твиттер
- Подписаться на еще один Твиттер
- Заминтить эту NFT
- Посетить страницу
- Подписаться на Твиттер
- Заминтить NFT
- Подписаться на Твиттер
- Заминтить NFT
- Заминтить NFT
- Подписаться на Twitter
- Подписаться на Твиттер
- Посетить сайт
- Холдить 1000 $MIGGLES [CA:
0xB1a03EdA10342529bBF8EB700a06C60441fEf25d]Свапнуть можно на Uniswap
- Подписаться на Твиттер
- Подписаться на них на Galxe
- Внести коллатеральный депозит на 20 USDC
- Взять займ в эквиваленте 20$ в пуле weETH/WETH. Депозитим weETH и берем borrow WETH
- Подписаться на Твиттер
- Вступить в Дискорд
- Забриджить ETH из любой сети в Base
- Посетить страницу ивента
- Twitter подписка
- Вступить в Дискорд
- Подписаться на Телегу
- Переходите на SynFutures и открываете фьюч
- Не закрываете, пока не засчитает задание
- Подписаться на Твиттер
- Ретвитнуть пост
- Перейти на страницу
- Разместить DCA ордер
Скорее всего добавят новых заданий, но мы наконец-то можем перейти к экосистеме Base
Please open Telegram to view this post
VIEW IN TELEGRAM
5❤8🔥3🐳2
Сейчас Owlto не взымает комсу, поэтому можно фришно набить он-чейн вольюм в
Посты по экосистеме Base soon
Please open Telegram to view this post
VIEW IN TELEGRAM
В скором времени закроется
Успейте проявить активности, не дожидаясь основного гайда:
- Скачиваете Unisat
- Переходите в кран Fractal и клеймите токены.
Гайд soon, скорее всего выйдет днем
Также последняя возможность нафармить LXP в
Этот гайд подойдет не для всех, а лишь для тех, кто ранее взаимодействовал с Linea и имеет активные дни/недели/месяца. Гайд вам поможет довести отработку Linea до ума.
После 20 сентября вернемся к экосистеме
Пиздец, дайте 30 часов в сутках
P.S. если есть те, кто классно шарит в Биткоин экосистеме - напишите в личку, буду признателен за небольшую консультацию
Сейчас активно тыкаюсь в Fractal Testnet, конец через
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥11🐳3👍2