@@ -264,4 +264,137 @@ mod tests {
264264 . iter( )
265265 . any( |i| i. code == "FEE_ON_TRANSFER" && i. severity == IssueSeverity :: Error ) ) ;
266266 }
267+
268+ // ── Mode determination ─────────────────────────────────
269+
270+ #[ test]
271+ fn test_determine_mode_burning ( ) {
272+ let caps = TokenCapabilities {
273+ has_burn : true ,
274+ ..Default :: default ( )
275+ } ;
276+ assert_eq ! (
277+ CompatibilityChecker :: determine_mode( & caps) ,
278+ NttMode :: Burning
279+ ) ;
280+ }
281+
282+ #[ test]
283+ fn test_determine_mode_locking ( ) {
284+ assert_eq ! (
285+ CompatibilityChecker :: determine_mode( & TokenCapabilities :: default ( ) ) ,
286+ NttMode :: Locking
287+ ) ;
288+ }
289+
290+ // ── Decimal handling ───────────────────────────────────
291+
292+ #[ test]
293+ fn test_no_trimming_for_6_decimals ( ) {
294+ let token = TokenInfo {
295+ address : "0x0" . to_string ( ) ,
296+ chain : Chain :: Ethereum ,
297+ name : "Test" . to_string ( ) ,
298+ symbol : "TEST" . to_string ( ) ,
299+ decimals : 6 ,
300+ total_supply : "1000000" . to_string ( ) ,
301+ } ;
302+ let result = CompatibilityChecker :: check (
303+ & token,
304+ & TokenCapabilities :: default ( ) ,
305+ & BytecodeAnalysis :: default ( ) ,
306+ ) ;
307+ assert ! ( !result. decimal_trimming_required) ;
308+ assert_eq ! ( result. solana_decimals, 6 ) ;
309+ }
310+
311+ #[ test]
312+ fn test_trimming_for_9_decimals ( ) {
313+ let token = TokenInfo {
314+ address : "0x0" . to_string ( ) ,
315+ chain : Chain :: Ethereum ,
316+ name : "Test" . to_string ( ) ,
317+ symbol : "TEST" . to_string ( ) ,
318+ decimals : 9 ,
319+ total_supply : "1000000" . to_string ( ) ,
320+ } ;
321+ let result = CompatibilityChecker :: check (
322+ & token,
323+ & TokenCapabilities :: default ( ) ,
324+ & BytecodeAnalysis :: default ( ) ,
325+ ) ;
326+ assert ! ( result. decimal_trimming_required) ;
327+ assert_eq ! ( result. solana_decimals, 8 ) ;
328+ }
329+
330+ // ── Rebasing → incompatible ────────────────────────────
331+
332+ #[ test]
333+ fn test_rebasing_incompatible ( ) {
334+ let token = TokenInfo {
335+ address : "0x0" . to_string ( ) ,
336+ chain : Chain :: Ethereum ,
337+ name : "stETH" . to_string ( ) ,
338+ symbol : "stETH" . to_string ( ) ,
339+ decimals : 18 ,
340+ total_supply : "1000000" . to_string ( ) ,
341+ } ;
342+ let caps = TokenCapabilities {
343+ is_rebasing : true ,
344+ ..Default :: default ( )
345+ } ;
346+ let result = CompatibilityChecker :: check ( & token, & caps, & BytecodeAnalysis :: default ( ) ) ;
347+ assert ! ( !result. is_compatible) ;
348+ assert ! ( result
349+ . issues
350+ . iter( )
351+ . any( |i| i. code == "REBASING" && i. severity == IssueSeverity :: Error ) ) ;
352+ }
353+
354+ // ── Combined features: pausable + blacklistable ────────
355+
356+ #[ test]
357+ fn test_pausable_blacklistable_compatible_with_warnings ( ) {
358+ let token = TokenInfo {
359+ address : "0x0" . to_string ( ) ,
360+ chain : Chain :: Ethereum ,
361+ name : "Test" . to_string ( ) ,
362+ symbol : "TEST" . to_string ( ) ,
363+ decimals : 6 ,
364+ total_supply : "1000000" . to_string ( ) ,
365+ } ;
366+ let caps = TokenCapabilities {
367+ has_pause : true ,
368+ has_blacklist : true ,
369+ ..Default :: default ( )
370+ } ;
371+ let result = CompatibilityChecker :: check ( & token, & caps, & BytecodeAnalysis :: default ( ) ) ;
372+ assert ! ( result. is_compatible) ; // warnings don't block
373+ assert ! ( result. issues. iter( ) . any( |i| i. code == "PAUSABLE" ) ) ;
374+ assert ! ( result. issues. iter( ) . any( |i| i. code == "BLACKLIST" ) ) ;
375+ }
376+
377+ // ── Burnable token produces Info issue ──────────────────
378+
379+ #[ test]
380+ fn test_burnable_info_issue ( ) {
381+ let token = TokenInfo {
382+ address : "0x0" . to_string ( ) ,
383+ chain : Chain :: Ethereum ,
384+ name : "Test" . to_string ( ) ,
385+ symbol : "TEST" . to_string ( ) ,
386+ decimals : 6 ,
387+ total_supply : "1000000" . to_string ( ) ,
388+ } ;
389+ let caps = TokenCapabilities {
390+ has_burn : true ,
391+ ..Default :: default ( )
392+ } ;
393+ let result = CompatibilityChecker :: check ( & token, & caps, & BytecodeAnalysis :: default ( ) ) ;
394+ assert ! ( result. is_compatible) ;
395+ assert ! ( result
396+ . issues
397+ . iter( )
398+ . any( |i| i. code == "BURNABLE" && i. severity == IssueSeverity :: Info ) ) ;
399+ }
267400}
0 commit comments