DSRV
Published in

DSRV

[KO] 솔라나에서의 NFT 구현 3편: 캔디머신 코드 분석하기

솔라나 캔디머신 프로그램 코드 리뷰

시작하기 전에..

❗️ 본 글을 읽기 전에, 다음 자료를 통해 Rust와 Solana의 개념을 사전에 숙지하면 이해에 도움이 될 것입니다. 이번 글은 Candy Machine v4.0.0 버전을 중심으로 설명합니다.

1. 전체 과정 개요

1.1. Connection points with the client

Candy Machine Program의 트랜잭션 흐름도
[그림 3–1] Candy Machine Program의 트랜잭션 흐름도, 출처: Metaplex Docs

1.2. Account Flows

Candy Machine의 Account 흐름도
[그림 3-2] Candy Machine의 Account 흐름도, 출처: @c0wjay
> Only needed if candy machine has a gatekeeper 
gateway_token
> Only needed if candy machine has a gatekeeper and it has expire_on_use set to true:
gateway program
network_expire_feature
> Only needed if candy machine has whitelist_mint_settings whitelist_token_account > Only needed if candy machine has whitelist_mint_settings and mode is BurnEveryTime
whitelist_token_mint
whitelist_burn_authority
> Only needed if candy machine has token mint
token_account_info
transfer_authority_info
💡 예를 들어, gatekeeper == false && whitelist_mint_settings == false && token_mint == true 라면, 마지막 2개의 remaining_account들만 전송됩니다. ctx.remaining_accounts 대한 내용은 다음 링크를 참고하시기 바랍니다.

1.3. Json schema

1.4. Candy Machine 파일 계층 구조

src 
├── processor
│ ├── collection
│ │ ├── mod.rs
│ │ ├── remove_collection.rs
│ │ ├── set_collection_during_mint.rs
│ │ └── set_collection.rs
│ ├── add_config_lines.rs
│ ├── initialize.rs
│ ├── mint.rs
│ ├── mod.rs
│ ├── update.rs
│ └── withdraw.rs
├── constants.rs
├── errors.rs
├── lib.rs
├── state.rs
└── utils.rs

1.5. Candy Machine program (lib.rs)

2. handle_initialize_candy_machine 함수 (initialize.rs) 분석

Candy Machine Program Account 간의 관계도
[그림 3-3] Candy Machine Program Account 간의 관계도, 출처: @c0wjay

2.1 InitializeCandyMachine instruction (initialize.rs L11 ~ L25)

Candy Machine PDA Account 구조도
[그림 3-4] Candy Machine PDA Account 구조도, 출처: @c0wjay
💡 DSRV’s Tip: #[account(zero)] attribute가 무엇인가요?#[account(init, payer = <target_account>, space = <num_bytes>)] 다음 attribute는 System Program에 CPI (Cross Program Invocation) 과정을 거쳐 Account를 Initialize합니다. 이 때, Initialize 과정에서 Account Discriminator가 설정됩니다. Account 생성 과정에서 드는 비용은 payer가 부담하며, account가 사용하는 공간만큼 space Constraint에 지정해야 합니다. 여기서 Account Discriminator가 사용하는 공간이 8 byte이므로, 최소 8 byte 이상은 지정해야 합니다.#[account(zero)] 다음 Attribute는 Initialize하려는 Account의 크기가 10 Kibibyte 보다 클 때 init Attribute 대신 사용됩니다. Account의 크기가 10Kibibyte보다 크다면, CPI를 통해 account 생성이 불가합니다. 따라서 미리 이전 instruction으로부터 생성은 되었으나 비어있는 account를 받아서, 해당 account를 initialize합니다. 이 때 #[account(zero)] 의 역할은, 해당 Account의 Discriminator가 0인지 확인하여, Initialize되지 않은 Account가 맞는지 확인합니다.
💡 Account Constraint에 대해 더욱 궁금하시다면, 다음 Anchor Docs의 내용을 참고하시기 바랍니다.

2.2. handle_initialize_candy_machine 함수 (initialize.rs L27 ~ L99)

Candy Machine Data Account 설계도
[그림 3–5] Candy Machine Data Account 설계도, 출처: @c0wjay
Candy Machine Program의 Wallet과 Authority 관계도
[그림 3–6] Candy Machine Program의 Wallet과 Authority 관계도, 출처: @c0wjay
💡 여기부터는 ctx.accounts.wallet, ctx.remaining_accounts 와 같은 Anchor 문법에 익숙하다는 것을 가정하겠습니다. 별도로 추가적인 설명은 하지 않고, ctx.accounts.wallet 와 같은 형태를 차용하겠습니다.
Candy Machine PDA Account와 CW Token Mint Account 간의 관계
[그림 3–7] Candy Machine PDA Account와 CW Token Mint Account 간의 관계, 출처: @c0wjay

3. handle_mint_nft 메소드 (mint.rs) 분석

NFT Token Mint와 Standard Edition, Master Edition Account 간의 관계 구조도
[그림 3–8] NFT Token Mint와 Standard Edition, Master Edition Account 간의 관계 구조도, 출처: @c0wjay

3.1. MintNFT instruction (mint.rs L35 ~ L90)

3.2. 객체 선언 (L96 ~ L108)

3.3. Validation (L109 ~ L192)

”Suspicious transaction detected, Candy Machine Botting is taxed at 10000000 lamports”

1) 2번째 instruction을 candy machine이 아닌 다른 프로그램이 보냈는가?

2) 2번째 instruction의 식별자인 == ix.data[0..8][103, 17, 200, 25, 118, 95, 125, 61] 와 다른가?

3) 3번째 instruction이 Ok(_) 를 반환하는가?

조건 1. Candy Machine Program의 ID인가?

조건 2. SPL Token Program의 ID인가?

조건 3. System Program의 ID인가?

조건 4. Associated Token Program의 ID인가?

instruciton_sysvar의 unsigned integer 8byte로 구성된 배열의 내부 구조
[그림 3–9] instruciton_sysvar의 unsigned integer 8byte로 구성된 배열의 내부 구조, 출처: @c0wjay

3.4. EndSetting 확인 (L195 ~ L227)

3.5. Gatekeeper (L228 ~ L292)

Solana Gateway의 구조
[그림 3-10] Solana Gateway의 구조, 출처: identity-com gateway 백서
❗️ 이번 글에서 언급한 Gateway 코드는 Candy Machine v3.2.5 까지는 Candy Machine Program 내부에서 많은 연산이 진행되었습니다. 그러나 v4.0.0 이후 대부분의 연산이 CPI를 통해 Gateway Program으로 비즈니스 로직이 이전되었습니다. CPI 이후의 자세한 과정이 궁금하신 분은 다음 링크를 참고하시기 바랍니다.

3.6. Whitelist Mint Settings (L294 ~ L444)

3.7. Token mint 설정 (L457 ~ L491)

3.9. 메타데이터 생성 (L508 ~ L611)

[그림 3–11] DSRV Dev Guild Example을 Metaplex NFT로 발행한 모습

4. ErrorCode (errors.rs)

글을 마무리하며..

--

--

[DSRV’s Official Publication on Medium | DSRV 공식 미디엄 채널입니다] “Onboarding the World to Web3”

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store