Compare commits
1 Commits
feature/ex
...
f290298244
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f290298244 |
@@ -599,6 +599,31 @@
|
||||
Double-check the address before sending.
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
id="confirm-contract-warning"
|
||||
class="mb-2"
|
||||
style="visibility: hidden"
|
||||
>
|
||||
<div
|
||||
class="border border-red-500 border-dashed p-2 text-xs font-bold text-red-500"
|
||||
>
|
||||
WARNING: The recipient is a smart contract. Sending ETH
|
||||
or tokens directly to a contract may result in permanent
|
||||
loss of funds.
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
id="confirm-burn-warning"
|
||||
class="mb-2"
|
||||
style="visibility: hidden"
|
||||
>
|
||||
<div
|
||||
class="border border-red-500 border-dashed p-2 text-xs font-bold text-red-500"
|
||||
>
|
||||
WARNING: This is a known null/burn address. Funds sent
|
||||
here are permanently destroyed and cannot be recovered.
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
id="confirm-errors"
|
||||
class="mb-2 border border-border border-dashed p-2 hidden"
|
||||
|
||||
@@ -24,8 +24,8 @@ const { getSignerForAddress } = require("../../shared/wallet");
|
||||
const { decryptWithPassword } = require("../../shared/vault");
|
||||
const { formatUsd, getPrice } = require("../../shared/prices");
|
||||
const { getProvider } = require("../../shared/balances");
|
||||
const { isScamAddress, isNullOrBurnAddress } = require("../../shared/scamlist");
|
||||
const { ERC20_ABI } = require("../../shared/constants");
|
||||
const { isScamAddress } = require("../../shared/scamlist");
|
||||
const { ERC20_ABI, isBurnAddress } = require("../../shared/constants");
|
||||
const { log } = require("../../shared/log");
|
||||
const makeBlockie = require("ethereum-blockies-base64");
|
||||
const txStatus = require("./txStatus");
|
||||
@@ -38,28 +38,6 @@ const EXT_ICON =
|
||||
`</svg></span>`;
|
||||
|
||||
let pendingTx = null;
|
||||
// Track active warnings so async checks can append without overwriting.
|
||||
let activeWarnings = [];
|
||||
|
||||
function renderWarnings(el, warnings) {
|
||||
activeWarnings = warnings.slice();
|
||||
if (warnings.length > 0) {
|
||||
el.innerHTML = warnings
|
||||
.map(
|
||||
(w) =>
|
||||
`<div class="border border-border border-dashed p-2 mb-1 text-xs font-bold">WARNING: ${w}</div>`,
|
||||
)
|
||||
.join("");
|
||||
el.classList.remove("hidden");
|
||||
} else {
|
||||
el.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
function appendWarning(el, message) {
|
||||
activeWarnings.push(message);
|
||||
renderWarnings(el, activeWarnings);
|
||||
}
|
||||
|
||||
function restore() {
|
||||
const d = state.viewData;
|
||||
@@ -187,16 +165,16 @@ function show(txInfo) {
|
||||
$("confirm-balance").textContent = valueWithUsd(bal + " ETH", balUsd);
|
||||
}
|
||||
|
||||
// Check for warnings (synchronous checks first, async checks added later)
|
||||
// Check for warnings (synchronous checks)
|
||||
const warnings = [];
|
||||
if (isScamAddress(txInfo.to)) {
|
||||
warnings.push(
|
||||
"This address is on a known scam/fraud list. Do not send funds to this address.",
|
||||
);
|
||||
}
|
||||
if (isNullOrBurnAddress(txInfo.to)) {
|
||||
if (isBurnAddress(txInfo.to)) {
|
||||
warnings.push(
|
||||
"This is a null or burn address. Funds sent here will be permanently lost.",
|
||||
"This is a known null/burn address. Funds sent here are permanently destroyed and cannot be recovered.",
|
||||
);
|
||||
}
|
||||
if (txInfo.to.toLowerCase() === txInfo.from.toLowerCase()) {
|
||||
@@ -204,7 +182,17 @@ function show(txInfo) {
|
||||
}
|
||||
|
||||
const warningsEl = $("confirm-warnings");
|
||||
renderWarnings(warningsEl, warnings);
|
||||
if (warnings.length > 0) {
|
||||
warningsEl.innerHTML = warnings
|
||||
.map(
|
||||
(w) =>
|
||||
`<div class="border border-border border-dashed p-2 mb-1 text-xs font-bold">WARNING: ${w}</div>`,
|
||||
)
|
||||
.join("");
|
||||
warningsEl.classList.remove("hidden");
|
||||
} else {
|
||||
warningsEl.classList.add("hidden");
|
||||
}
|
||||
|
||||
// Check for errors
|
||||
const errors = [];
|
||||
@@ -260,10 +248,14 @@ function show(txInfo) {
|
||||
state.viewData = { pendingTx: txInfo };
|
||||
showView("confirm-tx");
|
||||
|
||||
// Hide the legacy recipient warning element (warnings now unified)
|
||||
const legacyWarningEl = $("confirm-recipient-warning");
|
||||
if (legacyWarningEl) {
|
||||
legacyWarningEl.style.display = "none";
|
||||
// Reset async warnings to hidden (space always reserved, no layout shift)
|
||||
$("confirm-recipient-warning").style.visibility = "hidden";
|
||||
$("confirm-contract-warning").style.visibility = "hidden";
|
||||
$("confirm-burn-warning").style.visibility = "hidden";
|
||||
|
||||
// Show burn warning via reserved element (in addition to inline warning)
|
||||
if (isBurnAddress(txInfo.to)) {
|
||||
$("confirm-burn-warning").style.visibility = "visible";
|
||||
}
|
||||
|
||||
estimateGas(txInfo);
|
||||
@@ -311,24 +303,17 @@ async function estimateGas(txInfo) {
|
||||
}
|
||||
|
||||
async function checkRecipientHistory(txInfo) {
|
||||
const warningsEl = $("confirm-warnings");
|
||||
try {
|
||||
const provider = getProvider(state.rpcUrl);
|
||||
const code = await provider.getCode(txInfo.to);
|
||||
if (code && code !== "0x") {
|
||||
// Recipient is a contract address — warn the user
|
||||
appendWarning(
|
||||
warningsEl,
|
||||
"The recipient is a contract address. Sending tokens directly to a contract may result in permanent loss of funds.",
|
||||
);
|
||||
// Recipient is a contract — warn the user
|
||||
$("confirm-contract-warning").style.visibility = "visible";
|
||||
return;
|
||||
}
|
||||
const txCount = await provider.getTransactionCount(txInfo.to);
|
||||
if (txCount === 0) {
|
||||
appendWarning(
|
||||
warningsEl,
|
||||
"The recipient address has ZERO transaction history. This may indicate a fresh or unused address. Double-check the address before sending.",
|
||||
);
|
||||
$("confirm-recipient-warning").style.visibility = "visible";
|
||||
}
|
||||
} catch (e) {
|
||||
log.errorf("recipient history check failed:", e.message);
|
||||
|
||||
@@ -20,6 +20,19 @@ const ERC20_ABI = [
|
||||
"function approve(address spender, uint256 amount) returns (bool)",
|
||||
];
|
||||
|
||||
// Known null/burn addresses that permanently destroy funds.
|
||||
const BURN_ADDRESSES = new Set([
|
||||
"0x0000000000000000000000000000000000000000",
|
||||
"0x0000000000000000000000000000000000000001",
|
||||
"0x000000000000000000000000000000000000dead",
|
||||
"0xdead000000000000000000000000000000000000",
|
||||
"0x00000000000000000000000000000000deadbeef",
|
||||
]);
|
||||
|
||||
function isBurnAddress(address) {
|
||||
return BURN_ADDRESSES.has(address.toLowerCase());
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
DEBUG,
|
||||
DEBUG_MNEMONIC,
|
||||
@@ -28,4 +41,6 @@ module.exports = {
|
||||
DEFAULT_BLOCKSCOUT_URL,
|
||||
BIP44_ETH_PATH,
|
||||
ERC20_ABI,
|
||||
BURN_ADDRESSES,
|
||||
isBurnAddress,
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user