3

I've been able to successfully transfer Lamports between accounts using these two different ways but I was wondering if there were any advantages doing it one way or another. I know that in the first way, I would have to pass the system program into the accounts where as the second method I don't, but are there any other reasons why I would choose one over another?

let cpi_context = CpiContext::new(
ctx.accounts.system_program.to_account_info(), 
Transfer {
    from: ctx.accounts.blog.to_account_info().clone(),
    to: ctx.accounts.user.clone(),
});
transfer(cpi_context, lamports)?;

vs

let user_lamports = ctx.accounts.user.lamports();
let blog_lamports = ctx.accounts.blog.to_account_info().lamports();

**ctx.accounts.user.lamports.borrow_mut() = user_lamports
   .checked_add(lamports)
   .unwrap();
        
**ctx.accounts.blog.to_account_info().lamports.borrow_mut() = blog_lamports
   .checked_sub(lamports)
   .unwrap();

1 Answer 1

6

First one is a cross program invocation of the SystemProgram. Both accounts need to be owned by the SystemProgram.

Second one also works with PDAs that are owned by your program. So useful for some kind of vault account for example.

Here is another related question: Error : Signature verification failed when using PDA ,,when transfering sol from a PDA to another address

Internally they do pretty much the same. SystemTransfer does some more checks.
When using lamports.borrow_mut() you need to make sure that in the end the sum of all lamports stays the same as before.

Here is an anchor example that also explains both cases: https://beta.solpg.io/tutorials/tiny-adventure-two

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.