AIshiba作为arb上一个比较早期的土狗NFT,毫不夸张的说引燃了arb上的NFT潮流。floor price曾一度最高达到0.04e,但是现在已经跌倒了0.004e(大概8刀)。
这就是妥妥的土狗项目,官网做的也是极其简陋,连白皮书都没有,只有路线图。但是没办法,赶上了风口,猪都能飞上天,赶上arb的aidog热度。
并且在今天凌晨进行nft空投发币,空投规则是按照快照时的地址NFT个数计算,即NFT拥有数量越多,空投claim的代币越多,nft空投上限10个,超过按照10个计算。
谁知道发币出现bug,导致科学家发现漏洞,单号直接mint最大量的token 17700000000000 * 10 ** 6 。最高点卖出大概1e+。 代币k线
核心原因是项目方利用Merkle Tree
发放 空投token,但是本应该在后台的保存了全量地址被项目方放在了前端,并且未做任何混淆代码的保护处理。导致proof被轻易计算得到。(了解原理可参阅文末参考文献)
只需要在官网按 F12
整个代码一览无余:
merkleProof.js
const { WHITELIST_ADDRESS } = require("./whitelist_Address")
const keccak256 = require("keccak256")
const { MerkleTree } = require("merkletreejs")
const addressLeaves = WHITELIST_ADDRESS.map(x => keccak256(x))
const merkleTree = new MerkleTree(addressLeaves, keccak256, {
sortPairs : true
})
const rootHash = merkleTree.getHexRoot()
module.exports = { merkleTree, rootHash }
并且调用合约的方法,传入参数也非常清晰:
index.js
const handleClaimForNfts = async () => {
try {
const signer = await getProviderOrSigner(true);
const userAddress = signer.getAddress();
const aiShibaContract = new Contract(
AISHIBA_CONTRACT_ADDRESS,
AISHIBA_CONTRACT_ABI,
signer
);
const txn = await aiShibaContract.claimTokensForNft(merkleProof, nftBalance);
await txn.wait();
console.log("txn", txn);
console.log("txn", "successful");
} catch (error) {
console.error(error);
}
};
可以看到调用了合约的 claimTokensForNft()
方法,传入了merkleProof
和 nftBalance
两个变量,nftBalance 代表着快照拥有NFT的数量。
其中merkleProof
只需要 用下列方法 merkleTree.getHexProof(_leaf)
即可获取
index.js
const getProof = async () => {
const signer = await getProviderOrSigner(true);
const _userAddress = await signer.getAddress();
const _leaf = keccak256(_userAddress);
const _merkleProof = merkleTree.getHexProof(_leaf);
setUserAddress(_userAddress);
setMerkleProof(_merkleProof);
};
再看一下领取的合约代码
function claimTokensForNft(bytes32[] calldata proof, uint256 _amount) public claimIsLive {
bytes32 leaf = keccak256(abi.encodePacked(msg.sender));
require(MerkleProof.verify(proof, merkleRootNFT, leaf), "Wallet not eligible to claim");
require(_amount > 0, "You do not own any tokens");
require(!hasClaimedNFT[msg.sender], "You have claimed your Tokens");
uint256 amountOfTokensToClaim;
if(_amount<= 2) {
amountOfTokensToClaim = tier1Claim;
} else if( _amount > 2 && _amount <= 4){
amountOfTokensToClaim = tier2Claim;
} else if(_amount > 4 && _amount <= 9) {
amountOfTokensToClaim = tier3Claim;
} else if(_amount >= 10) {
amountOfTokensToClaim = tier4Claim;
}
totalTokensClaimed += amountOfTokensToClaim;
hasClaimedNFT[msg.sender] = true;
require(tokenContract.transfer(msg.sender, amountOfTokensToClaim), "Transfer failed");
emit HasClaimedNFT(msg.sender, amountOfTokensToClaim);
}
_amount
即为nft的数量,合约按照 _amount
数量进行空投token。
_amount<=2
空投代币 1475000000000 * 10 ** 6
2<_amount<=4
空投代币 3375000000000 * 10 ** 6
4<_amount<=9
空投代币 7750000000000 * 10 ** 6
_amount>=10
空投代币 17700000000000 * 10 ** 6
合约中没有对_amount的校验操作,即使你的钱包地址拥有1个nft(即拥有白名单权限),只要Merkle tree
验证成功,_amount传入10或者更大值也能mint
到单地址最高数量代币,即 17700000000000 * 10 ** 6 。
大概有1800个地址领取了空投,绝大部分都是科学家
项目方发现了不对劲,在凌晨的00:45已经关闭了合约,并在接下来转走了合约中所有token。
据传言(道听途说):背后的项目方是大学生,整个寝室一起出动一起赚钱,如果真是这样,现在这大学生还真他娘的敢想敢干,割起韭菜来也是毫不手软。
可惜 螳螂捕蝉,黄雀在后
,项目成了科学家的提款机,最可怜的还是那些真金白银在DEX和CEX中买Token的韭菜们。
不玩土狗的我 看着大佬们的卖币截图和聊天记录,又一次感慨道:
别人赚钱如呼吸般简单,自己赚钱如吃屎般困难。
本人推特:@coolberwin_eth
文章参考:
Merkle tree的 原理: WTF Ethers极简入门: MerkleTree脚本