Base là blockchain Layer 2 (L2) được phát triển bởi cái tên lâu đời trên thị trường Crypto là Coinbase mới đây vừa tiết lộ sẽ khám phá việc phát hành token. Thông tin trên đã dấy lên kỳ vọng nền tảng này chuẩn bị airdrop cho người dùng. Với vị thế hàng đầu của mình, đây rất có thể là đợt thưởng token "khủng" mà nhiều thợ săn airdrop đang chờ đợi.
Trong bài viết này, Block24 sẽ hướng dẫn chi tiết cách hoàn thành Base Learn để thu thập 5 role trên Discord, tăng footprint trên blockchain để có cơ hội nhận airdrop từ L2 này nhé!
Điều kiện săn airdrop Base
Base hiện chưa đưa ra bất kỳ thông báo chính thức vào về việc airdrop token cho người dùng. Do đó, không có điều kiện hoặc tiêu chí cụ thể nào cho việc săn airdrop Base, bất kỳ người nào cũng có thể tham gia và làm theo những bước dưới đây để có cơ hội trúng airdrop khi dự án này ra mắt token chính thức.
Chuẩn bị gì để săn airdrop Base
Trước khi bắt đầu săn airdrop Base, bạn nên chuẩn bị những thứ dưới đây để quá trình diễn ra thuận lợi và nhanh chóng. Bao gồm:
- Ví đã giao dịch nhiều trên mạng Base: Vì nền tảng L2 này đã mainnet hơn 2 năm (09/08/2023) và footprint (dấu chân trên mạng) thường được lựa chọn làm tiêu chí để airdrop. Do đó, việc sử dụng ví đã có footprint trên mạng Base để "cày" sẽ làm tăng khả năng trúng airdrop của bạn. Tuy nhiên, bạn chỉ nên sử dụng ví phụ cày airdrop để tránh rủi ro đến tài sản nắm giữ dài hạn
- Nhập seed phrase vào ví Coinbase Wallet để làm nhiệm vụ
- ETH trong ví để thanh toán phí gas hoặc sử dụng trong các dApp. Về phần này sẽ tùy thuộc khả năng của mỗi người, cày free (chỉ thanh toán phí gas) có thể giảm khả năng trúng airdrop của bạn
- Tài khoản Discord đã tham gia vào kênh của Base để nhận role
Những cách săn airdrop Base
Nhận role Discord đầu tiên của Base Learn
Mặc dù những nhiệm vụ này đã có được khoảng 1 năm, nhưng kể từ khi Base tiết lộ việc khám phá cho ra mắt token thì chúng lại nổi lên. Nhiều người cho ra đây sẽ là một trong những tiêu chí để nhận airdrop khi Base ra mắt token chính thức.
Để hoàn thành những nhiệm vụ này, bạn cần đọc tài liệu Base Learn để học cách deploy (triển khai) smart contract trên mạng testnet Base Sepolia và thu thập tất cả là 5 role trong kênh Discord của Base thông qua nền tảng Guild. Những role và source code tham khảo để hoàn thành nhiệm vụ bao gồm:
Role Base Learn Newcomer chỉ cần thu thập Basic Contracts Pin NFT. Cách thực hiện:
Bước 1: Truy cập công cụ Remix IDE để deploy smart contract. Nhấn File explorer, chọn Create new file để tạo trang lập trình mới và đặt tên là BasicMath.sol.

Bước 2: Lập trình để tạo ra smart contract đầu tiên dựa trên tài liệu Base Learn. Bạn cũng có thể nhập source code tham khảo này vào trong ô:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract BasicMath {
function adder(uint _a, uint _b) external pure returns (uint sum, bool error) {
unchecked {
sum = _a + _b;
if (sum < _a) {
return (0, true); // Overflow
}
return (sum, false);
}
}
function subtractor(uint _a, uint _b) external pure returns (uint difference, bool error) {
if (_b > _a) {
return (0, true); // Underflow
}
difference = _a - _b;
return (difference, false);
}
}

Bước 3: Sau đó, chuyển xuống tab Solidity Compiler và nhấn Compile để biên dịch source code. Nếu icon ngay tab Solidity Compiler hiện dấu tích xanh như trong ảnh là đã biên dịch thành công.
Lưu ý: Nếu gặp lỗi thì bạn hãy thử đổi Compiler sang những phiên bản 0.8.x cao hơn nhé.

