> ## Documentation Index
> Fetch the complete documentation index at: https://docs.raydium.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Farm / Staking 명령어

> CreateFarm, Deposit, Withdraw, Harvest, AddReward / SetRewards / RestartRewards, WithdrawReward — farm v3, v5, v6 전체 명령어 표면입니다.

<Info>
  **이 페이지는 AI 자동 번역입니다. 모든 내용은 영문판을 기준으로 합니다.**

  [영문판 보기 →](/products/farm-staking/instructions)
</Info>

<Info>
  Farm 명령어는 버전별로 다릅니다. v6의 `Deposit`은 v5 farm에서 호출할 수 없으며 그 반대도 마찬가지입니다. SDK는 farm의 프로그램 소유자를 읽어 버전을 판단합니다. 온체인 CPI의 경우 처음부터 올바른 프로그램 ID를 선택해야 합니다.
</Info>

## 명령어 목록

| 목적                        | v3                   | v5                       | v6               |
| ------------------------- | -------------------- | ------------------------ | ---------------- |
| Farm 생성                   | `CreateFarm`         | `CreateFarm`             | `CreateFarm`     |
| 사용자 ledger 추가 (암시적일 수 있음) | `CreateUserLedger`   | `CreateAssociatedLedger` | `Deposit`에서 암시적  |
| 스테이크                      | `Deposit`            | `Deposit`                | `Deposit`        |
| 언스테이크                     | `Withdraw`           | `Withdraw`               | `Withdraw`       |
| 리워드만 청구                   | N/A (`Deposit 0` 사용) | N/A (`Deposit 0` 사용)     | `Harvest`        |
| 생성 후 리워드 스트림 추가           | N/A                  | `AddReward`              | `AddReward`      |
| 기존 리워드 스트림 편집             | N/A                  | `SetRewards`             | `SetRewards`     |
| end\_time 이후 리워드 재시작      | N/A                  | `RestartRewards`         | `RestartRewards` |
| 미청구 리워드 예산 인출 (관리자)       | N/A                  | `WithdrawReward`         | `WithdrawReward` |

v3 및 v5에서 스테이크를 변경하지 않고 리워드를 청구하는 표준적인 방법은 `amount = 0`으로 `Deposit`을 호출하는 것입니다. 프로그램은 이를 순수 정산으로 처리합니다. v6에서는 명확성을 위해 명시적 `Harvest`를 도입했습니다.

SDK는 이 모든 것을 `raydium.farm.deposit({ ... })` 등 뒤에서 추상화합니다. 다음 섹션에서는 수동으로 명령어를 구성해야 하는 통합자 (애그리게이터, 모니터링 도구, SDK 확장)를 위해 기본 계정 목록을 문서화합니다.

## `CreateFarm` (v6)

새로운 v6 farm을 시작합니다.

**인자**

```
reward_info_count: u8               // 생성 시 리워드 스트림 수 (1..=5)
reward_infos: [
  {
    open_time:            u64,
    end_time:             u64,
    emission_per_second_x64: u128,   // Q64.64
    mint:                 Pubkey,    // reward mint
    token_program:        Pubkey,    // SPL 또는 Token-2022
  }
]
```

**계정** (요약, `reward_info_count = 1`의 경우)

| #  | 이름                         | W | S | 설명                                        |
| -- | -------------------------- | - | - | ----------------------------------------- |
| 1  | `creator`                  | W | S | 렌트 지불, farm 소유.                           |
| 2  | `farm_state`               | W |   | 새로운 `FarmState` 계정.                       |
| 3  | `farm_authority`           |   |   | PDA `[farm_id]`.                          |
| 4  | `staking_mint`             |   |   |                                           |
| 5  | `staking_vault`            | W |   | authority의 ATA 또는 PDA vault로 생성.          |
| 6  | `staking_token_program`    |   |   |                                           |
| 7  | `reward_mint`              |   |   |                                           |
| 8  | `reward_vault`             | W |   | 초기 예산을 수신합니다.                             |
| 9  | `reward_token_program`     |   |   |                                           |
| 10 | `reward_sender_ata`        | W |   | Creator의 reward mint에 대한 ATA; 이 명령어로 소모됨. |
| 11 | `system_program`           |   |   |                                           |
| 12 | `token_program`            |   |   |                                           |
| 13 | `associated_token_program` |   |   |                                           |
| 14 | `rent`                     |   |   |                                           |

**사전조건**

