Token ve NFT Tutanlara Airdrop Nasıl Atılır?
Cüzdanında belirli bir token veya NFT tutan kişilere airdrop nasıl yapılır?
Merhabalar, bugün yeni çıkartılacak olan bir tokenı ekosistem içerisinde yayma veya marketing amacı ile belirli token ve NFT holderlarına nasıl airdrop atabileceğimizi göreceğiz. Her zaman ki gibi kodları Github adresimizde bulabilirsiniz.
Önemli not: Bu kontratlar eğitim amacıyla yazıldı ve sadece ilgili konuya değinildi. Bu nedenle kullanıma hazır kontratlar değiller! O yüzden direkt alıp kullanmayınız, sadece airdrop mekanizmasını alıp kendi kontratınıza entegre edebilirsiniz.
Token Holderlarına Airdrop
Token tutanlara adil bir airdrop yapabilmemiz için airdrop yapmak istediğimiz token kontratının snaphot özelliğinin olması ve snapshot alınmış olması gerekmektedir.
Snapshot özelliği yoksa da airdrop atabilirsiniz fakat bu durumda aynı miktardaki tokenı olan kişi bu tokenlarını farklı cüzdanlara aktararak tekrar tekrar airdrop claim edecektir. Böyle olunca 50,000 holder olan bir tokenda 500 kişi tüm airdrop’u alabilir.
Fakat bu yaptığınız airdrop esnasında hype aşırı yüksekse ve tüm holderların alacağı kadar değil de, belirli bir sayıda holderın hemen gelip bitirebileceği kadar kısıtlı airdrop atarsanız, bu durumda bir kişi airdrop aldıktan sonra farklı cüzdana tokenları atıp tekrar claim edene kadar airdrop bitmiş olur ve adil bir şekilde dağıtmış olursunuz.
Snapshot ile
Snaphot özelliği olan kontratlara airdrop atabilmek için öncelikle biz de kendi kontratımıza ERC20Snapshot.sol kütüphanesini yüklüyoruz.
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Snapshot.sol";
Kontratımıza hedef tokenın adresini ERC20Snapshot olarak kaydediyoruz. Claim edenlerin listesini claimed adında bir mapping ile tutalım ve total claim edilen airdrop miktarını da airdropClaims adında bir uint256 olarak tutalım.
ERC20Snapshot ApeCoin = ERC20Snapshot(0x4d224452801ACEd8B2F0aebE155379bb5D594381);
mapping (address => bool) claimed;
uint256 airdropClaims;
Sırada airdrop mekanizmamız var. Öncelikle anlatımda kolaylık olsun diye kendi tokenımızı MyToken olarak isimlendirelim. MyToken’ın 1 milyar max supply var ve bunun %10’unu airdrop ile farklı bir token holderlarına vereceğiz. Bu durumda 100 milyon MyToken dağıtacağız.
Fakat kaç tane tokenla gelene kaç tane vereceğiz? Snapshot özelliği olduğu için kısıtlayarak hemen bitirmeye ihtiyacımız yok. Dolayısıyla hedef tokenın dolaşımdaki miktarının %10-20 arasındaki bir kitleye dağıtsak yeter. Tüm dolaşımdakilere eşit bir şekilde dağıtırsanız muhtemelen çoğu token claim edilmeden kalır çünkü bu airdrop haberini çoğu holder duymayabilir.
Örnek olarak ApeCoin holderlarına airdrop yapacağımızı farz edelim. ApeCoin’in snapshot özelliği yok, fakat ben varmış gibi kodları yazacağım. Snapshop özelliği sizin hedeflediğiniz tokenda varsa, bu kodları direkt kullanabilirsiniz.
ApeCoin’in max supply 1 milyar fakat dolaşımda 360 milyon token var. Bunların %10’una airdrop atacak olursak 36 milyon token tutana airdrop atacağız demektir. 100 milyon token ayırdığımıza göre her 1 ApeCoin tutana kabaca 2.7 MyToken dağıtacağız.
Yukarıda gördüğünüz gibi öncelikle iki adet require fonksiyonumuz ile aynı kişinin tekrar mintlemesi engelliyoruz ve airdrop miktarının 100 milyonu geçmemesini garantiliyoruz. Daha sonra hak edilen miktarı mintliyoruz. Fakat hak edilen miktar 100 milyon airdrop adedini aşıyorsa fazlalığı çıkarıp mintliyoruz ki totalde 100 milyon tokenı geçmeyelim.
Yukarıda gördüğünüz örnekte fark etmeniz gereken şey bu fonsiyon ile biz airdrop tokenlarını claim esnasında mint ediyoruz. Yani max supply’ın tamamının pre-mint diye adlandırılan, önceden topluca mint edildiği bir sistemde bunu kod çalışmaz.
Eğer siz genel olarak uygulanan pre-mint yöntemi ile tüm tokenları zaten mintlemişseniz, burada tek yapmanız gereken şey mint fonksiyonu yerine transferFrom fonksiyonu yazmak olacaktır. Onu da yorum satırı olarak yukarıda yazdığım kodun içerisinde görmektesiniz.
Bu durumda owner’ın, yani airdrop tokenlarını elinde tutan kişinin MyToken kontratına allowance vermesi lazım ki bu tokenları MyToken kontratımız owner’dan alıp claim yapan kişiye yollayabilsin.
Snapshot Olmadan
Eğer bizim örneğimizdeki ApeCoin gibi snapshot özelliği olmayan bir tokena airdrop yapacaksanız dolaşımdaki miktarın çok azına bu airdrop’u yapmanız gerekiyor ki bir kişi aynı tokenları farklı cüzdana atıp oradan da claim edemeden tüm herkes claim etmiş olsun.
Diyelim ki dolaşımdaki miktarın %1’ine airdrop atıyorsunuz fakat ApeCoin holderlarına bunu yeterince ulaştıramadınız veya ilgilerini çekip claim ettiremediniz. O zaman çok az kişi tüm 100 milyon airdrop tokenını claim edip sizin projenizi daha başlamadan bitirebilir. O yüzden dolaşımdaki miktarın %1’ine vermekle birlikte hedef kitlenin ilgisini çekip hype da yaratmalısınız. Ek olarak riskinizi azaltmak istiyorsanız MyToken max supply’ın %10’u yerine %5’ini airdrop olarak dağıtabilirsiniz.
Bu sefer ApeCoin’i sadece düz ERC20 olarak kaydediyoruz ve yine claimed ve airdropClaims ile claim takibini yapıyoruz.
ERC20 ApeCoin = ERC20(0x4d224452801ACEd8B2F0aebE155379bb5D594381);
mapping (address => bool) claimed;
uint256 airdropClaims;
Farz edelim riskimizi azaltmaya karar verdik ve %5 yani 50 milyon token dağıtacağız. ApeCoin tutanların %1’ine bunu dağıtacağız. Bu durumda 3.6 milyon ApeCoin holderına dağıtacağız demektir. 50 milyon token ayırdığımıza göre her 1 ApeCoin için 13.8 MyToken mintlenecek.
Bu durumda snapshot ile arasındaki tek fark holdingAmount’u hesapladığımız satır. Burada ApeCoin.balanceOfAt(_msgSender(), 1); yerine ApeCoin.balanceOf(_msgSender()); yazarak o an claim eden kişinin elinde ne kadar token tuttuğunu direkt alıyoruz. Tek satır değişiklikle Snapshot özelliği olmadan normal olarak airdrop atabiliyoruz. Github’dan kodları direk inceleyebilirsiniz.
uint256 holdingAmount = ApeCoin.balanceOf(_msgSender());
İşte bu yüzden eğer bu airdrop hemen claim edilip bitmezse aynı kişi bu tokenları farklı cüzdana atarak sürekli olarak aynı miktarda airdrop claim edebilir.
NFT Holderların Airdrop
Snapshot ile
NFT’lerde kontrat içerisinde snapshot özelliği kullanılmaya ihtiyaç duyulmamıştır çünkü zaten her 1 NFT’nin sadece 1 sahibi olabilir. Snapshot’ı biz kendimiz off-chain olarak alıp, kimin kaç adet NFT tuttuğunu görüyoruz ve buna göre bir Whitelist oluşturuyoruz.
Snapshot’ı almak için NFT kontratının ownerOf fonksiyonunu çağırarak tek tek her NFT’nin sahibi kim onu kaydedeceğiz. Bu işlemi off-chain olarak yapacak bir yazılım yazmanız gerekiyor veya çok uzun da olsa etherscan üzerinden manuel olarak da yapabilirsiniz.
Snapshot’ımızı aldıktan sonra NFT’yi tutanlara whitelist oluşturacağız. Kaç adet NFT tutanlara kaç adet MyToken mint edeceğiniz tamamen size kalmış. Adet fark etmeksizin her tutana eşit miktarda da dağıtabilirsiniz.
Whitelist nasıl oluşturacağınızı ve nasıl kullanacağınızı buradaki Merkle Tree ile Whitelist Oluşturma adlı yazımızda bahsetmiştik. Burada tek değiştirmeniz gereken şey whitelistMint fonksiyonunda safeMint fonksiyonu ile NFT mintlemek yerine _mint fonksiyonu ile token mintleyeceğiz. Kaç adet tuttuğu fark etmeksizin her NFT tutana 10 bin token mintleyeceğimiz fonksiyon aşağıdaki gibidir.
function NFTwhitelistMint(bytes32[] calldata _merkleProof) public {
require(merkleCheck(_merkleProof), "You are not in the whitelist!");
require(!claimed[_msgSender()], "You have already minted!");
claimed[_msgSender()] = true;
_mint(_msgSender(), 10000 ether);
}
Snapshot Olmadan
NFT’lerde de snapshot almadan, whitelist ile uğraşmadan direkt kontrat üzerinden NFT holderları mintleyebilirler. Tokenlarda olandan farklı olarak burada aynı NFT’yi farklı cüzdana gönderip tekrar tekrar mintleyemezler çünkü biz hangi NFT’nin mintlediğini kaydedeceğiz.
Buradaki snapshot almadan yapılan airdrop’taki tek dezavantaj şu ki, airdrop hakkını mintleyen kişi mintten sonra kendi NFT’sini başkasına satabilir. Alan kişi de airdrop için alıyorsa yazık olur çünkü o NFT ile çoktan airdrop hakkı alındı. Fakat airdrop için alacak olan kişi, almadan önce MyToken kontratına gelerek almak istediği NFT airdrop mintlemiş mi yoksa daha mintlememiş mi görebilir.
Görece hafif bir kusur olsa da off-chain işlem olmadığı için blockchain felsefesine daha uygun bir yöntemdir. Aksi takdirde proje sahibine whitelist’e koyduğu adreslerin tamamının NFT holderı olduğuna güvenmeniz gerekiyor. Yada siz de kendiniz off-chain snapshot alıp, tüm adreslerle merkle tree oluşturup, merkle root’u kontrol edebilir ve işin içinde hile olup olmadığını görebilirsiniz. Fakat bu işlemle kimse uğraşmayacağı için proje sahipleri pek ala araya hile karıştırabilirler.
Off-chain snapshot olmadan airdrop yapmak istediğimiz fonksiyon aşağıdaki gibidir. 10 bin NFT’lik bir koleksiyona her NFT başına 10 bin token dağıtırsak 100 milyon token dağıtmış oluruz.
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
...
ERC721 collection = ERC721(0x0A8D311B99DdAA9EBb45FD606Eb0A1533004f26b);
mapping (uint256 => bool) NFTclaimed;
...
function NFTmint(uint256 tokenID) public {
require(!NFTclaimed[tokenID], "You have already claimed!");
NFTclaimed[tokenID] = true; // NFT'yi claim etti olarak kaydedelim.
require(_msgSender() == collection.ownerOf(tokenID), "You are not the owner of this NFT!");
_mint(_msgSender(), 10000 ether);
}
Öncelikle ERC721.sol kütüphanemizi import ediyoruz. Ardından koleksiyon adresini ERC721 olarak kaydediyoruz ve NFTclaimed adında bir mapping ile claim eden NFT’leri kaydediyoruz.
NFTmint fonksiyonumuz ile NFT holderları sahip oldukları NFT’nin id’sini girerek airdrop minti yapabilirler. Require fonksiyonları ile her NFT için sadece 1 kere 10k token mint etme hakkı veriyoruz ve sadece o NFT’nin sahibi gelip kendisi için mint edebilir. Tüm kodlara Github repomuzdan erişebilirsiniz. Unutmayın, bunlar eğitim içindir ve kontrat tamamlanmamıştır. Sadece airdrop fonksiyonları tamamlanmıştır!
Son Söz
Bugün de belirli token ve NFT holderlarına yeni çıkartacağımız bir tokendan airdrop pay vermeyi ele aldık. Umarım faydalı olmuştur. Teknik konularda yardımlaşmak veya sohbet için Discord kanalımıza buradan ulaşabilirsiniz. Bizi Twitter’dan takip etmeyi unutmayın! Herkese sağlıklı günler dilerim.
~ Bora