Bước 4: Chuyển xuống tab Deploy & run transactions. Ở mũi tên số 1, bạn hãy chọn Browser extension và kết nối ví Coinbase Wallet bằng hình thức Injected Provider - Coinbase Wallet (mũi tên số 2). Sau đó, nhấn Deploy (mũi tên số 3) và xác nhận trên ví.
Lưu ý: Bạn nhớ kiểm tra xem có phải đang ở mạng Base Sepolia hay không nhé. Nếu không thì hãy chỉnh lại ở trên Coinbase Wallet nhé.

Bước 5: Sau khi Deploy thành công, ở mục Deployed Contracts sẽ xuất hiện thông tin của hợp đồng thông minh mới tạo. Tại đây, bạn hãy nhấn nút copy để lấy địa chỉ của hợp đồng (contract address) này.

Bước 6: Vào trang Exercise Contracts của Base Learn, chọn nhiệm vụ Deploying to a Testnet.

Bước 7: Kéo xuống nhấn vào nút Connect Wallet và kết nối bằng ví Coinbase Wallet.

Bước 8: Dán địa chỉ của contract mà bạn đã copy ở bước 5 vào. Nhấn Submit và xác nhận trên ví.

Bước 9: Khi xuất hiện những dấu tick hoàn thành này thì contract mà bạn tạo đạt yêu cầu và Basic Contracts Pin NFT cũng đã được mint vào ví của bạn.
Lưu ý: Bạn có thể sẽ phải submit lần 2 hoặc 3 thì mới xuất hiện những dòng tick hoàn thành này.

Bước 10: Vào Guild và nhấn dấu refresh để nhận role trong Discord của Base.

Vậy là bạn đã biết cách deploy contract lên mạng testnet Base Sepolia. Bây giờ bạn phải tiếp tục đọc tài liệu Base Learn rồi áp dụng tương tự để hoàn thành bài tập và nhận 4 NFT, role còn lại.
Source code role Base Learn Acolyte
Bạn cũng có thể tham khảo những source code dưới đây để hoàn thành bài tập của role Base Learn Acolyte (role thứ 2 trên Base Learn).
Source code cho Storage Pin NFT:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract EmployeeStorage {
uint16 private shares;
uint32 private salary;
uint256 public idNumber;
string public name;
error TooManyShares(uint16 _shares);
constructor(uint16 _shares, string memory _name, uint32 _salary, uint _idNumber) {
shares = _shares;
name = _name;
salary = _salary;
idNumber = _idNumber;
}
function viewShares() public view returns (uint16) {
return shares;
}
function viewSalary() public view returns (uint32) {
return salary;
}
function grantShares(uint16 _newShares) public {
if (_newShares > 5000) {
revert("Too many shares");
} else if (shares + _newShares > 5000) {
revert TooManyShares(shares + _newShares);
}
shares += _newShares;
}
function checkForPacking(uint _slot) public view returns (uint r) {
assembly {
r := sload(_slot)
}
}
function debugResetShares() public {
shares = 1000;
}
}
Nhập những tham số dưới đây khi deploy contract này:
- _shares: 1000
- _name: Pat
- _salary: 50000
- _idNumber: 112358132134

