Skip to content

Commit 72cb295

Browse files
committed
Revamp scripts
1 parent f52a265 commit 72cb295

15 files changed

Lines changed: 1197 additions & 165 deletions

File tree

Anchor.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1+
[toolchain]
2+
13
[features]
2-
seeds = true
4+
resolution = true
35
skip-lint = false
6+
47
[programs.localnet]
58
program_authority_escrow = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
69

710
[registry]
811
url = "https://api.apr.dev"
912

1013
[provider]
11-
cluster = "Localnet"
14+
cluster = "localnet"
1215
wallet = "/home/gbescos/.config/solana/id.json"
1316

1417
[scripts]

Cargo.lock

Lines changed: 58 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,43 @@
11
# program-authority-escrow
22

3-
A minimalistic, stateless program to safely transfer a solana program from one upgrade authority to another one.
3+
A stateless Solana program for safe program authority transfers.
44

5-
The way it works :
6-
- The current authority uses Propose to transfer the authority of any program to a PDA of the escrow seeded by (current_authority, new_authority)
7-
- Once the authority has been transferred two outcomes are possible :
8-
- If the current authority calls Revert, the PDA will give the authority back to the current authority
9-
- If the new authority calls Accept, the PDA will give the authority to the new authority
5+
The current authority calls `propose` to transfer authority to an escrow PDA seeded by `(current_authority, new_authority)`. From there:
6+
- The current authority can call `revert` to reclaim authority
7+
- The new authority can call `accept` to complete the transfer
108

11-
Basically, this program enforces that the new authority has signed before they accept the authority.
12-
This makes errors where we mistakenly transfer the authority to a key that we don't own reversible.
9+
This ensures the new authority has signed before accepting, making accidental transfers to wrong keys reversible.
10+
11+
Build with `cargo build-sbf` and test with `cargo test-sbf`.
12+
13+
## Scripts
14+
15+
TypeScript scripts are provided to interact with the on-chain program. All scripts support:
16+
- File-based keypairs or Ledger hardware wallets
17+
- Squads v3 multisig proposals via `--multisig`
18+
19+
Install dependencies with `yarn install`. See `scripts/helpers.ts` for documentation on CLI arguments.
20+
21+
### Propose
22+
23+
Transfer program authority to the escrow. The current authority proposes the transfer:
1324

14-
## Testing
15-
To run tests:
1625
```shell
17-
cargo test-sbf
26+
yarn propose --keypair <path|ledger> --program <program_address> --authority <new_authority>
1827
```
1928

20-
## Building
21-
To build:
29+
### Accept
30+
31+
Accept a proposed authority transfer. The new authority accepts:
32+
33+
```shell
34+
yarn accept --keypair <path|ledger> --program <program_address> --authority <previous_authority>
35+
```
36+
37+
### Revert
38+
39+
Revert a proposed transfer before it's accepted. The current authority reverts:
2240

2341
```shell
24-
cargo build-sbf
42+
yarn revert --keypair <path|ledger> --program <program_address> --authority <new_authority>
2543
```
26-
Artifacts will be placed at: `target/deploy/*.so`

package.json

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
{
2-
"scripts": {
3-
"lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w",
4-
"lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check"
5-
},
6-
"dependencies": {
7-
"@project-serum/anchor": "^0.26.0"
8-
},
9-
"devDependencies": {
10-
"chai": "^4.3.4",
11-
"mocha": "^9.0.3",
12-
"ts-mocha": "^10.0.0",
13-
"@types/bn.js": "^5.1.0",
14-
"@types/chai": "^4.3.0",
15-
"@types/mocha": "^9.0.0",
16-
"typescript": "^4.3.5",
17-
"prettier": "^2.6.2"
18-
}
2+
"scripts": {
3+
"lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w",
4+
"lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check",
5+
"propose": "ts-node scripts/propose.ts",
6+
"revert": "ts-node scripts/revert.ts",
7+
"accept": "ts-node scripts/accept.ts"
8+
},
9+
"dependencies": {
10+
"@coral-xyz/anchor": "^0.30.0",
11+
"@ledgerhq/hw-transport": "^6.31.13",
12+
"@ledgerhq/hw-transport-node-hid": "^6.29.14",
13+
"@sqds/sdk": "^2.0.4",
14+
"@types/minimist": "^1.2.5",
15+
"minimist": "^1.2.8",
16+
"ts-node": "^10.9.2"
17+
},
18+
"devDependencies": {
19+
"@types/bn.js": "^5.1.0",
20+
"@types/chai": "^4.3.0",
21+
"@types/mocha": "^9.0.0",
22+
"chai": "^4.3.4",
23+
"mocha": "^9.0.3",
24+
"prettier": "^2.6.2",
25+
"ts-mocha": "^10.0.0",
26+
"typescript": "^4.3.5"
27+
}
1928
}

