-
Notifications
You must be signed in to change notification settings - Fork 150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Example: program that creates/closes a SPL Token account that it owns #3
base: master
Are you sure you want to change the base?
Conversation
let program_token_signer_seeds: &[&[_]] = &[br"program-token", &[program_token_bump_seed]]; | ||
|
||
match instruction_data.get(0) { | ||
Some(0) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that the create instruction is currently unprivileged, meaning that anybody can grief you by creating an arbitrary token at the fixed program address. In the real world, some authority should be checked before creating the token account
let rent = &Rent::from_account_info(rent_sysvar_info)?; | ||
|
||
invoke_signed( | ||
&system_instruction::create_account( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i noticed you used system_instruction::create_account()
here, is that any different than using pubkey::create_program_address()
https://github.com/solana-labs/solana/blob/89b474e192ea2f4b2274ad26cbc47443d5767571/sdk/program/src/pubkey.rs#L135 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, very different. Sadly the names are close enough that I can see where confusion can arise!
system_instruction::create_account()
- this is transaction instruction implemented by the system program that when executed allocates a new account on the chain based on the given parameters. The address that the account is allocated at is also provided as an input to this instruction
pubkey::create_program_address()
- a local function that returns an account address owned by the specified program, assuming the seeds are valid. This is just an address, a 32 byte number.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, and i presume you chose to use Pubkey::find_program_address()
instead of Pubkey::create_program_address()
, because as you mentioned above in the initial comments we have a constant address in this program for users to deposit SPL tokens
i'll try it myself, but it seems to me that i can also just call the Pubkey::find_program_address(&[br"program-token2"], program_id);
and it'll make a second associated account users can send same tokens to
then, i can use a totally different program_id for a whole different SPL token in this same program and be able to intake 2 SPL tokens: Pubkey::find_program_address(&[br"program-token"], program_id2);
right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and after creating them, this program can do invoke_signed on them and send them wherever they want
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, that's right.
i can use a totally different program_id for a whole different SPL token in this same program and be able to intake 2 SPL tokens: Pubkey::find_program_address(&[br"program-token"], program_id2); right?
Alternatively you use the same program, but adding more seeds to find_program_address
:
Pubkey::find_program_address(&[br"program-token", some_other_seed], program_id);
Here's an example to check out: https://github.com/solana-labs/solana-program-library/blob/487ad2d2d7cb0b8a58f02a156a659e6c8a74f354/associated-token-account/program/src/lib.rs#L24-L32
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you, this is very helpful
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is program_id
in the Pubkey::find_program_address()
function supposed to be the SPL token address that i've created (not the spl_token::id()
? for example, I've created an SPL token, and i want to create an associated account for that token for my program (same as the one above)
pc.add_program( | ||
"spl_token", | ||
spl_token::id(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm still confused by this pc.add_program()
function, it seems like it's not even being used. i've browsed around through the repo and i can't really find precisely what spl_token::id()
is, though i'm pretty sure it's just the spl_token's account address that we've added to ProgramTest
what is spl_token::id()
here? and further, how is that the program itself and also the tests (see line 56) can simply use spl_token::id()
?
going back to my confusion of pc.add_program()
... on line 145, you've just called let program_id = Pubkey::new_unique();
that returns a unique account pubkey, shouldn't the spl_token program we added to the program test be the program_id we're using in our tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spl_token::id()
is actually this: https://github.com/solana-labs/solana-program-library/blob/master/token/program/src/lib.rs#L29
going back to my confusion of pc.add_program()... on line 145, you've just called let program_id = Pubkey::new_unique(); that returns a unique account pubkey, shouldn't the spl_token program we added to the program test be the program_id we're using in our tests?
let program_id = Pubkey::new_unique()
is the program id of bpf_program_template, the actual program that was written here. spl_token::id()
is the program id of the SPL Token program, which is invoked by bpf_program_template
#[tokio::test] | ||
async fn test_transaction() { | ||
async fn test_create_then_close() { | ||
let program_id = Pubkey::new_unique(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is a program_id
created here, when we have the pc.add_program()
call in fn program_test()
, which should just create a mock spl_token to use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i was just interpreting it incorrectly, Pubkey::new_unique()
creates the program_id we then instantiante
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the program_id for the "bpf-program-template program, passed in via
ProgramTest::new(..). It's just a unnamed, unique id here because the actual value doesn't matter for testing purposes -- it just needs to be something. On a real cluster, this would be the value returned by
solana deploy` when the program is deployed
A simple program that supports two instructions:
The unit test can be run by installing Solana 1.4.6 or greater and running
cargo test-bpf