Ease potential scam checks and handle case-insensitive addresses (#2497)
David Adegoke committed
Sep 5, 2025 at 22:05 UTC
31b9bb7f539849bb7d17ff7487666bf43c654965
1 file changed
+5
-64
lib/view_model/dashboard/home_settings_view_model.dart
+5
-64
@@ -81,7 +81,7 @@ abstract class HomeSettingsViewModelBase with Store {
81
name: token.name,
82
symbol: token.title,
83
decimal: token.decimals,
84
- contractAddress: contractAddress,
84
+ contractAddress: contractAddress.toLowerCase(),
85
iconPath: token.iconPath,
86
isPotentialScam: token.isPotentialScam,
87
);
@@ -94,7 +94,7 @@ abstract class HomeSettingsViewModelBase with Store {
94
name: token.name,
95
symbol: token.title,
96
decimal: token.decimals,
97
- contractAddress: contractAddress,
97
+ contractAddress: contractAddress.toLowerCase(),
98
iconPath: token.iconPath,
99
isPotentialScam: token.isPotentialScam,
100
);
@@ -198,18 +198,12 @@ abstract class HomeSettingsViewModelBase with Store {
198
isEthereum ? 'eth' : 'polygon',
199
);
200
201
- bool isPotentialScamViaExplorers = await _isPotentialScamTokenViaExplorers(
202
- contractAddress,
203
- isEthereum: isEthereum,
204
- );
205
-
201
bool isUnverifiedContract = await _isContractUnverified(
202
contractAddress,
203
isEthereum: isEthereum,
204
);
205
211
- final showWarningForContractAddress =
212
- isPotentialScamViaMoralis || isUnverifiedContract || isPotentialScamViaExplorers;
206
+ final showWarningForContractAddress = isPotentialScamViaMoralis || isUnverifiedContract;
207
208
return showWarningForContractAddress;
209
} finally {
@@ -275,7 +269,7 @@ abstract class HomeSettingsViewModelBase with Store {
269
"X-API-Key": secrets.moralisApiKey,
270
},
271
);
278
-
272
+
273
final decodedResponse = jsonDecode(response.body);
274
275
final tokenInfo = Erc20TokenInfoMoralis.fromJson(decodedResponse[0] as Map<String, dynamic>);
@@ -291,12 +285,7 @@ abstract class HomeSettingsViewModelBase with Store {
285
}
286
287
// Tokens with a security score less than 40 are potentially risky, requiring caution when dealing with them.
294
- if (tokenInfo.securityScore == null || tokenInfo.securityScore! < 40) {
295
- return true;
296
- }
297
-
298
- // Absence of a website URL for an ERC-20 token can be a potential red flag. A legitimate ERC-20 projects should have a well-maintained website that provides information about the token, its purpose, team, and roadmap.
299
- if (tokenInfo.links?.website == null || tokenInfo.links!.website!.isEmpty) {
288
+ if (tokenInfo.securityScore != null && tokenInfo.securityScore! < 40) {
289
return true;
290
}
291
@@ -308,11 +297,6 @@ abstract class HomeSettingsViewModelBase with Store {
297
return true;
298
}
299
311
- // I mean, a logo is the most basic of all the potential causes, but why does your fully functional project not have a logo?
312
- if (tokenInfo.logo == null) {
313
- return true;
314
- }
315
-
300
return false;
301
} catch (e) {
302
printV('Error while checking scam via moralis: ${e.toString()}');
@@ -320,48 +304,6 @@ abstract class HomeSettingsViewModelBase with Store {
304
}
305
}
306
323
- Future<bool> _isPotentialScamTokenViaExplorers(
324
- String contractAddress, {
325
- required bool isEthereum,
326
- }) async {
327
- final uri = Uri.https(
328
- "api.etherscan.io",
329
- "/v2/api",
330
- {
331
- "chainid": isEthereum ? "1" : "137",
332
- "module": "token",
333
- "action": "tokeninfo",
334
- "contractaddress": contractAddress,
335
- "apikey": secrets.etherScanApiKey,
336
- },
337
- );
338
-
339
- try {
340
- final response = await ProxyWrapper().get(clearnetUri: uri);
341
-
342
- final decodedResponse = jsonDecode(response.body) as Map<String, dynamic>;
343
-
344
- if (decodedResponse['status'] != '1') {
345
- log('${response.body}\n');
346
- log('${decodedResponse['result']}\n');
347
- return true;
348
- }
349
-
350
- final tokenInfo =
351
- Erc20TokenInfoExplorers.fromJson(decodedResponse['result'][0] as Map<String, dynamic>);
352
-
353
- // A token without a website is a potential red flag
354
- if (tokenInfo.website?.isEmpty == true) {
355
- return true;
356
- }
357
-
358
- return false;
359
- } catch (e) {
360
- printV('Error while checking scam via explorers: ${e.toString()}');
361
- return true;
362
- }
363
- }
364
-
307
Future<bool> _isContractUnverified(
308
String contractAddress, {
309
required bool isEthereum,
@@ -380,7 +322,6 @@ abstract class HomeSettingsViewModelBase with Store {
322
323
try {
324
final response = await ProxyWrapper().get(clearnetUri: uri);
383
-
325
326
final decodedResponse = jsonDecode(response.body) as Map<String, dynamic>;
327