Skip to main content
added 315 characters in body
Source Link
pub fn create_user_token_pda(
    program_id: &Pubkey,
    accounts: &[AccountInfo]
) -> ProgramResult {

    let account_info_iter = &mut accounts.iter();

    let initializer = next_account_info(account_info_iter)?;
    let pda_user_token = next_account_info(account_info_iter)?;
    let pda_user_token_ata = next_account_info(account_info_iter)?;
    let token = next_account_info(account_info_iter)?;
    let system_program = next_account_info(account_info_iter)?;
    let token_program = next_account_info(account_info_iter)?;
    let associated_token_program = next_account_info(account_info_iter)?;

    if !initializer.is_signer {
        msg!("Missing required signature");
        return Err(ProgramError::MissingRequiredSignature);
    }

    msg!("initializer: {}", initializer.key);
    msg!("pda_user_token: {}", pda_user_token.key);
    msg!("pda_user_token_ata: {}", pda_user_token_ata.key);
    msg!("token: {}", token.key);
    msg!("system_program: {}", system_program.key);
    msg!("token_program: {}", token_program.key);
    msg!("associated_token_program: {}", associated_token_program.key);
    
    let rent = Rent::get()?;
    let rent_lamports = rent.minimum_balance(1);

    let (user_token, user_token_bump) =
        Pubkey::find_program_address(&[initializer.key.as_ref(), "token".as_ref()], program_id);
    if user_token != *pda_user_token.key {
        msg!("Invalid seeds for PDA");
        return Err(ProgramError::InvalidArgument);
    }

    msg!("create user token pda"pda - 3");

    if **pda_user_token.try_borrow_lamports()? == 0 {

        invoke_signed(
            &system_instruction::create_account(
                initializer.key,
                pda_user_token.key,
                rent_lamports,
                1,
                program_id,
            ),
            &[
                initializer.clone(),
                pda_user_token.clone(),
                system_program.clone(),
            ],
            &[&[initializer.key.as_ref(), "token".as_ref(), &[user_token_bump]]],
        )?;
    }

    // let associated_token_address = get_associated_token_address(
    //     pda_user_token.key,
    //     token.key
    // );
    // msg!("associated_token_address: {}", associated_token_address.to_string());

    invoke(
        &create_associated_token_account(
            initializer.key,
            pda_user_token_atapda_user_token.key,
            token.key,
            associated_token_programtoken_program.key
        ),
        &[initializer.clone(), pda_user_token.clone(), pda_user_token_ata.clone(), token.clone(), associated_token_programtoken_program.clone(), pda_user_tokensystem_program.clone(), associated_token_program.clone()]
    )?;

    msg!("created user token pda");

    Ok(())
}
async function sendCreateUserTokenPda(signer: web3.Keypair, programId: web3.PublicKey, connection: web3.Connection) {
    let buffer = Buffer.alloc(1000)
    createUserTokenPdaInstructionLayout.encode(
        {
            variant: 1,
            title: ""
        },
        buffer
    )

    buffer = buffer.slice(0, createUserTokenPdaInstructionLayout.getSpan(buffer))
    
    const [userTokenPda] = await web3.PublicKey.findProgramAddressSync(
        [signer.publicKey.toBuffer(), Buffer.from("token")],
        programId
    )

    const userTokenPdaATA = await getAssociatedTokenAddress(
        customTokenProgramId,
        userTokenPda,
        true
    );

    console.log("User Token PDA:", userTokenPda.toBase58())
    console.log("User Token PDA ATA:", userTokenPdaATA.toBase58())
    

    const transaction = new web3.Transaction()
    
    const instruction = new web3.TransactionInstruction({
        programId: programId,
        data: buffer,
        keys: [
            {
                pubkey: signer.publicKey,
                isSigner: true,
                isWritable: false
            },
            {
                pubkey: userTokenPda,
                isSigner: false,
                isWritable: true
            },
            {
                pubkey: userTokenPdaATA,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: customTokenProgramId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: web3.SystemProgram.programId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: TOKEN_PROGRAM_ID,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: ASSOCIATED_TOKEN_PROGRAM_ID,
                isSigner: false,
                isWritable: false
            }            
        ]
    });

    transaction.add(instruction)
    const tx = await web3.sendAndConfirmTransaction(connection, transaction, [signer])
    console.log(`https://explorer.solana.com/tx/${tx}?cluster=custom&customUrl=http://localhost:88999`)
}

logs: [
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 invoke [1]',
    'Program log: process_instruction: FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6: 67 accounts, data=[1, 0, 0, 0, 0]',
    'Program log: initializer: Ggnjfap7FRubFPBWTpoPFHyPvVm9q1t9cB4GHx8MJT7d',
    'Program log: pda_user_token: DmmStsPFssdKnawJziTxfq7CbRgoHt9FTZjgMBD3jVKg',
    'Program log: pda_user_token_ata: HLELxBKDFPVYPz8ht5fDhzP3VbsCExcZWx4Qe8ASGVe1',
    'Program log: token: 3myLM5cXvikPWiqeTq2kHacFEdBq6wsRnxvhpd7HUHEC',
    'Program log: system_program: 11111111111111111111111111111111',
    'Program log: associated_token_programtoken_program: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
    'Program log: create user tokenassociated_token_program: pda'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL',
    'Program log: associated_token_address:create HLELxBKDFPVYPz8ht5fDhzP3VbsCExcZWx4Qe8ASGVe1',
user token pda - 'Instruction3',
 references an unknown account"HLELxBKDFPVYPz8ht5fDhzP3VbsCExcZWx4Qe8ASGVe1's 9834S4ZzyNUebJ5bV1eJDUYaCRmsNgfhpc9WgBry42Jb'writable privilege escalated",
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 consumed 9860697439 of 200000 compute units',
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 failed: AnCross-program accountinvocation requiredwith byunauthorized thesigner instructionor iswritable missing'account'
  ]
pub fn create_user_token_pda(
    program_id: &Pubkey,
    accounts: &[AccountInfo]
) -> ProgramResult {

    let account_info_iter = &mut accounts.iter();

    let initializer = next_account_info(account_info_iter)?;
    let pda_user_token = next_account_info(account_info_iter)?;
    let pda_user_token_ata = next_account_info(account_info_iter)?;
    let token = next_account_info(account_info_iter)?;
    let system_program = next_account_info(account_info_iter)?;
    let associated_token_program = next_account_info(account_info_iter)?;

    if !initializer.is_signer {
        msg!("Missing required signature");
        return Err(ProgramError::MissingRequiredSignature);
    }

    msg!("initializer: {}", initializer.key);
    msg!("pda_user_token: {}", pda_user_token.key);
    msg!("pda_user_token_ata: {}", pda_user_token_ata.key);
    msg!("token: {}", token.key);
    msg!("system_program: {}", system_program.key);
    msg!("associated_token_program: {}", associated_token_program.key);

    let rent = Rent::get()?;
    let rent_lamports = rent.minimum_balance(1);

    let (user_token, user_token_bump) =
        Pubkey::find_program_address(&[initializer.key.as_ref(), "token".as_ref()], program_id);
    if user_token != *pda_user_token.key {
        msg!("Invalid seeds for PDA");
        return Err(ProgramError::InvalidArgument);
    }

    msg!("create user token pda");

    if **pda_user_token.try_borrow_lamports()? == 0 {

        invoke_signed(
            &system_instruction::create_account(
                initializer.key,
                pda_user_token.key,
                rent_lamports,
                1,
                program_id,
            ),
            &[
                initializer.clone(),
                pda_user_token.clone(),
                system_program.clone(),
            ],
            &[&[initializer.key.as_ref(), "token".as_ref(), &[user_token_bump]]],
        )?;
    }

    let associated_token_address = get_associated_token_address(
        pda_user_token.key,
        token.key
    );
    msg!("associated_token_address: {}", associated_token_address.to_string());

    invoke(
        &create_associated_token_account(
            initializer.key,
            pda_user_token_ata.key,
            token.key,
            associated_token_program.key
        ),
        &[initializer.clone(), pda_user_token_ata.clone(), token.clone(), associated_token_program.clone(), pda_user_token.clone()]
    )?;

    msg!("created user token pda");

    Ok(())
}
async function sendCreateUserTokenPda(signer: web3.Keypair, programId: web3.PublicKey, connection: web3.Connection) {
    let buffer = Buffer.alloc(1000)
    createUserTokenPdaInstructionLayout.encode(
        {
            variant: 1,
            title: ""
        },
        buffer
    )

    buffer = buffer.slice(0, createUserTokenPdaInstructionLayout.getSpan(buffer))
    
    const [userTokenPda] = await web3.PublicKey.findProgramAddressSync(
        [signer.publicKey.toBuffer(), Buffer.from("token")],
        programId
    )

    const userTokenPdaATA = await getAssociatedTokenAddress(
        customTokenProgramId,
        userTokenPda,
        true
    );

    console.log("User Token PDA:", userTokenPda.toBase58())
    console.log("User Token PDA ATA:", userTokenPdaATA.toBase58())
    

    const transaction = new web3.Transaction()
    
    const instruction = new web3.TransactionInstruction({
        programId: programId,
        data: buffer,
        keys: [
            {
                pubkey: signer.publicKey,
                isSigner: true,
                isWritable: false
            },
            {
                pubkey: userTokenPda,
                isSigner: false,
                isWritable: true
            },
            {
                pubkey: userTokenPdaATA,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: customTokenProgramId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: web3.SystemProgram.programId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: ASSOCIATED_TOKEN_PROGRAM_ID,
                isSigner: false,
                isWritable: false
            }            
        ]
    })

    transaction.add(instruction)
    const tx = await web3.sendAndConfirmTransaction(connection, transaction, [signer])
    console.log(`https://explorer.solana.com/tx/${tx}?cluster=custom&customUrl=http://localhost:88999`)
}

logs: [
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 invoke [1]',
    'Program log: process_instruction: FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6: 6 accounts, data=[1, 0, 0, 0, 0]',
    'Program log: initializer: Ggnjfap7FRubFPBWTpoPFHyPvVm9q1t9cB4GHx8MJT7d',
    'Program log: pda_user_token: DmmStsPFssdKnawJziTxfq7CbRgoHt9FTZjgMBD3jVKg',
    'Program log: pda_user_token_ata: HLELxBKDFPVYPz8ht5fDhzP3VbsCExcZWx4Qe8ASGVe1',
    'Program log: token: 3myLM5cXvikPWiqeTq2kHacFEdBq6wsRnxvhpd7HUHEC',
    'Program log: system_program: 11111111111111111111111111111111',
    'Program log: associated_token_program: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL',
    'Program log: create user token pda',
    'Program log: associated_token_address: HLELxBKDFPVYPz8ht5fDhzP3VbsCExcZWx4Qe8ASGVe1',
    'Instruction references an unknown account 9834S4ZzyNUebJ5bV1eJDUYaCRmsNgfhpc9WgBry42Jb',
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 consumed 98606 of 200000 compute units',
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 failed: An account required by the instruction is missing'
  ]
pub fn create_user_token_pda(
    program_id: &Pubkey,
    accounts: &[AccountInfo]
) -> ProgramResult {

    let account_info_iter = &mut accounts.iter();

    let initializer = next_account_info(account_info_iter)?;
    let pda_user_token = next_account_info(account_info_iter)?;
    let pda_user_token_ata = next_account_info(account_info_iter)?;
    let token = next_account_info(account_info_iter)?;
    let system_program = next_account_info(account_info_iter)?;
    let token_program = next_account_info(account_info_iter)?;
    let associated_token_program = next_account_info(account_info_iter)?;

    if !initializer.is_signer {
        msg!("Missing required signature");
        return Err(ProgramError::MissingRequiredSignature);
    }

    msg!("initializer: {}", initializer.key);
    msg!("pda_user_token: {}", pda_user_token.key);
    msg!("pda_user_token_ata: {}", pda_user_token_ata.key);
    msg!("token: {}", token.key);
    msg!("system_program: {}", system_program.key);
    msg!("token_program: {}", token_program.key);
    msg!("associated_token_program: {}", associated_token_program.key);
    
    let rent = Rent::get()?;
    let rent_lamports = rent.minimum_balance(1);

    let (user_token, user_token_bump) =
        Pubkey::find_program_address(&[initializer.key.as_ref(), "token".as_ref()], program_id);
    if user_token != *pda_user_token.key {
        msg!("Invalid seeds for PDA");
        return Err(ProgramError::InvalidArgument);
    }

    msg!("create user token pda - 3");

    if **pda_user_token.try_borrow_lamports()? == 0 {

        invoke_signed(
            &system_instruction::create_account(
                initializer.key,
                pda_user_token.key,
                rent_lamports,
                1,
                program_id,
            ),
            &[
                initializer.clone(),
                pda_user_token.clone(),
                system_program.clone(),
            ],
            &[&[initializer.key.as_ref(), "token".as_ref(), &[user_token_bump]]],
        )?;
    }

    // let associated_token_address = get_associated_token_address(
    //     pda_user_token.key,
    //     token.key
    // );
    // msg!("associated_token_address: {}", associated_token_address.to_string());

    invoke(
        &create_associated_token_account(
            initializer.key,
            pda_user_token.key,
            token.key,
            token_program.key
        ),
        &[initializer.clone(), pda_user_token.clone(), pda_user_token_ata.clone(), token.clone(), token_program.clone(), system_program.clone(), associated_token_program.clone()]
    )?;

    msg!("created user token pda");

    Ok(())
}
async function sendCreateUserTokenPda(signer: web3.Keypair, programId: web3.PublicKey, connection: web3.Connection) {
    let buffer = Buffer.alloc(1000)
    createUserTokenPdaInstructionLayout.encode(
        {
            variant: 1,
            title: ""
        },
        buffer
    )

    buffer = buffer.slice(0, createUserTokenPdaInstructionLayout.getSpan(buffer))
    
    const [userTokenPda] = await web3.PublicKey.findProgramAddressSync(
        [signer.publicKey.toBuffer(), Buffer.from("token")],
        programId
    )

    const userTokenPdaATA = await getAssociatedTokenAddress(
        customTokenProgramId,
        userTokenPda,
        true
    );

    console.log("User Token PDA:", userTokenPda.toBase58())
    console.log("User Token PDA ATA:", userTokenPdaATA.toBase58())
    

    const transaction = new web3.Transaction()
    
    const instruction = new web3.TransactionInstruction({
        programId: programId,
        data: buffer,
        keys: [
            {
                pubkey: signer.publicKey,
                isSigner: true,
                isWritable: false
            },
            {
                pubkey: userTokenPda,
                isSigner: false,
                isWritable: true
            },
            {
                pubkey: userTokenPdaATA,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: customTokenProgramId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: web3.SystemProgram.programId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: TOKEN_PROGRAM_ID,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: ASSOCIATED_TOKEN_PROGRAM_ID,
                isSigner: false,
                isWritable: false
            }            
        ]
    });

    transaction.add(instruction)
    const tx = await web3.sendAndConfirmTransaction(connection, transaction, [signer])
    console.log(`https://explorer.solana.com/tx/${tx}?cluster=custom&customUrl=http://localhost:88999`)
}

logs: [
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 invoke [1]',
    'Program log: process_instruction: FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6: 7 accounts, data=[1, 0, 0, 0, 0]',
    'Program log: initializer: Ggnjfap7FRubFPBWTpoPFHyPvVm9q1t9cB4GHx8MJT7d',
    'Program log: pda_user_token: DmmStsPFssdKnawJziTxfq7CbRgoHt9FTZjgMBD3jVKg',
    'Program log: pda_user_token_ata: HLELxBKDFPVYPz8ht5fDhzP3VbsCExcZWx4Qe8ASGVe1',
    'Program log: token: 3myLM5cXvikPWiqeTq2kHacFEdBq6wsRnxvhpd7HUHEC',
    'Program log: system_program: 11111111111111111111111111111111',
    'Program log: token_program: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
    'Program log: associated_token_program: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL',
    'Program log: create user token pda - 3',
    "HLELxBKDFPVYPz8ht5fDhzP3VbsCExcZWx4Qe8ASGVe1's writable privilege escalated",
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 consumed 97439 of 200000 compute units',
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 failed: Cross-program invocation with unauthorized signer or writable account'
  ]
added 1166 characters in body
Source Link
  • create PDA for each user 
  • create ATA for the PDA program to 
  • transfer from from User's ATA to PDA ATA
pub fn create_user_token_pda(
    program_id: &Pubkey,
    accounts: &[AccountInfo]
) -> ProgramResult {

    let account_info_iter = &mut accounts.iter();

    let initializer = next_account_info(account_info_iter)?;
    let pda_user_token = next_account_info(account_info_iter)?;
    let pda_user_token_ata = next_account_info(account_info_iter)?;
    let token = next_account_info(account_info_iter)?;
    let system_program = next_account_info(account_info_iter)?;
    let associated_system_programassociated_token_program = next_account_info(account_info_iter)?;

    if !initializer.is_signer {
        msg!("Missing required signature");
        return Err(ProgramError::MissingRequiredSignature);
    }

    msg!("token"initializer: {}", tokeninitializer.key);
    msg!("pda_user_token: {}", pda_user_token.key);
    msg!("pda_user_token_ata: {}", pda_user_token_ata.key);
    msg!("associated_system_program"token: {}", associated_system_programtoken.key);
    msg!("system_program: {}", system_program.key);
    msg!("associated_token_program: {}", associated_token_program.key);

    let rent = Rent::get()?;
    let rent_lamports = rent.minimum_balance(1);

    let (user_token, user_token_bump) =
        Pubkey::find_program_address(&[initializer.key.as_ref(), "token".as_ref()], program_id);
    if user_token != *pda_user_token.key {
        msg!("Invalid seeds for PDA");
        return Err(ProgramError::InvalidArgument);
    }

    msg!("create user token pda");

    if **pda_user_token.try_borrow_lamports()? == 0 {

        invoke_signed(
            &system_instruction::create_account(
                initializer.key,
                pda_user_token.key,
                rent_lamports,
                1,
                program_id,
            ),
            &[
                initializer.clone(),
                pda_user_token.clone(),
                system_program.clone(),
            ],
            &[&[initializer.key.as_ref(), "token".as_ref(), &[user_token_bump]]],
        )?;
    }

    let associated_token_address = get_associated_token_address(
        pda_user_token.key,
        token.key
    );
    msg!("associated_token_address: {}", associated_token_address.to_string());

    invoke(
        &create_associated_token_account(
            initializer.key,
            pda_user_token_ata.key,
            token.key,
            associated_system_programassociated_token_program.key
        ),
        &[initializer.clone(), pda_user_token_ata.clone(), token.clone(), associated_system_programassociated_token_program.clone()], pda_user_token.clone()]
    )?;

    msg!("created user token pda");

    Ok(())
}
async function sendCreateUserTokenPda(signer: web3.Keypair, programId: web3.PublicKey, connection: web3.Connection) {
    let buffer = Buffer.alloc(1000)
    createUserTokenPdaInstructionLayout.encode(
        {
            variant: 1,
            title: ""
        },
        buffer
    )

    buffer = buffer.slice(0, createUserTokenPdaInstructionLayout.getSpan(buffer))
    
    const [userTokenPda] = await web3.PublicKey.findProgramAddressSync(
        [signer.publicKey.toBuffer(), Buffer.from("token")],
        programId
    )

    const userTokenPdaATA = await getAssociatedTokenAddress(
        customTokenProgramId,
        userTokenPda,
        true
    );

    console.log("User Token PDA:", userTokenPda.toBase58())
    console.log("User Token PDA ATA:", userTokenPdaATA.toBase58())
    

    const transaction = new web3.Transaction()
    
    const instruction = new web3.TransactionInstruction({
        programId: programId,
        data: buffer,
        keys: [
            {
                pubkey: signer.publicKey,
                isSigner: true,
                isWritable: false
            },
            {
                pubkey: userTokenPda,
                isSigner: false,
                isWritable: true
            },
            {
                pubkey: userTokenPdaATA,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: customTokenProgramId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: web3.SystemProgram.programId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: ASSOCIATED_TOKEN_PROGRAM_ID,
                isSigner: false,
                isWritable: false
            }            
        ]
    })

    transaction.add(instruction)
    const tx = await web3.sendAndConfirmTransaction(connection, transaction, [signer])
    console.log(`https://explorer.solana.com/tx/${tx}?cluster=custom&customUrl=http://localhost:88999`)
}

Error / Logs:


logs: [
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 invoke [1]',
    'Program log: process_instruction: FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6: 6 accounts, data=[1, 0, 0, 0, 0]',
    'Program log: initializer: Ggnjfap7FRubFPBWTpoPFHyPvVm9q1t9cB4GHx8MJT7d',
    'Program log: pda_user_token: DmmStsPFssdKnawJziTxfq7CbRgoHt9FTZjgMBD3jVKg',
    'Program log: pda_user_token_ata: HLELxBKDFPVYPz8ht5fDhzP3VbsCExcZWx4Qe8ASGVe1',
    'Program log: token: 3myLM5cXvikPWiqeTq2kHacFEdBq6wsRnxvhpd7HUHEC',
    'Program log: system_program: 11111111111111111111111111111111',
    'Program log: associated_token_program: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL',
    'Program log: create user token pda',
    'Program log: associated_token_address: HLELxBKDFPVYPz8ht5fDhzP3VbsCExcZWx4Qe8ASGVe1',
    'Instruction references an unknown account 9834S4ZzyNUebJ5bV1eJDUYaCRmsNgfhpc9WgBry42Jb',
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 consumed 98606 of 200000 compute units',
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 failed: An account required by the instruction is missing'
  ]
  • create PDA for each user create ATA for the PDA program to transfer from User's ATA to PDA ATA
pub fn create_user_token_pda(
    program_id: &Pubkey,
    accounts: &[AccountInfo]
) -> ProgramResult {

    let account_info_iter = &mut accounts.iter();

    let initializer = next_account_info(account_info_iter)?;
    let pda_user_token = next_account_info(account_info_iter)?;
    let pda_user_token_ata = next_account_info(account_info_iter)?;
    let token = next_account_info(account_info_iter)?;
    let system_program = next_account_info(account_info_iter)?;
    let associated_system_program = next_account_info(account_info_iter)?;

    if !initializer.is_signer {
        msg!("Missing required signature");
        return Err(ProgramError::MissingRequiredSignature);
    }

    msg!("token: {}", token.key);
    msg!("pda_user_token: {}", pda_user_token.key);
    msg!("pda_user_token_ata: {}", pda_user_token_ata.key);
    msg!("associated_system_program: {}", associated_system_program.key);

    let rent = Rent::get()?;
    let rent_lamports = rent.minimum_balance(1);

    let (user_token, user_token_bump) =
        Pubkey::find_program_address(&[initializer.key.as_ref(), "token".as_ref()], program_id);
    if user_token != *pda_user_token.key {
        msg!("Invalid seeds for PDA");
        return Err(ProgramError::InvalidArgument);
    }

    msg!("create user token pda");

    if **pda_user_token.try_borrow_lamports()? == 0 {

        invoke_signed(
            &system_instruction::create_account(
                initializer.key,
                pda_user_token.key,
                rent_lamports,
                1,
                program_id,
            ),
            &[
                initializer.clone(),
                pda_user_token.clone(),
                system_program.clone(),
            ],
            &[&[initializer.key.as_ref(), "token".as_ref(), &[user_token_bump]]],
        )?;
    }

    let associated_token_address = get_associated_token_address(
        pda_user_token.key,
        token.key
    );
    msg!("associated_token_address: {}", associated_token_address.to_string());

    invoke(
        &create_associated_token_account(
            initializer.key,
            pda_user_token_ata.key,
            token.key,
            associated_system_program.key
        ),
        &[initializer.clone(), pda_user_token_ata.clone(), token.clone(), associated_system_program.clone()],
    )?;

    msg!("created user token pda");

    Ok(())
}
async function sendCreateUserTokenPda(signer: web3.Keypair, programId: web3.PublicKey, connection: web3.Connection) {
    let buffer = Buffer.alloc(1000)
    createUserTokenPdaInstructionLayout.encode(
        {
            variant: 1,
            title: ""
        },
        buffer
    )

    buffer = buffer.slice(0, createUserTokenPdaInstructionLayout.getSpan(buffer))
    
    const [userTokenPda] = await web3.PublicKey.findProgramAddressSync(
        [signer.publicKey.toBuffer(), Buffer.from("token")],
        programId
    )

    const userTokenPdaATA = await getAssociatedTokenAddress(
        customTokenProgramId,
        userTokenPda,
        true
    );

    console.log("User Token PDA:", userTokenPda.toBase58())
    console.log("User Token PDA ATA:", userTokenPdaATA.toBase58())
    

    const transaction = new web3.Transaction()
    
    const instruction = new web3.TransactionInstruction({
        programId: programId,
        data: buffer,
        keys: [
            {
                pubkey: signer.publicKey,
                isSigner: true,
                isWritable: false
            },
            {
                pubkey: userTokenPda,
                isSigner: false,
                isWritable: true
            },
            {
                pubkey: userTokenPdaATA,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: customTokenProgramId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: web3.SystemProgram.programId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: ASSOCIATED_TOKEN_PROGRAM_ID,
                isSigner: false,
                isWritable: false
            }            
        ]
    })

    transaction.add(instruction)
    const tx = await web3.sendAndConfirmTransaction(connection, transaction, [signer])
    console.log(`https://explorer.solana.com/tx/${tx}?cluster=custom&customUrl=http://localhost:88999`)
}
  • create PDA for each user 
  • create ATA for the PDA program 
  • transfer from User's ATA to PDA ATA
pub fn create_user_token_pda(
    program_id: &Pubkey,
    accounts: &[AccountInfo]
) -> ProgramResult {

    let account_info_iter = &mut accounts.iter();

    let initializer = next_account_info(account_info_iter)?;
    let pda_user_token = next_account_info(account_info_iter)?;
    let pda_user_token_ata = next_account_info(account_info_iter)?;
    let token = next_account_info(account_info_iter)?;
    let system_program = next_account_info(account_info_iter)?;
    let associated_token_program = next_account_info(account_info_iter)?;

    if !initializer.is_signer {
        msg!("Missing required signature");
        return Err(ProgramError::MissingRequiredSignature);
    }

    msg!("initializer: {}", initializer.key);
    msg!("pda_user_token: {}", pda_user_token.key);
    msg!("pda_user_token_ata: {}", pda_user_token_ata.key);
    msg!("token: {}", token.key);
    msg!("system_program: {}", system_program.key);
    msg!("associated_token_program: {}", associated_token_program.key);

    let rent = Rent::get()?;
    let rent_lamports = rent.minimum_balance(1);

    let (user_token, user_token_bump) =
        Pubkey::find_program_address(&[initializer.key.as_ref(), "token".as_ref()], program_id);
    if user_token != *pda_user_token.key {
        msg!("Invalid seeds for PDA");
        return Err(ProgramError::InvalidArgument);
    }

    msg!("create user token pda");

    if **pda_user_token.try_borrow_lamports()? == 0 {

        invoke_signed(
            &system_instruction::create_account(
                initializer.key,
                pda_user_token.key,
                rent_lamports,
                1,
                program_id,
            ),
            &[
                initializer.clone(),
                pda_user_token.clone(),
                system_program.clone(),
            ],
            &[&[initializer.key.as_ref(), "token".as_ref(), &[user_token_bump]]],
        )?;
    }

    let associated_token_address = get_associated_token_address(
        pda_user_token.key,
        token.key
    );
    msg!("associated_token_address: {}", associated_token_address.to_string());

    invoke(
        &create_associated_token_account(
            initializer.key,
            pda_user_token_ata.key,
            token.key,
            associated_token_program.key
        ),
        &[initializer.clone(), pda_user_token_ata.clone(), token.clone(), associated_token_program.clone(), pda_user_token.clone()]
    )?;

    msg!("created user token pda");

    Ok(())
}
async function sendCreateUserTokenPda(signer: web3.Keypair, programId: web3.PublicKey, connection: web3.Connection) {
    let buffer = Buffer.alloc(1000)
    createUserTokenPdaInstructionLayout.encode(
        {
            variant: 1,
            title: ""
        },
        buffer
    )

    buffer = buffer.slice(0, createUserTokenPdaInstructionLayout.getSpan(buffer))
    
    const [userTokenPda] = await web3.PublicKey.findProgramAddressSync(
        [signer.publicKey.toBuffer(), Buffer.from("token")],
        programId
    )

    const userTokenPdaATA = await getAssociatedTokenAddress(
        customTokenProgramId,
        userTokenPda,
        true
    );

    console.log("User Token PDA:", userTokenPda.toBase58())
    console.log("User Token PDA ATA:", userTokenPdaATA.toBase58())
    

    const transaction = new web3.Transaction()
    
    const instruction = new web3.TransactionInstruction({
        programId: programId,
        data: buffer,
        keys: [
            {
                pubkey: signer.publicKey,
                isSigner: true,
                isWritable: false
            },
            {
                pubkey: userTokenPda,
                isSigner: false,
                isWritable: true
            },
            {
                pubkey: userTokenPdaATA,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: customTokenProgramId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: web3.SystemProgram.programId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: ASSOCIATED_TOKEN_PROGRAM_ID,
                isSigner: false,
                isWritable: false
            }            
        ]
    })

    transaction.add(instruction)
    const tx = await web3.sendAndConfirmTransaction(connection, transaction, [signer])
    console.log(`https://explorer.solana.com/tx/${tx}?cluster=custom&customUrl=http://localhost:88999`)
}

Error / Logs:


logs: [
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 invoke [1]',
    'Program log: process_instruction: FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6: 6 accounts, data=[1, 0, 0, 0, 0]',
    'Program log: initializer: Ggnjfap7FRubFPBWTpoPFHyPvVm9q1t9cB4GHx8MJT7d',
    'Program log: pda_user_token: DmmStsPFssdKnawJziTxfq7CbRgoHt9FTZjgMBD3jVKg',
    'Program log: pda_user_token_ata: HLELxBKDFPVYPz8ht5fDhzP3VbsCExcZWx4Qe8ASGVe1',
    'Program log: token: 3myLM5cXvikPWiqeTq2kHacFEdBq6wsRnxvhpd7HUHEC',
    'Program log: system_program: 11111111111111111111111111111111',
    'Program log: associated_token_program: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL',
    'Program log: create user token pda',
    'Program log: associated_token_address: HLELxBKDFPVYPz8ht5fDhzP3VbsCExcZWx4Qe8ASGVe1',
    'Instruction references an unknown account 9834S4ZzyNUebJ5bV1eJDUYaCRmsNgfhpc9WgBry42Jb',
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 consumed 98606 of 200000 compute units',
    'Program FHS8mWsaFNbTVGNV7PkhnZ3rNmtXnDmmkDE82QWGeLT6 failed: An account required by the instruction is missing'
  ]
added 2197 characters in body
Source Link

Here is the frontend code

async function sendCreateUserTokenPda(signer: web3.Keypair, programId: web3.PublicKey, connection: web3.Connection) {
    let buffer = Buffer.alloc(1000)
    createUserTokenPdaInstructionLayout.encode(
        {
            variant: 1,
            title: ""
        },
        buffer
    )

    buffer = buffer.slice(0, createUserTokenPdaInstructionLayout.getSpan(buffer))
    
    const [userTokenPda] = await web3.PublicKey.findProgramAddressSync(
        [signer.publicKey.toBuffer(), Buffer.from("token")],
        programId
    )

    const userTokenPdaATA = await getAssociatedTokenAddress(
        customTokenProgramId,
        userTokenPda,
        true
    );

    console.log("User Token PDA:", userTokenPda.toBase58())
    console.log("User Token PDA ATA:", userTokenPdaATA.toBase58())
    

    const transaction = new web3.Transaction()
    
    const instruction = new web3.TransactionInstruction({
        programId: programId,
        data: buffer,
        keys: [
            {
                pubkey: signer.publicKey,
                isSigner: true,
                isWritable: false
            },
            {
                pubkey: userTokenPda,
                isSigner: false,
                isWritable: true
            },
            {
                pubkey: userTokenPdaATA,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: customTokenProgramId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: web3.SystemProgram.programId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: ASSOCIATED_TOKEN_PROGRAM_ID,
                isSigner: false,
                isWritable: false
            }            
        ]
    })

    transaction.add(instruction)
    const tx = await web3.sendAndConfirmTransaction(connection, transaction, [signer])
    console.log(`https://explorer.solana.com/tx/${tx}?cluster=custom&customUrl=http://localhost:88999`)
}

Thanks

Thanks

Here is the frontend code

async function sendCreateUserTokenPda(signer: web3.Keypair, programId: web3.PublicKey, connection: web3.Connection) {
    let buffer = Buffer.alloc(1000)
    createUserTokenPdaInstructionLayout.encode(
        {
            variant: 1,
            title: ""
        },
        buffer
    )

    buffer = buffer.slice(0, createUserTokenPdaInstructionLayout.getSpan(buffer))
    
    const [userTokenPda] = await web3.PublicKey.findProgramAddressSync(
        [signer.publicKey.toBuffer(), Buffer.from("token")],
        programId
    )

    const userTokenPdaATA = await getAssociatedTokenAddress(
        customTokenProgramId,
        userTokenPda,
        true
    );

    console.log("User Token PDA:", userTokenPda.toBase58())
    console.log("User Token PDA ATA:", userTokenPdaATA.toBase58())
    

    const transaction = new web3.Transaction()
    
    const instruction = new web3.TransactionInstruction({
        programId: programId,
        data: buffer,
        keys: [
            {
                pubkey: signer.publicKey,
                isSigner: true,
                isWritable: false
            },
            {
                pubkey: userTokenPda,
                isSigner: false,
                isWritable: true
            },
            {
                pubkey: userTokenPdaATA,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: customTokenProgramId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: web3.SystemProgram.programId,
                isSigner: false,
                isWritable: false
            },
            {
                pubkey: ASSOCIATED_TOKEN_PROGRAM_ID,
                isSigner: false,
                isWritable: false
            }            
        ]
    })

    transaction.add(instruction)
    const tx = await web3.sendAndConfirmTransaction(connection, transaction, [signer])
    console.log(`https://explorer.solana.com/tx/${tx}?cluster=custom&customUrl=http://localhost:88999`)
}

Thanks

added 2530 characters in body
Source Link
Loading
Source Link
Loading