Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1ac51d514 |
@@ -1022,7 +1022,7 @@ on the approval screen, the amount on the wait, success and error screens, the
|
|||||||
transaction history and the transaction detail screen, and the refusal of a fee
|
transaction history and the transaction detail screen, and the refusal of a fee
|
||||||
above 1 ETH. A chain id that names no network reads `ETH`. Wherever this
|
above 1 ETH. A chain id that names no network reads `ETH`. Wherever this
|
||||||
document shows ETH as the label of a native balance, value or fee, in a "Native
|
document shows ETH as the label of a native balance, value or fee, in a "Native
|
||||||
ETH transfer" type line, in the two recipient warnings or in that refusal,
|
ETH transfer" type line, in the contract-recipient warning or in that refusal,
|
||||||
Sepolia shows `SepoliaETH`. The swap lines keep `ETH`, the router's own name for
|
Sepolia shows `SepoliaETH`. The swap lines keep `ETH`, the router's own name for
|
||||||
the native currency, and the ETH/USD price line, shown on mainnet only, keeps
|
the native currency, and the ETH/USD price line, shown on mainnet only, keeps
|
||||||
its fixed wording.
|
its fixed wording.
|
||||||
@@ -1740,10 +1740,8 @@ view would leave a wallet one click from deletion.
|
|||||||
reserved either way
|
reserved either way
|
||||||
- Warnings: inline warnings from the local checks (scam address, self-send)
|
- Warnings: inline warnings from the local checks (scam address, self-send)
|
||||||
plus four reserved warning boxes made visible by the async checks —
|
plus four reserved warning boxes made visible by the async checks —
|
||||||
recipient that has never sent a transaction and holds no ETH, recipient is
|
recipient with no transaction history, recipient is a contract, burn
|
||||||
a contract, burn address, and an Etherscan phishing/scam label. An address
|
address, and an Etherscan phishing/scam label
|
||||||
that has received ETH but never sent a transaction still holds that ETH,
|
|
||||||
so it gets no warning
|
|
||||||
- Errors (an invalid amount), plus five reserved error boxes, so the balance
|
- Errors (an invalid amount), plus five reserved error boxes, so the balance
|
||||||
and the fee arriving later move nothing — the amount exceeds the balance
|
and the fee arriving later move nothing — the amount exceeds the balance
|
||||||
(for a token whose scale is unknown it says the token's balance is
|
(for a token whose scale is unknown it says the token's balance is
|
||||||
|
|||||||
+11
-6
@@ -634,12 +634,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="confirm-warnings" class="mb-2 invisible"></div>
|
<div id="confirm-warnings" class="mb-2 invisible"></div>
|
||||||
<!-- These two sentences name the network's native token, so
|
<div id="confirm-recipient-warning" class="mb-2 invisible">
|
||||||
show() in confirmTx.js sets them. -->
|
<div
|
||||||
<div
|
class="border border-red-500 border-dashed p-2 text-xs font-bold text-red-500"
|
||||||
id="confirm-recipient-warning"
|
>
|
||||||
class="mb-2 border border-red-500 border-dashed p-2 text-xs font-bold text-red-500 invisible"
|
WARNING: The recipient address has ZERO transaction
|
||||||
></div>
|
history. This may indicate a fresh or unused address.
|
||||||
|
Double-check the address before sending.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Its sentence names the network's native token, so show()
|
||||||
|
in confirmTx.js sets it. -->
|
||||||
<div
|
<div
|
||||||
id="confirm-contract-warning"
|
id="confirm-contract-warning"
|
||||||
class="mb-2 border border-red-500 border-dashed p-2 text-xs font-bold text-red-500 invisible"
|
class="mb-2 border border-red-500 border-dashed p-2 text-xs font-bold text-red-500 invisible"
|
||||||
|
|||||||
@@ -243,14 +243,7 @@ function show(txInfo) {
|
|||||||
nativeCurrencyByChainId(txInfo.chainId) +
|
nativeCurrencyByChainId(txInfo.chainId) +
|
||||||
" to this address and try again.";
|
" to this address and try again.";
|
||||||
|
|
||||||
// Both shown later, by checkRecipientHistory(). The first sentence says
|
// Shown later, once checkRecipientHistory() finds a contract.
|
||||||
// exactly what getFullWarnings() checks.
|
|
||||||
$("confirm-recipient-warning").textContent =
|
|
||||||
"WARNING: The recipient address has never sent a transaction and" +
|
|
||||||
" holds no " +
|
|
||||||
nativeCurrencyByChainId(txInfo.chainId) +
|
|
||||||
". This may indicate a fresh or unused address. Double-check the" +
|
|
||||||
" address before sending.";
|
|
||||||
$("confirm-contract-warning").textContent =
|
$("confirm-contract-warning").textContent =
|
||||||
"WARNING: The recipient is a smart contract. Sending " +
|
"WARNING: The recipient is a smart contract. Sending " +
|
||||||
nativeCurrencyByChainId(txInfo.chainId) +
|
nativeCurrencyByChainId(txInfo.chainId) +
|
||||||
|
|||||||
@@ -51,8 +51,7 @@ function getLocalWarnings(address, options = {}) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check an address against local lists AND via RPC queries.
|
* Check an address against local lists AND via RPC queries.
|
||||||
* Async — performs network calls to check contract status, tx count and
|
* Async — performs network calls to check contract status and tx history.
|
||||||
* balance.
|
|
||||||
*
|
*
|
||||||
* @param {string} address - The target address to check.
|
* @param {string} address - The target address to check.
|
||||||
* @param {object} provider - An ethers.js provider instance.
|
* @param {object} provider - An ethers.js provider instance.
|
||||||
@@ -79,30 +78,21 @@ async function getFullWarnings(address, provider, options = {}) {
|
|||||||
log.errorf("contract check failed:", e.shortMessage || e.message);
|
log.errorf("contract check failed:", e.shortMessage || e.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The transaction count is the number of transactions the address has
|
// Skip tx count check for contracts — they may legitimately have
|
||||||
// sent, so an address that has only ever received has a count of zero.
|
// zero inbound EOA transactions.
|
||||||
// Native token it received stays in its balance until it sends a
|
|
||||||
// transaction, so the warning also needs a zero balance. A contract is
|
|
||||||
// skipped: it has its own warning above.
|
|
||||||
if (!isContract) {
|
if (!isContract) {
|
||||||
try {
|
try {
|
||||||
const txCount = await provider.getTransactionCount(address);
|
const txCount = await provider.getTransactionCount(address);
|
||||||
if (txCount === 0) {
|
if (txCount === 0) {
|
||||||
const balance = await provider.getBalance(address);
|
warnings.push({
|
||||||
if (balance === 0n) {
|
type: "new-address",
|
||||||
warnings.push({
|
message:
|
||||||
type: "new-address",
|
"This address has never sent a transaction. Double-check it is correct.",
|
||||||
message:
|
severity: "info",
|
||||||
"This address has never sent a transaction and holds none of the network's native token. Double-check it is correct.",
|
});
|
||||||
severity: "info",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.errorf(
|
log.errorf("tx count check failed:", e.shortMessage || e.message);
|
||||||
"tx count or balance check failed:",
|
|
||||||
e.shortMessage || e.message,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
// The confirmation screen's warning for a recipient that has never sent a
|
|
||||||
// transaction (https://git.eeqj.de/sneak/AutistMask/issues/528).
|
|
||||||
//
|
|
||||||
// The node's transaction count for an address is the number of transactions
|
|
||||||
// it has sent, so an address that only ever receives, such as a savings
|
|
||||||
// address or an exchange deposit address, has a count of zero. The warning
|
|
||||||
// used to fire on that count alone. It now also needs a zero balance: ETH an
|
|
||||||
// address received stays in its balance until it sends a transaction.
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const { getFullWarnings } = require("../src/shared/addressWarnings");
|
|
||||||
|
|
||||||
global.fetch = jest.fn(async () => {
|
|
||||||
throw new Error("tests must not perform network requests");
|
|
||||||
});
|
|
||||||
|
|
||||||
const RECIPIENT = "0x" + "b".repeat(40);
|
|
||||||
|
|
||||||
// The warning types getFullWarnings() returns for RECIPIENT when the node
|
|
||||||
// reports it as a regular address with `txCount` sent transactions and a
|
|
||||||
// balance of `balance` wei.
|
|
||||||
async function warningTypes(txCount, balance) {
|
|
||||||
const provider = {
|
|
||||||
getCode: async () => "0x",
|
|
||||||
getTransactionCount: async () => txCount,
|
|
||||||
getBalance: async () => balance,
|
|
||||||
};
|
|
||||||
const warnings = await getFullWarnings(RECIPIENT, provider);
|
|
||||||
return warnings.map((w) => w.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
test("a recipient that has received 0.5 ETH and never sent a transaction gets no warning", async () => {
|
|
||||||
expect(await warningTypes(0, 500000000000000000n)).toEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("a recipient that has never sent a transaction and holds no ETH gets the warning", async () => {
|
|
||||||
expect(await warningTypes(0, 0n)).toEqual(["new-address"]);
|
|
||||||
});
|
|
||||||
@@ -271,13 +271,6 @@ describe.each([
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("the warning for a recipient that has never sent a transaction", async () => {
|
|
||||||
await confirmSend("0.1");
|
|
||||||
expect(text("confirm-recipient-warning")).toContain(
|
|
||||||
"has never sent a transaction and holds no " + symbol + ".",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// A token reports whatever symbol it likes. One reporting the label the
|
// A token reports whatever symbol it likes. One reporting the label the
|
||||||
// wallet shows its native token under, on this network or any other, is
|
// wallet shows its native token under, on this network or any other, is
|
||||||
// a fake, exactly as one reporting `ETH` always was.
|
// a fake, exactly as one reporting `ETH` always was.
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ test("ethers puts the URL in the error message, not in the short message", async
|
|||||||
test("the recipient checks before a send", async () => {
|
test("the recipient checks before a send", async () => {
|
||||||
await getFullWarnings(ADDRESS, getProvider(RPC_URL, "mainnet"));
|
await getFullWarnings(ADDRESS, getProvider(RPC_URL, "mainnet"));
|
||||||
expectFailureLoggedWithoutKey("contract check failed");
|
expectFailureLoggedWithoutKey("contract check failed");
|
||||||
expectFailureLoggedWithoutKey("tx count or balance check failed");
|
expectFailureLoggedWithoutKey("tx count check failed");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("the ENS reverse lookup", async () => {
|
test("the ENS reverse lookup", async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user