-
Notifications
You must be signed in to change notification settings - Fork 7
Unwrap instruction #13
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -164,7 +164,7 @@ pub fn process_create_mint( | |
} | ||
|
||
/// Processes [`Wrap`](enum.TokenWrapInstruction.html) instruction. | ||
pub fn process_wrap(_program_id: &Pubkey, accounts: &[AccountInfo], amount: u64) -> ProgramResult { | ||
pub fn process_wrap(accounts: &[AccountInfo], amount: u64) -> ProgramResult { | ||
if amount == 0 { | ||
Err(TokenWrapError::ZeroWrapAmount)? | ||
} | ||
|
@@ -251,6 +251,87 @@ pub fn process_wrap(_program_id: &Pubkey, accounts: &[AccountInfo], amount: u64) | |
Ok(()) | ||
} | ||
|
||
/// Processes [`Unwrap`](enum.TokenWrapInstruction.html) instruction. | ||
pub fn process_unwrap(accounts: &[AccountInfo], amount: u64) -> ProgramResult { | ||
if amount == 0 { | ||
Err(TokenWrapError::ZeroWrapAmount)? | ||
} | ||
|
||
let account_info_iter = &mut accounts.iter(); | ||
|
||
let unwrapped_escrow = next_account_info(account_info_iter)?; | ||
let recipient_unwrapped_token = next_account_info(account_info_iter)?; | ||
let wrapped_mint_authority = next_account_info(account_info_iter)?; | ||
let unwrapped_mint = next_account_info(account_info_iter)?; | ||
let wrapped_token_program = next_account_info(account_info_iter)?; | ||
let unwrapped_token_program = next_account_info(account_info_iter)?; | ||
let wrapped_token_account = next_account_info(account_info_iter)?; | ||
let wrapped_mint = next_account_info(account_info_iter)?; | ||
let transfer_authority = next_account_info(account_info_iter)?; | ||
let multisig_signer_accounts = account_info_iter.as_slice(); | ||
|
||
// Validate accounts | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was comparing the checks here to the token-upgrade program, which is very similar to this instruction in particular. I'm not sure if it's actually needed, but that program does a whole bunch of checks on each account, to make sure they're really token accounts and all that. Here's some owner checks: https://github.com/solana-labs/solana-program-library/blob/63b217336276c1e41163a5ac030d1b5a85741782/token-upgrade/program/src/processor.rs#L96 And here's some account type checks: https://github.com/solana-labs/solana-program-library/blob/63b217336276c1e41163a5ac030d1b5a85741782/token-upgrade/program/src/processor.rs#L126 I could have been overly cautious in that program though. @buffalojoec do you think we need them? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would say no, we don't need account state and owner checks, since everything has to go through an SPL-Token instruction ( Verifying that you're unwrapping to the proper token (and wrapping in the previous instruction) is done by the PDA derivations, so I think we're covered. |
||
|
||
let expected_wrapped_mint = | ||
get_wrapped_mint_address(unwrapped_mint.key, wrapped_token_program.key); | ||
if expected_wrapped_mint != *wrapped_mint.key { | ||
Err(TokenWrapError::WrappedMintMismatch)? | ||
} | ||
|
||
let (expected_authority, bump) = get_wrapped_mint_authority_with_seed(wrapped_mint.key); | ||
if *wrapped_mint_authority.key != expected_authority { | ||
Err(TokenWrapError::MintAuthorityMismatch)? | ||
} | ||
|
||
// Burn wrapped tokens | ||
|
||
let multisig_signer_pubkeys = multisig_signer_accounts | ||
.iter() | ||
.map(|account| account.key) | ||
.collect::<Vec<_>>(); | ||
|
||
invoke( | ||
&spl_token_2022::instruction::burn( | ||
wrapped_token_program.key, | ||
wrapped_token_account.key, | ||
wrapped_mint.key, | ||
transfer_authority.key, | ||
&multisig_signer_pubkeys, | ||
amount, | ||
)?, | ||
&accounts[6..], | ||
)?; | ||
|
||
// Transfer unwrapped tokens from escrow to recipient | ||
|
||
let unwrapped_mint_data = unwrapped_mint.try_borrow_data()?; | ||
let unwrapped_mint_state = PodStateWithExtensions::<PodMint>::unpack(&unwrapped_mint_data)?; | ||
let bump_seed = [bump]; | ||
let signer_seeds = get_wrapped_mint_authority_signer_seeds(wrapped_mint.key, &bump_seed); | ||
|
||
invoke_signed( | ||
&spl_token_2022::instruction::transfer_checked( | ||
unwrapped_token_program.key, | ||
unwrapped_escrow.key, | ||
unwrapped_mint.key, | ||
recipient_unwrapped_token.key, | ||
wrapped_mint_authority.key, | ||
&[], | ||
amount, | ||
unwrapped_mint_state.base.decimals, | ||
)?, | ||
&[ | ||
unwrapped_escrow.clone(), | ||
unwrapped_mint.clone(), | ||
recipient_unwrapped_token.clone(), | ||
wrapped_mint_authority.clone(), | ||
], | ||
&[&signer_seeds], | ||
)?; | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Instruction processor | ||
pub fn process_instruction( | ||
program_id: &Pubkey, | ||
|
@@ -264,11 +345,11 @@ pub fn process_instruction( | |
} | ||
TokenWrapInstruction::Wrap { amount } => { | ||
msg!("Instruction: Wrap"); | ||
process_wrap(program_id, accounts, amount) | ||
process_wrap(accounts, amount) | ||
} | ||
TokenWrapInstruction::Unwrap { .. } => { | ||
TokenWrapInstruction::Unwrap { amount } => { | ||
msg!("Instruction: Unwrap"); | ||
unimplemented!(); | ||
process_unwrap(accounts, amount) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
pub mod common; | ||
pub mod create_mint_builder; | ||
pub mod unwrap_builder; | ||
pub mod wrap_builder; |
Uh oh!
There was an error while loading. Please reload this page.
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.
Re-arranged in order so that accounts can be sub-sliced into the transfer_checked account slice