3

System Program has two distinct instructions: CreateAccount and CreateWithSeed. The latter's documentation says:

Create a new account at an address derived from a base pubkey and a seed

This sounds pretty much like PDA, but actually it isn't. The algorithm for obtaining an address from seeds is different from the algorithm for PDA (see this and this)

So, what is the purpose of create_with_seed() function and the corresponding instruction?

3 Answers 3

6

Similar to how PDAs associate additional accounts with programs, seeded accounts associate additional accounts with normal users.

The system program allows you to operate on accounts that are derived from your signing key, while only requiring the signature of the base account. This derivation is done by create_with_seed.

let derived = await PublicKey.createWithSeed(basePubkey, seed, programId);

The private key of the basePubKey you used to create the derived address can sign for any transaction relating to that account.

1

With the basic version we don't care about the key generated for the account. For example we just spawn some account like this:

    let a: PublicKey = new Keypair().publicKey;
    let params: CreateAccountParams  = {
      fromPubkey: wallet.payer.publicKey,
      newAccountPubkey: a,
      lamports: 9999,
      space: 500,
      programId: program.programId
    };

We can't recover this account if we don't have access to the original key that we made. Usually we don't care about this because you can easily look up the account on-chain, or you've already stored it somewhere.

The seed version requires you to create a base pubkey. You can use PublicKey.createWithSeed() to derive a key for your account given that base key. This means that now if you have have the seed_key and the seed string, you can easily derive the account's address.

    let seed_key: PublicKey = new Keypair().publicKey;
    let b = await PublicKey.createWithSeed(seed_key, "cake", program.programId);
    let seedParams: CreateAccountWithSeedParams = {
      fromPubkey: wallet.payer.publicKey,
      newAccountPubkey: b,
      lamports: 9999,
      space: 500,
      programId: program.programId,
      basePubkey: seed_key,
      seed: "cake"
    };

So let's say you want others to come use your program and write bots on it or something. So they can easily find various accounts your program uses, you might share the seed_key and the seed strings.

0

Heres another use-case for createWithSeed: creating PDA derived accounts.

Contrived example: lets say youre building a SOL vault program and have the SOL vault located at PDA [“vault”] that holds the SOL. Now youve decide to create another account to record some data in and you want to it to be at an address derived from the vault PDA. You also want the SOL vault to pay for this account’s rent. If you use a PDA derived from the vault PDA you need both PDAs to sign the createAccount system instruction, but invoke_signed only allows 1 set of seeds. In this case, you can instead use createWithSeed with the vault PDA as the base and only need to sign with the vault PDA.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.