UNPKG

check-ethereum-scanner

Version:

Safety checks for new Ethereum tokens

157 lines (156 loc) 4.86 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("./utils"); /** * Returns true if the bloom is a valid bloom * @param bloom The bloom */ function isBloom(bloom) { if (typeof bloom !== 'string') { return false; } if (!/^(0x)?[0-9a-f]{512}$/i.test(bloom)) { return false; } if (/^(0x)?[0-9a-f]{512}$/.test(bloom) || /^(0x)?[0-9A-F]{512}$/.test(bloom)) { return true; } return false; } exports.isBloom = isBloom; /** * Returns true if the value is part of the given bloom * note: false positives are possible. * @param bloom encoded bloom * @param value The value */ function isInBloom(bloom, value) { if (typeof value === 'object' && value.constructor === Uint8Array) { value = utils_1.bytesToHex(value); } const hash = utils_1.keccak256(value).replace('0x', ''); for (let i = 0; i < 12; i += 4) { // calculate bit position in bloom filter that must be active const bitpos = ((parseInt(hash.substr(i, 2), 16) << 8) + parseInt(hash.substr(i + 2, 2), 16)) & 2047; // test if bitpos in bloom is active const code = codePointToInt(bloom.charCodeAt(bloom.length - 1 - Math.floor(bitpos / 4))); const offset = 1 << bitpos % 4; if ((code & offset) !== offset) { return false; } } return true; } exports.isInBloom = isInBloom; /** * Code points to int * @param codePoint The code point */ function codePointToInt(codePoint) { if (codePoint >= 48 && codePoint <= 57) { /* ['0'..'9'] -> [0..9] */ return codePoint - 48; } if (codePoint >= 65 && codePoint <= 70) { /* ['A'..'F'] -> [10..15] */ return codePoint - 55; } if (codePoint >= 97 && codePoint <= 102) { /* ['a'..'f'] -> [10..15] */ return codePoint - 87; } throw new Error('invalid bloom'); } /** * Returns true if the ethereum users address is part of the given bloom. * note: false positives are possible. * @param bloom encoded bloom * @param address the address to test */ function isUserEthereumAddressInBloom(bloom, ethereumAddress) { if (!isBloom(bloom)) { throw new Error('Invalid bloom given'); } if (!isAddress(ethereumAddress)) { throw new Error(`Invalid ethereum address given: "${ethereumAddress}"`); } // you have to pad the ethereum address to 32 bytes // else the bloom filter does not work // this is only if your matching the USERS // ethereum address. Contract address do not need this // hence why we have 2 methods // (0x is not in the 2nd parameter of padleft so 64 chars is fine) const address = utils_1.padLeft(ethereumAddress, 64); return isInBloom(bloom, address); } exports.isUserEthereumAddressInBloom = isUserEthereumAddressInBloom; /** * Returns true if the contract address is part of the given bloom. * note: false positives are possible. * @param bloom encoded bloom * @param contractAddress the contract address to test */ function isContractAddressInBloom(bloom, contractAddress) { if (!isBloom(bloom)) { throw new Error('Invalid bloom given'); } if (!isAddress(contractAddress)) { throw new Error(`Invalid contract address given: "${contractAddress}"`); } return isInBloom(bloom, contractAddress); } exports.isContractAddressInBloom = isContractAddressInBloom; /** * Returns true if the topic is part of the given bloom. * note: false positives are possible. * @param bloom encoded bloom * @param topic the topic encoded hex */ function isTopicInBloom(bloom, topic) { if (!isBloom(bloom)) { throw new Error('Invalid bloom given'); } if (!isTopic(topic)) { throw new Error('Invalid topic'); } return isInBloom(bloom, topic); } exports.isTopicInBloom = isTopicInBloom; /** * Checks if its a valid topic * @param topic encoded hex topic */ function isTopic(topic) { if (typeof topic !== 'string') { return false; } if (!/^(0x)?[0-9a-f]{64}$/i.test(topic)) { return false; } else if (/^(0x)?[0-9a-f]{64}$/.test(topic) || /^(0x)?[0-9A-F]{64}$/.test(topic)) { return true; } return false; } exports.isTopic = isTopic; /** * Is valid address * @param address The address */ function isAddress(address) { if (typeof address !== 'string') { return false; } if (address.match(/^(0x)?[0-9a-fA-F]{40}$/)) { return true; } if (address.match(/^XE[0-9]{2}[0-9A-Za-z]{30,31}$/)) { return true; } return false; } exports.isAddress = isAddress;