programs/program-authority-escrow/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ default = []
2020
custom-heap = []
2121
custom-panic = []
2222
anchor-debug = []
23+
idl-build = ["anchor-lang/idl-build"]
2324

2425
[dependencies]
2526
anchor-lang.workspace = true
@@ -29,4 +30,3 @@ solana-program-test.workspace = true
2930
solana-sdk.workspace = true
3031
tokio.workspace = true
3132
bincode.workspace = true
32-

programs/program-authority-timelock/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ default = []
2020
custom-heap = []
2121
custom-panic = []
2222
anchor-debug = []
23+
idl-build = ["anchor-lang/idl-build"]
2324

2425
[dependencies]
2526
anchor-lang.workspace = true
@@ -29,4 +30,3 @@ solana-program-test.workspace = true
2930
solana-sdk.workspace = true
3031
tokio.workspace = true
3132
bincode.workspace = true
32-

scripts/accept.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { PublicKey } from "@solana/web3.js";
2+
import { getAuthorityPDA, DEFAULT_MULTISIG_PROGRAM_ID } from "@sqds/sdk";
3+
import BN from "bn.js";
4+
import {
5+
parseArgs,
6+
createWallet,
7+
initEscrowProgram,
8+
parseMultisig,
9+
executeOrPropose,
10+
} from "./helpers";
11+
12+
const BPF_UPGRADABLE_LOADER = new PublicKey(
13+
"BPFLoaderUpgradeab1e11111111111111111111111"
14+
);
15+
16+
async function main() {
17+
const args = parseArgs();
18+
const wallet = await createWallet(args);
19+
const { connection, program, programId } = initEscrowProgram(args, wallet);
20+
const multisigAddress = parseMultisig(args);
21+
22+
const programToTransfer = new PublicKey(args.program);
23+
const currentAuthority = new PublicKey(args.authority);
24+
25+
const programData = PublicKey.findProgramAddressSync(
26+
[programToTransfer.toBuffer()],
27+
BPF_UPGRADABLE_LOADER
28+
)[0];
29+
30+
// In multisig mode, the vault becomes the new authority
31+
let newAuthority: PublicKey;
32+
if (multisigAddress) {
33+
[newAuthority] = getAuthorityPDA(
34+
multisigAddress,
35+
new BN(1),
36+
DEFAULT_MULTISIG_PROGRAM_ID
37+
);
38+
} else {
39+
newAuthority = wallet.publicKey;
40+
}
41+
42+
const escrowAuthority = PublicKey.findProgramAddressSync(
43+
[currentAuthority.toBuffer(), newAuthority.toBuffer()],
44+
programId
45+
)[0];
46+
47+
console.log("Accepting program authority transfer...");
48+
console.log(` Wallet: ${wallet.publicKey.toBase58()}`);
49+
console.log(` Program: ${programToTransfer.toBase58()}`);
50+
console.log(` Current Authority: ${currentAuthority.toBase58()}`);
51+
console.log(` New Authority: ${newAuthority.toBase58()}`);
52+
console.log(` Escrow Authority: ${escrowAuthority.toBase58()}`);
53+
54+
if (multisigAddress) {
55+
console.log(` Multisig: ${multisigAddress.toBase58()}`);
56+
}
57+
58+
const instruction = await program.methods
59+
.accept()
60+
.accounts({
61+
currentAuthority: currentAuthority,
62+
newAuthority: newAuthority,
63+
programAccount: programToTransfer,
64+
})
65+
.accountsPartial({
66+
escrowAuthority: escrowAuthority,
67+
programData: programData,
68+
})
69+
.instruction();
70+
71+
await executeOrPropose(connection, wallet, multisigAddress, instruction);
72+
}
73+
74+
main().catch((err) => {
75+
console.error(err);
76+
process.exit(1);
77+
});

scripts/commit.ts

Lines changed: 0 additions & 41 deletions
This file was deleted.

0 commit comments

Comments
 (0)