@@ -1676,18 +1676,16 @@ async fn command_gc(
1676
1676
continue ;
1677
1677
}
1678
1678
1679
- // Sanity check!
1680
- // we shouldn't ever be here, but if we are here, abort!
1681
- if is_associated && amount > 0 {
1682
- panic ! ( "gc should NEVER attempt to close a nonempty ata" ) ;
1683
- }
1684
-
1685
- if close_authority == owner {
1686
- let res = if is_associated || amount == 0 {
1679
+ // this logic is quite fiendish, but its more readable this way than if/else
1680
+ let maybe_res = match ( close_authority == owner, is_associated, amount == 0 ) {
1681
+ // owner authority, associated or auxiliary, empty -> close
1682
+ ( true , _, true ) => Some (
1687
1683
token
1688
1684
. close_account ( & address, & owner, & owner, & bulk_signers)
1689
- . await
1690
- } else {
1685
+ . await ,
1686
+ ) ,
1687
+ // owner authority, auxiliary, nonempty -> empty and close
1688
+ ( true , false , false ) => Some (
1691
1689
token
1692
1690
. empty_and_close_auxiliary_account (
1693
1691
& address,
@@ -1696,10 +1694,40 @@ async fn command_gc(
1696
1694
decimals,
1697
1695
& bulk_signers,
1698
1696
)
1699
- . await
1700
- } ?;
1697
+ . await ,
1698
+ ) ,
1699
+ // separate authority, auxiliary, nonempty -> transfer
1700
+ ( false , false , false ) => Some (
1701
+ token
1702
+ . transfer (
1703
+ & address,
1704
+ & associated_token_account,
1705
+ & owner,
1706
+ amount,
1707
+ Some ( decimals) ,
1708
+ Some ( owner) ,
1709
+ & bulk_signers,
1710
+ )
1711
+ . await ,
1712
+ ) ,
1713
+ // separate authority, associated or auxiliary, empty -> print warning
1714
+ ( false , _, true ) => {
1715
+ println_display (
1716
+ config,
1717
+ format ! (
1718
+ "Note: skipping {} due to separate close authority {}; \
1719
+ revoke authority and rerun gc, or rerun gc with --owner",
1720
+ address, close_authority
1721
+ ) ,
1722
+ ) ;
1723
+ None
1724
+ }
1725
+ // anything else, including a nonempty associated account -> unreachable
1726
+ ( _, _, _) => unreachable ! ( ) ,
1727
+ } ;
1701
1728
1702
- let tx_return = finish_tx ( config, & res, false ) . await ?;
1729
+ if let Some ( res) = maybe_res {
1730
+ let tx_return = finish_tx ( config, & res?, false ) . await ?;
1703
1731
1704
1732
results. push ( match tx_return {
1705
1733
TransactionReturnData :: CliSignature ( signature) => {
@@ -1709,16 +1737,7 @@ async fn command_gc(
1709
1737
config. output_format . formatted_string ( & sign_only_data)
1710
1738
}
1711
1739
} ) ;
1712
- } else {
1713
- println_display (
1714
- config,
1715
- format ! (
1716
- "Note: skipping {} due to separate close authority {}; \
1717
- revoke authority and rerun gc, or rerun gc with --owner",
1718
- address, close_authority
1719
- ) ,
1720
- ) ;
1721
- }
1740
+ } ;
1722
1741
}
1723
1742
}
1724
1743
@@ -4352,6 +4371,41 @@ mod tests {
4352
4371
// aux is gone and its tokens are in ata, and ata has not been closed
4353
4372
assert_eq ! ( ui_ata. token_amount. amount, "1" ) ;
4354
4373
config. rpc_client . get_account ( & aux) . await . unwrap_err ( ) ;
4374
+
4375
+ // test that balance moves off an uncloseable account
4376
+ let token = create_token ( & config, & payer) . await ;
4377
+ let ata = create_associated_account ( & config, & payer, token) . await ;
4378
+ let aux = create_auxiliary_account ( & config, & payer, token) . await ;
4379
+ let close_authority = Keypair :: new ( ) . pubkey ( ) ;
4380
+ mint_tokens ( & config, & payer, token, 1.0 , aux) . await ;
4381
+
4382
+ process_test_command (
4383
+ & config,
4384
+ & payer,
4385
+ & [
4386
+ "spl-token" ,
4387
+ CommandName :: Authorize . into ( ) ,
4388
+ & aux. to_string ( ) ,
4389
+ "close" ,
4390
+ & close_authority. to_string ( ) ,
4391
+ ] ,
4392
+ )
4393
+ . await
4394
+ . unwrap ( ) ;
4395
+
4396
+ process_test_command ( & config, & payer, & [ "spl-token" , CommandName :: Gc . into ( ) ] )
4397
+ . await
4398
+ . unwrap ( ) ;
4399
+
4400
+ let ui_ata = config
4401
+ . rpc_client
4402
+ . get_token_account ( & ata)
4403
+ . await
4404
+ . unwrap ( )
4405
+ . unwrap ( ) ;
4406
+
4407
+ // aux tokens are now in ata
4408
+ assert_eq ! ( ui_ata. token_amount. amount, "1" ) ;
4355
4409
}
4356
4410
}
4357
4411
0 commit comments