Преглед изворни кода

feat(xc-admin): support closing buffer accounts (#1584)

Ali Behjati пре 1 година
родитељ
комит
f4cc19520e

+ 51 - 19
governance/xc_admin/packages/xc_admin_cli/src/index.ts

@@ -274,6 +274,40 @@ multisigCommand("upgrade-program", "Upgrade a program from a buffer")
     );
   });
 
+async function closeProgramOrBuffer(
+  vault: MultisigVault,
+  cluster: PythCluster,
+  programDataOrBufferAccount: PublicKey,
+  spill: PublicKey,
+  programId?: PublicKey
+) {
+  let accounts = [
+    { pubkey: programDataOrBufferAccount, isSigner: false, isWritable: true },
+    { pubkey: spill, isSigner: false, isWritable: true },
+    {
+      pubkey: await vault.getVaultAuthorityPDA(cluster),
+      isSigner: true,
+      isWritable: false,
+    },
+  ];
+  if (programId) {
+    accounts.push({ pubkey: programId, isSigner: false, isWritable: true });
+  }
+
+  const proposalInstruction: TransactionInstruction = {
+    programId: BPF_UPGRADABLE_LOADER,
+    // 4-bytes instruction discriminator, got it from https://docs.rs/solana-program/latest/src/solana_program/loader_upgradeable_instruction.rs.html
+    data: Buffer.from([5, 0, 0, 0]),
+    keys: accounts,
+  };
+
+  await vault.proposeInstructions(
+    [proposalInstruction],
+    cluster,
+    DEFAULT_PRIORITY_FEE_CONFIG
+  );
+}
+
 multisigCommand(
   "close-program",
   "Close a program, retrieve the funds. WARNING : THIS WILL BRICK THE PROGRAM AND THE ACCOUNTS IT OWNS FOREVER"
@@ -291,29 +325,27 @@ multisigCommand(
       BPF_UPGRADABLE_LOADER
     )[0];
 
-    const proposalInstruction: TransactionInstruction = {
-      programId: BPF_UPGRADABLE_LOADER,
-      // 4-bytes instruction discriminator, got it from https://docs.rs/solana-program/latest/src/solana_program/loader_upgradeable_instruction.rs.html
-      data: Buffer.from([5, 0, 0, 0]),
-      keys: [
-        { pubkey: programDataAccount, isSigner: false, isWritable: true },
-        { pubkey: spill, isSigner: false, isWritable: true },
-        {
-          pubkey: await vault.getVaultAuthorityPDA(cluster),
-          isSigner: true,
-          isWritable: false,
-        },
-        { pubkey: programId, isSigner: false, isWritable: true },
-      ],
-    };
-
-    await vault.proposeInstructions(
-      [proposalInstruction],
+    await closeProgramOrBuffer(
+      vault,
       cluster,
-      DEFAULT_PRIORITY_FEE_CONFIG
+      programDataAccount,
+      spill,
+      programId
     );
   });
 
+multisigCommand("close-buffer", "Close a buffer, retrieve the funds.")
+  .requiredOption("-b, --buffer <pubkey>", "buffer that you want to close")
+  .requiredOption("-s, --spill <pubkey>", "address to receive the funds")
+  .action(async (options: any) => {
+    const vault = await loadVaultFromOptions(options);
+    const spill = new PublicKey(options.spill);
+    const cluster: PythCluster = options.cluster;
+    const bufferAccount = new PublicKey(options.buffer);
+
+    await closeProgramOrBuffer(vault, cluster, bufferAccount, spill);
+  });
+
 multisigCommand(
   "deactivate-stake",
   "Deactivate the delegated stake from the account"

+ 19 - 6
governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/BpfUpgradableLoaderMultisigInstruction.ts

@@ -62,10 +62,12 @@ export class BpfUpgradableLoaderInstruction implements MultisigInstruction {
             }
           );
         case 5:
-          return new BpfUpgradableLoaderInstruction(
-            "Close",
-            {},
-            {
+          let args;
+          // Close instruction supports closing two types of accounts:
+          // - A program which takes 4 keys (programData, spill, upgradeAuthority, program)
+          // - A buffer which takes 3 keys (buffer, spill, upgradeAuthority)
+          if (instruction.keys.length >= 4) {
+            args = {
               named: {
                 programData: instruction.keys[0],
                 spill: instruction.keys[1],
@@ -73,8 +75,19 @@ export class BpfUpgradableLoaderInstruction implements MultisigInstruction {
                 program: instruction.keys[3],
               },
               remaining: instruction.keys.slice(4),
-            }
-          );
+            };
+          } else {
+            args = {
+              named: {
+                buffer: instruction.keys[0],
+                spill: instruction.keys[1],
+                upgradeAuthority: instruction.keys[2],
+              },
+              remaining: instruction.keys.slice(3),
+            };
+          }
+
+          return new BpfUpgradableLoaderInstruction("Close", {}, args);
         default: // Many more cases are not supported
           throw Error("Not implemented");
       }