All checks were successful
check / check (push) Successful in 10s
Bug 1: getFullWarnings returned early for contract addresses, skipping checkEtherscanLabel. Restructured to use isContract flag so the Etherscan check runs for all addresses (contracts are often the most dangerous). Bug 2: confirmTx.js only handled 'contract' and 'new-address' warning types, silently discarding 'etherscan-phishing'. Added confirm-etherscan-warning HTML element and handler in the async warnings loop. Style: converted inline style attributes on phishing warning banners (approve-tx, approve-sign, approve-site) to Tailwind utility classes (bg-red-100 text-red-800 border-2 border-red-600 rounded-md).
115 lines
3.8 KiB
JavaScript
115 lines
3.8 KiB
JavaScript
// Address warning module.
|
|
// Provides local and async (RPC-based) warning checks for Ethereum addresses.
|
|
// Returns arrays of {type, message, severity} objects.
|
|
|
|
const { isScamAddress } = require("./scamlist");
|
|
const { isBurnAddress } = require("./constants");
|
|
const { checkEtherscanLabel } = require("./etherscanLabels");
|
|
const { log } = require("./log");
|
|
|
|
/**
|
|
* Check an address against local-only lists (scam, burn, self-send).
|
|
* Synchronous — no network calls.
|
|
*
|
|
* @param {string} address - The target address to check.
|
|
* @param {object} [options] - Optional context.
|
|
* @param {string} [options.fromAddress] - Sender address (for self-send check).
|
|
* @returns {Array<{type: string, message: string, severity: string}>}
|
|
*/
|
|
function getLocalWarnings(address, options = {}) {
|
|
const warnings = [];
|
|
const addr = address.toLowerCase();
|
|
|
|
if (isScamAddress(addr)) {
|
|
warnings.push({
|
|
type: "scam",
|
|
message:
|
|
"This address is on a known scam/fraud list. Do not send funds to this address.",
|
|
severity: "critical",
|
|
});
|
|
}
|
|
|
|
if (isBurnAddress(addr)) {
|
|
warnings.push({
|
|
type: "burn",
|
|
message:
|
|
"This is a known null/burn address. Funds sent here are permanently destroyed and cannot be recovered.",
|
|
severity: "critical",
|
|
});
|
|
}
|
|
|
|
if (options.fromAddress && addr === options.fromAddress.toLowerCase()) {
|
|
warnings.push({
|
|
type: "self-send",
|
|
message: "You are sending to your own address.",
|
|
severity: "warning",
|
|
});
|
|
}
|
|
|
|
return warnings;
|
|
}
|
|
|
|
/**
|
|
* Check an address against local lists AND via RPC queries.
|
|
* Async — performs network calls to check contract status and tx history.
|
|
*
|
|
* @param {string} address - The target address to check.
|
|
* @param {object} provider - An ethers.js provider instance.
|
|
* @param {object} [options] - Optional context.
|
|
* @param {string} [options.fromAddress] - Sender address (for self-send check).
|
|
* @returns {Promise<Array<{type: string, message: string, severity: string}>>}
|
|
*/
|
|
async function getFullWarnings(address, provider, options = {}) {
|
|
const warnings = getLocalWarnings(address, options);
|
|
|
|
let isContract = false;
|
|
try {
|
|
const code = await provider.getCode(address);
|
|
if (code && code !== "0x") {
|
|
isContract = true;
|
|
warnings.push({
|
|
type: "contract",
|
|
message:
|
|
"This address is a smart contract, not a regular wallet.",
|
|
severity: "warning",
|
|
});
|
|
}
|
|
} catch (e) {
|
|
log.errorf("contract check failed:", e.message);
|
|
}
|
|
|
|
// Skip tx count check for contracts — they may legitimately have
|
|
// zero inbound EOA transactions.
|
|
if (!isContract) {
|
|
try {
|
|
const txCount = await provider.getTransactionCount(address);
|
|
if (txCount === 0) {
|
|
warnings.push({
|
|
type: "new-address",
|
|
message:
|
|
"This address has never sent a transaction. Double-check it is correct.",
|
|
severity: "info",
|
|
});
|
|
}
|
|
} catch (e) {
|
|
log.errorf("tx count check failed:", e.message);
|
|
}
|
|
}
|
|
|
|
// Etherscan label check (best-effort async — network failures are silent).
|
|
// Runs for ALL addresses including contracts, since many dangerous
|
|
// flagged addresses on Etherscan (drainers, phishing contracts) are contracts.
|
|
try {
|
|
const etherscanWarning = await checkEtherscanLabel(address);
|
|
if (etherscanWarning) {
|
|
warnings.push(etherscanWarning);
|
|
}
|
|
} catch (e) {
|
|
log.errorf("etherscan label check failed:", e.message);
|
|
}
|
|
|
|
return warnings;
|
|
}
|
|
|
|
module.exports = { getLocalWarnings, getFullWarnings };
|