Source code cho Control Structures Pin NFT:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract ControlStructures {
error AfterHours(uint256 time);
error AtLunch();
function fizzBuzz(uint _number) public pure returns (string memory response) {
if (_number % 3 == 0 && _number % 5 == 0) {
return "FizzBuzz";
} else if (_number % 3 == 0) {
return "Fizz";
} else if (_number % 5 == 0) {
return "Buzz";
} else {
return "Splat";
}
}
function doNotDisturb(uint _time) public pure returns (string memory result) {
assert(_time < 2400);
if (_time > 2200 || _time < 800) {
revert AfterHours(_time);
}
if (_time >= 1200 && _time <= 1299) {
revert AtLunch();
}
if (_time >= 800 && _time <= 1199) {
return "Morning!";
} else if (_time >= 1300 && _time <= 1799) {
return "Afternoon!";
} else if (_time >= 1800 && _time <= 2200) {
return "Evening!";
}
}
}
Source code cho Arrays Pin NFT:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract ArraysExercise {
uint[] public numbers = [1,2,3,4,5,6,7,8,9,10];
uint[] public timestamps;
address[] public senders;
uint256 constant Y2K = 946702800;
function getNumbers() external view returns (uint[] memory) {
uint[] memory _numbers = new uint[](numbers.length);
for (uint i = 0; i < numbers.length; i++) {
_numbers[i] = numbers[i];
}
return _numbers;
}
function resetNumbers() public {
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 {
timestamps.push(_unixTimestamp);
senders.push(msg.sender);
}
function afterY2K() public view returns (uint256[] memory, address[] memory) {
uint count = 0;
for (uint i = 0; i < timestamps.length; i++) {
if (timestamps[i] > Y2K) {
count++;
}
}
uint256[] memory _timestamps = new uint256[](count);
address[] memory _senders = new address[](count);
uint j = 0;
for (uint i = 0; i < timestamps.length; i++) {
if (timestamps[i] > Y2K) {
_timestamps[j] = timestamps[i];
_senders[j] = senders[i];
j++;
}
}
return (_timestamps, _senders);
}
function resetSenders() public {
delete senders;
}
function resetTimestamps() public {
delete timestamps;
}
}
Source code role Base Learn Consul
Source code cho Mappings Pin NFT:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract MappingsExercise {
mapping(uint => string) public approvedRecords;
mapping(string => bool) private approved;
string[] private approvedRecordsIndex;
mapping(address => mapping(string => bool)) public userFavorites;
mapping(address => string[]) public userFavoritesIndex;
error NotApproved(string albumName);
constructor() {
string[9] memory records = [
"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 < 9; i++) {
approvedRecords[i] = records[i];
approved[records[i]] = true;
approvedRecordsIndex.push(records[i]);
}
}
function getApprovedRecords() public view returns (string[] memory) {
return approvedRecordsIndex;
}
function addRecord(string memory albumName) public {
if (!approved[albumName]) {
revert NotApproved(albumName);
}
if (userFavorites[msg.sender][albumName]) {
return; // Already added
}
userFavorites[msg.sender][albumName] = true;
userFavoritesIndex[msg.sender].push(albumName);
}
function getUserFavorites(address user) public view returns (string[] memory) {
return userFavoritesIndex[user];
}
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];
}
}
Source code cho Inheritance NFT:
// 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 view 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 view override 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 view override 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;
}
}
Source code cho Structs Pin NFT:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract GarageManager {
struct Car {
string make;
string model;
string color;
uint numberOfDoors;
}
mapping(address => Car[]) public garage;
error BadCarIndex(uint row);
function addCar(string memory make, string memory model, string memory color, uint numberOfDoors) public {
garage[msg.sender].push(Car(make, model, color, numberOfDoors));
}
function getMyCars() public view returns (Car[] memory) {
return garage[msg.sender];
}
function getUserCars(address user) public view returns (Car[] memory) {
return garage[user];
}
function updateCar(uint row, string memory make, string memory model, string memory color, uint numberOfDoors) public {
if (row >= garage[msg.sender].length) {
revert BadCarIndex(row);
}
garage[msg.sender][row] = Car(make, model, color, numberOfDoors);
}
function resetMyGarage() public {
delete garage[msg.sender];
}
}
Source code role Base Learn Prefect
Source code để mint Error Triage Pin NFT:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract ErrorTriageExercise {
/**
* 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.
*/
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 the modifier. There are no restrictions on base or
* modifier values.
*/
function applyModifier(
uint _base,
int _modifier
) public pure returns (int) {
if (_modifier > 0) {
return int(_base) + _modifier;
} else {
return int(_base) + _modifier;
}
}
uint[] arr;
function popWithReturn() public returns (uint returnNum) {
if (arr.length > 0) {
uint index = arr.length - 1;
uint _pop = arr[index];
arr.pop();
return _pop;
}
}
// 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;
}
}
Source code để mint New Keyword Pin NFT bao gồm 2 file theo thứ tự:
- AddressBook.sol (chỉ compile, không deploy):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/access/Ownable.sol";
contract AddressBook is Ownable {
error ContactNotFound(address owner, string name);
mapping(string => address) public contacts;
constructor(address _initialOwner) Ownable(_initialOwner) {}
function addContact(string memory _name, address _address) public onlyOwner {
contacts[_name] = _address;
}
function getContact(string memory _name) public view returns (address) {
if (contacts[_name] == address(0)) {
revert ContactNotFound(msg.sender, _name);
}
return contacts[_name];
}
function removeContact(string memory _name) public onlyOwner {
if (contacts[_name] == address(0)) {
revert ContactNotFound(msg.sender, _name);
}
delete contacts[_name];
}
}
- AddressBookFactory.sol (compile và deploy):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "./AddressBook.sol";
contract AddressBookFactory {
string private salt = "value";
function deploy() public returns (address) {
return address(new AddressBook(msg.sender));
}
}
Source code để mint Imports Pin NFT, bao gồm 2 file theo thứ tự:
- SillyStringUtils.sol (chỉ compile, không deploy):
// 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" 🤷");
}
}
- ImportsExercise.sol (compile và deploy):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "./SillyStringUtils.sol";
contract ImportsExercise {
using SillyStringUtils for string;
SillyStringUtils.Haiku public haiku;
function saveHaiku(string memory _line1, string memory _line2, string memory _line3) public {
haiku = SillyStringUtils.Haiku(_line1, _line2, _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 = haiku.line3.shruggie();
return newHaiku;
}
}
Source code role Base Learn Supreme
Source code để mint SCD ERC721 Pin NFT:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract HaikuNFT is ERC721 {
struct Haiku {
address author;
string line1;
string line2;
string line3;
}
Haiku[] public haikus;
mapping(address => uint[]) public sharedHaikus;
mapping(string => bool) private usedLines;
error HaikuNotUnique();
error NotYourHaiku(uint haikuId);
error NoHaikusShared();
uint public counter = 1;
constructor() ERC721("HaikuNFT", "HAIKU") {
haikus.push(); // Burn ID 0
}
function mintHaiku(string memory _line1, string memory _line2, string memory _line3) external {
if (usedLines[_line1] || usedLines[_line2] || usedLines[_line3]) {
revert HaikuNotUnique();
}
usedLines[_line1] = true;
usedLines[_line2] = true;
usedLines[_line3] = true;
_safeMint(msg.sender, counter);
haikus.push(Haiku(msg.sender, _line1, _line2, _line3));
counter++;
}
function shareHaiku(uint _haikuId, address _shareWith) public {
if (ownerOf(_haikuId) != msg.sender) {
revert NotYourHaiku(_haikuId);
}
sharedHaikus[_shareWith].push(_haikuId);
}
function getMySharedHaikus() public view returns (Haiku[] memory) {
if (sharedHaikus[msg.sender].length == 0) {
revert NoHaikusShared();
}
Haiku[] memory result = new Haiku[](sharedHaikus[msg.sender].length);
for (uint i = 0; i < sharedHaikus[msg.sender].length; i++) {
uint id = sharedHaikus[msg.sender][i];
result[i] = haikus[id];
}
return result;
}
}
Source code để mint Minimal Token Pin NFT:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
// 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;
}
}
Source code để mint ERC20 Pin NFT:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.25;
// 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 = "13241234"; // 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;
}
}
}
}
Cày footprint (tx, volume trade, NFT)
Ngoài các role kiếm được từ Base Learn ra, bạn cũng có thể để lại dấu chân (footprint) của mình trên blockchain Base bằng cách thực hiện các giao dịch để tăng các chỉ số như transaction (tx), khối lượng giao dịch (volume trade) và sở hữu nhiều NFT. Những dấu chân này thể hiện sự ủng hộ, đóng góp và hoạt động của bạn trên mạng lưới, từ đó, dự án có thể sẽ “tri ân” bằng cách airdrop token.
Bạn có thể tham khảo những dApp nằm trong trang thống kê hệ sinh thái Base. Tại đây, bạn nên chọn tương tác với những dự án có tiềm lực tốt hoặc được đầu tư bởi chính Base (ví dụ: Aerodrome) để có khả năng cao đạt tiêu chí nhận airdrop.
Bên cạnh đó, vì Base nằm trong liên minh L2 mang tên Superchain, nên bạn cũng có thể tương tác cross-chain (xuyên chuỗi) với những “thành viên” trong hệ sinh thái này để tăng thêm cơ hội trúng tiêu chí airdrop.
Mẹo tối ưu hiệu quả săn airdrop Base
Một số mẹo có thể giúp bạn nâng cao hiệu quả của quá trình săn airdrop Base, bao gồm:
- Đặt tâm thế là người dùng thật: Thay vì tương tác một cách chớp nhoáng thì bạn hãy đặt tâm thế là một người dùng thực thụ của nền tảng. Điều này có thể làm cho footprint của bạn khác biệt so với phần còn lại, đạt được những role hoặc achievements hiếm, giúp tránh bị liệt vào danh sách sybil và nâng cao tỷ lệ trúng airdrop.
- Kết hợp săn airdrop nhiều dự án khác: Cách làm này một mặt giúp bạn không cảm thấy nhàm chán, mặt khác còn mang lại khả năng trúng airdrop, phần thưởng từ nhiều dự án cùng một lúc.
- Hoạt động thường xuyên: Việc hoạt động thường xuyên không chỉ cho thấy bạn là người dùng thực mà còn giúp "tích lũy" footprint một cách tự động, giúp bạn nâng cao tỷ lệ trúng airdrop mà không bị cưỡng ép hay gặp tình trạng nản trong quá trình cày dự án này.
Base có airdrop không?
Cho đến thời điểm hiện tại (01/10/2025), Base chưa có xác nhận chính thức nào về việc airdrop cũng như các tiêu chí đánh giá tiềm năng. Tuy nhiên, trong buổi AMA mới đây, đội ngũ phát triển của Base đã tiết lộ họ đang khám phá việc cho ra mắt token của nền tảng này.
Với một nền tảng hướng về cộng đồng và có cùng tầm nhìn public goods của Superchain, điều này gợi cho ta khả năng Base sẽ có đợt airdrop cho những người đóng góp sớm cho dự án. Do đó, mặc dù không có xác nhận chính thức, nhưng chúng ta có thể dựa vào những tiêu chí thường được lựa chọn để airdrop từ những dự án trước đây để tìm kiếm cơ hội đến từ Base.
Vì sao nên săn airdrop Base?
Base là blockchain Layer 2 được phát triển bởi Coinbase, sàn giao dịch Crypto tập trung (CEX) lâu đời và hàng đầu có trụ sở tại Hoa Kỳ. Với mục tiêu Bring the World Onchain (tạm dịch: Đưa cả thế giới lên blockchain), Base liên tục phát triển để trở thành blockchain L2 có tốc độ giao dịch nhanh và phí gas rẻ bậc nhất trên thị trường.
Tính cho đến nay, Base đang là L2 lớn thứ 2 trên thị trường chỉ sau Arbitrum nếu dựa trên chỉ số Total Value Secured (TVS), theo L2Beat. Tuy nhiên, nếu xét trong liên minh L2 Superchain thì Base đang dẫn đầu nhờ vào giai đoạn bùng nổ người dùng trong tháng 8 và 9 năm 2024.
Với vị thế hàng đầu như vậy, việc săn airdrop Base có thể mang tới khả năng nhận được phần thưởng lớn từ kỳ vọng giá trị token này sẽ cao khi được ra mắt. chính thức Điều này khiến cho airdrop của Base trở nên rất hấp dẫn, đặc biệt là đối với những người thường xuyên sử dụng L2 này cùng với các “thành viên” khác của liên minh Superchain.
Xem thêm >> Base chain là gì? So sánh Base với các L2 khác & hướng đi 2025
Trên đây là bài hướng dẫn cách để săn airdrop Base. Nếu như trong quá trình thực hiện mà bạn có bất kỳ thắc mắc hoặc phát hiện nhiệm vụ giúp nâng cao tỷ lệ trúng airdrop nào thì hãy bình luận ở phía dưới để anh em trong cộng đồng Block24 biết với nhé!
Lưu ý: Nội dung bên trên không phải là lời khuyên đầu tư. Anh em chỉ nên tham khảo và tự mình tìm hiểu kỹ trước khi quyết định xuống tiền. Hãy là nhà đầu tư có trách nhiệm với tài sản của mình, chúc anh em thành công!
Bình luận
Chưa có bình luận