solana #1

R A·2023년 8월 12일
0

SPL 사용하여 토큰 발급하기

SPL

spl-token create-token

spl-token create-account address

spl-token mint address amount

solana 체인에서는 각 토큰별 지갑이 필요

솔라나의 계정( account ) 는 크게 3가지

1. PA ( Program Account )

EVM 의 컨트렉트와 유사
상태는 저장X
데이터 어카운트에 저장된 상태 사용

2. DA ( Data Account )

상태를 저장하는 계정

3. 네이티브 어카운트

시스템 정보와 관련된 계정


SPL 사용시

  1. DA 생성 - Mint Account( 메타 데이터 보유 )
    발행 권한은 유저지갑이 가지고 있음.

  2. 유저는 토큰 프로그램에 Token Account 생성 가능
    -> 특정 토큰에 대한 지갑과 같은 역할, 해당 토큰의 수 저장
    전송시 받는 사람도 토큰 어카운트가 있어야함.

문제 방지를 위해 ATA 프로그램이 존재
( Associated Token Account )

serum-dex token_mint

pub fn new_token_mint(bump: &Bump, rent: Rent) -> AccountInfo {
    let data = bump.alloc_slice_fill_copy(Mint::LEN, 0u8);
    let mut mint = Mint::default();
    mint.is_initialized = true;
    // mint.supply = initial_supply; 초기 공급량 설정
    Mint::pack(mint, data).unwrap();
    AccountInfo::new(
        random_pubkey(bump), // bump 사용해서 token_account 생성
        false,
        true,
        bump.alloc(rent.minimum_balance(data.len())),
        data,
        &spl_token::ID,
        false,
        Epoch::default(),
    )
}
key: &'a Pubkey
[−]
Public key of the account

is_signer: bool
[−]
Was the transaction signed by this account's public key?

is_writable: bool
[−]
Is the account writable?

lamports: Rc<RefCell<&'a mut u64>>
[−]
The lamports in the account. Modifiable by programs.

data: Rc<RefCell<&'a mut [u8]>>
[−]
The data held in this account. Modifiable by programs.

owner: &'a Pubkey
[−]
Program that owns this account

executable: bool
[−]
This account's data contains a loaded program (and is now read-only)

rent_epoch: u64
[−]
The epoch at which this account will next owe rent

캔디머신 코드 분석

토큰 구매 컨트렉트 코드

use anchor_lang::prelude::*;

use anchor_lang::solana_program::pubkey::Pubkey;
use spl_token::instruction::transfer;
use anchor_lang::solana_program::program::invoke;
use anchor_lang::solana_program::program::invoke_signed;
use anchor_spl::{token::TokenAccount, token::Token};
use spl_associated_token_account::instruction::create_associated_token_account;
use spl_associated_token_account::get_associated_token_address;


declare_id!("HJ7gcMbUghckevVRc1e8y2QrQXq2BZMkNHe82JNGo41a");

const TREASURY_PDA_SEED: &[u8] = b"test_seed";

#[program]
pub mod develop {
    use super::*;

    pub fn initialize(_ctx: Context<NoAccounts>) -> Result<()> {
        msg!("first program got called!!!");
        Ok(())

    }

    pub fn withdraw(_ctx: Context<WithdrawAccounts>, receiver: Pubkey, amount: u64) -> Result<()> {
        let (pda, _bump_seed) = Pubkey::find_program_address(&[TREASURY_PDA_SEED], _ctx.program_id);

        let TOKEN_PROGRAM_ID = spl_token::ID;

        msg!("start withdraw!!!");

        let fig_amount = amount * 1000000000;
        let sol_amount = amount * 2000000;

        let ix = anchor_lang::solana_program::system_instruction::transfer(
            &_ctx.accounts.user.key,
            &_ctx.accounts.owner.key,
            sol_amount);

        invoke(
            &ix,
            &[
                _ctx.accounts.user.clone(),
                _ctx.accounts.owner.clone(),
                _ctx.accounts.system_program.to_account_info().clone()
            ]
        )?;

        let transfer_instruction = transfer(
            &TOKEN_PROGRAM_ID,
            &_ctx.accounts.treasury_token.key,
            &receiver,
            &pda,
            &[&pda],
            fig_amount,
        )?;

        msg!("calling the token program to transfer tokens");

        invoke_signed(
                &transfer_instruction,
                &[
                    _ctx.accounts.treasury_token.clone(),
                    _ctx.accounts.destination.clone(),
                    _ctx.accounts.treasury.clone(),
                    _ctx.accounts.token_program.to_account_info().clone(),
                ],
                &[&[
                    &TREASURY_PDA_SEED.as_ref(),
                    &[_bump_seed],

                ]],
            )?;
   
        Ok(())
    }
}

#[derive(Accounts)]
pub struct NoAccounts {

}

#[derive(Accounts)]
pub struct WithdrawAccounts<'info> {
    #[account(mut)]
    /// CHECK :
    pub treasury: AccountInfo<'info>,

    #[account(mut)]
    /// CHECK : 
    pub treasury_token: AccountInfo<'info>,

    #[account(mut)]
    /// CHECK : 
    pub destination: AccountInfo<'info>,

    #[account(mut)]
    /// CHECK :
    pub user: AccountInfo<'info>,

    #[account(mut)]
    /// CHECK :
    pub owner: AccountInfo<'info>,

    /// CHECK:
    pub system_program: Program<'info, System>,

    /// CHECK :
    pub token_program: Program<'info, Token>,
}

#[error_code]
pub enum ErrorCode {
    #[msg("Stop : Insufficient SOL")]
    InsufficientFundsForTransaction,
}
profile
복숭아가 좋아요

1개의 댓글

comment-user-thumbnail
2023년 8월 13일

좋은 글 감사합니다. 자주 올게요 :)

답글 달기