check-ethereum-scanner
Version:
Safety checks for new Ethereum tokens
157 lines (156 loc) • 4.86 kB
JavaScript
;
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;