* `open_time > now`, `end_time > open_time`.
* `creator` ATA가 최소 `emission_per_second_x64 × (end_time − open_time) / 2^64` 개의 reward mint를 보유합니다.
* `staking_mint`는 동결 권한이 없거나 동결 권한이 비활성화되어 있습니다.

**사후조건**

* `FarmState` 초기화, `total_staked = 0`.
* 리워드 vault가 전체 스트림 예산으로 펀딩됨.
* Creator의 reward ATA가 해당 금액만큼 소모됨.

## `Deposit` (v6)

스테이킹 민트의 `amount`를 스테이크합니다.

**인자**

```
amount: u64
```

**계정**

| #        | 이름                         | W | S |
| -------- | -------------------------- | - | - |
| 1        | `user`                     | W | S |
| 2        | `user_ledger`              | W |   |
| 3        | `farm_state`               | W |   |
| 4        | `farm_authority`           |   |   |
| 5        | `staking_vault`            | W |   |
| 6        | `user_staking_ata`         | W |   |
| 7..(7+n) | `reward_vault_{i}`         | W |   |
| ...      | `user_reward_ata_{i}`      | W |   |
| last−2   | `system_program`           |   |   |
| last−1   | `token_program`            |   |   |
| last     | `associated_token_program` |   |   |

`user_ledger`가 존재하지 않으면 SDK는 `CreateAccount` 스타일의 ix를 앞에 추가합니다. v6 프로그램은 시스템 프로그램 계정이 주어지면 이를 지연 생성할 수도 있습니다. 남은 계정 패턴: 각 활성 리워드마다 `(reward_vault, user_reward_ata)`를 추가하여 정산이 지급될 수 있도록 합니다.

**효과**

1. 각 활성 리워드 스트림에 대해 지연 업데이트 공식을 사용하여 `reward_per_share_x64[i]`을 새로고칩니다.
2. `pending_i = user_ledger.deposited × reward_per_share_x64[i] / 2^64 − user_ledger.reward_debts[i]`를 계산합니다.
3. `reward_vault_{i}`에서 `user_reward_ata_{i}`로 `pending_i`를 전송합니다.
4. `user_staking_ata`에서 `staking_vault`로 `amount` 스테이킹 민트를 전송합니다.
5. `user_ledger.deposited += amount`를 업데이트하고 `reward_debts[i]`를 다시 스냅샷합니다.
6. `farm_state.total_staked += amount`를 업데이트합니다.

**사전조건**

* 실제 스테이크의 경우 `amount > 0` (v6은 `amount = 0`을 금지합니다 — 청구만의 경우 `Harvest` 사용).
* `user_staking_ata`가 최소 `amount`를 보유합니다.
* 각 활성 리워드 vault가 이 사용자에게 빚진 pending 이상을 보유합니다.

## `Withdraw` (v6)

`amount`를 언스테이크합니다.

**인자**

```
amount: u64
```

**계정** — `Deposit`과 동일합니다.

**효과** — `Deposit`과 동일한 정산을 수행한 후 스테이킹 민트를 사용자에게로 돌립니다: `staking_vault → user_staking_ata`. `total_staked`와 `user_ledger.deposited` 모두 감소합니다.

**사전조건**

* `amount ≤ user_ledger.deposited`.
* Farm이 일시 중지되지 않았습니다.

## `Harvest` (v6)

스테이크를 변경하지 않고 pending 리워드를 청구합니다.

**인자** — 없음.

**계정** — `Deposit`과 동일, 스테이킹 측 이동 없음.

**효과** — `reward_per_share_x64[i]`을 새로고치고 `pending_i`를 지급하며 `reward_debts[i]`을 다시 스냅샷합니다. `total_staked` 또는 `deposited`에 변화 없음.

## `AddReward` (v5/v6)

미사용 슬롯이 있는 기존 farm에 새로운 리워드 스트림을 추가합니다.

**인자**

```
reward_info: {
  open_time:            u64,
  end_time:             u64,
  emission_per_second_x64: u128,
  mint:                 Pubkey,
  token_program:        Pubkey,
}
```

**사전조건**

* 빈 슬롯이 존재합니다 (v6에서는 `reward_info_count < 5`, v5에서는 `< 2`).
* `open_time ≥ now` (미래일 수 있음) 또는 `open_time < now`는 프로그램 버전이 허용하는 경우에만 가능합니다 — v6은 허용, v5는 허용하지 않음.

**사후조건**

* 새로운 스트림이 인덱스 `reward_info_count`에서 초기화되고 `reward_info_count++`됩니다.
* 리워드 vault가 호출자의 ATA에서 전체 스트림 예산으로 크레딧됩니다.

**일반 오류** — 민트가 기존 슬롯과 충돌하면 `RewardAlreadyExists`.

## `SetRewards` (v5/v6)

기존 리워드 스트림을 연장하거나 충전합니다. 민트를 변경할 수 없습니다. `end_time`을 단축할 수 없습니다. 실행 중인 경우 `emission_per_second_x64`를 낮출 수 없습니다.

**인자**

```
reward_index:         u8
new_open_time:        u64,
new_end_time:         u64,
new_emission_per_second_x64: u128,
```

**사전조건**

* 스트림이 여전히 실행 중입니다 (`reward_state == 1`).
* `new_end_time ≥ current end_time`.
* 필요한 추가 예산 `(new_emission × new_duration − already_emissioned)`이 발신자의 ATA에 있고 명령어로 리워드 vault로 전송됩니다.

v5에서는 동등한 호출이 더 작은 인자 세트를 가진 `SetRewards`입니다 (활성 스트림에 대한 초당 변경 없음).

## `RestartRewards` (v5/v6)

`end_time`이 지난 후 스트림을 재시작합니다. 개념적으로 이미 슬롯이 있는 민트에 대한 `AddReward`와 동일합니다.

**인자** — 해당 인덱스에서 `AddReward`와 동일한 형태.

**사전조건**

* `reward_state == 2` (종료됨).
* 호출자는 슬롯의 `reward_sender` (v6) 또는 farm `owner` (v5).

## `WithdrawReward` (v5/v6)

스트림이 종료되고 모든 스테이커가 청구할 기회를 가진 후 미청구 리워드 vault 잔액의 관리자 청소입니다.

**인자**

```
reward_index: u8
```

**사전조건**

* 스트림이 종료됨 (`reward_state == 2`).
* `reward_total_emissioned == reward_claimed + vault_balance` (현재 빚진 것이 없음).

**효과** — 나머지를 `reward_sender_ata`로 이동합니다. 프로그램은 스테이커가 여전히 pending 청구가 있는 동안 인출하는 것을 방지하지 않습니다. 관리자는 지연 스테이커 대신에 먼저 청구하거나 청구하도록 해야 합니다. 조기에 청소하면 사용자가 미청구 리워드에 접근할 수 없습니다. **이를 조기에 호출하지 마세요.**

## v5 변형

* `Deposit` / `Withdraw`는 v6과 동일한 형태이지만 최대 2개의 리워드 슬롯을 사용하고 `reward_per_share`는 `u128`입니다 (다른 기수를 가진 고정소수점).
* `CreateAssociatedLedger`는 첫 `Deposit` 전에 필수 별도 호출입니다. v6은 이를 병합했습니다.
* `AddReward`는 사용 가능하고 `Harvest`는 불가능합니다 (`Deposit 0` 사용).

## v3 변형

* 단일 리워드 스트림. `AddReward` 없음, 두 번째 슬롯 없음.
* `Deposit 0`이 청구하는 유일한 방법입니다.
* 첫 `Deposit` 전에 `CreateUserLedger`를 호출해야 합니다.

## 상태 변화 매트릭스

| 명령어              | `total_staked` | `user.deposited` | `reward_per_share` | 리워드 vault      |
| ---------------- | -------------- | ---------------- | ------------------ | -------------- |
| `CreateFarm`     | 0              | —                | 0                  | creator로 펀딩됨   |
| `Deposit(n)`     | +n             | +n               | 새로고쳐짐              | −pending (지급됨) |
| `Withdraw(n)`    | −n             | −n               | 새로고쳐짐              | −pending       |
| `Harvest`        | —              | —                | 새로고쳐짐              | −pending       |
| `AddReward`      | —              | —                | —                  | +new budget    |
| `SetRewards`     | —              | —                | —                  | +delta budget  |
| `RestartRewards` | —              | —                | —                  | +budget        |
| `WithdrawReward` | —              | —                | —                  | −remainder     |

## 다음 단계

* [`products/farm-staking/code-demos`](/ko/products/farm-staking/code-demos) — TypeScript 예제.
* [`products/farm-staking/accounts`](/ko/products/farm-staking/accounts) — `FarmState` / `UserLedger` / `UserStake` 레이아웃.
* [`reference/error-codes`](/ko/reference/error-codes) — farm 오류 enum.

출처:

* [Raydium SDK v2 `Farm` module](https://github.com/raydium-io/raydium-sdk-V2)
* Raydium farm 프로그램 소스 (v3 / v5 / v6)
